2 * Author: Humberto Naves (hsnaves@gmail.com)
8 const uint32 regmask_localvars
[NUM_REGMASK
] = { 0x43FFFFFE, 0x00000003 };
11 void mark_ssavar (struct ssavar
*var
, enum ssavartype type
, int num
)
18 useel
= list_head (var
->uses
);
20 struct operation
*use
= element_getvalue (useel
);
21 if (use
->type
== OP_PHI
) {
22 phiel
= list_head (use
->operands
);
24 struct value
*val
= element_getvalue (phiel
);
25 if (val
->val
.variable
->type
== SSAVAR_UNK
) {
26 mark_ssavar (val
->val
.variable
, type
, num
);
28 phiel
= element_next (phiel
);
30 val
= list_headvalue (use
->results
);
31 if (val
->val
.variable
->type
== SSAVAR_UNK
)
32 mark_ssavar (val
->val
.variable
, type
, num
);
34 useel
= element_next (useel
);
37 if (var
->def
->type
== OP_PHI
) {
38 phiel
= list_head (var
->def
->operands
);
40 struct value
*val
= element_getvalue (phiel
);
41 if (val
->val
.variable
->type
== SSAVAR_UNK
) {
42 mark_ssavar (val
->val
.variable
, type
, num
);
44 phiel
= element_next (phiel
);
51 int check_regs (list l
)
57 operel
= list_head (l
);
59 val
= element_getvalue (operel
);
60 operel
= element_next (operel
);
62 if (val
->type
== VAL_REGISTER
) {
63 reg
= val
->val
.intval
;
64 } else if (val
->type
== VAL_SSAVAR
) {
65 reg
= val
->val
.variable
->name
.val
.intval
;
68 if (!IS_BIT_SET (regmask_localvars
, reg
)) return TRUE
;
75 void check_special_regs (struct subroutine
*sub
)
80 blockel
= list_head (sub
->blocks
);
82 struct basicblock
*block
= element_getvalue (blockel
);
83 opel
= list_head (block
->operations
);
85 struct operation
*op
= element_getvalue (opel
);
86 if (op
->type
== OP_INSTRUCTION
|| op
->type
== OP_MOVE
) {
87 if (check_regs (op
->operands
) || check_regs (op
->results
)) {
88 op
->status
|= OP_STAT_SPECIALREGS
;
91 opel
= element_next (opel
);
93 blockel
= element_next (blockel
);
97 void extract_variables (struct subroutine
*sub
)
102 check_special_regs (sub
);
104 varel
= list_head (sub
->ssavars
);
106 struct ssavar
*var
= element_getvalue (varel
);
107 struct operation
*op
= var
->def
;
109 if (var
->type
== SSAVAR_UNK
) {
110 if (IS_BIT_SET (regmask_localvars
, var
->name
.val
.intval
)) {
111 if (op
->type
== OP_START
) {
112 mark_ssavar (var
, SSAVAR_ARGUMENT
, var
->name
.val
.intval
);
113 } else if (op
->type
== OP_CALL
&& var
->name
.val
.intval
!= REGISTER_GPR_V0
&&
114 var
->name
.val
.intval
!= REGISTER_GPR_V1
) {
115 mark_ssavar (var
, SSAVAR_INVALID
, 0);
118 if (op
->type
== OP_MOVE
|| op
->type
== OP_INSTRUCTION
) {
119 if (!(var
->status
& (VAR_STAT_PHIARG
| VAR_STAT_ASMARG
))) {
120 if (list_size (var
->uses
) <= 1) {
121 op
->status
|= OP_STAT_DEFERRED
;
125 if (op
->type
== OP_INSTRUCTION
) {
126 if (op
->info
.iop
.loc
->insn
->flags
& (INSN_LOAD
| INSN_STORE
))
127 op
->status
&= ~OP_STAT_DEFERRED
;
128 else if ((op
->info
.iop
.loc
->insn
->flags
& (INSN_BRANCH
)) &&
129 !op
->info
.iop
.loc
->branchalways
)
130 op
->status
&= ~OP_STAT_DEFERRED
;
134 if (op
->status
& OP_STAT_SPECIALREGS
) {
135 op
->status
&= ~OP_STAT_DEFERRED
;
138 if (op
->status
& OP_STAT_DEFERRED
) {
139 var
->type
= SSAVAR_TEMP
;
142 mark_ssavar (var
, SSAVAR_LOCAL
, ++count
);
146 mark_ssavar (var
, SSAVAR_ARGUMENT
, var
->name
.val
.intval
);
149 varel
= element_next (varel
);