blob: 836cdd452c08741333ea0438f3d9a85dd77ffee0 [file] [log] [blame]
Ken Thompsona0160812009-05-21 13:46:07 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include "go.h"
6
7static struct
8{
9 Node* list;
10 Node* mapname;
11 Type* type;
12} xxx;
13
14/*
15 * the init code (thru initfix) reformats the
16 * var = ...
17 * statements, rewriting the automatic
18 * variables with the static variables.
19 * this allows the code generator to
20 * generate DATA statements instead
21 * of assignment statements.
22 * it is quadradic, may need to change.
23 * it is extremely fragile knowing exactly
24 * how the code from (struct|array|map)lit
25 * will look. ideally the lit routines could
26 * write the code in this form, but ...
27 */
28
29void
30initlin(Node* n)
31{
32 if(n == N)
33 return;
34 initlin(n->ninit);
35 switch(n->op) {
36 default:
37 print("o = %O\n", n->op);
38 n->ninit = N;
39 xxx.list = list(xxx.list, n);
40 break;
41
42 case OCALL:
43 // call to mapassign1
Ken Thompsona0160812009-05-21 13:46:07 -070044 n->ninit = N;
45 xxx.list = list(xxx.list, n);
46 break;
47
48 case OAS:
49 n->ninit = N;
50 xxx.list = list(xxx.list, n);
51 break;
52
53 case OLIST:
54 initlin(n->left);
55 initlin(n->right);
56 break;
57 }
58}
59
60int
61inittmp(Node *n)
62{
63 if(n != N)
64 if(n->op == ONAME)
65 if(n->sym != S)
66 if(n->class == PAUTO)
Ken Thompson4238b182009-05-23 15:34:29 -070067 if(memcmp(n->sym->name, "autotmp_", 8) == 0)
Ken Thompsona0160812009-05-21 13:46:07 -070068 return 1;
69 return 0;
70}
71
72int
73sametmp(Node *n1, Node *n2)
74{
75 if(inittmp(n1))
76 if(n1->xoffset == n2->xoffset)
77 return 1;
78 return 0;
79}
80
81int
82indsametmp(Node *n1, Node *n2)
83{
84 if(n1->op == OIND)
85 if(inittmp(n1->left))
86 if(n1->left->xoffset == n2->xoffset)
87 return 1;
88 return 0;
89}
90
91Node*
92findarg(Node *n, char *arg, char *fn)
93{
94 Iter param;
95 Node *a;
96
97 if(n == N || n->op != OCALL ||
98 n->left == N || n->left->sym == S ||
99 strcmp(n->left->sym->name, fn) != 0)
100 return N;
101
102 a = listfirst(&param, &n->right);
103 while(a != N) {
104 if(a->op == OAS &&
105 a->left != N && a->right != N &&
106 a->left->op == OINDREG &&
107 a->left->sym != S)
108 if(strcmp(a->left->sym->name, arg) == 0)
109 return a->right;
110 a = listnext(&param);
111 }
112 return N;
113}
114
115Node*
116slicerewrite(Node *n)
117{
118 Node *nel;
119 Type *t;
120 int b;
121 Node *a;
122
123 // call to newarray - find nel argument
124 nel = findarg(n, "nel", "newarray");
125 if(nel == N || !isslice(n->type))
126 goto no;
127
128 b = mpgetfix(nel->val.u.xval);
129 t = shallow(n->type);
130 t->bound = b;
131
132 // special hack for zero-size array
133 // invent an l-value to point at
134 if(b == 0)
135 a = staticname(types[TBOOL]);
136 else
137 a = staticname(t);
138
139 a = nod(OCOMPSLICE, a, N);
140 a->type = n->type;
141 return a;
142
143no:
144 return N;
145}
146
147Node*
148maprewrite(Node *n)
149{
150 Node *nel;
151 Type *ta, *tb;
152 Node *a;
153
154 // call to newarray - find nel argument
155 nel = findarg(n, "hint", "newmap");
156 if(nel == N)
157 goto no;
158 ta = n->type;
159 if(ta->etype != TMAP)
160 goto no;
161
162 // create a new type from map[index]value
163 // [0]struct { a index; b value) }
164
165 tb = typ(TFIELD);
166 tb->type = ta->down;
167 tb->sym = lookup("key");
168 tb->nname = newname(tb->sym);
169 tb->down = typ(TFIELD);
170 tb->down->type = ta->type;
171 tb->down->sym = lookup("val");
172 tb->down->nname = newname(tb->down->sym);
173
174 ta = typ(TSTRUCT);
175 ta->type = tb;
176
177 tb = typ(TARRAY);
178 tb->type = ta;
179 tb->bound = 0;
180
181 dowidth(tb);
182
183 a = staticname(tb);
184 a = nod(OCOMPMAP, a, N);
185 a->type = n->type;
186
187 // save stuff for this iteration
188 xxx.mapname = a->left;
189 xxx.type = tb;
190
191 return a;
192
193no:
194 return N;
195}
196
197// convert the call to mapassign1
198// into static[i].key = k, static[i].val = v
199Node*
200mapindex(Node *n)
201{
202 Node *index, *val, *key, *a, *b;
203
204 // pull all the primatives
205 key = findarg(n, "key", "mapassign1");
206 val = findarg(n, "val", "mapassign1");
207 index = nodintconst(xxx.type->bound);
208 xxx.type->bound++;
209 dowidth(xxx.type);
210
211 // build tree
212 a = nod(OINDEX, xxx.mapname, index);
213 a = nod(ODOT, a, newname(lookup("key")));
214 a = nod(OAS, a, key);
215
216 b = nod(OINDEX, xxx.mapname, index);
217 b = nod(ODOT, b, newname(lookup("val")));
218 b = nod(OAS, b, val);
219
220 a = nod(OLIST, a, b);
221 walktype(a, Etop);
222
223 return a;
224}
225
226// for a copy out reference, A = B,
227// look through the whole structure
228// and substitute references of B to A.
229// some rewrite goes on also.
230int
231initsub(Node *n, Node *nam)
232{
233 Iter iter;
234 Node *r, *w;
235 int any;
236
237 any = 0;
238 r = listfirst(&iter, &xxx.list);
239 while(r != N) {
240 switch(r->op) {
241 case OAS:
242 case OEMPTY:
243 if(r->left != N)
244 switch(r->left->op) {
245 case ONAME:
246 if(sametmp(r->left, nam)) {
247 any = 1;
248 r->left = n;
249
250 w = slicerewrite(r->right);
251 if(w != N) {
252 n = w->left; // from now on use fixed array
253 r->right = w;
254 break;
255 }
256
257 w = maprewrite(r->right);
258 if(w != N) {
259 n = w->left; // from now on use fixed array
260 r->right = w;
261 break;
262 }
263 }
264 break;
265 case ODOT:
266 if(sametmp(r->left->left, nam)) {
267 any = 1;
268 r->left->left = n;
269 }
270 if(indsametmp(r->left->left, nam)) {
271 any = 1;
272 r->left->left->left = n;
273 }
274 break;
275 case OINDEX:
276 if(sametmp(r->left->left, nam)) {
277 any = 1;
278 r->left->left = n;
279 }
280 if(indsametmp(r->left->left, nam)) {
281 any = 1;
282 r->left->left->left = n;
283 }
284 break;
285 }
286 break;
287 case OCALL:
288 // call to mapassign1
289 // look through the parameters
290 w = findarg(r, "hmap", "mapassign1");
291 if(w == N)
292 break;
293 if(sametmp(w, nam)) {
294 any = 1;
295 *r = *mapindex(r);
296 }
297 if(indsametmp(w, nam)) {
298fatal("indirect map index");
299 any = 1;
300 w->right->left = n;
301 }
302 break;
303 }
304 r = listnext(&iter);
305 }
306 return any;
307}
308
309Node*
310initfix(Node* n)
311{
312 Iter iter;
313 Node *r;
314
315//dump("prelin", n);
316
317 xxx.list = N;
318 initlin(n);
319 xxx.list = rev(xxx.list);
Ken Thompson4238b182009-05-23 15:34:29 -0700320if(1)
Ken Thompsona0160812009-05-21 13:46:07 -0700321return xxx.list;
Ken Thompson4238b182009-05-23 15:34:29 -0700322
Ken Thompsona0160812009-05-21 13:46:07 -0700323if(debug['A'])
324dump("preinitfix", xxx.list);
325
326 // look for the copy-out reference
327 r = listfirst(&iter, &xxx.list);
328 while(r != N) {
329 if(r->op == OAS)
330 if(inittmp(r->right)) {
331 if(initsub(r->left, r->right))
332 r->op = OEMPTY;
333 }
334 r = listnext(&iter);
335 }
336if(debug['A'])
337dump("postinitfix", xxx.list);
338 return xxx.list;
339}