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