sethi.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
sethi.c (3599B)
---
1 #include <scc/scc.h>
2
3 #include "cc2.h"
4
5 static Node *
6 assignnode(Type *tp, Node *lhs, Node *rhs)
7 {
8 Node *np;
9
10 np = node(OASSIG);
11 np->type = *tp;
12 np->left = lhs;
13 np->right = rhs;
14 return sethi(np);
15 }
16
17 static Node *
18 branchnode(Node *cond, Symbol *sym)
19 {
20 Node *np;
21 int op = cond ? OBRANCH : OJMP;
22
23 np = node(op);
24 np->op = op;
25 np->left = sethi(cond);
26 np->u.sym = sym;
27 sym->refcnt++;
28
29 return np;
30 }
31
32 static Node *
33 bool(Node *cond, Symbol *true, Symbol *false)
34 {
35 Symbol *label;
36 Node *p, *l = cond->left, *r = cond->right;
37
38 switch (cond->op) {
39 case ONEG:
40 l = bool(l, false, true);
41 break;
42 case OAND:
43 label = newlabel();
44 l = bool(l, label, false);
45 prestmt(labelstmt(NULL, label));
46 r = bool(r, true, false);
47 break;
48 case OOR:
49 label = newlabel();
50 l = bool(l, true, label);
51 prestmt(labelstmt(NULL, label));
52 r = bool(r, true, false);
53 break;
54 default:
55 prestmt(branchnode(cond, true));
56 prestmt(branchnode(NULL, false));
57 return NULL;
58 }
59
60 cond->left = l;
61 cond->right = r;
62 return cond;
63 }
64
65 Node *
66 logicexpr(Node *np)
67 {
68 Node *tmpvar, *p, *zero, *one;
69 Type *tp = &np->type;
70 Symbol *true, *false, *phi, *tmpsym;
71
72 true = newlabel();
73 false = newlabel();
74 phi = newlabel();
75
76 bool(np, true, false);
77
78 tmpvar = tmpnode(tp, NULL);
79 tmpsym = tmpvar->u.sym;
80 zero = constnode(NULL, 0, tp);
81 one = constnode(NULL, 1, tp);
82
83 p = assignnode(tp, tmpnode(tp, tmpsym), one);
84 prestmt(labelstmt(p, true));
85
86 prestmt(branchnode(NULL, phi));
87
88 p = assignnode(tp, tmpnode(tp, tmpsym), zero);
89 prestmt(labelstmt(p, false));
90
91 prestmt(labelstmt(NULL, phi));
92
93 return sethi(tmpvar);
94 }
95
96 static void
97 comma(Node *np)
98 {
99 if (np->op != OCOMMA) {
100 prestmt(sethi(np));
101 } else {
102 comma(np->left);
103 prestmt(sethi(np->right));
104 delnode(np);
105 }
106 }
107
108 static Node *
109 ternary(Node *np)
110 {
111 Type *tp;
112 Node *tmpvar, *colon, *p;
113 Symbol *tmpsym, *true, *false, *phi;
114
115 true = newlabel();
116 false = newlabel();
117 phi = newlabel();
118 bool(np->left, true, false);
119
120 tp = &np->type;
121 colon = np->right;
122 tmpvar = tmpnode(tp, NULL);
123 tmpsym = tmpvar->u.sym;
124
125 prestmt(labelstmt(NULL, true));
126 p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->left));
127 prestmt(p);
128 prestmt(branchnode(NULL, phi));
129
130 prestmt(labelstmt(NULL, false));
131 p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->right));
132 prestmt(p);
133
134 prestmt(labelstmt(NULL, phi));
135
136 return sethi(tmpvar);
137 }
138
139 static Node *
140 replace(Node *what, Node *with)
141 {
142 Node *prev, *next;
143
144 next = what->next, prev = what->prev;
145 *what = *with;
146 delnode(with);
147 what->next = next, what->prev = prev;
148
149 return sethi(what);
150 }
151
152 Node *
153 sethi(Node *np)
154 {
155 int op;
156 Node *next, *l, *r;
157
158 if (!np)
159 return np;
160
161 np->complex = 0;
162 np->address = 0;
163
164 switch (np->op) {
165 case OBSWITCH:
166 np = swtch(np);
167 break;
168 case OBRANCH:
169 next = np->next;
170 if (!next->label)
171 labelstmt(next, NULL);
172
173 op = np->left->op;
174 if (op != ONEG && op != OOR && op != OAND) {
175 sethi(np->left);
176 return np;
177 }
178
179 bool(np->left, np->u.sym, next->label);
180 np->u.sym->refcnt--;
181 return NULL;
182 case OCOMMA:
183 r = np->right;
184 comma(np->left);
185 return replace(np, r);
186 case OASK:
187 return replace(np, ternary(np));
188 case ONEG:
189 case OAND:
190 case OOR:
191 return replace(np, logicexpr(np));
192 default:
193 np = tsethi(np);
194 break;
195 }
196
197 l = np->left;
198 r = np->right;
199
200 if (np->address > 10)
201 return np;
202 if (l)
203 np->complex = l->complex;
204 if (r) {
205 int d = np->complex - r->complex;
206
207 if (d == 0)
208 ++np->complex;
209 else if (d < 0)
210 np->complex = r->complex;
211 }
212 if (np->complex == 0)
213 ++np->complex;
214
215 return np;
216 }
217
218 void
219 genaddr(void)
220 {
221 apply(sethi);
222 PRTREE("after sethi");
223 }