sethi.c - scc - simple c99 compiler
HTML git clone git://git.simple-cc.org/scc
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
sethi.c (3758B)
---
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 Symbol *label;
144
145 label = what->label;
146 next = what->next, prev = what->prev;
147
148 *what = *with;
149 delnode(with);
150 what->next = next, what->prev = prev;
151 what->label = label;
152
153 return sethi(what);
154 }
155
156 Node *
157 sethi(Node *np)
158 {
159 int op;
160 Node *next, *l, *r;
161
162 if (!np)
163 return np;
164
165 np->complex = 0;
166 np->address = 0;
167
168 switch (np->op) {
169 case OBSWITCH:
170 np = swtch(np);
171 break;
172 case OBRANCH:
173 next = np->next;
174 if (!next->label)
175 labelstmt(next, NULL);
176
177 op = np->left->op;
178 if (op != ONEG && op != OOR && op != OAND) {
179 sethi(np->left);
180 return np;
181 }
182
183 bool(np->left, np->u.sym, next->label);
184 np->u.sym->refcnt--;
185 return NULL;
186 case OCOMMA:
187 r = np->right;
188 comma(np->left);
189 return replace(np, r);
190 case OASK:
191 return replace(np, ternary(np));
192 case ONEG:
193 case OAND:
194 case OOR:
195 return replace(np, logicexpr(np));
196 default:
197 np = tsethi(np);
198 break;
199 }
200
201 l = np->left;
202 r = np->right;
203
204 if (np->address > 10)
205 return np;
206 if (l)
207 np->complex = l->complex;
208 if (r) {
209 int d = np->complex - r->complex;
210
211 if (d == 0)
212 ++np->complex;
213 else if (d < 0)
214 np->complex = r->complex;
215 }
216 if (np->complex == 0)
217 ++np->complex;
218
219 return np;
220 }
221
222 static Node *
223 presethi(Node *np)
224 {
225 /* just in case ... */
226 savelabel();
227 return sethi(np);
228 }
229
230 void
231 genaddr(void)
232 {
233 apply(presethi);
234 PRTREE("after sethi");
235 }