2 * Author: Humberto Naves (hsnaves@gmail.com)
10 uint32
get_constant_value (struct value
*val
)
12 if (val
->type
== VAL_SSAVAR
)
13 return val
->val
.variable
->value
;
15 return val
->val
.intval
;
19 void combine_constants (struct ssavar
*out
, struct value
*val
)
22 if (CONST_TYPE (out
->status
) == VAR_STAT_NOTCONSTANT
) return;
24 if (val
->type
== VAL_REGISTER
) {
25 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
28 if (val
->type
== VAL_SSAVAR
) {
29 if (CONST_TYPE (val
->val
.variable
->status
) == VAR_STAT_UNKCONSTANT
)
31 if (CONST_TYPE (val
->val
.variable
->status
) == VAR_STAT_NOTCONSTANT
) {
32 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
37 constant
= get_constant_value (val
);
38 if (CONST_TYPE (out
->status
) == VAR_STAT_UNKCONSTANT
) {
39 CONST_SETTYPE (out
->status
, VAR_STAT_CONSTANT
);
40 out
->value
= constant
;
42 if (out
->value
!= constant
)
43 CONST_SETTYPE (out
->status
, VAR_STAT_NOTCONSTANT
);
47 void propagate_constants (struct subroutine
*sub
)
49 list worklist
= list_alloc (sub
->code
->lstpool
);
52 if (sub
->begin
->address
== 0x42c) {
56 varel
= list_head (sub
->ssavars
);
58 struct ssavar
*var
= element_getvalue (varel
);
59 struct operation
*op
= var
->def
;
60 CONST_SETTYPE (var
->status
, VAR_STAT_UNKCONSTANT
);
61 if (op
->type
== OP_ASM
||
62 op
->type
== OP_CALL
||
63 op
->type
== OP_START
||
64 !(IS_BIT_SET (regmask_localvars
, var
->name
.val
.intval
)))
65 CONST_SETTYPE (var
->status
, VAR_STAT_NOTCONSTANT
);
68 list_inserttail (worklist
, var
);
70 varel
= element_next (varel
);
73 while (list_size (worklist
) != 0) {
74 struct ssavar
*aux
, *var
= list_removehead (worklist
);
81 op
->status
&= ~OP_STAT_CONSTANT
;
82 if (CONST_TYPE (var
->status
) == VAR_STAT_NOTCONSTANT
) continue;
85 if (op
->type
== OP_PHI
) {
86 temp
.status
= VAR_STAT_UNKCONSTANT
;
88 opel
= list_head (op
->operands
);
90 val
= element_getvalue (opel
);
91 combine_constants (&temp
, val
);
92 opel
= element_next (opel
);
95 temp
.status
= VAR_STAT_CONSTANT
;
97 opel
= list_head (op
->operands
);
99 val
= element_getvalue (opel
);
100 if (val
->type
== VAL_SSAVAR
) {
101 aux
= val
->val
.variable
;
102 if (CONST_TYPE (aux
->status
) == VAR_STAT_NOTCONSTANT
) {
103 temp
.status
= VAR_STAT_NOTCONSTANT
;
105 } else if (CONST_TYPE (aux
->status
) == VAR_STAT_UNKCONSTANT
)
106 temp
.status
= VAR_STAT_UNKCONSTANT
;
108 opel
= element_next (opel
);
111 if (temp
.status
== VAR_STAT_CONSTANT
) {
112 if (op
->type
== OP_MOVE
) {
113 val
= list_headvalue (op
->operands
);
114 temp
.value
= get_constant_value (val
);
115 op
->status
|= OP_STAT_CONSTANT
;
116 } else if (op
->type
== OP_INSTRUCTION
) {
118 switch (op
->info
.iop
.insn
) {
121 val1
= get_constant_value (list_headvalue (op
->operands
));
122 val2
= get_constant_value (list_tailvalue (op
->operands
));
123 op
->status
|= OP_STAT_CONSTANT
;
124 temp
.value
= val1
+ val2
;
127 val1
= get_constant_value (list_headvalue (op
->operands
));
128 val2
= get_constant_value (list_tailvalue (op
->operands
));
129 op
->status
|= OP_STAT_CONSTANT
;
130 temp
.value
= val1
| val2
;
133 temp
.status
= VAR_STAT_NOTCONSTANT
;
141 if (temp
.status
!= CONST_TYPE (var
->status
)) {
143 useel
= list_head (var
->uses
);
145 struct operation
*use
= element_getvalue (useel
);
146 if (use
->type
== OP_INSTRUCTION
|| use
->type
== OP_MOVE
|| use
->type
== OP_PHI
) {
147 varel
= list_head (use
->results
);
149 val
= element_getvalue (varel
);
150 if (val
->type
== VAL_SSAVAR
) {
151 aux
= val
->val
.variable
;
154 list_inserttail (worklist
, aux
);
157 varel
= element_next (varel
);
160 useel
= element_next (useel
);
163 CONST_SETTYPE (var
->status
, temp
.status
);
164 var
->value
= temp
.value
;
167 list_free (worklist
);
170 varel
= list_head (sub
->ssavars
);
172 struct ssavar
*var
= element_getvalue (varel
);
173 struct operation
*op
= var
->def
;
176 if (CONST_TYPE (var
->status
) == VAR_STAT_CONSTANT
) {
177 op
->status
|= OP_STAT_DEFERRED
;
178 useel
= list_head (var
->uses
);
180 struct operation
*use
= element_getvalue (useel
);
181 if (use
->type
== OP_PHI
) {
182 struct value
*val
= list_headvalue (use
->results
);
183 if (val
->type
!= VAL_SSAVAR
) break;
184 if (CONST_TYPE (val
->val
.variable
->status
) != VAR_STAT_CONSTANT
)
186 } else if (use
->type
== OP_ASM
) break;
187 useel
= element_next (useel
);
190 op
->status
&= ~OP_STAT_DEFERRED
;
194 varel
= element_next (varel
);