#include "all.h" enum { Ksb = 4, /* matches Oarg/Opar/Jret */ Kub, Ksh, Kuh, Kc, K0, Ke = -2, /* erroneous mode */ Km = Kl, /* memory pointer */}; Op optab[NOp] = {#define O(op, t, cf) [O##op]={#op, t, cf}, #include "ops.h"}; typedef enum { PXXX, PLbl, PPhi, PIns, PEnd,} PState; enum Token { Txxx = 0, /* aliases */ Tloadw = NPubOp, Tloadl, Tloads, Tloadd, Talloc1, Talloc2, Tblit, Tcall, Tenv, Tphi, Tjmp, Tjnz, Tret, Thlt, Texport, Tthread, Tfunc, Ttype, Tdata, Tsection, Talign, Tl, Tw, Tsh, Tuh, Th, Tsb, Tub, Tb, Td, Ts, Tz, Tint, Tflts, Tfltd, Ttmp, Tlbl, Tglo, Ttyp, Tstr, Tplus, Teq, Tcomma, Tlparen, Trparen, Tlbrace, Trbrace, Tnl, Tdots, Teof, Ntok}; static char *kwmap[Ntok] = { [Tloadw] = "loadw", [Tloadl] = "loadl", [Tloads] = "loads", [Tloadd] = "loadd", [Talloc1] = "alloc1", [Talloc2] = "alloc2", [Tblit] = "blit", [Tcall] = "call", [Tenv] = "env", [Tphi] = "phi", [Tjmp] = "jmp", [Tjnz] = "jnz", [Tret] = "ret", [Thlt] = "hlt", [Texport] = "export", [Tthread] = "thread", [Tfunc] = "function", [Ttype] = "type", [Tdata] = "data", [Tsection] = "section", [Talign] = "align", [Tsb] = "sb", [Tub] = "ub", [Tsh] = "sh", [Tuh] = "uh", [Tb] = "b", [Th] = "h", [Tw] = "w", [Tl] = "l", [Ts] = "s", [Td] = "d", [Tz] = "z", [Tdots] = "...",}; enum { NPred = 63, TMask = 16383, /* for temps hash */ BMask = 8191, /* for blocks hash */ K = 9583425, /* found using tools/lexh.c */ M = 23,}; static uchar lexh[1 << (32-M)];static FILE *inf;static char *inpath;static int thead;static struct { char chr; double fltd; float flts; int64_t num; char *str;} tokval;static int lnum; static Fn *curf;static int tmph[TMask+1];static Phi **plink;static Blk *curb;static Blk **blink;static Blk *blkh[BMask+1];static int nblk;static int rcls;static uint ntyp; voiderr(char *s, ...){ va_list ap; va_start(ap, s); fprintf(stderr, "qbe:%s:%d: ", inpath, lnum); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); va_end(ap); exit(1);} static voidlexinit(void){ static int done; int i; long h; if (done) return; for (i=0; i<NPubOp; ++i) if (optab[i].name) kwmap[i] = optab[i].name; assert(Ntok <= UCHAR_MAX); for (i=0; i<Ntok; ++i) if (kwmap[i]) { h = hash(kwmap[i])*K >> M; assert(lexh[h] == Txxx); lexh[h] = i; } done = 1;} static int64_tgetint(void){ uint64_t n; int c, m; n = 0; c = fgetc(inf); m = (c == '-'); if (m || c == '+') c = fgetc(inf); do { n = 10*n + (c - '0'); c = fgetc(inf); } while ('0' <= c && c <= '9'); ungetc(c, inf); if (m) n = 1 + ~n; return *(int64_t *)&n;} static intlex(void){ static char tok[NString]; int c, i, esc; int t; do c = fgetc(inf); while (isblank(c)); t = Txxx; tokval.chr = c; switch (c) { case EOF: return Teof; case ',': return Tcomma; case '(': return Tlparen; case ')': return Trparen; case '{': return Tlbrace; case '}': return Trbrace; case '=': return Teq; case '+': return Tplus; case 's': if (fscanf(inf, "_%f", &tokval.flts) != 1) break; return Tflts; case 'd': if (fscanf(inf, "_%lf", &tokval.fltd) != 1) break; return Tfltd; case '%': t = Ttmp; c = fgetc(inf); goto Alpha; case '@': t = Tlbl; c = fgetc(inf); goto Alpha; case '$': t = Tglo; if ((c = fgetc(inf)) == '"') goto Quoted; goto Alpha; case ':': t = Ttyp; c = fgetc(inf); goto Alpha; case '#': while ((c=fgetc(inf)) != '\n' && c != EOF) ; /* fall through */ case '\n': lnum++; return Tnl; } if (isdigit(c) || c == '-' || c == '+') { ungetc(c, inf); tokval.num = getint(); return Tint; } if (c == '"') { t = Tstr; Quoted: tokval.str = vnew(2, 1, PFn); tokval.str[0] = c; esc = 0; for (i=1;; i++) { c = fgetc(inf); if (c == EOF) err("unterminated string"); vgrow(&tokval.str, i+2); tokval.str[i] = c; if (c == '"' && !esc) { tokval.str[i+1] = 0; return t; } esc = (c == '\\' && !esc); } }Alpha: if (!isalpha(c) && c != '.' && c != '_') err("invalid character %c (%d)", c, c); i = 0; do { if (i >= NString-1) err("identifier too long"); tok[i++] = c; c = fgetc(inf); } while (isalpha(c) || c == '$' || c == '.' || c == '_' || isdigit(c)); tok[i] = 0; ungetc(c, inf); tokval.str = tok; if (t != Txxx) { return t; } t = lexh[hash(tok)*K >> M]; if (t == Txxx || strcmp(kwmap[t], tok) != 0) { err("unknown keyword %s", tok); return Txxx; } return t;} static intpeek(void){ if (thead == Txxx) thead = lex(); return thead;} static intnext(void){ int t; t = peek(); thead = Txxx; return t;} static intnextnl(void){ int t; while ((t = next()) == Tnl) ; return t;} static voidexpect(int t){ static char *ttoa[] = { [Tlbl] = "label", [Tcomma] = ",", [Teq] = "=", [Tnl] = "newline", [Tlparen] = "(", [Trparen] = ")", [Tlbrace] = "{", [Trbrace] = "}", [Teof] = 0, }; char buf[128], *s1, *s2; int t1; t1 = next(); if (t == t1) return; s1 = ttoa[t] ? ttoa[t] : "??"; s2 = ttoa[t1] ? ttoa[t1] : "??"; sprintf(buf, "%s expected, got %s instead", s1, s2); err(buf);} static Reftmpref(char *v){ int t, *h; h = &tmph[hash(v) & TMask]; t = *h; if (t) { if (strcmp(curf->tmp[t].name, v) == 0) return TMP(t); for (t=curf->ntmp-1; t>=Tmp0; t--) if (strcmp(curf->tmp[t].name, v) == 0) return TMP(t); } t = curf->ntmp; *h = t; newtmp(0, Kx, curf); strcpy(curf->tmp[t].name, v); return TMP(t);} static Refparseref(void){ Con c; memset(&c, 0, sizeof c); switch (next()) { default: return R; case Ttmp: return tmpref(tokval.str); case Tint: c.type = CBits; c.bits.i = tokval.num; break; case Tflts: c.type = CBits; c.bits.s = tokval.flts; c.flt = 1; break; case Tfltd: c.type = CBits; c.bits.d = tokval.fltd; c.flt = 2; break; case Tthread: c.sym.type = SThr; expect(Tglo); /* fall through */ case Tglo: c.type = CAddr; c.sym.id = intern(tokval.str); break; } return newcon(&c, curf);} static intfindtyp(int i){ while (--i >= 0) if (strcmp(tokval.str, typ[i].name) == 0) return i; err("undefined type :%s", tokval.str); return -1;} static intparsecls(int *tyn){ switch (next()) { default: err("invalid class specifier"); case Ttyp: *tyn = findtyp(ntyp); return Kc; case Tsb: return Ksb; case Tub: return Kub; case Tsh: return Ksh; case Tuh: return Kuh; case Tw: return Kw; case Tl: return Kl; case Ts: return Ks; case Td: return Kd; }} static intparserefl(int arg){ int k, ty, env, hasenv, vararg; Ref r; hasenv = 0; vararg = 0; expect(Tlparen); while (peek() != Trparen) { if (curi - insb >= NIns) err("too many instructions"); if (!arg && vararg) err("no parameters allowed after '...'"); switch (peek()) { case Tdots: if (vararg) err("only one '...' allowed"); vararg = 1; if (arg) { memset(curi, 0, sizeof(*curi)); curi->op = Oargv; curi++; } next(); goto Next; case Tenv:Lines 1–500 of 1409. Load more
#include "all.h" enum { Ksb = 4, /* matches Oarg/Opar/Jret */ Kub, Ksh, Kuh, Kc, K0, Ke = -2, /* erroneous mode */ Km = Kl, /* memory pointer */ }; Op optab[NOp] = { #define O(op, t, cf) [O##op]={#op, t, cf}, #include "ops.h" }; typedef enum { PXXX, PLbl, PPhi, PIns, PEnd, } PState; enum Token { Txxx = 0, /* aliases */ Tloadw = NPubOp, Tloadl, Tloads, Tloadd, Talloc1, Talloc2, Tblit, Tcall, Tenv, Tphi, Tjmp, Tjnz, Tret, Thlt, Texport, Tthread, Tfunc, Ttype, Tdata, Tsection, Talign, Tl, Tw, Tsh, Tuh, Th, Tsb, Tub, Tb, Td, Ts, Tz, Tint, Tflts, Tfltd, Ttmp, Tlbl, Tglo, Ttyp, Tstr, Tplus, Teq, Tcomma, Tlparen, Trparen, Tlbrace, Trbrace, Tnl, Tdots, Teof, Ntok }; static char *kwmap[Ntok] = { [Tloadw] = "loadw", [Tloadl] = "loadl", [Tloads] = "loads", [Tloadd] = "loadd", [Talloc1] = "alloc1", [Talloc2] = "alloc2", [Tblit] = "blit", [Tcall] = "call", [Tenv] = "env", [Tphi] = "phi", [Tjmp] = "jmp", [Tjnz] = "jnz", [Tret] = "ret", [Thlt] = "hlt", [Texport] = "export", [Tthread] = "thread", [Tfunc] = "function", [Ttype] = "type", [Tdata] = "data", [Tsection] = "section", [Talign] = "align", [Tsb] = "sb", [Tub] = "ub", [Tsh] = "sh", [Tuh] = "uh", [Tb] = "b", [Th] = "h", [Tw] = "w", [Tl] = "l", [Ts] = "s", [Td] = "d", [Tz] = "z", [Tdots] = "...", }; enum { NPred = 63, TMask = 16383, /* for temps hash */ BMask = 8191, /* for blocks hash */ K = 9583425, /* found using tools/lexh.c */ M = 23, }; static uchar lexh[1 << (32-M)]; static FILE *inf; static char *inpath; static int thead; static struct { char chr; double fltd; float flts; int64_t num; char *str; } tokval; static int lnum; static Fn *curf; static int tmph[TMask+1]; static Phi **plink; static Blk *curb; static Blk **blink; static Blk *blkh[BMask+1]; static int nblk; static int rcls; static uint ntyp; void err(char *s, ...) { va_list ap; va_start(ap, s); fprintf(stderr, "qbe:%s:%d: ", inpath, lnum); vfprintf(stderr, s, ap); fprintf(stderr, "\n"); va_end(ap); exit(1); } static void lexinit(void) { static int done; int i; long h; if (done) return; for (i=0; i<NPubOp; ++i) if (optab[i].name) kwmap[i] = optab[i].name; assert(Ntok <= UCHAR_MAX); for (i=0; i<Ntok; ++i) if (kwmap[i]) { h = hash(kwmap[i])*K >> M; assert(lexh[h] == Txxx); lexh[h] = i; } done = 1; } static int64_t getint(void) { uint64_t n; int c, m; n = 0; c = fgetc(inf); m = (c == '-'); if (m || c == '+') c = fgetc(inf); do { n = 10*n + (c - '0'); c = fgetc(inf); } while ('0' <= c && c <= '9'); ungetc(c, inf); if (m) n = 1 + ~n; return *(int64_t *)&n; } static int lex(void) { static char tok[NString]; int c, i, esc; int t; do c = fgetc(inf); while (isblank(c)); t = Txxx; tokval.chr = c; switch (c) { case EOF: return Teof; case ',': return Tcomma; case '(': return Tlparen; case ')': return Trparen; case '{': return Tlbrace; case '}': return Trbrace; case '=': return Teq; case '+': return Tplus; case 's': if (fscanf(inf, "_%f", &tokval.flts) != 1) break; return Tflts; case 'd': if (fscanf(inf, "_%lf", &tokval.fltd) != 1) break; return Tfltd; case '%': t = Ttmp; c = fgetc(inf); goto Alpha; case '@': t = Tlbl; c = fgetc(inf); goto Alpha; case '$': t = Tglo; if ((c = fgetc(inf)) == '"') goto Quoted; goto Alpha; case ':': t = Ttyp; c = fgetc(inf); goto Alpha; case '#': while ((c=fgetc(inf)) != '\n' && c != EOF) ; /* fall through */ case '\n': lnum++; return Tnl; } if (isdigit(c) || c == '-' || c == '+') { ungetc(c, inf); tokval.num = getint(); return Tint; } if (c == '"') { t = Tstr; Quoted: tokval.str = vnew(2, 1, PFn); tokval.str[0] = c; esc = 0; for (i=1;; i++) { c = fgetc(inf); if (c == EOF) err("unterminated string"); vgrow(&tokval.str, i+2); tokval.str[i] = c; if (c == '"' && !esc) { tokval.str[i+1] = 0; return t; } esc = (c == '\\' && !esc); } } Alpha: if (!isalpha(c) && c != '.' && c != '_') err("invalid character %c (%d)", c, c); i = 0; do { if (i >= NString-1) err("identifier too long"); tok[i++] = c; c = fgetc(inf); } while (isalpha(c) || c == '$' || c == '.' || c == '_' || isdigit(c)); tok[i] = 0; ungetc(c, inf); tokval.str = tok; if (t != Txxx) { return t; } t = lexh[hash(tok)*K >> M]; if (t == Txxx || strcmp(kwmap[t], tok) != 0) { err("unknown keyword %s", tok); return Txxx; } return t; } static int peek(void) { if (thead == Txxx) thead = lex(); return thead; } static int next(void) { int t; t = peek(); thead = Txxx; return t; } static int nextnl(void) { int t; while ((t = next()) == Tnl) ; return t; } static void expect(int t) { static char *ttoa[] = { [Tlbl] = "label", [Tcomma] = ",", [Teq] = "=", [Tnl] = "newline", [Tlparen] = "(", [Trparen] = ")", [Tlbrace] = "{", [Trbrace] = "}", [Teof] = 0, }; char buf[128], *s1, *s2; int t1; t1 = next(); if (t == t1) return; s1 = ttoa[t] ? ttoa[t] : "??"; s2 = ttoa[t1] ? ttoa[t1] : "??"; sprintf(buf, "%s expected, got %s instead", s1, s2); err(buf); } static Ref tmpref(char *v) { int t, *h; h = &tmph[hash(v) & TMask]; t = *h; if (t) { if (strcmp(curf->tmp[t].name, v) == 0) return TMP(t); for (t=curf->ntmp-1; t>=Tmp0; t--) if (strcmp(curf->tmp[t].name, v) == 0) return TMP(t); } t = curf->ntmp; *h = t; newtmp(0, Kx, curf); strcpy(curf->tmp[t].name, v); return TMP(t); } static Ref parseref(void) { Con c; memset(&c, 0, sizeof c); switch (next()) { default: return R; case Ttmp: return tmpref(tokval.str); case Tint: c.type = CBits; c.bits.i = tokval.num; break; case Tflts: c.type = CBits; c.bits.s = tokval.flts; c.flt = 1; break; case Tfltd: c.type = CBits; c.bits.d = tokval.fltd; c.flt = 2; break; case Tthread: c.sym.type = SThr; expect(Tglo); /* fall through */ case Tglo: c.type = CAddr; c.sym.id = intern(tokval.str); break; } return newcon(&c, curf); } static int findtyp(int i) { while (--i >= 0) if (strcmp(tokval.str, typ[i].name) == 0) return i; err("undefined type :%s", tokval.str); return -1; } static int parsecls(int *tyn) { switch (next()) { default: err("invalid class specifier"); case Ttyp: *tyn = findtyp(ntyp); return Kc; case Tsb: return Ksb; case Tub: return Kub; case Tsh: return Ksh; case Tuh: return Kuh; case Tw: return Kw; case Tl: return Kl; case Ts: return Ks; case Td: return Kd; } } static int parserefl(int arg) { int k, ty, env, hasenv, vararg; Ref r; hasenv = 0; vararg = 0; expect(Tlparen); while (peek() != Trparen) { if (curi - insb >= NIns) err("too many instructions"); if (!arg && vararg) err("no parameters allowed after '...'"); switch (peek()) { case Tdots: if (vararg) err("only one '...' allowed"); vararg = 1; if (arg) { memset(curi, 0, sizeof(*curi)); curi->op = Oargv; curi++; } next(); goto Next; case Tenv: