7 uint32
get_constant_value (struct value
*val
)
9 if (val
->type
== VAL_SSAVAR
)
10 return val
->val
.variable
->info
;
12 return val
->val
.intval
;
16 void combine_constants (struct ssavar
*out
, struct value
*val
)
19 if (out
->type
== SSAVAR_UNK
) return;
21 if (val
->type
== VAL_REGISTER
) {
22 out
->type
= SSAVAR_UNK
;
26 if (val
->type
== VAL_SSAVAR
) {
27 if (val
->val
.variable
->type
== SSAVAR_CONSTANTUNK
)
29 if (val
->val
.variable
->type
== SSAVAR_UNK
) {
30 out
->type
= SSAVAR_UNK
;
35 constant
= get_constant_value (val
);
36 if (out
->type
== SSAVAR_CONSTANTUNK
) {
37 out
->type
= SSAVAR_CONSTANT
;
40 if (out
->info
!= constant
)
41 out
->type
= SSAVAR_UNK
;
45 void propagate_constants (struct subroutine
*sub
)
47 list worklist
= list_alloc (sub
->code
->lstpool
);
50 varel
= list_head (sub
->ssavars
);
52 struct ssavar
*var
= element_getvalue (varel
);
53 var
->type
= SSAVAR_CONSTANTUNK
;
54 if (var
->def
->type
== OP_ASM
||
55 var
->def
->type
== OP_CALL
||
56 var
->def
->type
== OP_START
||
57 !(IS_BIT_SET (regmask_localvars
, var
->name
.val
.intval
)))
58 var
->type
= SSAVAR_UNK
;
60 list_inserttail (worklist
, var
);
61 varel
= element_next (varel
);
64 while (list_size (worklist
) != 0) {
65 struct ssavar
*var
= list_removehead (worklist
);
70 if (var
->type
== SSAVAR_UNK
) continue;
72 if (var
->def
->type
== OP_PHI
) {
73 temp
.type
= SSAVAR_CONSTANTUNK
;
75 opel
= list_head (var
->def
->operands
);
77 val
= element_getvalue (opel
);
78 combine_constants (&temp
, val
);
79 opel
= element_next (opel
);
82 temp
.type
= SSAVAR_CONSTANT
;
84 opel
= list_head (var
->def
->operands
);
86 val
= element_getvalue (opel
);
87 if (val
->type
== VAL_CONSTANT
) {
88 } else if (val
->type
== VAL_SSAVAR
) {
89 if (val
->val
.variable
->type
== SSAVAR_UNK
)
90 temp
.type
= SSAVAR_UNK
;
91 else if (val
->val
.variable
->type
== SSAVAR_CONSTANTUNK
&&
92 temp
.type
!= SSAVAR_UNK
)
93 temp
.type
= SSAVAR_CONSTANTUNK
;
95 opel
= element_next (opel
);
98 if (temp
.type
== SSAVAR_CONSTANT
) {
99 if (var
->def
->type
== OP_MOVE
) {
100 val
= list_headvalue (var
->def
->operands
);
101 temp
.info
= get_constant_value (val
);
102 var
->def
->status
|= OPERATION_DEFERRED
;
103 } else if (var
->def
->type
== OP_INSTRUCTION
) {
105 switch (var
->def
->info
.iop
.insn
) {
108 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
109 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
110 temp
.info
= val1
+ val2
;
111 var
->def
->status
|= OPERATION_DEFERRED
;
114 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
115 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
116 temp
.info
= val1
| val2
;
117 var
->def
->status
|= OPERATION_DEFERRED
;
120 temp
.type
= SSAVAR_UNK
;
128 if (temp
.type
!= var
->type
) {
130 useel
= list_head (var
->uses
);
132 struct operation
*use
= element_getvalue (useel
);
133 varel
= list_head (use
->results
);
135 val
= element_getvalue (varel
);
136 if (val
->type
== VAL_SSAVAR
)
137 list_inserttail (worklist
, val
->val
.variable
);
138 varel
= element_next (varel
);
140 useel
= element_next (useel
);
143 var
->type
= temp
.type
;
144 var
->info
= temp
.info
;
148 list_free (worklist
);