7 uint32
get_constant_value (struct value
*val
)
9 if (val
->type
== VAL_VARIABLE
)
10 return val
->val
.variable
->info
;
12 return val
->val
.intval
;
16 void combine_constants (struct variable
*out
, struct value
*val
)
19 if (out
->type
== VARIABLE_UNK
) return;
21 if (val
->type
== VAL_REGISTER
) {
22 out
->type
= VARIABLE_UNK
;
26 if (val
->type
== VAL_VARIABLE
) {
27 if (val
->val
.variable
->type
== VARIABLE_CONSTANTUNK
)
29 if (val
->val
.variable
->type
== VARIABLE_UNK
) {
30 out
->type
= VARIABLE_UNK
;
35 constant
= get_constant_value (val
);
36 if (out
->type
== VARIABLE_CONSTANTUNK
) {
37 out
->type
= VARIABLE_CONSTANT
;
40 if (out
->info
!= constant
)
41 out
->type
= VARIABLE_UNK
;
45 void propagate_constants (struct subroutine
*sub
)
47 list worklist
= list_alloc (sub
->code
->lstpool
);
50 varel
= list_head (sub
->variables
);
52 struct variable
*var
= element_getvalue (varel
);
53 var
->type
= VARIABLE_CONSTANTUNK
;
54 if (var
->def
->type
== OP_ASM
||
55 var
->def
->type
== OP_CALL
||
56 var
->def
->type
== OP_START
)
57 var
->type
= VARIABLE_UNK
;
59 list_inserttail (worklist
, var
);
60 varel
= element_next (varel
);
63 while (list_size (worklist
) != 0) {
64 struct variable
*var
= list_removehead (worklist
);
69 if (var
->type
== VARIABLE_UNK
) continue;
71 if (var
->def
->type
== OP_PHI
) {
72 temp
.type
= VARIABLE_CONSTANTUNK
;
74 opel
= list_head (var
->def
->operands
);
76 val
= element_getvalue (opel
);
77 combine_constants (&temp
, val
);
78 opel
= element_next (opel
);
81 temp
.type
= VARIABLE_CONSTANT
;
83 opel
= list_head (var
->def
->operands
);
85 val
= element_getvalue (opel
);
86 if (val
->type
== VAL_CONSTANT
) {
87 } else if (val
->type
== VAL_VARIABLE
) {
88 if (val
->val
.variable
->type
== VARIABLE_UNK
)
89 temp
.type
= VARIABLE_UNK
;
90 else if (val
->val
.variable
->type
== VARIABLE_CONSTANTUNK
&&
91 temp
.type
!= VARIABLE_UNK
)
92 temp
.type
= VARIABLE_CONSTANTUNK
;
94 opel
= element_next (opel
);
97 if (temp
.type
== VARIABLE_CONSTANT
) {
98 if (var
->def
->type
== OP_MOVE
) {
99 val
= list_headvalue (var
->def
->operands
);
100 temp
.info
= get_constant_value (val
);
101 var
->def
->deferred
= TRUE
;
102 } else if (var
->def
->type
== OP_INSTRUCTION
) {
104 switch (var
->def
->info
.iop
.insn
) {
107 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
108 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
109 temp
.info
= val1
+ val2
;
110 var
->def
->deferred
= TRUE
;
113 val1
= get_constant_value (list_headvalue (var
->def
->operands
));
114 val2
= get_constant_value (list_tailvalue (var
->def
->operands
));
115 temp
.info
= val1
| val2
;
116 var
->def
->deferred
= TRUE
;
119 temp
.type
= VARIABLE_UNK
;
127 if (temp
.type
!= var
->type
) {
129 useel
= list_head (var
->uses
);
131 struct operation
*use
= element_getvalue (useel
);
132 varel
= list_head (use
->results
);
134 val
= element_getvalue (varel
);
135 if (val
->type
== VAL_VARIABLE
)
136 list_inserttail (worklist
, val
->val
.variable
);
137 varel
= element_next (varel
);
139 useel
= element_next (useel
);
142 var
->type
= temp
.type
;
143 var
->info
= temp
.info
;
147 list_free (worklist
);