fix various codegen bugs on arm64
[qbe.git] / parse.c
blobe89667992fb09f130dee01bcbb5d7705dea229cd
1 #include "all.h"
2 #include <ctype.h>
3 #include <stdarg.h>
5 enum {
6 Ksb = 4, /* matches Oarg/Opar/Jret */
7 Kub,
8 Ksh,
9 Kuh,
10 Kc,
11 K0,
13 Ke = -2, /* erroneous mode */
14 Km = Kl, /* memory pointer */
17 Op optab[NOp] = {
18 #undef P
19 #define P(cf, hi, id) .canfold = cf, .hasid = hi, .idval = id
20 #define O(op, t, p) [O##op]={.name = #op, .argcls = t, p},
21 #include "ops.h"
22 #undef P
25 typedef enum {
26 PXXX,
27 PLbl,
28 PPhi,
29 PIns,
30 PEnd,
31 } PState;
33 enum Token {
34 Txxx = 0,
36 /* aliases */
37 Tloadw = NPubOp,
38 Tloadl,
39 Tloads,
40 Tloadd,
41 Talloc1,
42 Talloc2,
44 Tblit,
45 Tcall,
46 Tenv,
47 Tphi,
48 Tjmp,
49 Tjnz,
50 Tret,
51 Thlt,
52 Texport,
53 Tthread,
54 Tcommon,
55 Tfunc,
56 Ttype,
57 Tdata,
58 Tsection,
59 Talign,
60 Tdbgfile,
61 Tl,
62 Tw,
63 Tsh,
64 Tuh,
65 Th,
66 Tsb,
67 Tub,
68 Tb,
69 Td,
70 Ts,
71 Tz,
73 Tint,
74 Tflts,
75 Tfltd,
76 Ttmp,
77 Tlbl,
78 Tglo,
79 Ttyp,
80 Tstr,
82 Tplus,
83 Teq,
84 Tcomma,
85 Tlparen,
86 Trparen,
87 Tlbrace,
88 Trbrace,
89 Tnl,
90 Tdots,
91 Teof,
93 Ntok
96 static char *kwmap[Ntok] = {
97 [Tloadw] = "loadw",
98 [Tloadl] = "loadl",
99 [Tloads] = "loads",
100 [Tloadd] = "loadd",
101 [Talloc1] = "alloc1",
102 [Talloc2] = "alloc2",
103 [Tblit] = "blit",
104 [Tcall] = "call",
105 [Tenv] = "env",
106 [Tphi] = "phi",
107 [Tjmp] = "jmp",
108 [Tjnz] = "jnz",
109 [Tret] = "ret",
110 [Thlt] = "hlt",
111 [Texport] = "export",
112 [Tthread] = "thread",
113 [Tcommon] = "common",
114 [Tfunc] = "function",
115 [Ttype] = "type",
116 [Tdata] = "data",
117 [Tsection] = "section",
118 [Talign] = "align",
119 [Tdbgfile] = "dbgfile",
120 [Tsb] = "sb",
121 [Tub] = "ub",
122 [Tsh] = "sh",
123 [Tuh] = "uh",
124 [Tb] = "b",
125 [Th] = "h",
126 [Tw] = "w",
127 [Tl] = "l",
128 [Ts] = "s",
129 [Td] = "d",
130 [Tz] = "z",
131 [Tdots] = "...",
134 enum {
135 NPred = 63,
137 TMask = 16383, /* for temps hash */
138 BMask = 8191, /* for blocks hash */
140 K = 11183273, /* found using tools/lexh.c */
141 M = 23,
144 static uchar lexh[1 << (32-M)];
145 static FILE *inf;
146 static char *inpath;
147 static int thead;
148 static struct {
149 char chr;
150 double fltd;
151 float flts;
152 int64_t num;
153 char *str;
154 } tokval;
155 static int lnum;
157 static Fn *curf;
158 static int *tmph;
159 static int tmphcap;
160 static Phi **plink;
161 static Blk *curb;
162 static Blk **blink;
163 static Blk *blkh[BMask+1];
164 static int nblk;
165 static int rcls;
166 static uint ntyp;
168 void
169 err(char *s, ...)
171 va_list ap;
173 va_start(ap, s);
174 fprintf(stderr, "qbe:%s:%d: ", inpath, lnum);
175 vfprintf(stderr, s, ap);
176 fprintf(stderr, "\n");
177 va_end(ap);
178 exit(1);
181 static void
182 lexinit()
184 static int done;
185 int i;
186 long h;
188 if (done)
189 return;
190 for (i=0; i<NPubOp; ++i)
191 if (optab[i].name)
192 kwmap[i] = optab[i].name;
193 assert(Ntok <= UCHAR_MAX);
194 for (i=0; i<Ntok; ++i)
195 if (kwmap[i]) {
196 h = hash(kwmap[i])*K >> M;
197 assert(lexh[h] == Txxx);
198 lexh[h] = i;
200 done = 1;
203 static int64_t
204 getint()
206 uint64_t n;
207 int c, m;
209 n = 0;
210 c = fgetc(inf);
211 m = (c == '-');
212 if (m)
213 c = fgetc(inf);
214 do {
215 n = 10*n + (c - '0');
216 c = fgetc(inf);
217 } while ('0' <= c && c <= '9');
218 ungetc(c, inf);
219 if (m)
220 n = 1 + ~n;
221 return *(int64_t *)&n;
224 static int
225 lex()
227 static char tok[NString];
228 int c, i, esc;
229 int t;
232 c = fgetc(inf);
233 while (isblank(c));
234 t = Txxx;
235 tokval.chr = c;
236 switch (c) {
237 case EOF:
238 return Teof;
239 case ',':
240 return Tcomma;
241 case '(':
242 return Tlparen;
243 case ')':
244 return Trparen;
245 case '{':
246 return Tlbrace;
247 case '}':
248 return Trbrace;
249 case '=':
250 return Teq;
251 case '+':
252 return Tplus;
253 case 's':
254 if (fscanf(inf, "_%f", &tokval.flts) != 1)
255 break;
256 return Tflts;
257 case 'd':
258 if (fscanf(inf, "_%lf", &tokval.fltd) != 1)
259 break;
260 return Tfltd;
261 case '%':
262 t = Ttmp;
263 c = fgetc(inf);
264 goto Alpha;
265 case '@':
266 t = Tlbl;
267 c = fgetc(inf);
268 goto Alpha;
269 case '$':
270 t = Tglo;
271 if ((c = fgetc(inf)) == '"')
272 goto Quoted;
273 goto Alpha;
274 case ':':
275 t = Ttyp;
276 c = fgetc(inf);
277 goto Alpha;
278 case '#':
279 while ((c=fgetc(inf)) != '\n' && c != EOF)
281 /* fall through */
282 case '\n':
283 lnum++;
284 return Tnl;
286 if (isdigit(c) || c == '-') {
287 ungetc(c, inf);
288 tokval.num = getint();
289 return Tint;
291 if (c == '"') {
292 t = Tstr;
293 Quoted:
294 tokval.str = vnew(2, 1, PFn);
295 tokval.str[0] = c;
296 esc = 0;
297 for (i=1;; i++) {
298 c = fgetc(inf);
299 if (c == EOF)
300 err("unterminated string");
301 vgrow(&tokval.str, i+2);
302 tokval.str[i] = c;
303 if (c == '"' && !esc) {
304 tokval.str[i+1] = 0;
305 return t;
307 esc = (c == '\\' && !esc);
310 Alpha:
311 if (!isalpha(c) && c != '.' && c != '_')
312 err("invalid character %c (%d)", c, c);
313 i = 0;
314 do {
315 if (i >= NString-1)
316 err("identifier too long");
317 tok[i++] = c;
318 c = fgetc(inf);
319 } while (isalpha(c) || c == '$' || c == '.' || c == '_' || isdigit(c));
320 tok[i] = 0;
321 ungetc(c, inf);
322 tokval.str = tok;
323 if (t != Txxx) {
324 return t;
326 t = lexh[hash(tok)*K >> M];
327 if (t == Txxx || strcmp(kwmap[t], tok) != 0) {
328 err("unknown keyword %s", tok);
329 return Txxx;
331 return t;
334 static int
335 peek()
337 if (thead == Txxx)
338 thead = lex();
339 return thead;
342 static int
343 next()
345 int t;
347 t = peek();
348 thead = Txxx;
349 return t;
352 static int
353 nextnl()
355 int t;
357 while ((t = next()) == Tnl)
359 return t;
362 static void
363 expect(int t)
365 static char *ttoa[] = {
366 [Tlbl] = "label",
367 [Tcomma] = ",",
368 [Teq] = "=",
369 [Tnl] = "newline",
370 [Tlparen] = "(",
371 [Trparen] = ")",
372 [Tlbrace] = "{",
373 [Trbrace] = "}",
374 [Teof] = 0,
376 char buf[128], *s1, *s2;
377 int t1;
379 t1 = next();
380 if (t == t1)
381 return;
382 s1 = ttoa[t] ? ttoa[t] : "??";
383 s2 = ttoa[t1] ? ttoa[t1] : "??";
384 sprintf(buf, "%s expected, got %s instead", s1, s2);
385 err(buf);
388 static Ref
389 tmpref(char *v)
391 int t, i;
393 if (tmphcap/2 <= curf->ntmp-Tmp0) {
394 free(tmph);
395 tmphcap = tmphcap ? tmphcap*2 : TMask+1;
396 tmph = emalloc(tmphcap * sizeof tmph[0]);
397 for (t=Tmp0; t<curf->ntmp; t++) {
398 i = hash(curf->tmp[t].name) & (tmphcap-1);
399 for (; tmph[i]; i=(i+1) & (tmphcap-1))
401 tmph[i] = t;
404 i = hash(v) & (tmphcap-1);
405 for (; tmph[i]; i=(i+1) & (tmphcap-1)) {
406 t = tmph[i];
407 if (strcmp(curf->tmp[t].name, v) == 0)
408 return TMP(t);
410 t = curf->ntmp;
411 tmph[i] = t;
412 newtmp(0, Kx, curf);
413 strcpy(curf->tmp[t].name, v);
414 return TMP(t);
417 static Ref
418 parseref()
420 Con c;
422 memset(&c, 0, sizeof c);
423 switch (next()) {
424 default:
425 return R;
426 case Ttmp:
427 return tmpref(tokval.str);
428 case Tint:
429 c.type = CBits;
430 c.bits.i = tokval.num;
431 break;
432 case Tflts:
433 c.type = CBits;
434 c.bits.s = tokval.flts;
435 c.flt = 1;
436 break;
437 case Tfltd:
438 c.type = CBits;
439 c.bits.d = tokval.fltd;
440 c.flt = 2;
441 break;
442 case Tthread:
443 c.sym.type = SThr;
444 expect(Tglo);
445 /* fall through */
446 case Tglo:
447 c.type = CAddr;
448 c.sym.id = intern(tokval.str);
449 break;
451 return newcon(&c, curf);
454 static int
455 findtyp(int i)
457 while (--i >= 0)
458 if (strcmp(tokval.str, typ[i].name) == 0)
459 return i;
460 err("undefined type :%s", tokval.str);
463 static int
464 parsecls(int *tyn)
466 switch (next()) {
467 default:
468 err("invalid class specifier");
469 case Ttyp:
470 *tyn = findtyp(ntyp);
471 return Kc;
472 case Tsb:
473 return Ksb;
474 case Tub:
475 return Kub;
476 case Tsh:
477 return Ksh;
478 case Tuh:
479 return Kuh;
480 case Tw:
481 return Kw;
482 case Tl:
483 return Kl;
484 case Ts:
485 return Ks;
486 case Td:
487 return Kd;
491 static int
492 parserefl(int arg)
494 int k, ty, env, hasenv, vararg;
495 Ref r;
497 hasenv = 0;
498 vararg = 0;
499 expect(Tlparen);
500 while (peek() != Trparen) {
501 if (curi - insb >= NIns)
502 err("too many instructions");
503 if (!arg && vararg)
504 err("no parameters allowed after '...'");
505 switch (peek()) {
506 case Tdots:
507 if (vararg)
508 err("only one '...' allowed");
509 vararg = 1;
510 if (arg) {
511 *curi = (Ins){.op = Oargv};
512 curi++;
514 next();
515 goto Next;
516 case Tenv:
517 if (hasenv)
518 err("only one environment allowed");
519 hasenv = 1;
520 env = 1;
521 next();
522 k = Kl;
523 break;
524 default:
525 env = 0;
526 k = parsecls(&ty);
527 break;
529 r = parseref();
530 if (req(r, R))
531 err("invalid argument");
532 if (!arg && rtype(r) != RTmp)
533 err("invalid function parameter");
534 if (env)
535 if (arg)
536 *curi = (Ins){Oarge, k, R, {r}};
537 else
538 *curi = (Ins){Opare, k, r, {R}};
539 else if (k == Kc)
540 if (arg)
541 *curi = (Ins){Oargc, Kl, R, {TYPE(ty), r}};
542 else
543 *curi = (Ins){Oparc, Kl, r, {TYPE(ty)}};
544 else if (k >= Ksb)
545 if (arg)
546 *curi = (Ins){Oargsb+(k-Ksb), Kw, R, {r}};
547 else
548 *curi = (Ins){Oparsb+(k-Ksb), Kw, r, {R}};
549 else
550 if (arg)
551 *curi = (Ins){Oarg, k, R, {r}};
552 else
553 *curi = (Ins){Opar, k, r, {R}};
554 curi++;
555 Next:
556 if (peek() == Trparen)
557 break;
558 expect(Tcomma);
560 expect(Trparen);
561 return vararg;
564 static Blk *
565 findblk(char *name)
567 Blk *b;
568 uint32_t h;
570 h = hash(name) & BMask;
571 for (b=blkh[h]; b; b=b->dlink)
572 if (strcmp(b->name, name) == 0)
573 return b;
574 b = newblk();
575 b->id = nblk++;
576 strcpy(b->name, name);
577 b->dlink = blkh[h];
578 blkh[h] = b;
579 return b;
582 static void
583 closeblk()
585 curb->nins = curi - insb;
586 idup(&curb->ins, insb, curb->nins);
587 blink = &curb->link;
588 curi = insb;
591 static PState
592 parseline(PState ps)
594 Ref arg[NPred] = {R};
595 Blk *blk[NPred];
596 Phi *phi;
597 Ref r;
598 Blk *b;
599 Con *c;
600 int t, op, i, k, ty;
602 t = nextnl();
603 if (ps == PLbl && t != Tlbl && t != Trbrace)
604 err("label or } expected");
605 switch (t) {
606 case Ttmp:
607 r = tmpref(tokval.str);
608 expect(Teq);
609 k = parsecls(&ty);
610 op = next();
611 break;
612 default:
613 if (isstore(t)) {
614 case Tblit:
615 case Tcall:
616 case Ovastart:
617 /* operations without result */
618 r = R;
619 k = Kw;
620 op = t;
621 break;
623 err("label, instruction or jump expected");
624 case Trbrace:
625 return PEnd;
626 case Tlbl:
627 b = findblk(tokval.str);
628 if (curb && curb->jmp.type == Jxxx) {
629 closeblk();
630 curb->jmp.type = Jjmp;
631 curb->s1 = b;
633 if (b->jmp.type != Jxxx)
634 err("multiple definitions of block @%s", b->name);
635 *blink = b;
636 curb = b;
637 plink = &curb->phi;
638 expect(Tnl);
639 return PPhi;
640 case Tret:
641 curb->jmp.type = Jretw + rcls;
642 if (peek() == Tnl)
643 curb->jmp.type = Jret0;
644 else if (rcls != K0) {
645 r = parseref();
646 if (req(r, R))
647 err("invalid return value");
648 curb->jmp.arg = r;
650 goto Close;
651 case Tjmp:
652 curb->jmp.type = Jjmp;
653 goto Jump;
654 case Tjnz:
655 curb->jmp.type = Jjnz;
656 r = parseref();
657 if (req(r, R))
658 err("invalid argument for jnz jump");
659 curb->jmp.arg = r;
660 expect(Tcomma);
661 Jump:
662 expect(Tlbl);
663 curb->s1 = findblk(tokval.str);
664 if (curb->jmp.type != Jjmp) {
665 expect(Tcomma);
666 expect(Tlbl);
667 curb->s2 = findblk(tokval.str);
669 if (curb->s1 == curf->start || curb->s2 == curf->start)
670 err("invalid jump to the start block");
671 goto Close;
672 case Thlt:
673 curb->jmp.type = Jhlt;
674 Close:
675 expect(Tnl);
676 closeblk();
677 return PLbl;
678 case Odbgloc:
679 op = t;
680 k = Kw;
681 r = R;
682 expect(Tint);
683 arg[0] = INT(tokval.num);
684 if (arg[0].val != tokval.num)
685 err("line number too big");
686 if (peek() == Tcomma) {
687 next();
688 expect(Tint);
689 arg[1] = INT(tokval.num);
690 if (arg[1].val != tokval.num)
691 err("column number too big");
692 } else
693 arg[1] = INT(0);
694 goto Ins;
696 if (op == Tcall) {
697 curf->leaf = 0;
698 arg[0] = parseref();
699 parserefl(1);
700 op = Ocall;
701 expect(Tnl);
702 if (k == Kc) {
703 k = Kl;
704 arg[1] = TYPE(ty);
706 if (k >= Ksb)
707 k = Kw;
708 goto Ins;
710 if (op == Tloadw)
711 op = Oloadsw;
712 if (op >= Tloadl && op <= Tloadd)
713 op = Oload;
714 if (op == Talloc1 || op == Talloc2)
715 op = Oalloc;
716 if (op == Ovastart && !curf->vararg)
717 err("cannot use vastart in non-variadic function");
718 if (k >= Ksb)
719 err("size class must be w, l, s, or d");
720 i = 0;
721 if (peek() != Tnl)
722 for (;;) {
723 if (i == NPred)
724 err("too many arguments");
725 if (op == Tphi) {
726 expect(Tlbl);
727 blk[i] = findblk(tokval.str);
729 arg[i] = parseref();
730 if (req(arg[i], R))
731 err("invalid instruction argument");
732 i++;
733 t = peek();
734 if (t == Tnl)
735 break;
736 if (t != Tcomma)
737 err(", or end of line expected");
738 next();
740 next();
741 switch (op) {
742 case Tphi:
743 if (ps != PPhi || curb == curf->start)
744 err("unexpected phi instruction");
745 phi = alloc(sizeof *phi);
746 phi->to = r;
747 phi->cls = k;
748 phi->arg = vnew(i, sizeof arg[0], PFn);
749 memcpy(phi->arg, arg, i * sizeof arg[0]);
750 phi->blk = vnew(i, sizeof blk[0], PFn);
751 memcpy(phi->blk, blk, i * sizeof blk[0]);
752 phi->narg = i;
753 *plink = phi;
754 plink = &phi->link;
755 return PPhi;
756 case Tblit:
757 if (curi - insb >= NIns-1)
758 err("too many instructions");
759 memset(curi, 0, 2 * sizeof(Ins));
760 curi->op = Oblit0;
761 curi->arg[0] = arg[0];
762 curi->arg[1] = arg[1];
763 curi++;
764 if (rtype(arg[2]) != RCon)
765 err("blit size must be constant");
766 c = &curf->con[arg[2].val];
767 r = INT(c->bits.i);
768 if (c->type != CBits
769 || rsval(r) < 0
770 || rsval(r) != c->bits.i)
771 err("invalid blit size");
772 curi->op = Oblit1;
773 curi->arg[0] = r;
774 curi++;
775 return PIns;
776 default:
777 if (op >= NPubOp)
778 err("invalid instruction");
779 Ins:
780 if (curi - insb >= NIns)
781 err("too many instructions");
782 curi->op = op;
783 curi->cls = k;
784 curi->to = r;
785 curi->arg[0] = arg[0];
786 curi->arg[1] = arg[1];
787 curi++;
788 return PIns;
792 static int
793 usecheck(Ref r, int k, Fn *fn)
795 return rtype(r) != RTmp || fn->tmp[r.val].cls == k
796 || (fn->tmp[r.val].cls == Kl && k == Kw);
799 static void
800 typecheck(Fn *fn)
802 Blk *b;
803 Phi *p;
804 Ins *i;
805 uint n;
806 int k;
807 Tmp *t;
808 Ref r;
809 BSet pb[1], ppb[1];
811 fillpreds(fn);
812 bsinit(pb, fn->nblk);
813 bsinit(ppb, fn->nblk);
814 for (b=fn->start; b; b=b->link) {
815 for (p=b->phi; p; p=p->link)
816 fn->tmp[p->to.val].cls = p->cls;
817 for (i=b->ins; i<&b->ins[b->nins]; i++)
818 if (rtype(i->to) == RTmp) {
819 t = &fn->tmp[i->to.val];
820 if (clsmerge(&t->cls, i->cls))
821 err("temporary %%%s is assigned with"
822 " multiple types", t->name);
825 for (b=fn->start; b; b=b->link) {
826 bszero(pb);
827 for (n=0; n<b->npred; n++)
828 bsset(pb, b->pred[n]->id);
829 for (p=b->phi; p; p=p->link) {
830 bszero(ppb);
831 t = &fn->tmp[p->to.val];
832 for (n=0; n<p->narg; n++) {
833 k = t->cls;
834 if (bshas(ppb, p->blk[n]->id))
835 err("multiple entries for @%s in phi %%%s",
836 p->blk[n]->name, t->name);
837 if (!usecheck(p->arg[n], k, fn))
838 err("invalid type for operand %%%s in phi %%%s",
839 fn->tmp[p->arg[n].val].name, t->name);
840 bsset(ppb, p->blk[n]->id);
842 if (!bsequal(pb, ppb))
843 err("predecessors not matched in phi %%%s", t->name);
845 for (i=b->ins; i<&b->ins[b->nins]; i++)
846 for (n=0; n<2; n++) {
847 k = optab[i->op].argcls[n][i->cls];
848 r = i->arg[n];
849 t = &fn->tmp[r.val];
850 if (k == Ke)
851 err("invalid instruction type in %s",
852 optab[i->op].name);
853 if (rtype(r) == RType)
854 continue;
855 if (rtype(r) != -1 && k == Kx)
856 err("no %s operand expected in %s",
857 n == 1 ? "second" : "first",
858 optab[i->op].name);
859 if (rtype(r) == -1 && k != Kx)
860 err("missing %s operand in %s",
861 n == 1 ? "second" : "first",
862 optab[i->op].name);
863 if (!usecheck(r, k, fn))
864 err("invalid type for %s operand %%%s in %s",
865 n == 1 ? "second" : "first",
866 t->name, optab[i->op].name);
868 r = b->jmp.arg;
869 if (isret(b->jmp.type)) {
870 if (b->jmp.type == Jretc)
871 k = Kl;
872 else if (b->jmp.type >= Jretsb)
873 k = Kw;
874 else
875 k = b->jmp.type - Jretw;
876 if (!usecheck(r, k, fn))
877 goto JErr;
879 if (b->jmp.type == Jjnz && !usecheck(r, Kw, fn))
880 JErr:
881 err("invalid type for jump argument %%%s in block @%s",
882 fn->tmp[r.val].name, b->name);
883 if (b->s1 && b->s1->jmp.type == Jxxx)
884 err("block @%s is used undefined", b->s1->name);
885 if (b->s2 && b->s2->jmp.type == Jxxx)
886 err("block @%s is used undefined", b->s2->name);
890 static Fn *
891 parsefn(Lnk *lnk)
893 Blk *b;
894 int i;
895 PState ps;
897 curb = 0;
898 nblk = 0;
899 curi = insb;
900 curf = alloc(sizeof *curf);
901 curf->ntmp = 0;
902 curf->ncon = 2;
903 curf->tmp = vnew(curf->ntmp, sizeof curf->tmp[0], PFn);
904 curf->con = vnew(curf->ncon, sizeof curf->con[0], PFn);
905 for (i=0; i<Tmp0; ++i)
906 if (T.fpr0 <= i && i < T.fpr0 + T.nfpr)
907 newtmp(0, Kd, curf);
908 else
909 newtmp(0, Kl, curf);
910 curf->con[0].type = CBits;
911 curf->con[0].bits.i = 0xdeaddead; /* UNDEF */
912 curf->con[1].type = CBits;
913 curf->lnk = *lnk;
914 curf->leaf = 1;
915 blink = &curf->start;
916 curf->retty = Kx;
917 if (peek() != Tglo)
918 rcls = parsecls(&curf->retty);
919 else
920 rcls = K0;
921 if (next() != Tglo)
922 err("function name expected");
923 strncpy(curf->name, tokval.str, NString-1);
924 curf->vararg = parserefl(0);
925 if (nextnl() != Tlbrace)
926 err("function body must start with {");
927 ps = PLbl;
929 ps = parseline(ps);
930 while (ps != PEnd);
931 if (!curb)
932 err("empty function");
933 if (curb->jmp.type == Jxxx)
934 err("last block misses jump");
935 curf->mem = vnew(0, sizeof curf->mem[0], PFn);
936 curf->nmem = 0;
937 curf->nblk = nblk;
938 curf->rpo = 0;
939 for (b=curf->start; b; b=b->link)
940 b->dlink = 0; /* was trashed by findblk() */
941 for (i=0; i<BMask+1; ++i)
942 blkh[i] = 0;
943 memset(tmph, 0, tmphcap * sizeof tmph[0]);
944 typecheck(curf);
945 return curf;
948 static void
949 parsefields(Field *fld, Typ *ty, int t)
951 Typ *ty1;
952 int n, c, a, al, type;
953 uint64_t sz, s;
955 n = 0;
956 sz = 0;
957 al = ty->align;
958 while (t != Trbrace) {
959 ty1 = 0;
960 switch (t) {
961 default: err("invalid type member specifier");
962 case Td: type = Fd; s = 8; a = 3; break;
963 case Tl: type = Fl; s = 8; a = 3; break;
964 case Ts: type = Fs; s = 4; a = 2; break;
965 case Tw: type = Fw; s = 4; a = 2; break;
966 case Th: type = Fh; s = 2; a = 1; break;
967 case Tb: type = Fb; s = 1; a = 0; break;
968 case Ttyp:
969 type = FTyp;
970 ty1 = &typ[findtyp(ntyp-1)];
971 s = ty1->size;
972 a = ty1->align;
973 break;
975 if (a > al)
976 al = a;
977 a = (1 << a) - 1;
978 a = ((sz + a) & ~a) - sz;
979 if (a) {
980 if (n < NField) {
981 /* padding */
982 fld[n].type = FPad;
983 fld[n].len = a;
984 n++;
987 t = nextnl();
988 if (t == Tint) {
989 c = tokval.num;
990 t = nextnl();
991 } else
992 c = 1;
993 sz += a + c*s;
994 if (type == FTyp)
995 s = ty1 - typ;
996 for (; c>0 && n<NField; c--, n++) {
997 fld[n].type = type;
998 fld[n].len = s;
1000 if (t != Tcomma)
1001 break;
1002 t = nextnl();
1004 if (t != Trbrace)
1005 err(", or } expected");
1006 fld[n].type = FEnd;
1007 a = 1 << al;
1008 if (sz < ty->size)
1009 sz = ty->size;
1010 ty->size = (sz + a - 1) & -a;
1011 ty->align = al;
1014 static void
1015 parsetyp()
1017 Typ *ty;
1018 int t, al;
1019 uint n;
1021 /* be careful if extending the syntax
1022 * to handle nested types, any pointer
1023 * held to typ[] might be invalidated!
1025 vgrow(&typ, ntyp+1);
1026 ty = &typ[ntyp++];
1027 ty->isdark = 0;
1028 ty->isunion = 0;
1029 ty->align = -1;
1030 ty->size = 0;
1031 if (nextnl() != Ttyp || nextnl() != Teq)
1032 err("type name and then = expected");
1033 strcpy(ty->name, tokval.str);
1034 t = nextnl();
1035 if (t == Talign) {
1036 if (nextnl() != Tint)
1037 err("alignment expected");
1038 for (al=0; tokval.num /= 2; al++)
1040 ty->align = al;
1041 t = nextnl();
1043 if (t != Tlbrace)
1044 err("type body must start with {");
1045 t = nextnl();
1046 if (t == Tint) {
1047 ty->isdark = 1;
1048 ty->size = tokval.num;
1049 if (ty->align == -1)
1050 err("dark types need alignment");
1051 if (nextnl() != Trbrace)
1052 err("} expected");
1053 return;
1055 n = 0;
1056 ty->fields = vnew(1, sizeof ty->fields[0], PHeap);
1057 if (t == Tlbrace) {
1058 ty->isunion = 1;
1059 do {
1060 if (t != Tlbrace)
1061 err("invalid union member");
1062 vgrow(&ty->fields, n+1);
1063 parsefields(ty->fields[n++], ty, nextnl());
1064 t = nextnl();
1065 } while (t != Trbrace);
1066 } else
1067 parsefields(ty->fields[n++], ty, t);
1068 ty->nunion = n;
1071 static void
1072 parsedatref(Dat *d)
1074 int t;
1076 d->isref = 1;
1077 d->u.ref.name = tokval.str;
1078 d->u.ref.off = 0;
1079 t = peek();
1080 if (t == Tplus) {
1081 next();
1082 if (next() != Tint)
1083 err("invalid token after offset in ref");
1084 d->u.ref.off = tokval.num;
1088 static void
1089 parsedatstr(Dat *d)
1091 d->isstr = 1;
1092 d->u.str = tokval.str;
1095 static void
1096 parsedat(void cb(Dat *), Lnk *lnk)
1098 char name[NString] = {0};
1099 int t;
1100 Dat d;
1102 if (nextnl() != Tglo || nextnl() != Teq)
1103 err("data name, then = expected");
1104 strncpy(name, tokval.str, NString-1);
1105 t = nextnl();
1106 lnk->align = 8;
1107 if (t == Talign) {
1108 if (nextnl() != Tint)
1109 err("alignment expected");
1110 if (tokval.num <= 0 || tokval.num > CHAR_MAX
1111 || (tokval.num & (tokval.num-1)) != 0)
1112 err("invalid alignment");
1113 lnk->align = tokval.num;
1114 t = nextnl();
1116 d.type = DStart;
1117 d.name = name;
1118 d.lnk = lnk;
1119 cb(&d);
1121 if (t != Tlbrace)
1122 err("expected data contents in { .. }");
1123 for (;;) {
1124 switch (nextnl()) {
1125 default: err("invalid size specifier %c in data", tokval.chr);
1126 case Trbrace: goto Done;
1127 case Tl: d.type = DL; break;
1128 case Tw: d.type = DW; break;
1129 case Th: d.type = DH; break;
1130 case Tb: d.type = DB; break;
1131 case Ts: d.type = DW; break;
1132 case Td: d.type = DL; break;
1133 case Tz: d.type = DZ; break;
1135 t = nextnl();
1136 do {
1137 d.isstr = 0;
1138 d.isref = 0;
1139 memset(&d.u, 0, sizeof d.u);
1140 if (t == Tflts)
1141 d.u.flts = tokval.flts;
1142 else if (t == Tfltd)
1143 d.u.fltd = tokval.fltd;
1144 else if (t == Tint)
1145 d.u.num = tokval.num;
1146 else if (t == Tglo)
1147 parsedatref(&d);
1148 else if (t == Tstr)
1149 parsedatstr(&d);
1150 else
1151 err("constant literal expected");
1152 cb(&d);
1153 t = nextnl();
1154 } while (t == Tint || t == Tflts || t == Tfltd || t == Tstr || t == Tglo);
1155 if (t == Trbrace)
1156 break;
1157 if (t != Tcomma)
1158 err(", or } expected");
1160 Done:
1161 d.type = DEnd;
1162 cb(&d);
1165 static int
1166 parselnk(Lnk *lnk)
1168 int t, haslnk;
1170 for (haslnk=0;; haslnk=1)
1171 switch ((t=nextnl())) {
1172 case Texport:
1173 lnk->export = 1;
1174 break;
1175 case Tthread:
1176 lnk->thread = 1;
1177 break;
1178 case Tcommon:
1179 lnk->common = 1;
1180 break;
1181 case Tsection:
1182 if (lnk->sec)
1183 err("only one section allowed");
1184 if (next() != Tstr)
1185 err("section \"name\" expected");
1186 lnk->sec = tokval.str;
1187 if (peek() == Tstr) {
1188 next();
1189 lnk->secf = tokval.str;
1191 break;
1192 default:
1193 if (t == Tfunc && lnk->thread)
1194 err("only data may have thread linkage");
1195 if (haslnk && t != Tdata && t != Tfunc)
1196 err("only data and function have linkage");
1197 return t;
1201 void
1202 parse(FILE *f, char *path, void dbgfile(char *), void data(Dat *), void func(Fn *))
1204 Lnk lnk;
1205 uint n;
1207 lexinit();
1208 inf = f;
1209 inpath = path;
1210 lnum = 1;
1211 thead = Txxx;
1212 ntyp = 0;
1213 typ = vnew(0, sizeof typ[0], PHeap);
1214 for (;;) {
1215 lnk = (Lnk){0};
1216 switch (parselnk(&lnk)) {
1217 default:
1218 err("top-level definition expected");
1219 case Tdbgfile:
1220 expect(Tstr);
1221 dbgfile(tokval.str);
1222 break;
1223 case Tfunc:
1224 lnk.align = 16;
1225 func(parsefn(&lnk));
1226 break;
1227 case Tdata:
1228 parsedat(data, &lnk);
1229 break;
1230 case Ttype:
1231 parsetyp();
1232 break;
1233 case Teof:
1234 for (n=0; n<ntyp; n++)
1235 if (typ[n].nunion)
1236 vfree(typ[n].fields);
1237 vfree(typ);
1238 return;
1243 static void
1244 printcon(Con *c, FILE *f)
1246 switch (c->type) {
1247 case CUndef:
1248 break;
1249 case CAddr:
1250 if (c->sym.type == SThr)
1251 fprintf(f, "thread ");
1252 fprintf(f, "$%s", str(c->sym.id));
1253 if (c->bits.i)
1254 fprintf(f, "%+"PRIi64, c->bits.i);
1255 break;
1256 case CBits:
1257 if (c->flt == 1)
1258 fprintf(f, "s_%f", c->bits.s);
1259 else if (c->flt == 2)
1260 fprintf(f, "d_%lf", c->bits.d);
1261 else
1262 fprintf(f, "%"PRIi64, c->bits.i);
1263 break;
1267 void
1268 printref(Ref r, Fn *fn, FILE *f)
1270 int i;
1271 Mem *m;
1273 switch (rtype(r)) {
1274 case RTmp:
1275 if (r.val < Tmp0)
1276 fprintf(f, "R%d", r.val);
1277 else
1278 fprintf(f, "%%%s", fn->tmp[r.val].name);
1279 break;
1280 case RCon:
1281 if (req(r, UNDEF))
1282 fprintf(f, "UNDEF");
1283 else
1284 printcon(&fn->con[r.val], f);
1285 break;
1286 case RSlot:
1287 fprintf(f, "S%d", rsval(r));
1288 break;
1289 case RCall:
1290 fprintf(f, "%04x", r.val);
1291 break;
1292 case RType:
1293 fprintf(f, ":%s", typ[r.val].name);
1294 break;
1295 case RMem:
1296 i = 0;
1297 m = &fn->mem[r.val];
1298 fputc('[', f);
1299 if (m->offset.type != CUndef) {
1300 printcon(&m->offset, f);
1301 i = 1;
1303 if (!req(m->base, R)) {
1304 if (i)
1305 fprintf(f, " + ");
1306 printref(m->base, fn, f);
1307 i = 1;
1309 if (!req(m->index, R)) {
1310 if (i)
1311 fprintf(f, " + ");
1312 fprintf(f, "%d * ", m->scale);
1313 printref(m->index, fn, f);
1315 fputc(']', f);
1316 break;
1317 case RInt:
1318 fprintf(f, "%d", rsval(r));
1319 break;
1320 case -1:
1321 fprintf(f, "R");
1322 break;
1326 void
1327 printfn(Fn *fn, FILE *f)
1329 static char ktoc[] = "wlsd";
1330 static char *jtoa[NJmp] = {
1331 #define X(j) [J##j] = #j,
1332 JMPS(X)
1333 #undef X
1335 Blk *b;
1336 Phi *p;
1337 Ins *i;
1338 uint n;
1340 fprintf(f, "function $%s() {\n", fn->name);
1341 for (b=fn->start; b; b=b->link) {
1342 fprintf(f, "@%s\n", b->name);
1343 for (p=b->phi; p; p=p->link) {
1344 fprintf(f, "\t");
1345 printref(p->to, fn, f);
1346 fprintf(f, " =%c phi ", ktoc[p->cls]);
1347 assert(p->narg);
1348 for (n=0;; n++) {
1349 fprintf(f, "@%s ", p->blk[n]->name);
1350 printref(p->arg[n], fn, f);
1351 if (n == p->narg-1) {
1352 fprintf(f, "\n");
1353 break;
1354 } else
1355 fprintf(f, ", ");
1358 for (i=b->ins; i<&b->ins[b->nins]; i++) {
1359 fprintf(f, "\t");
1360 if (!req(i->to, R)) {
1361 printref(i->to, fn, f);
1362 fprintf(f, " =%c ", ktoc[i->cls]);
1364 assert(optab[i->op].name);
1365 fprintf(f, "%s", optab[i->op].name);
1366 if (req(i->to, R))
1367 switch (i->op) {
1368 case Oarg:
1369 case Oswap:
1370 case Oxcmp:
1371 case Oacmp:
1372 case Oacmn:
1373 case Oafcmp:
1374 case Oxtest:
1375 case Oxdiv:
1376 case Oxidiv:
1377 fputc(ktoc[i->cls], f);
1379 if (!req(i->arg[0], R)) {
1380 fprintf(f, " ");
1381 printref(i->arg[0], fn, f);
1383 if (!req(i->arg[1], R)) {
1384 fprintf(f, ", ");
1385 printref(i->arg[1], fn, f);
1387 fprintf(f, "\n");
1389 switch (b->jmp.type) {
1390 case Jret0:
1391 case Jretsb:
1392 case Jretub:
1393 case Jretsh:
1394 case Jretuh:
1395 case Jretw:
1396 case Jretl:
1397 case Jrets:
1398 case Jretd:
1399 case Jretc:
1400 fprintf(f, "\t%s", jtoa[b->jmp.type]);
1401 if (b->jmp.type != Jret0 || !req(b->jmp.arg, R)) {
1402 fprintf(f, " ");
1403 printref(b->jmp.arg, fn, f);
1405 if (b->jmp.type == Jretc)
1406 fprintf(f, ", :%s", typ[fn->retty].name);
1407 fprintf(f, "\n");
1408 break;
1409 case Jhlt:
1410 fprintf(f, "\thlt\n");
1411 break;
1412 case Jjmp:
1413 if (b->s1 != b->link)
1414 fprintf(f, "\tjmp @%s\n", b->s1->name);
1415 break;
1416 default:
1417 fprintf(f, "\t%s ", jtoa[b->jmp.type]);
1418 if (b->jmp.type == Jjnz) {
1419 printref(b->jmp.arg, fn, f);
1420 fprintf(f, ", ");
1422 assert(b->s1 && b->s2);
1423 fprintf(f, "@%s, @%s\n", b->s1->name, b->s2->name);
1424 break;
1427 fprintf(f, "}\n");