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
->info
;
15 return val
->val
.intval
;
19 void combine_constants (struct ssavar
*out
, struct value
*val
)
22 if (out
->type
== SSAVAR_UNK
) return;
24 if (val
->type
== VAL_REGISTER
) {
25 out
->type
= SSAVAR_UNK
;
29 if (val
->type
== VAL_SSAVAR
) {
30 if (val
->val
.variable
->type
== SSAVAR_CONSTANTUNK
)
32 if (val
->val
.variable
->type
== SSAVAR_UNK
) {
33 out
->type
= SSAVAR_UNK
;
38 constant
= get_constant_value (val
);
39 if (out
->type
== SSAVAR_CONSTANTUNK
) {
40 out
->type
= SSAVAR_CONSTANT
;
43 if (out
->info
!= constant
)
44 out
->type
= SSAVAR_UNK
;
48 void propagate_constants (struct subroutine
*sub
)
50 list worklist
= list_alloc (sub
->code
->lstpool
);
53 varel
= list_head (sub
->ssavars
);
55 struct ssavar
*var
= element_getvalue (varel
);
56 var
->type
= SSAVAR_CONSTANTUNK
;
57 if (var
->def
->type
== OP_ASM
||
58 var
->def
->type
== OP_CALL
||
59 var
->def
->type
== OP_START
||
60 !(IS_BIT_SET (regmask_localvars
, var
->name
.val
.intval
)))
61 var
->type
= SSAVAR_UNK
;
63 list_inserttail (worklist
, var
);
64 varel
= element_next (varel
);
67 while (list_size (worklist
) != 0) {
68 struct ssavar
*var
= list_removehead (worklist
);
73 if (var
->type
== SSAVAR_UNK
) continue;
75 if (var
->def
->type
== OP_PHI
) {
76 temp
.type
= SSAVAR_CONSTANTUNK
;
78 opel
= list_head (var
->def
->operands
);
80 val
= element_getvalue (opel
);
81 combine_constants (&temp
, val
);
82 opel
= element_next (opel
);
85 temp
.type
= SSAVAR_CONSTANT
;
87 opel
= list_head (var
->def
->operands
);
89 val
= element_getvalue (opel
);
90 if (val
->type
== VAL_CONSTANT
) {
91 } else if (val
->type
== VAL_SSAVAR
) {
92 if (val
->val
.variable
->type
== SSAVAR_UNK
)
93 temp
.type
= SSAVAR_UNK
;
94 else if (val
->val
.variable
->type
== SSAVAR_CONSTANTUNK
&&
95 temp
.type
!= SSAVAR_UNK
)
96 temp
.type
= SSAVAR_CONSTANTUNK
;
98 opel
= element_next (opel
);
101 if (temp
.type
== SSAVAR_CONSTANT
) {
102 if (var
->def
->type
== OP_MOVE
) {
103 val
= list_headvalue (var
->def
->operands
);
104 temp
.info
= get_constant_value (val
);
105 var
->def
->status
|= OP_STAT_DEFERRED
;
106 } else if (var
->def
->type
== OP_INSTRUCTION
) {
108 switch (var
->def
->info
.iop
.insn
) {
111 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
112 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
113 temp
.info
= val1
+ val2
;
114 var
->def
->status
|= OP_STAT_DEFERRED
;
117 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
118 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
119 temp
.info
= val1
| val2
;
120 var
->def
->status
|= OP_STAT_DEFERRED
;
123 temp
.type
= SSAVAR_UNK
;
131 if (temp
.type
!= var
->type
) {
133 useel
= list_head (var
->uses
);
135 struct operation
*use
= element_getvalue (useel
);
136 varel
= list_head (use
->results
);
138 val
= element_getvalue (varel
);
139 if (val
->type
== VAL_SSAVAR
)
140 list_inserttail (worklist
, val
->val
.variable
);
141 varel
= element_next (varel
);
143 useel
= element_next (useel
);
146 var
->type
= temp
.type
;
147 var
->info
= temp
.info
;
151 list_free (worklist
);