#include "limbo.h" static Inst **breaks;static Inst **conts;static Decl **labels;static Node **bcscps;static int labdep;static Inst nocont; static int scp;static Node *scps[MaxScope]; static int trcom(Node*, Node*, int); static voidpushscp(Node *n){ if (scp >= MaxScope) fatal("scope too deep"); scps[scp++] = n;} static voidpopscp(void){ scp--;} static Node *curscp(void){ if (scp == 0) return nil; return scps[scp-1];} static voidzeroscopes(Node *stop){ int i; Node *cs; for (i = scp-1; i >= 0; i--) { cs = scps[i]; if (cs == stop) break; zcom(cs->left, nil); }} static voidzeroallscopes(Node *n, Node **nn){ if(n == nil) return; for(; n != nil; n = n->right){ switch(n->op){ case Oscope: zeroallscopes(n->right, nn); zcom(n->left, nn); return; case Olabel: case Odo: zeroallscopes(n->right, nn); return; case Oif: case Ofor: zeroallscopes(n->right->left, nn); zeroallscopes(n->right->right, nn); return; case Oalt: case Ocase: case Opick: case Oexcept: for(n = n->right; n != nil; n = n->right) zeroallscopes(n->left->right, nn); return; case Oseq: zeroallscopes(n->left, nn); break; case Oexstmt: zeroallscopes(n->left, nn); zeroallscopes(n->right, nn); return; default: return; } }} static Except *excs; static voidinstallexc(Node *en, Inst *p1, Inst *p2, Node *zn){ int i, ne; Except *e; Case *c; Label *lab; e = allocmem(sizeof(Except)); e->p1 = p1; e->p2 = p2; e->c = en->ty->cse; e->d = en->left->decl; e->zn = zn; e->desc = nil; e->next = excs; excs = e; ne = 0; c = e->c; for(i = 0; i < c->nlab; i++){ lab = &c->labs[i]; if(lab->start->ty->kind == Texception) ne++; } e->ne = ne;} static intinlist(Decl *d, Decl *dd){ for( ; dd != nil; dd = dd->next) if(d == dd) return 1; return 0;} static voidexcdesc(void){ ulong o, maxo; Except *e; Node *n; Decl *d, *dd, *nd; for(e = excs; e != nil; e = e->next){ if(e->zn != nil){ /* set up a decl list for gendesc */ dd = nil; maxo = 0; for(n = e->zn ; n != nil; n = n->right){ d = n->decl; d->locals = d->next; if(!inlist(d, dd)){ d->next = dd; dd = d; o = d->offset+d->ty->size; if(o > maxo) maxo = o; } } e->desc = gendesc(e->d, align(maxo, MaxAlign), dd); for(d = dd; d != nil; d = nd){ nd = d->next; d->next = d->locals; d->locals = nil; } e->zn = nil; } }} static Except*reve(Except *e){ Except *l, *n; l = nil; for( ; e != nil; e = n){ n = e->next; e->next = l; l = e; } return l;} static intckinline0(Node *n, Decl *d){ Decl *dd; if(n == nil) return 1; if(n->op == Oname){ dd = n->decl; if(d == dd) return 0; if(dd->caninline == 1) return ckinline0(dd->init->right, d); return 1; } return ckinline0(n->left, d) && ckinline0(n->right, d);} static voidckinline(Decl *d){ d->caninline = ckinline0(d->init->right, d);} voidmodcom(Decl *entry){ Decl *globals, *m, *nils, *d, *ldts; long ninst, ndata, ndesc, nlink, offset, ldtoff; int ok, i, hints; Dlist *dl; if(errors) return; if(emitcode || emitstub || emittab != nil){ emit(curscope()); popscope(); return; } /* * scom introduces global variables for case statements * and unaddressable constants, so it must be done before * popping the global scope */ nlabel = 0; maxstack = MaxTemp; genstart(); for(i = 0; i < nfns; i++) if(fns[i]->caninline == 1) ckinline(fns[i]); ok = 0; for(i = 0; i < nfns; i++){ d = fns[i];if(debug['v']) print("fncom: %s %d %p\n", d->sym->name, d->refs, d); if(d->refs > 1 && !(d->caninline == 1 && local(d) && d->iface == nil)){ fns[ok++] = d; fncom(d); } } nfns = ok; if(blocks != -1) fatal("blocks not nested correctly"); firstinst = firstinst->next; if(errors) return; globals = popscope(); checkrefs(globals); if(errors) return; globals = vars(globals); moddataref(); nils = popscope(); m = nil; for(d = nils; d != nil; d = d->next){ if(debug['n']) print("nil '%s' ref %d\n", d->sym->name, d->refs); if(d->refs && m == nil) m = dupdecl(d); d->offset = 0; } globals = appdecls(m, globals); globals = namesort(globals); globals = modglobals(impdecls->d, globals); vcom(globals); narrowmods(); ldts = nil; if(LDT) globals = resolveldts(globals, &ldts); offset = idoffsets(globals, 0, IBY2WD); if(LDT) ldtoff = idindices(ldts); /* ldtoff = idoffsets(ldts, 0, IBY2WD); */ for(d = nils; d != nil; d = d->next){ if(debug['n']) print("nil '%s' ref %d\n", d->sym->name, d->refs); if(d->refs) d->offset = m->offset; } if(debug['g']){ print("globals:\n"); printdecls(globals); } ndata = 0; for(d = globals; d != nil; d = d->next) ndata++; ndesc = resolvedesc(impdecls->d, offset, globals); ninst = resolvepcs(firstinst); modresolve(); if(impdecls->next != nil) for(dl = impdecls; dl != nil; dl = dl->next) resolvemod(dl->d); nlink = resolvemod(impdecl); maxstack *= 10; if(fixss != 0) maxstack = fixss; if(debug['s']) print("%ld instructions\n%ld data elements\n%ld type descriptors\n%ld functions exported\n%ld stack size\n", ninst, ndata, ndesc, nlink, maxstack); excs = reve(excs); if(gendis){ discon(XMAGIC); hints = 0; if(mustcompile) hints |= MUSTCOMPILE; if(dontcompile) hints |= DONTCOMPILE; if(LDT) hints |= HASLDT; if(excs != nil) hints |= HASEXCEPT; discon(hints); /* runtime hints */ discon(maxstack); /* minimum stack extent size */ discon(ninst); discon(offset); discon(ndesc); discon(nlink); disentry(entry); disinst(firstinst); disdesc(descriptors); disvar(offset, globals); dismod(impdecl); if(LDT) disldt(ldtoff, ldts); if(excs != nil) disexc(excs); dispath(); }else{ asminst(firstinst); asmentry(entry); asmdesc(descriptors); asmvar(offset, globals); asmmod(impdecl); if(LDT) asmldt(ldtoff, ldts); if(excs != nil) asmexc(excs); asmpath(); } if(bsym != nil){ sblmod(impdecl); sblfiles(); sblinst(firstinst, ninst); sblty(adts, nadts); sblfn(fns, nfns); sblvar(globals); } firstinst = nil; lastinst = nil; excs = nil;} voidfncom(Decl *decl){ Src src; Node *n; Decl *loc, *last; Inst *in; int valued; curfn = decl; if(ispoly(decl)) addfnptrs(decl, 1); /* * pick up the function body and compile it * this code tries to clean up the parse nodes as fast as possible * function is Ofunc(name, body) */ decl->pc = nextinst(); tinit(); labdep = 0; scp = 0; breaks = allocmem(maxlabdep * sizeof breaks[0]); conts = allocmem(maxlabdep * sizeof conts[0]); labels = allocmem(maxlabdep * sizeof labels[0]); bcscps = allocmem(maxlabdep * sizeof bcscps[0]); n = decl->init; if(decl->caninline == 1) decl->init = dupn(0, nil, n); else decl->init = n->left; src = n->right->src; src.start.line = src.stop.line; src.start.pos = src.stop.pos - 1; for(n = n->right; n != nil; n = n->right){ if(n->op != Oseq){ if(n->op == Ocall && trcom(n, nil, 1)) break; scom(n); break; } if(n->left->op == Ocall && trcom(n->left, n->right, 1)){ n = n->right; if(n == nil || n->op != Oseq) break; } else scom(n->left); } pushblock(); valued = decl->ty->tof != tnone; in = genrawop(&src, valued? IRAISE: IRET, nil, nil, nil); popblock(); reach(decl->pc); if(valued && in->reach) error(src.start, "no return at end of function %D", decl); /* decl->endpc = lastinst; */ if(labdep != 0) fatal("unbalanced label stack"); free(breaks); free(conts); free(labels); free(bcscps); loc = declsort(appdecls(vars(decl->locals), tdecls())); decl->offset = idoffsets(loc, decl->offset, MaxAlign); for(last = decl->ty->ids; last != nil && last->next != nil; last = last->next) ; if(last != nil) last->next = loc; else decl->ty->ids = loc; if(debug['f']){ print("fn: %s\n", decl->sym->name); printdecls(decl->ty->ids); } decl->desc = gendesc(decl, decl->offset, decl->ty->ids); decl->locals = loc; excdesc(); if(decl->offset > maxstack) maxstack = decl->offset; if(optims) optim(decl->pc, decl); if(last != nil) last->next = nil; else decl->ty->ids = nil;} /* * statement compiler */voidscom(Node *n){ Inst *p, *pp, *p1, *p2, *p3; Node tret, *left, *zn; for(; n != nil; n = n->right){ switch(n->op){ case Ocondecl: case Otypedecl: case Ovardecl: case Oimport: case Oexdecl: return; case Ovardecli: break; case Oscope: pushscp(n); scom(n->right); popscp(); zcom(n->left, nil); return; case Olabel: scom(n->right); return; case Oif: pushblock(); left = simplify(n->left); if(left->op == Oconst && left->ty == tint){ if(left->val != 0) scom(n->right->left); else scom(n->right->right); popblock(); return; } sumark(left); pushblock(); p = bcom(left, 1, nil); tfreenow(); popblock(); scom(n->right->left); if(n->right->right != nil){Lines 1–500 of 1495. Load more
#include "limbo.h" static Inst **breaks; static Inst **conts; static Decl **labels; static Node **bcscps; static int labdep; static Inst nocont; static int scp; static Node *scps[MaxScope]; static int trcom(Node*, Node*, int); static void pushscp(Node *n) { if (scp >= MaxScope) fatal("scope too deep"); scps[scp++] = n; } static void popscp(void) { scp--; } static Node * curscp(void) { if (scp == 0) return nil; return scps[scp-1]; } static void zeroscopes(Node *stop) { int i; Node *cs; for (i = scp-1; i >= 0; i--) { cs = scps[i]; if (cs == stop) break; zcom(cs->left, nil); } } static void zeroallscopes(Node *n, Node **nn) { if(n == nil) return; for(; n != nil; n = n->right){ switch(n->op){ case Oscope: zeroallscopes(n->right, nn); zcom(n->left, nn); return; case Olabel: case Odo: zeroallscopes(n->right, nn); return; case Oif: case Ofor: zeroallscopes(n->right->left, nn); zeroallscopes(n->right->right, nn); return; case Oalt: case Ocase: case Opick: case Oexcept: for(n = n->right; n != nil; n = n->right) zeroallscopes(n->left->right, nn); return; case Oseq: zeroallscopes(n->left, nn); break; case Oexstmt: zeroallscopes(n->left, nn); zeroallscopes(n->right, nn); return; default: return; } } } static Except *excs; static void installexc(Node *en, Inst *p1, Inst *p2, Node *zn) { int i, ne; Except *e; Case *c; Label *lab; e = allocmem(sizeof(Except)); e->p1 = p1; e->p2 = p2; e->c = en->ty->cse; e->d = en->left->decl; e->zn = zn; e->desc = nil; e->next = excs; excs = e; ne = 0; c = e->c; for(i = 0; i < c->nlab; i++){ lab = &c->labs[i]; if(lab->start->ty->kind == Texception) ne++; } e->ne = ne; } static int inlist(Decl *d, Decl *dd) { for( ; dd != nil; dd = dd->next) if(d == dd) return 1; return 0; } static void excdesc(void) { ulong o, maxo; Except *e; Node *n; Decl *d, *dd, *nd; for(e = excs; e != nil; e = e->next){ if(e->zn != nil){ /* set up a decl list for gendesc */ dd = nil; maxo = 0; for(n = e->zn ; n != nil; n = n->right){ d = n->decl; d->locals = d->next; if(!inlist(d, dd)){ d->next = dd; dd = d; o = d->offset+d->ty->size; if(o > maxo) maxo = o; } } e->desc = gendesc(e->d, align(maxo, MaxAlign), dd); for(d = dd; d != nil; d = nd){ nd = d->next; d->next = d->locals; d->locals = nil; } e->zn = nil; } } } static Except* reve(Except *e) { Except *l, *n; l = nil; for( ; e != nil; e = n){ n = e->next; e->next = l; l = e; } return l; } static int ckinline0(Node *n, Decl *d) { Decl *dd; if(n == nil) return 1; if(n->op == Oname){ dd = n->decl; if(d == dd) return 0; if(dd->caninline == 1) return ckinline0(dd->init->right, d); return 1; } return ckinline0(n->left, d) && ckinline0(n->right, d); } static void ckinline(Decl *d) { d->caninline = ckinline0(d->init->right, d); } void modcom(Decl *entry) { Decl *globals, *m, *nils, *d, *ldts; long ninst, ndata, ndesc, nlink, offset, ldtoff; int ok, i, hints; Dlist *dl; if(errors) return; if(emitcode || emitstub || emittab != nil){ emit(curscope()); popscope(); return; } /* * scom introduces global variables for case statements * and unaddressable constants, so it must be done before * popping the global scope */ nlabel = 0; maxstack = MaxTemp; genstart(); for(i = 0; i < nfns; i++) if(fns[i]->caninline == 1) ckinline(fns[i]); ok = 0; for(i = 0; i < nfns; i++){ d = fns[i]; if(debug['v']) print("fncom: %s %d %p\n", d->sym->name, d->refs, d); if(d->refs > 1 && !(d->caninline == 1 && local(d) && d->iface == nil)){ fns[ok++] = d; fncom(d); } } nfns = ok; if(blocks != -1) fatal("blocks not nested correctly"); firstinst = firstinst->next; if(errors) return; globals = popscope(); checkrefs(globals); if(errors) return; globals = vars(globals); moddataref(); nils = popscope(); m = nil; for(d = nils; d != nil; d = d->next){ if(debug['n']) print("nil '%s' ref %d\n", d->sym->name, d->refs); if(d->refs && m == nil) m = dupdecl(d); d->offset = 0; } globals = appdecls(m, globals); globals = namesort(globals); globals = modglobals(impdecls->d, globals); vcom(globals); narrowmods(); ldts = nil; if(LDT) globals = resolveldts(globals, &ldts); offset = idoffsets(globals, 0, IBY2WD); if(LDT) ldtoff = idindices(ldts); /* ldtoff = idoffsets(ldts, 0, IBY2WD); */ for(d = nils; d != nil; d = d->next){ if(debug['n']) print("nil '%s' ref %d\n", d->sym->name, d->refs); if(d->refs) d->offset = m->offset; } if(debug['g']){ print("globals:\n"); printdecls(globals); } ndata = 0; for(d = globals; d != nil; d = d->next) ndata++; ndesc = resolvedesc(impdecls->d, offset, globals); ninst = resolvepcs(firstinst); modresolve(); if(impdecls->next != nil) for(dl = impdecls; dl != nil; dl = dl->next) resolvemod(dl->d); nlink = resolvemod(impdecl); maxstack *= 10; if(fixss != 0) maxstack = fixss; if(debug['s']) print("%ld instructions\n%ld data elements\n%ld type descriptors\n%ld functions exported\n%ld stack size\n", ninst, ndata, ndesc, nlink, maxstack); excs = reve(excs); if(gendis){ discon(XMAGIC); hints = 0; if(mustcompile) hints |= MUSTCOMPILE; if(dontcompile) hints |= DONTCOMPILE; if(LDT) hints |= HASLDT; if(excs != nil) hints |= HASEXCEPT; discon(hints); /* runtime hints */ discon(maxstack); /* minimum stack extent size */ discon(ninst); discon(offset); discon(ndesc); discon(nlink); disentry(entry); disinst(firstinst); disdesc(descriptors); disvar(offset, globals); dismod(impdecl); if(LDT) disldt(ldtoff, ldts); if(excs != nil) disexc(excs); dispath(); }else{ asminst(firstinst); asmentry(entry); asmdesc(descriptors); asmvar(offset, globals); asmmod(impdecl); if(LDT) asmldt(ldtoff, ldts); if(excs != nil) asmexc(excs); asmpath(); } if(bsym != nil){ sblmod(impdecl); sblfiles(); sblinst(firstinst, ninst); sblty(adts, nadts); sblfn(fns, nfns); sblvar(globals); } firstinst = nil; lastinst = nil; excs = nil; } void fncom(Decl *decl) { Src src; Node *n; Decl *loc, *last; Inst *in; int valued; curfn = decl; if(ispoly(decl)) addfnptrs(decl, 1); /* * pick up the function body and compile it * this code tries to clean up the parse nodes as fast as possible * function is Ofunc(name, body) */ decl->pc = nextinst(); tinit(); labdep = 0; scp = 0; breaks = allocmem(maxlabdep * sizeof breaks[0]); conts = allocmem(maxlabdep * sizeof conts[0]); labels = allocmem(maxlabdep * sizeof labels[0]); bcscps = allocmem(maxlabdep * sizeof bcscps[0]); n = decl->init; if(decl->caninline == 1) decl->init = dupn(0, nil, n); else decl->init = n->left; src = n->right->src; src.start.line = src.stop.line; src.start.pos = src.stop.pos - 1; for(n = n->right; n != nil; n = n->right){ if(n->op != Oseq){ if(n->op == Ocall && trcom(n, nil, 1)) break; scom(n); break; } if(n->left->op == Ocall && trcom(n->left, n->right, 1)){ n = n->right; if(n == nil || n->op != Oseq) break; } else scom(n->left); } pushblock(); valued = decl->ty->tof != tnone; in = genrawop(&src, valued? IRAISE: IRET, nil, nil, nil); popblock(); reach(decl->pc); if(valued && in->reach) error(src.start, "no return at end of function %D", decl); /* decl->endpc = lastinst; */ if(labdep != 0) fatal("unbalanced label stack"); free(breaks); free(conts); free(labels); free(bcscps); loc = declsort(appdecls(vars(decl->locals), tdecls())); decl->offset = idoffsets(loc, decl->offset, MaxAlign); for(last = decl->ty->ids; last != nil && last->next != nil; last = last->next) ; if(last != nil) last->next = loc; else decl->ty->ids = loc; if(debug['f']){ print("fn: %s\n", decl->sym->name); printdecls(decl->ty->ids); } decl->desc = gendesc(decl, decl->offset, decl->ty->ids); decl->locals = loc; excdesc(); if(decl->offset > maxstack) maxstack = decl->offset; if(optims) optim(decl->pc, decl); if(last != nil) last->next = nil; else decl->ty->ids = nil; } /* * statement compiler */ void scom(Node *n) { Inst *p, *pp, *p1, *p2, *p3; Node tret, *left, *zn; for(; n != nil; n = n->right){ switch(n->op){ case Ocondecl: case Otypedecl: case Ovardecl: case Oimport: case Oexdecl: return; case Ovardecli: break; case Oscope: pushscp(n); scom(n->right); popscp(); zcom(n->left, nil); return; case Olabel: scom(n->right); return; case Oif: pushblock(); left = simplify(n->left); if(left->op == Oconst && left->ty == tint){ if(left->val != 0) scom(n->right->left); else scom(n->right->right); popblock(); return; } sumark(left); pushblock(); p = bcom(left, 1, nil); tfreenow(); popblock(); scom(n->right->left); if(n->right->right != nil){