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