Bug in var->Def
[pspdecompiler.git] / dataflow.c
blob520e7a41dfc1920f0f4b70d52e96b1d2f41612d6
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
5 #include "code.h"
6 #include "utils.h"
8 const uint32 regmask_localvars[NUM_REGMASK] = { 0x43FFFFFE, 0x00000003 };
10 static
11 void mark_ssavar (struct ssavar *var, enum ssavartype type, int num)
13 element useel, phiel;
14 struct value *val;
16 var->info = num;
17 var->type = type;
18 useel = list_head (var->uses);
19 while (useel) {
20 struct operation *use = element_getvalue (useel);
21 if (use->type == OP_PHI) {
22 phiel = list_head (use->operands);
23 while (phiel) {
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);
39 while (phiel) {
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);
50 static
51 int check_regs (list l)
53 struct value *val;
54 element operel;
55 int reg;
57 operel = list_head (l);
58 while (operel) {
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;
66 } else continue;
68 if (!IS_BIT_SET (regmask_localvars, reg)) return TRUE;
71 return FALSE;
74 static
75 void check_special_regs (struct subroutine *sub)
77 element blockel;
78 element opel;
80 blockel = list_head (sub->blocks);
81 while (blockel) {
82 struct basicblock *block = element_getvalue (blockel);
83 opel = list_head (block->operations);
84 while (opel) {
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)
99 element varel;
100 int count = 0;
102 check_special_regs (sub);
104 varel = list_head (sub->ssavars);
105 while (varel) {
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);
116 } else {
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;
140 var->info = 0;
141 } else {
142 mark_ssavar (var, SSAVAR_LOCAL, ++count);
145 } else {
146 mark_ssavar (var, SSAVAR_ARGUMENT, var->name.val.intval);
149 varel = element_next (varel);