#include <u.h>#include <libc.h>#include "dat.h"#include "fns.h" SymTab global;SymTab *scope = &global;int curlevel; Type types[NTYPE] = { {TXXX, 0, 0, 0}, {TUCHAR, 0, 1, 0}, {TCHAR, 1, 1, 0}, {TUSHORT, 0, 2, 2}, {TSHORT, 1, 2, 2}, {TUINT, 0, 4, 4}, {TINT, 1, 4, 4}, {TUVLONG, 0, 8, 4}, {TVLONG, 1, 8, 4}, {TFLOAT, 1, 4, 4}, {TDOUBLE, 1, 8, 4}, {TVOID, 0},};Type *typelist;static char *astname[] = { "ASTCLONG", "ASTBIN", "ASTASS", "ASTTERN", "ASTDEREF", "ASTADDROF", "ASTUN", "ASTINC", "ASTIF", "ASTSYM", "ASTARRAY", "ASTFUNCTYPE", "ASTCAST", "ASTCOMMA", "ASTBLOCK", "ASTWHILE", "ASTDOWHILE", "ASTFOR", "ASTBREAK", "ASTCONTINUE", "ASTRETURN", "ASTLABEL", "ASTGOTO", "ASTMEMB", "ASTCALL",};static char *copname[] = { [OPMOV] "MOV", [OPUPLUS] "unary +", [OPNEG] "unary -", [OPISZ] "!", [OPADD] "+", [OPSUB] "-", [OPMUL] "*", [OPDIV] "/", [OPMOD] "%", [OPEQ] "==", [OPNE] "!=", [OPLT] "<", [OPLE] "<=", [OPGT] ">", [OPGE] ">=", [OPB] "unsigned <", [OPBE] "unsigned <=", [OPA] "unsigned >", [OPAE] "unsigned >=", [OPAND] "&", [OPOR] "|", [OPXOR] "^", [OPLSH] "<<", [OPRSH] "unsigned >>", [OPASR] "signed >>", [OPCOM] "~", [OPLOR] "||", [OPLAND] "&&",};static char *iropname[] = { [OPMOV] "MOV", [OPNEG] "NEG", [OPISZ] "ISZ", [OPTST] "TST", [OPLD] "LD", [OPST] "ST", [OPLDB] "LDB", [OPLDSB] "LDSB", [OPSTB] "STB", [OPLDH] "LDH", [OPLDSH] "LDSH", [OPSTH] "STH", [OPLDD] "LDD", [OPSTD] "STD", [OPADD] "ADD", [OPSUB] "SUB", [OPRSB] "RSB", [OPMUL] "MUL", [OPDIV] "DIV", [OPMOD] "MOD", [OPCMP] "CMP", [OPEQ] "BEQ", [OPNE] "BNE", [OPLT] "BLT", [OPLE] "BLE", [OPGT] "BGT", [OPGE] "BGE", [OPB] "BB", [OPBE] "BBE", [OPA] "BA", [OPAE] "BAE", [OPAND] "AND", [OPOR] "OR", [OPXOR] "XOR", [OPLSH] "LSH", [OPRSH] "RSH", [OPASR] "ASR", [OPCOM] "COM", [OPSXTB] "SXTB", [OPSXTH] "SXTH", [OPSXTW] "SXTW", [OPZXTB] "ZXTB", [OPZXTH] "ZXTH", [OPZXTW] "ZXTW", [OPPHI] "φ", [OPCALL] "CALL", [OPFADD] "FADD", [OPFSUB] "FSUB", [OPFMUL] "FMUL", [OPFDIV] "FDIV", [OPFCMP] "FCMP",};static char *typename[] = { "XXX", "uchar", "char", "ushort", "short", "uint", "int", "uvlong", "vlong", "float", "double", "void",}; static uinthash(char *s){ uint c; c = 0; while(*s != 0) c += *s++; return c;} static Symbol *makesym(char *n){ SymTab *st; Symbol *s; int h; if(curlevel != scope->level){ st = emalloc(sizeof(*st)); st->up = scope; scope = st; } s = emalloc(sizeof(*s)); s->num = -1; s->name = strdup(n); h = hash(n) % SYMHASH; s->next = scope->sym[h]; s->Line = curline; s->level = curlevel; scope->sym[h] = s; return s;} Symbol *getsym(char *n){ SymTab *st; Symbol *s; int h; h = hash(n) % SYMHASH; for(st = scope; st != nil; st = st->up) for(s = st->sym[h]; s != nil; s = s->next) if(strcmp(s->name, n) == 0) return s; return makesym(n);} voidchecksym(Symbol *s){ if(s->t == nil){ error(nil, "'%s' undeclared", s->name); s->t = &types[TINT]; }} static voidfuncparams(void){ Member *m, *me; Symbol *s, **sp; me = curfunc->type->memb + curfunc->type->nmemb; curfunc->arg = sp = emalloc(sizeof(Member *) * curfunc->type->nmemb); for(m = curfunc->type->memb; m < me; m++, sp++) if(m->name != nil){ s = makesym(m->name); s->t = m->type; s->off = m->off; *sp = s; }} voidlevelch(int n){ SymTab *st, *stn; curlevel += n; if(curlevel == 1 && n > 0) funcparams(); assert(curlevel >= 0); if(n < 0){ st = scope; while(st->level > curlevel){ stn = st->up; free(st); st = stn; assert(st != nil); } scope = st; }} intopfmt(Fmt *f){ int t; t = va_arg(f->args, int); if(t >= nelem(copname) || copname[t] == nil) return fmtprint(f, "??? (%d)", t); return fmtstrcpy(f, copname[t]);} intastfmt(Fmt *f){ int t; t = va_arg(f->args, int); if(t >= nelem(astname)) return fmtprint(f, "??? (%d)", t); return fmtstrcpy(f, astname[t]);} inttypefmtrec(Fmt *f, Type *t){ int rc, i; if(t == nil) return fmtstrcpy(f, "??? (nil)"); switch(t->t){ case TIND: rc = typefmtrec(f, t->link); rc += fmtstrcpy(f, "*"); return rc; case TFUNC: rc = typefmtrec(f, t->link); rc += fmtstrcpy(f, "()("); if(t->nmemb != 0) for(i = 0;;){ rc += typefmtrec(f, t->memb[i].type); if(++i != t->nmemb) rc += fmtstrcpy(f, ", "); else break; } rc += fmtstrcpy(f, ")"); return rc; case TSTRUCT: if(t->tag != nil) rc = fmtprint(f, "struct %s", t->tag); else rc = fmtprint(f, "struct %p", t); return rc; case TUNION: if(t->tag != nil) rc = fmtprint(f, "union %s", t->tag); else rc = fmtprint(f, "union %p", t); return rc; } if(t->t >= nelem(typename)) return fmtprint(f, "??? (%d)", t->t); return fmtstrcpy(f, typename[t->t]);} inttypefmt(Fmt *f){ return typefmtrec(f, va_arg(f->args, Type *));} intirtargfmt(Fmt *f){ Targ *t; int rc; t = va_arg(f->args, Targ *); if(t == nil) return fmtstrcpy(f, "nil"); switch(t->t){ case TARGSYM: rc = fmtstrcpy(f, t->sym->name); break; case TARGSSA: rc = fmtprint(f, "%s:%d", t->sym->name, t->n); break; case TARGTEMP: rc = fmtprint(f, "t%d", t->tn); if(t->type != nil) switch(t->type->t){ case TFLOAT: rc += fmtrune(f, 'f'); break; case TDOUBLE: rc += fmtrune(f, 'd'); break; } break; case TARGCONST: rc = fmtprint(f, "$%#ux", t->lval); break; case TARGRETV: rc = fmtprint(f, t->type == &types[TFLOAT] || t->type == &types[TDOUBLE] ? "F0" : "R0"); break; case TARGFP: rc = fmtprint(f, "FP(%d)", t->off); break; case TARGARG: rc =fmtprint(f, "ARG(%d)", t->off); break; case TARGIND: rc = fmtprint(f, "(%J)", t->link); break; case TARGADDR: rc = fmtprint(f, "&%s%+d", t->sym->name, t->n); break; case TARGSH: rc = fmtprint(f, "%s(%J, %J)", iropname[t->op], t->a, t->b); break; default: return fmtprint(f, "???(%d)", t->t); } if(t->Rn >= 32) rc += fmtprint(f, "<F%d>", t->Rn - 32); else if(t->Rn >= 0) rc += fmtprint(f, "<R%d>", t->Rn); return rc;} intirfmt(Fmt *f){ IR *i; int rc, j, fi; i = va_arg(f->args, IR *); if(i->op >= nelem(iropname) || iropname[i->op] == nil) rc = fmtprint(f, "???(%#x)", i->op); else rc = fmtstrcpy(f, iropname[i->op]); switch(OPTYPE(i->op)){ case OPNORM: if(i->a != nil) rc += fmtprint(f, " %J", i->a); if(i->b != nil && i->a != nil) rc += fmtrune(f, ','); if(i->b != nil) rc += fmtprint(f, " %J", i->b); if((i->a != nil || i->b != nil) && i->r != nil) rc += fmtrune(f, ','); if(i->r != nil) rc += fmtprint(f, " %J", i->r); return rc; case OPBRANCH: rc += fmtprint(f, " %p", i->targ); return rc; case OPPHI: fi = 0; if(i->r != nil){ rc += fmtprint(f, " %J", i->r); fi++; } for(j = 0; j < i->φ.n; j++){ if(fi++ != 0) rc += fmtrune(f, ','); rc += fmtprint(f, " %J", i->φ.a[j]); } return rc; default: rc += fmtprint(f, " ???(%#x)", OPTYPE(i->op)); return rc; }} ASTNode*node(int type, ...){ va_list va; ASTNode *n, *l, *m; int i; n = emalloc(sizeof(*n)); n->t = type; n->Line = curline; va_start(va, type); switch(type){ case ASTCLONG: n->lval = va_arg(va, vlong); break; case ASTSYM: case ASTGOTO: case ASTLABEL: n->sym = va_arg(va, Symbol *); break; case ASTBIN: case ASTASS: n->op = va_arg(va, int); case ASTARRAY: case ASTCOMMA: n->n1 = va_arg(va, ASTNode *); n->n2 = va_arg(va, ASTNode *); break; case ASTMEMB: n->mb.n = va_arg(va, ASTNode *); n->mb.name = va_arg(va, char *); break; case ASTUN: case ASTINC: n->op = va_arg(va, int); n->n1 = va_arg(va, ASTNode *); break; case ASTFUNCTYPE: n->name = va_arg(va, ASTNode *); n->memb = va_arg(va, Member *); n->nmemb = va_arg(va, int); break; case ASTDEREF: case ASTRETURN: case ASTADDROF: n->n = va_arg(va, ASTNode *); break; case ASTBLOCK: n->last = &n->first; break; case ASTTERN: case ASTIF: n->cond = va_arg(va, ASTNode *); n->block = va_arg(va, ASTNode *); n->elsebl = va_arg(va, ASTNode *); break; case ASTWHILE: case ASTDOWHILE: n->cond = va_arg(va, ASTNode *); n->block = va_arg(va, ASTNode *); n->elsebl = nil; break; case ASTFOR: n->forl.once = va_arg(va, ASTNode*); n->forl.cond = va_arg(va, ASTNode*); n->forl.iter = va_arg(va, ASTNode*); n->forl.block = va_arg(va, ASTNode*); break; case ASTCAST: n->cast.n = va_arg(va, ASTNode *); n->cast.t = va_arg(va, Type *); break; case ASTBREAK: case ASTCONTINUE: break; case ASTCALL: n->func.n = va_arg(va, ASTNode *); l = va_arg(va, ASTNode *); for(i = 0, m = l; m != nil; i++) m = m->next; n->func.argn = i; n->func.args = emalloc(sizeof(ASTNode *) * i); for(i = 0, m = l; m != nil; i++){ l = m->next;Lines 1–500 of 1322. Load more
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" SymTab global; SymTab *scope = &global; int curlevel; Type types[NTYPE] = { {TXXX, 0, 0, 0}, {TUCHAR, 0, 1, 0}, {TCHAR, 1, 1, 0}, {TUSHORT, 0, 2, 2}, {TSHORT, 1, 2, 2}, {TUINT, 0, 4, 4}, {TINT, 1, 4, 4}, {TUVLONG, 0, 8, 4}, {TVLONG, 1, 8, 4}, {TFLOAT, 1, 4, 4}, {TDOUBLE, 1, 8, 4}, {TVOID, 0}, }; Type *typelist; static char *astname[] = { "ASTCLONG", "ASTBIN", "ASTASS", "ASTTERN", "ASTDEREF", "ASTADDROF", "ASTUN", "ASTINC", "ASTIF", "ASTSYM", "ASTARRAY", "ASTFUNCTYPE", "ASTCAST", "ASTCOMMA", "ASTBLOCK", "ASTWHILE", "ASTDOWHILE", "ASTFOR", "ASTBREAK", "ASTCONTINUE", "ASTRETURN", "ASTLABEL", "ASTGOTO", "ASTMEMB", "ASTCALL", }; static char *copname[] = { [OPMOV] "MOV", [OPUPLUS] "unary +", [OPNEG] "unary -", [OPISZ] "!", [OPADD] "+", [OPSUB] "-", [OPMUL] "*", [OPDIV] "/", [OPMOD] "%", [OPEQ] "==", [OPNE] "!=", [OPLT] "<", [OPLE] "<=", [OPGT] ">", [OPGE] ">=", [OPB] "unsigned <", [OPBE] "unsigned <=", [OPA] "unsigned >", [OPAE] "unsigned >=", [OPAND] "&", [OPOR] "|", [OPXOR] "^", [OPLSH] "<<", [OPRSH] "unsigned >>", [OPASR] "signed >>", [OPCOM] "~", [OPLOR] "||", [OPLAND] "&&", }; static char *iropname[] = { [OPMOV] "MOV", [OPNEG] "NEG", [OPISZ] "ISZ", [OPTST] "TST", [OPLD] "LD", [OPST] "ST", [OPLDB] "LDB", [OPLDSB] "LDSB", [OPSTB] "STB", [OPLDH] "LDH", [OPLDSH] "LDSH", [OPSTH] "STH", [OPLDD] "LDD", [OPSTD] "STD", [OPADD] "ADD", [OPSUB] "SUB", [OPRSB] "RSB", [OPMUL] "MUL", [OPDIV] "DIV", [OPMOD] "MOD", [OPCMP] "CMP", [OPEQ] "BEQ", [OPNE] "BNE", [OPLT] "BLT", [OPLE] "BLE", [OPGT] "BGT", [OPGE] "BGE", [OPB] "BB", [OPBE] "BBE", [OPA] "BA", [OPAE] "BAE", [OPAND] "AND", [OPOR] "OR", [OPXOR] "XOR", [OPLSH] "LSH", [OPRSH] "RSH", [OPASR] "ASR", [OPCOM] "COM", [OPSXTB] "SXTB", [OPSXTH] "SXTH", [OPSXTW] "SXTW", [OPZXTB] "ZXTB", [OPZXTH] "ZXTH", [OPZXTW] "ZXTW", [OPPHI] "φ", [OPCALL] "CALL", [OPFADD] "FADD", [OPFSUB] "FSUB", [OPFMUL] "FMUL", [OPFDIV] "FDIV", [OPFCMP] "FCMP", }; static char *typename[] = { "XXX", "uchar", "char", "ushort", "short", "uint", "int", "uvlong", "vlong", "float", "double", "void", }; static uint hash(char *s) { uint c; c = 0; while(*s != 0) c += *s++; return c; } static Symbol * makesym(char *n) { SymTab *st; Symbol *s; int h; if(curlevel != scope->level){ st = emalloc(sizeof(*st)); st->up = scope; scope = st; } s = emalloc(sizeof(*s)); s->num = -1; s->name = strdup(n); h = hash(n) % SYMHASH; s->next = scope->sym[h]; s->Line = curline; s->level = curlevel; scope->sym[h] = s; return s; } Symbol * getsym(char *n) { SymTab *st; Symbol *s; int h; h = hash(n) % SYMHASH; for(st = scope; st != nil; st = st->up) for(s = st->sym[h]; s != nil; s = s->next) if(strcmp(s->name, n) == 0) return s; return makesym(n); } void checksym(Symbol *s) { if(s->t == nil){ error(nil, "'%s' undeclared", s->name); s->t = &types[TINT]; } } static void funcparams(void) { Member *m, *me; Symbol *s, **sp; me = curfunc->type->memb + curfunc->type->nmemb; curfunc->arg = sp = emalloc(sizeof(Member *) * curfunc->type->nmemb); for(m = curfunc->type->memb; m < me; m++, sp++) if(m->name != nil){ s = makesym(m->name); s->t = m->type; s->off = m->off; *sp = s; } } void levelch(int n) { SymTab *st, *stn; curlevel += n; if(curlevel == 1 && n > 0) funcparams(); assert(curlevel >= 0); if(n < 0){ st = scope; while(st->level > curlevel){ stn = st->up; free(st); st = stn; assert(st != nil); } scope = st; } } int opfmt(Fmt *f) { int t; t = va_arg(f->args, int); if(t >= nelem(copname) || copname[t] == nil) return fmtprint(f, "??? (%d)", t); return fmtstrcpy(f, copname[t]); } int astfmt(Fmt *f) { int t; t = va_arg(f->args, int); if(t >= nelem(astname)) return fmtprint(f, "??? (%d)", t); return fmtstrcpy(f, astname[t]); } int typefmtrec(Fmt *f, Type *t) { int rc, i; if(t == nil) return fmtstrcpy(f, "??? (nil)"); switch(t->t){ case TIND: rc = typefmtrec(f, t->link); rc += fmtstrcpy(f, "*"); return rc; case TFUNC: rc = typefmtrec(f, t->link); rc += fmtstrcpy(f, "()("); if(t->nmemb != 0) for(i = 0;;){ rc += typefmtrec(f, t->memb[i].type); if(++i != t->nmemb) rc += fmtstrcpy(f, ", "); else break; } rc += fmtstrcpy(f, ")"); return rc; case TSTRUCT: if(t->tag != nil) rc = fmtprint(f, "struct %s", t->tag); else rc = fmtprint(f, "struct %p", t); return rc; case TUNION: if(t->tag != nil) rc = fmtprint(f, "union %s", t->tag); else rc = fmtprint(f, "union %p", t); return rc; } if(t->t >= nelem(typename)) return fmtprint(f, "??? (%d)", t->t); return fmtstrcpy(f, typename[t->t]); } int typefmt(Fmt *f) { return typefmtrec(f, va_arg(f->args, Type *)); } int irtargfmt(Fmt *f) { Targ *t; int rc; t = va_arg(f->args, Targ *); if(t == nil) return fmtstrcpy(f, "nil"); switch(t->t){ case TARGSYM: rc = fmtstrcpy(f, t->sym->name); break; case TARGSSA: rc = fmtprint(f, "%s:%d", t->sym->name, t->n); break; case TARGTEMP: rc = fmtprint(f, "t%d", t->tn); if(t->type != nil) switch(t->type->t){ case TFLOAT: rc += fmtrune(f, 'f'); break; case TDOUBLE: rc += fmtrune(f, 'd'); break; } break; case TARGCONST: rc = fmtprint(f, "$%#ux", t->lval); break; case TARGRETV: rc = fmtprint(f, t->type == &types[TFLOAT] || t->type == &types[TDOUBLE] ? "F0" : "R0"); break; case TARGFP: rc = fmtprint(f, "FP(%d)", t->off); break; case TARGARG: rc =fmtprint(f, "ARG(%d)", t->off); break; case TARGIND: rc = fmtprint(f, "(%J)", t->link); break; case TARGADDR: rc = fmtprint(f, "&%s%+d", t->sym->name, t->n); break; case TARGSH: rc = fmtprint(f, "%s(%J, %J)", iropname[t->op], t->a, t->b); break; default: return fmtprint(f, "???(%d)", t->t); } if(t->Rn >= 32) rc += fmtprint(f, "<F%d>", t->Rn - 32); else if(t->Rn >= 0) rc += fmtprint(f, "<R%d>", t->Rn); return rc; } int irfmt(Fmt *f) { IR *i; int rc, j, fi; i = va_arg(f->args, IR *); if(i->op >= nelem(iropname) || iropname[i->op] == nil) rc = fmtprint(f, "???(%#x)", i->op); else rc = fmtstrcpy(f, iropname[i->op]); switch(OPTYPE(i->op)){ case OPNORM: if(i->a != nil) rc += fmtprint(f, " %J", i->a); if(i->b != nil && i->a != nil) rc += fmtrune(f, ','); if(i->b != nil) rc += fmtprint(f, " %J", i->b); if((i->a != nil || i->b != nil) && i->r != nil) rc += fmtrune(f, ','); if(i->r != nil) rc += fmtprint(f, " %J", i->r); return rc; case OPBRANCH: rc += fmtprint(f, " %p", i->targ); return rc; case OPPHI: fi = 0; if(i->r != nil){ rc += fmtprint(f, " %J", i->r); fi++; } for(j = 0; j < i->φ.n; j++){ if(fi++ != 0) rc += fmtrune(f, ','); rc += fmtprint(f, " %J", i->φ.a[j]); } return rc; default: rc += fmtprint(f, " ???(%#x)", OPTYPE(i->op)); return rc; } } ASTNode* node(int type, ...) { va_list va; ASTNode *n, *l, *m; int i; n = emalloc(sizeof(*n)); n->t = type; n->Line = curline; va_start(va, type); switch(type){ case ASTCLONG: n->lval = va_arg(va, vlong); break; case ASTSYM: case ASTGOTO: case ASTLABEL: n->sym = va_arg(va, Symbol *); break; case ASTBIN: case ASTASS: n->op = va_arg(va, int); case ASTARRAY: case ASTCOMMA: n->n1 = va_arg(va, ASTNode *); n->n2 = va_arg(va, ASTNode *); break; case ASTMEMB: n->mb.n = va_arg(va, ASTNode *); n->mb.name = va_arg(va, char *); break; case ASTUN: case ASTINC: n->op = va_arg(va, int); n->n1 = va_arg(va, ASTNode *); break; case ASTFUNCTYPE: n->name = va_arg(va, ASTNode *); n->memb = va_arg(va, Member *); n->nmemb = va_arg(va, int); break; case ASTDEREF: case ASTRETURN: case ASTADDROF: n->n = va_arg(va, ASTNode *); break; case ASTBLOCK: n->last = &n->first; break; case ASTTERN: case ASTIF: n->cond = va_arg(va, ASTNode *); n->block = va_arg(va, ASTNode *); n->elsebl = va_arg(va, ASTNode *); break; case ASTWHILE: case ASTDOWHILE: n->cond = va_arg(va, ASTNode *); n->block = va_arg(va, ASTNode *); n->elsebl = nil; break; case ASTFOR: n->forl.once = va_arg(va, ASTNode*); n->forl.cond = va_arg(va, ASTNode*); n->forl.iter = va_arg(va, ASTNode*); n->forl.block = va_arg(va, ASTNode*); break; case ASTCAST: n->cast.n = va_arg(va, ASTNode *); n->cast.t = va_arg(va, Type *); break; case ASTBREAK: case ASTCONTINUE: break; case ASTCALL: n->func.n = va_arg(va, ASTNode *); l = va_arg(va, ASTNode *); for(i = 0, m = l; m != nil; i++) m = m->next; n->func.argn = i; n->func.args = emalloc(sizeof(ASTNode *) * i); for(i = 0, m = l; m != nil; i++){ l = m->next;