isel fixes for lame apple assembler
[qbe.git] / parse.c
bloba435754c4c00a6fc27dbac0be25c0d59083693f6
1 #include "all.h"
2 #include <ctype.h>
3 #include <stdarg.h>
5 enum {
6 Ke = -2, /* Erroneous mode */
7 Km = Kl, /* Memory pointer (for x64) */
8 };
10 OpDesc opdesc[NOp] = {
11 #define A(a,b,c,d) {[Kw]=K##a, [Kl]=K##b, [Ks]=K##c, [Kd]=K##d}
13 /* NAME NM ARGCLS0 ARGCLS1 SF LF FLD*/
14 [Oadd] = { "add", 2, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 1 },
15 [Osub] = { "sub", 2, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 1 },
16 [Odiv] = { "div", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 1 },
17 [Orem] = { "rem", 2, {A(w,l,e,e), A(w,l,e,e)}, 0, 0, 1 },
18 [Oudiv] = { "udiv", 2, {A(w,l,e,e), A(w,l,e,e)}, 0, 0, 1 },
19 [Ourem] = { "urem", 2, {A(w,l,e,e), A(w,l,e,e)}, 0, 0, 1 },
20 [Omul] = { "mul", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 1 },
21 [Oand] = { "and", 2, {A(w,l,e,e), A(w,l,e,e)}, 1, 0, 1 },
22 [Oor] = { "or", 2, {A(w,l,e,e), A(w,l,e,e)}, 1, 0, 1 },
23 [Oxor] = { "xor", 2, {A(w,l,e,e), A(w,l,e,e)}, 1, 0, 1 },
24 [Osar] = { "sar", 1, {A(w,l,e,e), A(w,w,e,e)}, 1, 0, 1 },
25 [Oshr] = { "shr", 1, {A(w,l,e,e), A(w,w,e,e)}, 1, 0, 1 },
26 [Oshl] = { "shl", 1, {A(w,l,e,e), A(w,w,e,e)}, 1, 0, 1 },
27 [Ostored] = { "stored", 0, {A(d,d,d,d), A(m,m,m,m)}, 0, 1, 0 },
28 [Ostores] = { "stores", 0, {A(s,s,s,s), A(m,m,m,m)}, 0, 1, 0 },
29 [Ostorel] = { "storel", 0, {A(l,l,l,l), A(m,m,m,m)}, 0, 1, 0 },
30 [Ostorew] = { "storew", 0, {A(w,w,w,w), A(m,m,m,m)}, 0, 1, 0 },
31 [Ostoreh] = { "storeh", 0, {A(w,w,w,w), A(m,m,m,m)}, 0, 1, 0 },
32 [Ostoreb] = { "storeb", 0, {A(w,w,w,w), A(m,m,m,m)}, 0, 1, 0 },
33 [Oload] = { "load", 0, {A(m,m,m,m), A(x,x,x,x)}, 0, 1, 0 },
34 [Oloadsw] = { "loadsw", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
35 [Oloaduw] = { "loaduw", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
36 [Oloadsh] = { "loadsh", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
37 [Oloaduh] = { "loaduh", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
38 [Oloadsb] = { "loadsb", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
39 [Oloadub] = { "loadub", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
40 [Oextsw] = { "extsw", 0, {A(e,w,e,e), A(e,x,e,e)}, 0, 1, 1 },
41 [Oextuw] = { "extuw", 0, {A(e,w,e,e), A(e,x,e,e)}, 0, 1, 1 },
42 [Oextsh] = { "extsh", 0, {A(w,w,e,e), A(x,x,e,e)}, 0, 1, 1 },
43 [Oextuh] = { "extuh", 0, {A(w,w,e,e), A(x,x,e,e)}, 0, 1, 1 },
44 [Oextsb] = { "extsb", 0, {A(w,w,e,e), A(x,x,e,e)}, 0, 1, 1 },
45 [Oextub] = { "extub", 0, {A(w,w,e,e), A(x,x,e,e)}, 0, 1, 1 },
46 [Oexts] = { "exts", 0, {A(e,e,e,s), A(e,e,e,x)}, 0, 1, 1 },
47 [Otruncd] = { "truncd", 0, {A(e,e,d,e), A(e,e,x,e)}, 0, 1, 1 },
48 [Ostosi] = { "stosi", 0, {A(s,s,e,e), A(x,x,e,e)}, 0, 1, 1 },
49 [Odtosi] = { "dtosi", 0, {A(d,d,e,e), A(x,x,e,e)}, 0, 1, 1 },
50 [Oswtof] = { "swtof", 0, {A(e,e,w,w), A(e,e,x,x)}, 0, 1, 1 },
51 [Osltof] = { "sltof", 0, {A(e,e,l,l), A(e,e,x,x)}, 0, 1, 1 },
52 [Ocast] = { "cast", 0, {A(s,d,w,l), A(x,x,x,x)}, 0, 1, 1 },
53 [Ocopy] = { "copy", 1, {A(w,l,s,d), A(x,x,x,x)}, 0, 1, 0 },
54 [Onop] = { "nop", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 1, 0 },
55 [Oswap] = { "swap", 2, {A(w,l,s,d), A(w,l,s,d)}, 0, 0, 0 },
56 [Osign] = { "sign", 0, {A(w,l,e,e), A(x,x,e,e)}, 0, 0, 0 },
57 [Osalloc] = { "salloc", 0, {A(e,l,e,e), A(e,x,e,e)}, 0, 0, 0 },
58 [Oxidiv] = { "xidiv", 1, {A(w,l,e,e), A(x,x,e,e)}, 0, 0, 0 },
59 [Oxdiv] = { "xdiv", 1, {A(w,l,e,e), A(x,x,e,e)}, 0, 0, 0 },
60 [Oxcmp] = { "xcmp", 1, {A(w,l,s,d), A(w,l,s,d)}, 1, 0, 0 },
61 [Oxtest] = { "xtest", 1, {A(w,l,e,e), A(w,l,e,e)}, 1, 0, 0 },
62 [Oaddr] = { "addr", 0, {A(m,m,e,e), A(x,x,e,e)}, 0, 1, 0 },
63 [Opar] = { "parn", 0, {A(x,x,x,x), A(x,x,x,x)}, 0, 0, 0 },
64 [Oparc] = { "parc", 0, {A(e,x,e,e), A(e,x,e,e)}, 0, 0, 0 },
65 [Oarg] = { "arg", 0, {A(w,l,s,d), A(x,x,x,x)}, 0, 0, 0 },
66 [Oargc] = { "argc", 0, {A(e,x,e,e), A(e,l,e,e)}, 0, 0, 0 },
67 [Ocall] = { "call", 0, {A(m,m,m,m), A(x,x,x,x)}, 0, 0, 0 },
68 [Oxsetnp] = { "xsetnp", 0, {A(x,x,e,e), A(x,x,e,e)}, 0, 0, 0 },
69 [Oxsetp] = { "xsetp", 0, {A(x,x,e,e), A(x,x,e,e)}, 0, 0, 0 },
70 [Oalloc] = { "alloc4", 1, {A(e,l,e,e), A(e,x,e,e)}, 0, 0, 0 },
71 [Oalloc+1] = { "alloc8", 1, {A(e,l,e,e), A(e,x,e,e)}, 0, 0, 0 },
72 [Oalloc+2] = { "alloc16", 1, {A(e,l,e,e), A(e,x,e,e)}, 0, 0, 0 },
73 #define X(c) \
74 [Ocmpw+IC##c] = { "c" #c "w", 0, {A(w,w,e,e), A(w,w,e,e)}, 1, 0, 1 }, \
75 [Ocmpl+IC##c] = { "c" #c "l", 0, {A(l,l,e,e), A(l,l,e,e)}, 1, 0, 1 }, \
76 [Oxset+IC##c] = { "xset" #c, 0, {A(x,x,e,e), A(x,x,e,e)}, 0, 1, 0 },
77 ICMPS(X)
78 #undef X
79 #define X(c) \
80 [Ocmps+FC##c] = { "c" #c "s", 0, {A(s,s,e,e), A(s,s,e,e)}, 1, 0, 1 }, \
81 [Ocmpd+FC##c] = { "c" #c "d", 0, {A(d,d,e,e), A(d,d,e,e)}, 1, 0, 1 },
82 FCMPS(X)
83 #undef X
86 #undef A
88 typedef enum {
89 PXXX,
90 PLbl,
91 PPhi,
92 PIns,
93 PEnd,
94 } PState;
96 enum {
97 Txxx = 0,
99 /* aliases */
100 Tloadw = NPubOp,
101 Tloadl,
102 Tloads,
103 Tloadd,
104 Talloc1,
105 Talloc2,
107 Tcall,
108 Tphi,
109 Tjmp,
110 Tjnz,
111 Tret,
112 Texport,
113 Tfunc,
114 Ttype,
115 Tdata,
116 Talign,
125 Tint,
126 Tflts,
127 Tfltd,
128 Ttmp,
129 Tlbl,
130 Tglo,
131 Ttyp,
132 Tstr,
134 Tplus,
135 Teq,
136 Tcomma,
137 Tlparen,
138 Trparen,
139 Tlbrace,
140 Trbrace,
141 Tnl,
142 Teof,
144 Ntok
147 static char *kwmap[Ntok] = {
148 [Tloadw] = "loadw",
149 [Tloadl] = "loadl",
150 [Tloads] = "loads",
151 [Tloadd] = "loadd",
152 [Talloc1] = "alloc1",
153 [Talloc2] = "alloc2",
154 [Tcall] = "call",
155 [Tphi] = "phi",
156 [Tjmp] = "jmp",
157 [Tjnz] = "jnz",
158 [Tret] = "ret",
159 [Texport] = "export",
160 [Tfunc] = "function",
161 [Ttype] = "type",
162 [Tdata] = "data",
163 [Talign] = "align",
164 [Tl] = "l",
165 [Tw] = "w",
166 [Th] = "h",
167 [Tb] = "b",
168 [Td] = "d",
169 [Ts] = "s",
170 [Tz] = "z",
173 enum {
174 BMask = 8191, /* for blocks hash */
176 K = 2047061843, /* found using tools/lexh.c */
177 M = 24,
180 static char lexh[1 << (32-M)];
181 static FILE *inf;
182 static char *inpath;
183 static int thead;
184 static struct {
185 char chr;
186 double fltd;
187 float flts;
188 int64_t num;
189 char *str;
190 } tokval;
191 static int lnum;
193 static Fn *curf;
194 static Phi **plink;
195 static Blk *curb;
196 static Blk **blink;
197 static Blk *blkh[BMask+1];
198 static int nblk;
199 static int rcls;
200 static int ntyp;
202 void
203 err(char *s, ...)
205 va_list ap;
207 va_start(ap, s);
208 fprintf(stderr, "%s:%d: ", inpath, lnum);
209 vfprintf(stderr, s, ap);
210 fprintf(stderr, "\n");
211 va_end(ap);
212 exit(1);
215 static inline uint32_t
216 hash(char *s)
218 uint32_t h;
220 h = 0;
221 for (; *s; ++s)
222 h = *s + 17*h;
223 return h;
226 static void
227 lexinit()
229 static int done;
230 int i;
231 long h;
233 if (done)
234 return;
235 for (i=0; i<NPubOp; ++i)
236 if (opdesc[i].name)
237 kwmap[i] = opdesc[i].name;
238 assert(Ntok <= CHAR_MAX);
239 for (i=0; i<Ntok; ++i)
240 if (kwmap[i]) {
241 h = hash(kwmap[i])*K >> M;
242 assert(lexh[h] == Txxx);
243 lexh[h] = i;
245 done = 1;
248 static int
249 lex()
251 static char tok[NString];
252 int c, i, esc;
253 int t;
256 c = fgetc(inf);
257 while (isblank(c));
258 t = Txxx;
259 tokval.chr = c;
260 switch (c) {
261 case EOF:
262 return Teof;
263 case ',':
264 return Tcomma;
265 case '(':
266 return Tlparen;
267 case ')':
268 return Trparen;
269 case '{':
270 return Tlbrace;
271 case '}':
272 return Trbrace;
273 case '=':
274 return Teq;
275 case '+':
276 return Tplus;
277 case 's':
278 if (fscanf(inf, "_%f", &tokval.flts) != 1)
279 break;
280 return Tflts;
281 case 'd':
282 if (fscanf(inf, "_%lf", &tokval.fltd) != 1)
283 break;
284 return Tfltd;
285 case '%':
286 t = Ttmp;
287 goto Alpha;
288 case '@':
289 t = Tlbl;
290 goto Alpha;
291 case '$':
292 t = Tglo;
293 goto Alpha;
294 case ':':
295 t = Ttyp;
296 goto Alpha;
297 case '#':
298 while ((c=fgetc(inf)) != '\n' && c != EOF)
300 case '\n':
301 lnum++;
302 return Tnl;
304 if (isdigit(c) || c == '-' || c == '+') {
305 ungetc(c, inf);
306 if (fscanf(inf, "%"SCNd64, &tokval.num) != 1)
307 err("invalid integer literal");
308 return Tint;
310 if (c == '"') {
311 tokval.str = vnew(0, 1, alloc);
312 esc = 0;
313 for (i=0;; i++) {
314 c = fgetc(inf);
315 if (c == EOF)
316 err("unterminated string");
317 vgrow(&tokval.str, i+1);
318 if (c == '"' && !esc) {
319 tokval.str[i] = 0;
320 return Tstr;
322 esc = (c == '\\' && !esc);
323 tokval.str[i] = c;
326 if (0)
327 Alpha: c = fgetc(inf);
328 if (!isalpha(c) && c != '.' && c != '_')
329 err("lexing failure: invalid character %c (%d)", c, c);
330 i = 0;
331 do {
332 if (i >= NString-1)
333 err("identifier too long");
334 tok[i++] = c;
335 c = fgetc(inf);
336 } while (isalpha(c) || c == '$' || c == '.' || c == '_' || isdigit(c));
337 tok[i] = 0;
338 ungetc(c, inf);
339 tokval.str = tok;
340 if (t != Txxx) {
341 return t;
343 t = lexh[hash(tok)*K >> M];
344 if (t == Txxx || strcmp(kwmap[t], tok) != 0) {
345 err("unknown keyword %s", tok);
346 return Txxx;
348 return t;
351 static int
352 peek()
354 if (thead == Txxx)
355 thead = lex();
356 return thead;
359 static int
360 next()
362 int t;
364 t = peek();
365 thead = Txxx;
366 return t;
369 static int
370 nextnl()
372 int t;
374 while ((t = next()) == Tnl)
376 return t;
379 static void
380 expect(int t)
382 static char *ttoa[] = {
383 [Tlbl] = "label",
384 [Tcomma] = ",",
385 [Teq] = "=",
386 [Tnl] = "newline",
387 [Tlparen] = "(",
388 [Trparen] = ")",
389 [Tlbrace] = "{",
390 [Trbrace] = "}",
391 [Teof] = 0,
393 char buf[128], *s1, *s2;
394 int t1;
396 t1 = next();
397 if (t == t1)
398 return;
399 s1 = ttoa[t] ? ttoa[t] : "??";
400 s2 = ttoa[t1] ? ttoa[t1] : "??";
401 sprintf(buf, "%s expected, got %s instead", s1, s2);
402 err(buf);
405 static Ref
406 tmpref(char *v)
408 int t;
410 for (t=Tmp0; t<curf->ntmp; t++)
411 if (strcmp(v, curf->tmp[t].name) == 0)
412 return TMP(t);
413 newtmp(0, Kx, curf);
414 strcpy(curf->tmp[t].name, v);
415 return TMP(t);
418 static Ref
419 parseref()
421 Con c;
422 int i;
424 memset(&c, 0, sizeof c);
425 switch (next()) {
426 case Ttmp:
427 return tmpref(tokval.str);
428 case Tint:
429 c.type = CBits;
430 c.bits.i = tokval.num;
431 goto Look;
432 case Tflts:
433 c.type = CBits;
434 c.bits.s = tokval.flts;
435 c.flt = 1;
436 goto Look;
437 case Tfltd:
438 c.type = CBits;
439 c.bits.d = tokval.fltd;
440 c.flt = 2;
441 goto Look;
442 case Tglo:
443 c.type = CAddr;
444 strcpy(c.label, tokval.str);
445 Look:
446 for (i=0; i<curf->ncon; i++)
447 if (curf->con[i].type == c.type
448 && curf->con[i].bits.i == c.bits.i
449 && strcmp(curf->con[i].label, c.label) == 0)
450 return CON(i);
451 vgrow(&curf->con, ++curf->ncon);
452 curf->con[i] = c;
453 return CON(i);
454 default:
455 return R;
459 static int
460 findtyp(int i)
462 while (--i >= 0)
463 if (strcmp(tokval.str, typ[i].name) == 0)
464 return i;
465 err("undefined type :%s", tokval.str);
468 static int
469 parsecls(int *tyn)
471 switch (next()) {
472 default:
473 err("invalid class specifier");
474 case Ttyp:
475 *tyn = findtyp(ntyp);
476 return 4;
477 case Tw:
478 return Kw;
479 case Tl:
480 return Kl;
481 case Ts:
482 return Ks;
483 case Td:
484 return Kd;
488 static void
489 parserefl(int arg)
491 int k, ty;
492 Ref r;
494 expect(Tlparen);
495 while (peek() != Trparen) {
496 if (curi - insb >= NIns)
497 err("too many instructions (1)");
498 k = parsecls(&ty);
499 r = parseref();
500 if (req(r, R))
501 err("invalid reference argument");
502 if (!arg && rtype(r) != RTmp)
503 err("invalid function parameter");
504 if (k == 4)
505 if (arg)
506 *curi = (Ins){Oargc, R, {TYPE(ty), r}, Kl};
507 else
508 *curi = (Ins){Oparc, r, {TYPE(ty)}, Kl};
509 else
510 if (arg)
511 *curi = (Ins){Oarg, R, {r}, k};
512 else
513 *curi = (Ins){Opar, r, {R}, k};
514 curi++;
515 if (peek() == Trparen)
516 break;
517 expect(Tcomma);
519 next();
522 static Blk *
523 findblk(char *name)
525 Blk *b;
526 uint32_t h;
528 h = hash(name) & BMask;
529 for (b=blkh[h]; b; b=b->dlink)
530 if (strcmp(b->name, name) == 0)
531 return b;
532 b = blknew();
533 b->id = nblk++;
534 strcpy(b->name, name);
535 b->dlink = blkh[h];
536 blkh[h] = b;
537 return b;
540 static void
541 closeblk()
543 curb->nins = curi - insb;
544 idup(&curb->ins, insb, curb->nins);
545 blink = &curb->link;
546 curi = insb;
549 static PState
550 parseline(PState ps)
552 Ref arg[NPred] = {R};
553 Blk *blk[NPred];
554 Phi *phi;
555 Ref r;
556 Blk *b;
557 int t, op, i, k, ty;
559 t = nextnl();
560 if (ps == PLbl && t != Tlbl && t != Trbrace)
561 err("label or } expected");
562 switch (t) {
563 default:
564 if (isstore(t) || t == Tcall) {
565 /* operations without result */
566 r = R;
567 k = Kw;
568 op = t;
569 goto DoOp;
571 err("label, instruction or jump expected");
572 case Trbrace:
573 return PEnd;
574 case Ttmp:
575 break;
576 case Tlbl:
577 b = findblk(tokval.str);
578 if (curb && curb->jmp.type == Jxxx) {
579 closeblk();
580 curb->jmp.type = Jjmp;
581 curb->s1 = b;
583 if (b->jmp.type != Jxxx)
584 err("multiple definitions of block @%s", b->name);
585 *blink = b;
586 curb = b;
587 plink = &curb->phi;
588 expect(Tnl);
589 return PPhi;
590 case Tret:
591 curb->jmp.type = (int[]){
592 Jretw, Jretl,
593 Jrets, Jretd,
594 Jretc, Jret0
595 }[rcls];
596 if (peek() == Tnl)
597 curb->jmp.type = Jret0;
598 else if (rcls < 5) {
599 r = parseref();
600 if (req(r, R))
601 err("invalid return value");
602 curb->jmp.arg = r;
604 goto Close;
605 case Tjmp:
606 curb->jmp.type = Jjmp;
607 goto Jump;
608 case Tjnz:
609 curb->jmp.type = Jjnz;
610 r = parseref();
611 if (req(r, R))
612 err("invalid argument for jnz jump");
613 curb->jmp.arg = r;
614 expect(Tcomma);
615 Jump:
616 expect(Tlbl);
617 curb->s1 = findblk(tokval.str);
618 if (curb->jmp.type != Jjmp) {
619 expect(Tcomma);
620 expect(Tlbl);
621 curb->s2 = findblk(tokval.str);
623 if (curb->s1 == curf->start || curb->s2 == curf->start)
624 err("invalid jump to the start node");
625 Close:
626 expect(Tnl);
627 closeblk();
628 return PLbl;
630 r = tmpref(tokval.str);
631 expect(Teq);
632 k = parsecls(&ty);
633 op = next();
634 DoOp:
635 if (op == Tphi) {
636 if (ps != PPhi || curb == curf->start)
637 err("unexpected phi instruction");
638 op = -1;
640 if (op == Tcall) {
641 arg[0] = parseref();
642 parserefl(1);
643 expect(Tnl);
644 op = Ocall;
645 if (k == 4) {
646 k = Kl;
647 arg[1] = TYPE(ty);
648 } else
649 arg[1] = R;
650 goto Ins;
652 if (op >= Tloadw && op <= Tloadd)
653 op = Oload;
654 if (op == Talloc1 || op == Talloc2)
655 op = Oalloc;
656 if (k == 4)
657 err("size class must be w, l, s, or d");
658 if (op >= NPubOp)
659 err("invalid instruction");
660 i = 0;
661 if (peek() != Tnl)
662 for (;;) {
663 if (i == NPred)
664 err("too many arguments");
665 if (op == -1) {
666 expect(Tlbl);
667 blk[i] = findblk(tokval.str);
669 arg[i] = parseref();
670 if (req(arg[i], R))
671 err("invalid instruction argument");
672 i++;
673 t = peek();
674 if (t == Tnl)
675 break;
676 if (t != Tcomma)
677 err(", or end of line expected");
678 next();
680 next();
681 Ins:
682 if (op != -1) {
683 if (curi - insb >= NIns)
684 err("too many instructions (2)");
685 curi->op = op;
686 curi->cls = k;
687 curi->to = r;
688 curi->arg[0] = arg[0];
689 curi->arg[1] = arg[1];
690 curi++;
691 return PIns;
692 } else {
693 phi = alloc(sizeof *phi);
694 phi->to = r;
695 phi->cls = k;
696 memcpy(phi->arg, arg, i * sizeof arg[0]);
697 memcpy(phi->blk, blk, i * sizeof blk[0]);
698 phi->narg = i;
699 *plink = phi;
700 plink = &phi->link;
701 return PPhi;
705 static int
706 usecheck(Ref r, int k, Fn *fn)
708 return rtype(r) != RTmp || fn->tmp[r.val].cls == k
709 || (fn->tmp[r.val].cls == Kl && k == Kw);
712 static void
713 typecheck(Fn *fn)
715 Blk *b;
716 Phi *p;
717 Ins *i;
718 uint n;
719 int k;
720 Tmp *t;
721 Ref r;
722 BSet pb[1], ppb[1];
724 fillpreds(fn);
725 bsinit(pb, fn->nblk);
726 bsinit(ppb, fn->nblk);
727 for (b=fn->start; b; b=b->link) {
728 for (p=b->phi; p; p=p->link)
729 fn->tmp[p->to.val].cls = p->cls;
730 for (i=b->ins; i-b->ins < b->nins; i++)
731 if (rtype(i->to) == RTmp) {
732 t = &fn->tmp[i->to.val];
733 if (clsmerge(&t->cls, i->cls))
734 err("temporary %%%s is assigned with"
735 " multiple types", t->name);
738 for (b=fn->start; b; b=b->link) {
739 bszero(pb);
740 for (n=0; n<b->npred; n++)
741 bsset(pb, b->pred[n]->id);
742 for (p=b->phi; p; p=p->link) {
743 bszero(ppb);
744 t = &fn->tmp[p->to.val];
745 for (n=0; n<p->narg; n++) {
746 k = t->cls;
747 if (bshas(ppb, p->blk[n]->id))
748 err("multiple entries for @%s in phi %%%s",
749 p->blk[n]->name, t->name);
750 if (!usecheck(p->arg[n], k, fn))
751 err("invalid type for operand %%%s in phi %%%s",
752 fn->tmp[p->arg[n].val].name, t->name);
753 bsset(ppb, p->blk[n]->id);
755 if (!bsequal(pb, ppb))
756 err("predecessors not matched in phi %%%s", t->name);
758 for (i=b->ins; i-b->ins < b->nins; i++)
759 for (n=0; n<2; n++) {
760 k = opdesc[i->op].argcls[n][i->cls];
761 r = i->arg[n];
762 t = &fn->tmp[r.val];
763 if (k == Ke)
764 err("invalid instruction type in %s",
765 opdesc[i->op].name);
766 if (rtype(r) == RType)
767 continue;
768 if (rtype(r) != -1 && k == Kx)
769 err("no %s operand expected in %s",
770 n == 1 ? "second" : "first",
771 opdesc[i->op].name);
772 if (rtype(r) == -1 && k != Kx)
773 err("missing %s operand in %s",
774 n == 1 ? "second" : "first",
775 opdesc[i->op].name);
776 if (!usecheck(r, k, fn))
777 err("invalid type for %s operand %%%s in %s",
778 n == 1 ? "second" : "first",
779 t->name, opdesc[i->op].name);
781 r = b->jmp.arg;
782 if (isret(b->jmp.type)) {
783 if (b->jmp.type == Jretc) {
784 if (!usecheck(r, Kl, fn))
785 goto JErr;
786 } else if (!usecheck(r, b->jmp.type-Jretw, fn))
787 goto JErr;
789 if (b->jmp.type == Jjnz && !usecheck(r, Kw, fn))
790 JErr:
791 err("invalid type for jump argument %%%s in block @%s",
792 fn->tmp[r.val].name, b->name);
793 if (b->s1 && b->s1->jmp.type == Jxxx)
794 err("block @%s is used undefined", b->s1->name);
795 if (b->s2 && b->s2->jmp.type == Jxxx)
796 err("block @%s is used undefined", b->s2->name);
800 static Fn *
801 parsefn(int export)
803 Blk *b;
804 int i;
805 PState ps;
807 curb = 0;
808 nblk = 0;
809 curi = insb;
810 curf = alloc(sizeof *curf);
811 curf->ntmp = 0;
812 curf->ncon = 1; /* first constant must be 0 */
813 curf->tmp = vnew(curf->ntmp, sizeof curf->tmp[0], alloc);
814 curf->con = vnew(curf->ncon, sizeof curf->con[0], alloc);
815 for (i=0; i<Tmp0; ++i)
816 newtmp(0, i < XMM0 ? Kl : Kd, curf);
817 curf->con[0].type = CBits;
818 curf->export = export;
819 blink = &curf->start;
820 curf->retty = Kx;
821 if (peek() != Tglo)
822 rcls = parsecls(&curf->retty);
823 else
824 rcls = 5;
825 if (next() != Tglo)
826 err("function name expected");
827 strcpy(curf->name, tokval.str);
828 parserefl(0);
829 if (nextnl() != Tlbrace)
830 err("function body must start with {");
831 ps = PLbl;
833 ps = parseline(ps);
834 while (ps != PEnd);
835 if (!curb)
836 err("empty function");
837 if (curb->jmp.type == Jxxx)
838 err("last block misses jump");
839 curf->mem = vnew(0, sizeof curf->mem[0], alloc);
840 curf->nmem = 0;
841 curf->nblk = nblk;
842 curf->rpo = 0;
843 for (b=0; b; b=b->link)
844 b->dlink = 0; /* was trashed by findblk() */
845 for (i=0; i<BMask+1; ++i)
846 blkh[i] = 0;
847 typecheck(curf);
848 return curf;
851 static void
852 parseseg(Seg *seg, Typ *ty, int t)
854 Typ *ty1;
855 int n, c, a, al, type;
856 size_t sz, s;
858 n = 0;
859 sz = 0;
860 al = ty->align;
861 while (t != Trbrace) {
862 type = Sint;
863 switch (t) {
864 default: err("invalid type member specifier");
865 case Td: type = Sflt;
866 case Tl: s = 8; a = 3; break;
867 case Ts: type = Sflt;
868 case Tw: s = 4; a = 2; break;
869 case Th: s = 2; a = 1; break;
870 case Tb: s = 1; a = 0; break;
871 case Ttyp:
872 type = Styp;
873 ty1 = &typ[findtyp(ntyp-1)];
874 s = ty1->size;
875 a = ty1->align;
876 break;
878 if (a > al)
879 al = a;
880 if ((a = sz & (s-1))) {
881 a = s - a;
882 if (n < NSeg) {
883 /* padding segment */
884 seg[n].type = Spad;
885 seg[n].len = a;
886 n++;
889 t = nextnl();
890 if (t == Tint) {
891 c = tokval.num;
892 t = nextnl();
893 } else
894 c = 1;
895 sz += a + c*s;
896 if (type == Styp)
897 s = ty1 - typ;
898 for (; c>0 && n<NSeg; c--, n++) {
899 seg[n].type = type;
900 seg[n].len = s;
902 if (t != Tcomma)
903 break;
904 t = nextnl();
906 if (t != Trbrace)
907 err(", or } expected");
908 seg[n].type = Send;
909 a = 1 << al;
910 sz = (sz + a - 1) & -a;
911 if (sz >= ty->size)
912 ty->size = sz;
913 ty->align = al;
916 static void
917 parsetyp()
919 Typ *ty;
920 int t, n, al;
922 if (ntyp >= NTyp)
923 err("too many type definitions");
924 ty = &typ[ntyp++];
925 ty->dark = 0;
926 ty->align = -1;
927 ty->size = 0;
928 if (nextnl() != Ttyp || nextnl() != Teq)
929 err("type name and then = expected");
930 strcpy(ty->name, tokval.str);
931 t = nextnl();
932 if (t == Talign) {
933 if (nextnl() != Tint)
934 err("alignment expected");
935 for (al=0; tokval.num /= 2; al++)
937 ty->align = al;
938 t = nextnl();
940 if (t != Tlbrace)
941 err("type body must start with {");
942 t = nextnl();
943 if (t == Tint) {
944 ty->dark = 1;
945 ty->size = tokval.num;
946 if (ty->align == -1)
947 err("dark types need alignment");
948 if (nextnl() != Trbrace)
949 err("} expected");
950 return;
952 n = 0;
953 ty->seg = vnew(1, sizeof ty->seg[0], emalloc);
954 if (t == Tlbrace)
955 do {
956 if (t != Tlbrace)
957 err("invalid union member");
958 vgrow(&ty->seg, n+1);
959 parseseg(ty->seg[n++], ty, nextnl());
960 t = nextnl();
961 } while (t != Trbrace);
962 else
963 parseseg(ty->seg[n++], ty, t);
964 ty->nunion = n;
967 static void
968 parsedatref(Dat *d)
970 int t;
972 d->isref = 1;
973 d->u.ref.nam = tokval.str;
974 d->u.ref.off = 0;
975 t = peek();
976 if (t == Tplus) {
977 next();
978 if (next() != Tint)
979 err("invalid token after offset in ref");
980 d->u.ref.off = tokval.num;
984 static void
985 parsedatstr(Dat *d)
987 d->isstr = 1;
988 d->u.str = tokval.str;
991 static void
992 parsedat(void cb(Dat *), int export)
994 char s[NString];
995 int t;
996 Dat d;
998 d.type = DStart;
999 d.isstr = 0;
1000 d.isref = 0;
1001 d.export = export;
1002 cb(&d);
1003 if (nextnl() != Tglo || nextnl() != Teq)
1004 err("data name, then = expected");
1005 strcpy(s, tokval.str);
1006 t = nextnl();
1007 if (t == Talign) {
1008 if (nextnl() != Tint)
1009 err("alignment expected");
1010 d.type = DAlign;
1011 d.u.num = tokval.num;
1012 cb(&d);
1013 t = nextnl();
1015 d.type = DName;
1016 d.u.str = s;
1017 cb(&d);
1019 if (t != Tlbrace)
1020 err("expected data contents in { .. }");
1021 for (;;) {
1022 switch (nextnl()) {
1023 default: err("invalid size specifier %c in data", tokval.chr);
1024 case Trbrace: goto Done;
1025 case Tl: d.type = DL; break;
1026 case Tw: d.type = DW; break;
1027 case Th: d.type = DH; break;
1028 case Tb: d.type = DB; break;
1029 case Ts: d.type = DW; break;
1030 case Td: d.type = DL; break;
1031 case Tz: d.type = DZ; break;
1033 t = nextnl();
1034 do {
1035 d.isref = 0;
1036 d.isstr = 0;
1037 memset(&d.u, 0, sizeof d.u);
1038 if (t == Tflts)
1039 d.u.flts = tokval.flts;
1040 else if (t == Tfltd)
1041 d.u.fltd = tokval.fltd;
1042 else if (t == Tint)
1043 d.u.num = tokval.num;
1044 else if (t == Tglo)
1045 parsedatref(&d);
1046 else if (t == Tstr)
1047 parsedatstr(&d);
1048 else
1049 err("constant literal expected");
1050 cb(&d);
1051 t = nextnl();
1052 } while (t == Tint || t == Tflts || t == Tfltd);
1053 if (t == Trbrace)
1054 break;
1055 if (t != Tcomma)
1056 err(", or } expected");
1058 Done:
1059 d.type = DEnd;
1060 cb(&d);
1063 void
1064 parse(FILE *f, char *path, void data(Dat *), void func(Fn *))
1066 int t, export;
1068 lexinit();
1069 inf = f;
1070 inpath = path;
1071 lnum = 1;
1072 thead = Txxx;
1073 ntyp = 0;
1074 for (;;) {
1075 export = 0;
1076 switch (nextnl()) {
1077 default:
1078 err("top-level definition expected");
1079 case Texport:
1080 export = 1;
1081 t = nextnl();
1082 if (t == Tfunc) {
1083 case Tfunc:
1084 func(parsefn(export));
1085 break;
1087 else if (t == Tdata) {
1088 case Tdata:
1089 parsedat(data, export);
1090 break;
1092 else
1093 err("export can only qualify data and function");
1094 case Ttype:
1095 parsetyp();
1096 break;
1097 case Teof:
1098 return;
1103 static void
1104 printcon(Con *c, FILE *f)
1106 switch (c->type) {
1107 case CUndef:
1108 break;
1109 case CAddr:
1110 fprintf(f, "$%s", c->label);
1111 if (c->bits.i)
1112 fprintf(f, "%+"PRIi64, c->bits.i);
1113 break;
1114 case CBits:
1115 if (c->flt == 1)
1116 fprintf(f, "s_%f", c->bits.s);
1117 else if (c->flt == 2)
1118 fprintf(f, "d_%lf", c->bits.d);
1119 else
1120 fprintf(f, "%"PRIi64, c->bits.i);
1121 break;
1125 void
1126 printref(Ref r, Fn *fn, FILE *f)
1128 int i;
1129 Mem *m;
1131 switch (rtype(r)) {
1132 case RTmp:
1133 if (r.val < Tmp0)
1134 fprintf(f, "R%d", r.val);
1135 else
1136 fprintf(f, "%%%s", fn->tmp[r.val].name);
1137 break;
1138 case RCon:
1139 printcon(&fn->con[r.val], f);
1140 break;
1141 case RSlot:
1142 fprintf(f, "S%d", (r.val&(1<<28)) ? r.val-(1<<29) : r.val);
1143 break;
1144 case RCall:
1145 fprintf(f, "%03x", r.val);
1146 break;
1147 case RType:
1148 fprintf(f, ":%s", typ[r.val].name);
1149 break;
1150 case RMem:
1151 i = 0;
1152 m = &fn->mem[r.val];
1153 fputc('[', f);
1154 if (m->offset.type != CUndef) {
1155 printcon(&m->offset, f);
1156 i = 1;
1158 if (!req(m->base, R)) {
1159 if (i)
1160 fprintf(f, " + ");
1161 printref(m->base, fn, f);
1162 i = 1;
1164 if (!req(m->index, R)) {
1165 if (i)
1166 fprintf(f, " + ");
1167 fprintf(f, "%d * ", m->scale);
1168 printref(m->index, fn, f);
1170 fputc(']', f);
1171 break;
1175 void
1176 printfn(Fn *fn, FILE *f)
1178 static char *jtoa[NJmp] = {
1179 [Jret0] = "ret",
1180 [Jretw] = "retw",
1181 [Jretl] = "retl",
1182 [Jretc] = "retc",
1183 [Jrets] = "rets",
1184 [Jretd] = "retd",
1185 [Jjnz] = "jnz",
1186 [Jxjnp] = "xjnp",
1187 [Jxjp] = "xjp",
1188 #define X(c) [Jxjc+IC##c] = "xj" #c,
1189 ICMPS(X)
1190 #undef X
1192 static char prcls[NOp] = {
1193 [Oarg] = 1,
1194 [Oswap] = 1,
1195 [Oxcmp] = 1,
1196 [Oxtest] = 1,
1197 [Oxdiv] = 1,
1198 [Oxidiv] = 1,
1200 static char ktoc[] = "wlsd";
1201 Blk *b;
1202 Phi *p;
1203 Ins *i;
1204 uint n;
1206 if (fn->export)
1207 fprintf(f, "export ");
1208 fprintf(f, "function $%s() {\n", fn->name);
1209 for (b=fn->start; b; b=b->link) {
1210 fprintf(f, "@%s\n", b->name);
1211 for (p=b->phi; p; p=p->link) {
1212 fprintf(f, "\t");
1213 printref(p->to, fn, f);
1214 fprintf(f, " =%c phi ", ktoc[p->cls]);
1215 assert(p->narg);
1216 for (n=0;; n++) {
1217 fprintf(f, "@%s ", p->blk[n]->name);
1218 printref(p->arg[n], fn, f);
1219 if (n == p->narg-1) {
1220 fprintf(f, "\n");
1221 break;
1222 } else
1223 fprintf(f, ", ");
1226 for (i=b->ins; i-b->ins < b->nins; i++) {
1227 fprintf(f, "\t");
1228 if (!req(i->to, R)) {
1229 printref(i->to, fn, f);
1230 fprintf(f, " =%c ", ktoc[i->cls]);
1232 assert(opdesc[i->op].name);
1233 fprintf(f, "%s", opdesc[i->op].name);
1234 if (req(i->to, R) && prcls[i->op])
1235 fputc(ktoc[i->cls], f);
1236 if (!req(i->arg[0], R)) {
1237 fprintf(f, " ");
1238 printref(i->arg[0], fn, f);
1240 if (!req(i->arg[1], R)) {
1241 fprintf(f, ", ");
1242 printref(i->arg[1], fn, f);
1244 fprintf(f, "\n");
1246 switch (b->jmp.type) {
1247 case Jret0:
1248 case Jretw:
1249 case Jretl:
1250 case Jrets:
1251 case Jretd:
1252 case Jretc:
1253 fprintf(f, "\t%s", jtoa[b->jmp.type]);
1254 if (b->jmp.type != Jret0 || !req(b->jmp.arg, R)) {
1255 fprintf(f, " ");
1256 printref(b->jmp.arg, fn, f);
1258 if (b->jmp.type == Jretc)
1259 fprintf(f, ", :%s", typ[fn->retty].name);
1260 fprintf(f, "\n");
1261 break;
1262 case Jjmp:
1263 if (b->s1 != b->link)
1264 fprintf(f, "\tjmp @%s\n", b->s1->name);
1265 break;
1266 default:
1267 fprintf(f, "\t%s ", jtoa[b->jmp.type]);
1268 if (b->jmp.type == Jjnz) {
1269 printref(b->jmp.arg, fn, f);
1270 fprintf(f, ", ");
1272 fprintf(f, "@%s, @%s\n", b->s1->name, b->s2->name);
1273 break;
1276 fprintf(f, "}\n");