1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366 |
- #include "limbo.h"
- char *storename[Dend]=
- {
- /* Dtype */ "type",
- /* Dfn */ "function",
- /* Dglobal */ "global",
- /* Darg */ "argument",
- /* Dlocal */ "local",
- /* Dconst */ "con",
- /* Dfield */ "field",
- /* Dtag */ "pick tag",
- /* Dimport */ "import",
- /* Dunbound */ "unbound",
- /* Dundef */ "undefined",
- /* Dwundef */ "undefined",
- };
- char *storeart[Dend] =
- {
- /* Dtype */ "a ",
- /* Dfn */ "a ",
- /* Dglobal */ "a ",
- /* Darg */ "an ",
- /* Dlocal */ "a ",
- /* Dconst */ "a ",
- /* Dfield */ "a ",
- /* Dtag */ "a",
- /* Dimport */ "an ",
- /* Dunbound */ "",
- /* Dundef */ "",
- /* Dwundef */ "",
- };
- int storespace[Dend] =
- {
- /* Dtype */ 0,
- /* Dfn */ 0,
- /* Dglobal */ 1,
- /* Darg */ 1,
- /* Dlocal */ 1,
- /* Dconst */ 0,
- /* Dfield */ 1,
- /* Dtag */ 0,
- /* Dimport */ 0,
- /* Dunbound */ 0,
- /* Dundef */ 0,
- /* Dwundef */ 0,
- };
- static Decl *scopes[MaxScope];
- static Decl *tails[MaxScope];
- static Node *scopenode[MaxScope];
- static uchar scopekind[MaxScope];
- static void freeloc(Decl*);
- void
- popscopes(void)
- {
- Decl *d;
- Dlist *id;
- /*
- * clear out any decls left in syms
- */
- while(scope >= ScopeBuiltin){
- for(d = scopes[scope--]; d != nil; d = d->next){
- if(d->sym != nil){
- d->sym->decl = d->old;
- d->old = nil;
- }
- }
- }
- for(id = impdecls; id != nil; id = id->next){
- for(d = id->d->ty->ids; d != nil; d = d->next){
- d->sym->decl = nil;
- d->old = nil;
- }
- }
- impdecls = nil;
- scope = ScopeBuiltin;
- scopes[ScopeBuiltin] = nil;
- tails[ScopeBuiltin] = nil;
- }
- void
- declstart(void)
- {
- Decl *d;
- iota = mkids(&nosrc, enter("iota", 0), tint, nil);
- iota->init = mkconst(&nosrc, 0);
- scope = ScopeNils;
- scopes[ScopeNils] = nil;
- tails[ScopeNils] = nil;
- nildecl = mkdecl(&nosrc, Dglobal, tany);
- nildecl->sym = enter("nil", 0);
- installids(Dglobal, nildecl);
- d = mkdecl(&nosrc, Dglobal, tstring);
- d->sym = enter("", 0);
- installids(Dglobal, d);
- scope = ScopeGlobal;
- scopes[ScopeGlobal] = nil;
- tails[ScopeGlobal] = nil;
- }
- void
- redecl(Decl *d)
- {
- Decl *old;
- old = d->sym->decl;
- if(old->store == Dwundef)
- return;
- error(d->src.start, "redeclaration of %K, previously declared as %k on line %L",
- d, old, old->src.start);
- }
- void
- checkrefs(Decl *d)
- {
- Decl *id, *m;
- long refs;
- for(; d != nil; d = d->next){
- if(d->das)
- d->refs--;
- switch(d->store){
- case Dtype:
- refs = d->refs;
- if(d->ty->kind == Tadt){
- for(id = d->ty->ids; id != nil; id = id->next){
- d->refs += id->refs;
- if(id->store != Dfn)
- continue;
- if(id->init == nil && id->link == nil && d->importid == nil)
- error(d->src.start, "function %s.%s not defined", d->sym->name, id->sym->name);
- if(superwarn && !id->refs && d->importid == nil)
- warn(d->src.start, "function %s.%s not referenced", d->sym->name, id->sym->name);
- }
- }
- if(d->ty->kind == Tmodule){
- for(id = d->ty->ids; id != nil; id = id->next){
- refs += id->refs;
- if(id->iface != nil)
- id->iface->refs += id->refs;
- if(id->store == Dtype){
- for(m = id->ty->ids; m != nil; m = m->next){
- refs += m->refs;
- if(m->iface != nil)
- m->iface->refs += m->refs;
- }
- }
- }
- d->refs = refs;
- }
- if(superwarn && !refs && d->importid == nil)
- warn(d->src.start, "%K not referenced", d);
- break;
- case Dglobal:
- if(!superwarn)
- break;
- case Dlocal:
- case Darg:
- if(!d->refs && d->sym != nil
- && d->sym->name != nil && d->sym->name[0] != '.')
- warn(d->src.start, "%K not referenced", d);
- break;
- case Dconst:
- if(superwarn && !d->refs && d->sym != nil)
- warn(d->src.start, "%K not referenced", d);
- if(d->ty == tstring && d->init != nil)
- d->init->decl->refs += d->refs;
- break;
- case Dfn:
- if(d->init == nil && d->importid == nil)
- error(d->src.start, "%K not defined", d);
- if(superwarn && !d->refs)
- warn(d->src.start, "%K not referenced", d);
- break;
- case Dimport:
- if(superwarn && !d->refs)
- warn(d->src.start, "%K not referenced", d);
- break;
- }
- if(d->das)
- d->refs++;
- }
- }
- Node*
- vardecl(Decl *ids, Type *t)
- {
- Node *n;
- n = mkn(Ovardecl, mkn(Oseq, nil, nil), nil);
- n->decl = ids;
- n->ty = t;
- return n;
- }
- void
- vardecled(Node *n)
- {
- Decl *ids, *last;
- Type *t;
- int store;
- store = Dlocal;
- if(scope == ScopeGlobal)
- store = Dglobal;
- if(n->ty->kind == Texception && n->ty->cons){
- store = Dconst;
- fatal("Texception in vardecled");
- }
- ids = n->decl;
- installids(store, ids);
- t = n->ty;
- for(last = ids; ids != nil; ids = ids->next){
- ids->ty = t;
- last = ids;
- }
- n->left->decl = last;
- }
- Node*
- condecl(Decl *ids, Node *init)
- {
- Node *n;
- n = mkn(Ocondecl, mkn(Oseq, nil, nil), init);
- n->decl = ids;
- return n;
- }
- void
- condecled(Node *n)
- {
- Decl *ids, *last;
- ids = n->decl;
- installids(Dconst, ids);
- for(last = ids; ids != nil; ids = ids->next){
- ids->ty = tunknown;
- last = ids;
- }
- n->left->decl = last;
- }
- Node*
- exdecl(Decl *ids, Decl *tids)
- {
- Node *n;
- Type *t;
- t = mktype(&ids->src.start, &ids->src.stop, Texception, nil, tids);
- t->cons = 1;
- n = mkn(Oexdecl, mkn(Oseq, nil, nil), nil);
- n->decl = ids;
- n->ty = t;
- return n;
- }
- void
- exdecled(Node *n)
- {
- Decl *ids, *last;
- Type *t;
- ids = n->decl;
- installids(Dconst, ids);
- t = n->ty;
- for(last = ids; ids != nil; ids = ids->next){
- ids->ty = t;
- last = ids;
- }
- n->left->decl = last;
- }
- Node*
- importdecl(Node *m, Decl *ids)
- {
- Node *n;
- n = mkn(Oimport, mkn(Oseq, nil, nil), m);
- n->decl = ids;
- return n;
- }
- void
- importdecled(Node *n)
- {
- Decl *ids, *last;
- ids = n->decl;
- installids(Dimport, ids);
- for(last = ids; ids != nil; ids = ids->next){
- ids->ty = tunknown;
- last = ids;
- }
- n->left->decl = last;
- }
- Node*
- mkscope(Node *body)
- {
- Node *n;
- n = mkn(Oscope, nil, body);
- if(body != nil)
- n->src = body->src;
- return n;
- }
- Node*
- fndecl(Node *n, Type *t, Node *body)
- {
- n = mkbin(Ofunc, n, body);
- n->ty = t;
- return n;
- }
- void
- fndecled(Node *n)
- {
- Decl *d;
- Node *left;
- left = n->left;
- if(left->op == Oname){
- d = left->decl->sym->decl;
- if(d == nil || d->store == Dimport){
- d = mkids(&left->src, left->decl->sym, n->ty, nil);
- installids(Dfn, d);
- }
- left->decl = d;
- d->refs++;
- }
- if(left->op == Odot)
- pushscope(nil, Sother);
- if(n->ty->polys != nil){
- pushscope(nil, Sother);
- installids(Dtype, n->ty->polys);
- }
- pushscope(nil, Sother);
- installids(Darg, n->ty->ids);
- n->ty->ids = popscope();
- if(n->ty->val != nil)
- mergepolydecs(n->ty);
- if(n->ty->polys != nil)
- n->ty->polys = popscope();
- if(left->op == Odot)
- popscope();
- }
- /*
- * check the function declaration only
- * the body will be type checked later by fncheck
- */
- Decl *
- fnchk(Node *n)
- {
- int bad;
- Decl *d, *inadt, *adtp;
- Type *t;
- bad = 0;
- d = n->left->decl;
- if(n->left->op == Odot)
- d = n->left->right->decl;
- if(d == nil)
- fatal("decl() fnchk nil");
- n->left->decl = d;
- if(d->store == Dglobal || d->store == Dfield)
- d->store = Dfn;
- if(d->store != Dfn || d->init != nil){
- nerror(n, "redeclaration of function %D, previously declared as %k on line %L",
- d, d, d->src.start);
- if(d->store == Dfn && d->init != nil)
- bad = 1;
- }
- d->init = n;
- t = n->ty;
- inadt = d->dot;
- if(inadt != nil && (inadt->store != Dtype || inadt->ty->kind != Tadt))
- inadt = nil;
- if(n->left->op == Odot){
- pushscope(nil, Sother);
- adtp = outerpolys(n->left);
- if(adtp != nil)
- installids(Dtype, adtp);
- if(!polyequal(adtp, n->decl))
- nerror(n, "adt polymorphic type mismatch");
- n->decl = nil;
- }
- t = validtype(t, inadt);
- if(n->left->op == Odot)
- popscope();
- if(debug['d'])
- print("declare function %D ty %T newty %T\n", d, d->ty, t);
- t = usetype(t);
- if(!polyequal(d->ty->polys, t->polys))
- nerror(n, "function polymorphic type mismatch");
- if(!tcompat(d->ty, t, 0))
- nerror(n, "type mismatch: %D defined as %T declared as %T on line %L",
- d, t, d->ty, d->src.start);
- else if(!raisescompat(d->ty->u.eraises, t->u.eraises))
- nerror(n, "raises mismatch: %D", d);
- if(t->varargs != 0)
- nerror(n, "cannot define functions with a '*' argument, such as %D", d);
- t->u.eraises = d->ty->u.eraises;
- d->ty = t;
- d->offset = idoffsets(t->ids, MaxTemp, IBY2WD);
- d->src = n->src;
- d->locals = nil;
- n->ty = t;
- return bad ? nil: d;
- }
- Node*
- globalas(Node *dst, Node *v, int valok)
- {
- Node *tv;
- if(v == nil)
- return nil;
- if(v->op == Oas || v->op == Odas){
- v = globalas(v->left, v->right, valok);
- if(v == nil)
- return nil;
- }else if(valok && !initable(dst, v, 0))
- return nil;
- switch(dst->op){
- case Oname:
- if(dst->decl->init != nil)
- nerror(dst, "duplicate assignment to %V, previously assigned on line %L",
- dst, dst->decl->init->src.start);
- if(valok)
- dst->decl->init = v;
- return v;
- case Otuple:
- if(valok && v->op != Otuple)
- fatal("can't deal with %n in tuple case of globalas", v);
- tv = v->left;
- for(dst = dst->left; dst != nil; dst = dst->right){
- globalas(dst->left, tv->left, valok);
- if(valok)
- tv = tv->right;
- }
- return v;
- }
- fatal("can't deal with %n in globalas", dst);
- return nil;
- }
- int
- needsstore(Decl *d)
- {
- if(!d->refs)
- return 0;
- if(d->importid != nil)
- return 0;
- if(storespace[d->store])
- return 1;
- return 0;
- }
- /*
- * return the list of all referenced storage variables
- */
- Decl*
- vars(Decl *d)
- {
- Decl *v, *n;
- while(d != nil && !needsstore(d))
- d = d->next;
- for(v = d; v != nil; v = v->next){
- while(v->next != nil){
- n = v->next;
- if(needsstore(n))
- break;
- v->next = n->next;
- }
- }
- return d;
- }
- /*
- * declare variables from the left side of a := statement
- */
- static int
- recdasdecl(Node *n, int store, int *nid)
- {
- Decl *d, *old;
- int ok;
- switch(n->op){
- case Otuple:
- ok = 1;
- for(n = n->left; n != nil; n = n->right)
- ok &= recdasdecl(n->left, store, nid);
- return ok;
- case Oname:
- if(n->decl == nildecl){
- *nid = -1;
- return 1;
- }
- d = mkids(&n->src, n->decl->sym, nil, nil);
- installids(store, d);
- old = d->old;
- if(old != nil
- && old->store != Dfn
- && old->store != Dwundef
- && old->store != Dundef)
- warn(d->src.start, "redeclaration of %K, previously declared as %k on line %L",
- d, old, old->src.start);
- n->decl = d;
- d->refs++;
- d->das = 1;
- if(*nid >= 0)
- (*nid)++;
- return 1;
- }
- return 0;
- }
- static int
- recmark(Node *n, int nid)
- {
- switch(n->op){
- case Otuple:
- for(n = n->left; n != nil; n = n->right)
- nid = recmark(n->left, nid);
- break;
- case Oname:
- n->decl->nid = nid;
- nid = 0;
- break;
- }
- return nid;
- }
- int
- dasdecl(Node *n)
- {
- int store, ok, nid;
- nid = 0;
- if(scope == ScopeGlobal)
- store = Dglobal;
- else
- store = Dlocal;
- ok = recdasdecl(n, store, &nid);
- if(!ok)
- nerror(n, "illegal declaration expression %V", n);
- if(ok && store == Dlocal && nid > 1)
- recmark(n, nid);
- return ok;
- }
- /*
- * declare global variables in nested := expressions
- */
- void
- gdasdecl(Node *n)
- {
- if(n == nil)
- return;
- if(n->op == Odas){
- gdasdecl(n->right);
- dasdecl(n->left);
- }else{
- gdasdecl(n->left);
- gdasdecl(n->right);
- }
- }
- Decl*
- undefed(Src *src, Sym *s)
- {
- Decl *d;
- d = mkids(src, s, tnone, nil);
- error(src->start, "%s is not declared", s->name);
- installids(Dwundef, d);
- return d;
- }
- /*
- int
- inloop()
- {
- int i;
- for (i = scope; i > 0; i--)
- if (scopekind[i] == Sloop)
- return 1;
- return 0;
- }
- */
- int
- nested()
- {
- int i;
- for (i = scope; i > 0; i--)
- if (scopekind[i] == Sscope || scopekind[i] == Sloop)
- return 1;
- return 0;
- }
- void
- decltozero(Node *n)
- {
- Node *scp;
- if ((scp = scopenode[scope]) != nil) {
- /* can happen if we do
- * x[i] := ......
- * which is an error
- */
- if (n->right != nil && errors == 0)
- fatal("Ovardecl/Oname/Otuple has right field\n");
- n->right = scp->left;
- scp->left = n;
- }
- }
- void
- pushscope(Node *scp, int kind)
- {
- if(scope >= MaxScope)
- fatal("scope too deep");
- scope++;
- scopes[scope] = nil;
- tails[scope] = nil;
- scopenode[scope] = scp;
- scopekind[scope] = kind;
- }
- Decl*
- curscope(void)
- {
- return scopes[scope];
- }
- /*
- * revert to old declarations for each symbol in the currect scope.
- * remove the effects of any imported adt types
- * whenever the adt is imported from a module,
- * we record in the type's decl the module to use
- * when calling members. the process is reversed here.
- */
- Decl*
- popscope(void)
- {
- Decl *id;
- Type *t;
- if (debug['X'])
- print("popscope\n");
- for(id = scopes[scope]; id != nil; id = id->next){
- if(id->sym != nil){
- if (debug['X'])
- print("%s : %s %d\n", id->sym->name, kindname[id->ty->kind], id->init != nil ? id->init->op : 0);
- id->sym->decl = id->old;
- id->old = nil;
- }
- if(id->importid != nil)
- id->importid->refs += id->refs;
- t = id->ty;
- if(id->store == Dtype
- && t->decl != nil
- && t->decl->timport == id)
- t->decl->timport = id->timport;
- if(id->store == Dlocal)
- freeloc(id);
- }
- return scopes[scope--];
- }
- /*
- * make a new scope,
- * preinstalled with some previously installed identifiers
- * don't add the identifiers to the scope chain,
- * so they remain separate from any newly installed ids
- *
- * these routines assume no ids are imports
- */
- void
- repushids(Decl *ids)
- {
- Sym *s;
- if(scope >= MaxScope)
- fatal("scope too deep");
- scope++;
- scopes[scope] = nil;
- tails[scope] = nil;
- scopenode[scope] = nil;
- scopekind[scope] = Sother;
- for(; ids != nil; ids = ids->next){
- if(ids->scope != scope
- && (ids->dot == nil || !isimpmod(ids->dot->sym)
- || ids->scope != ScopeGlobal || scope != ScopeGlobal + 1))
- fatal("repushids scope mismatch");
- s = ids->sym;
- if(s != nil && ids->store != Dtag){
- if(s->decl != nil && s->decl->scope >= scope)
- ids->old = s->decl->old;
- else
- ids->old = s->decl;
- s->decl = ids;
- }
- }
- }
- /*
- * pop a scope which was started with repushids
- * return any newly installed ids
- */
- Decl*
- popids(Decl *ids)
- {
- for(; ids != nil; ids = ids->next){
- if(ids->sym != nil && ids->store != Dtag){
- ids->sym->decl = ids->old;
- ids->old = nil;
- }
- }
- return popscope();
- }
- void
- installids(int store, Decl *ids)
- {
- Decl *d, *last;
- Sym *s;
- last = nil;
- for(d = ids; d != nil; d = d->next){
- d->scope = scope;
- if(d->store == Dundef)
- d->store = store;
- s = d->sym;
- if(s != nil){
- if(s->decl != nil && s->decl->scope >= scope){
- redecl(d);
- d->old = s->decl->old;
- }else
- d->old = s->decl;
- s->decl = d;
- }
- last = d;
- }
- if(ids != nil){
- d = tails[scope];
- if(d == nil)
- scopes[scope] = ids;
- else
- d->next = ids;
- tails[scope] = last;
- }
- }
- Decl*
- lookup(Sym *sym)
- {
- int s;
- Decl *d;
- for(s = scope; s >= ScopeBuiltin; s--){
- for(d = scopes[s]; d != nil; d = d->next){
- if(d->sym == sym)
- return d;
- }
- }
- return nil;
- }
- Decl*
- mkids(Src *src, Sym *s, Type *t, Decl *next)
- {
- Decl *d;
- d = mkdecl(src, Dundef, t);
- d->next = next;
- d->sym = s;
- return d;
- }
- Decl*
- mkdecl(Src *src, int store, Type *t)
- {
- Decl *d;
- static Decl z;
- d = allocmem(sizeof *d);
- *d = z;
- d->src = *src;
- d->store = store;
- d->ty = t;
- d->nid = 1;
- return d;
- }
- Decl*
- dupdecl(Decl *old)
- {
- Decl *d;
- d = allocmem(sizeof *d);
- *d = *old;
- d->next = nil;
- return d;
- }
- Decl*
- dupdecls(Decl *old)
- {
- Decl *d, *nd, *first, *last;
- first = last = nil;
- for(d = old; d != nil; d = d->next){
- nd = dupdecl(d);
- if(first == nil)
- first = nd;
- else
- last->next = nd;
- last = nd;
- }
- return first;
- }
-
- Decl*
- appdecls(Decl *d, Decl *dd)
- {
- Decl *t;
- if(d == nil)
- return dd;
- for(t = d; t->next != nil; t = t->next)
- ;
- t->next = dd;
- return d;
- }
- Decl*
- revids(Decl *id)
- {
- Decl *d, *next;
- d = nil;
- for(; id != nil; id = next){
- next = id->next;
- id->next = d;
- d = id;
- }
- return d;
- }
- long
- idoffsets(Decl *id, long offset, int al)
- {
- int a, algn;
- Decl *d;
- algn = 1;
- for(; id != nil; id = id->next){
- if(storespace[id->store]){
- usedty(id->ty);
- if(id->store == Dlocal && id->link != nil){
- /* id->nid always 1 */
- id->offset = id->link->offset;
- continue;
- }
- a = id->ty->align;
- if(id->nid > 1){
- for(d = id->next; d != nil && d->nid == 0; d = d->next)
- if(d->ty->align > a)
- a = d->ty->align;
- algn = a;
- }
- offset = align(offset, a);
- id->offset = offset;
- offset += id->ty->size;
- if(id->nid == 0 && (id->next == nil || id->next->nid != 0))
- offset = align(offset, algn);
- }
- }
- return align(offset, al);
- }
- long
- idindices(Decl *id)
- {
- int i;
- i = 0;
- for(; id != nil; id = id->next){
- if(storespace[id->store]){
- usedty(id->ty);
- id->offset = i++;
- }
- }
- return i;
- }
- int
- declconv(Fmt *f)
- {
- Decl *d;
- char buf[4096], *s;
- d = va_arg(f->args, Decl*);
- if(d->sym == nil)
- s = "<nil>";
- else
- s = d->sym->name;
- seprint(buf, buf+sizeof(buf), "%s %s", storename[d->store], s);
- return fmtstrcpy(f, buf);
- }
- int
- storeconv(Fmt *f)
- {
- Decl *d;
- char buf[4096];
- d = va_arg(f->args, Decl*);
- seprint(buf, buf+sizeof(buf), "%s%s", storeart[d->store], storename[d->store]);
- return fmtstrcpy(f, buf);
- }
- int
- dotconv(Fmt *f)
- {
- Decl *d;
- char buf[4096], *p, *s;
- d = va_arg(f->args, Decl*);
- buf[0] = 0;
- p = buf;
- if(d->dot != nil && !isimpmod(d->dot->sym)){
- s = ".";
- if(d->dot->ty != nil && d->dot->ty->kind == Tmodule)
- s = "->";
- p = seprint(buf, buf+sizeof(buf), "%D%s", d->dot, s);
- }
- seprint(p, buf+sizeof(buf), "%s", d->sym->name);
- return fmtstrcpy(f, buf);
- }
- /*
- * merge together two sorted lists, yielding a sorted list
- */
- static Decl*
- namemerge(Decl *e, Decl *f)
- {
- Decl rock, *d;
- d = &rock;
- while(e != nil && f != nil){
- if(strcmp(e->sym->name, f->sym->name) <= 0){
- d->next = e;
- e = e->next;
- }else{
- d->next = f;
- f = f->next;
- }
- d = d->next;
- }
- if(e != nil)
- d->next = e;
- else
- d->next = f;
- return rock.next;
- }
- /*
- * recursively split lists and remerge them after they are sorted
- */
- static Decl*
- recnamesort(Decl *d, int n)
- {
- Decl *r, *dd;
- int i, m;
- if(n <= 1)
- return d;
- m = n / 2 - 1;
- dd = d;
- for(i = 0; i < m; i++)
- dd = dd->next;
- r = dd->next;
- dd->next = nil;
- return namemerge(recnamesort(d, n / 2),
- recnamesort(r, (n + 1) / 2));
- }
- /*
- * sort the ids by name
- */
- Decl*
- namesort(Decl *d)
- {
- Decl *dd;
- int n;
- n = 0;
- for(dd = d; dd != nil; dd = dd->next)
- n++;
- return recnamesort(d, n);
- }
- void
- printdecls(Decl *d)
- {
- for(; d != nil; d = d->next)
- print("%ld: %K %T ref %d\n", d->offset, d, d->ty, d->refs);
- }
- void
- mergepolydecs(Type *t)
- {
- Node *n, *nn;
- Decl *id, *ids, *ids1;
- for(n = t->val; n != nil; n = n->right){
- nn = n->left;
- for(ids = nn->decl; ids != nil; ids = ids->next){
- id = ids->sym->decl;
- if(id == nil){
- undefed(&ids->src, ids->sym);
- break;
- }
- if(id->store != Dtype){
- error(ids->src.start, "%K is not a type", id);
- break;
- }
- if(id->ty->kind != Tpoly){
- error(ids->src.start, "%K is not a polymorphic type", id);
- break;
- }
- if(id->ty->ids != nil)
- error(ids->src.start, "%K redefined", id);
- pushscope(nil, Sother);
- fielddecled(nn->left);
- id->ty->ids = popscope();
- for(ids1 = id->ty->ids; ids1 != nil; ids1 = ids1->next){
- ids1->dot = id;
- bindtypes(ids1->ty);
- if(ids1->ty->kind != Tfn){
- error(ids1->src.start, "only function types expected");
- id->ty->ids = nil;
- }
- }
- }
- }
- t->val = nil;
- }
- static void
- adjfnptrs(Decl *d, Decl *polys1, Decl *polys2)
- {
- int n;
- Decl *id, *idt, *idf, *arg;
- if(debug['U'])
- print("adjnptrs %s\n", d->sym->name);
- n = 0;
- for(id = d->ty->ids; id != nil; id = id->next)
- n++;
- for(idt = polys1; idt != nil; idt = idt->next)
- for(idf = idt->ty->ids; idf != nil; idf = idf->next)
- n -= 2;
- for(idt = polys2; idt != nil; idt = idt->next)
- for(idf = idt->ty->ids; idf != nil; idf = idf->next)
- n -= 2;
- for(arg = d->ty->ids; --n >= 0; arg = arg->next)
- ;
- for(idt = polys1; idt != nil; idt = idt->next){
- for(idf = idt->ty->ids; idf != nil; idf = idf->next){
- idf->link = arg;
- arg = arg->next->next;
- }
- }
- for(idt = polys2; idt != nil; idt = idt->next){
- for(idf = idt->ty->ids; idf != nil; idf = idf->next){
- idf->link = arg;
- arg = arg->next->next;
- }
- }
- }
- static void
- addptrs(Decl *polys, Decl** fps, Decl **last, int link, Src *src)
- {
- Decl *idt, *idf, *fp;
- if(debug['U'])
- print("addptrs\n");
- for(idt = polys; idt != nil; idt = idt->next){
- for(idf = idt->ty->ids; idf != nil; idf = idf->next){
- fp = mkdecl(src, Darg, tany);
- fp->sym = idf->sym;
- if(link)
- idf->link = fp;
- if(*fps == nil)
- *fps = fp;
- else
- (*last)->next = fp;
- *last = fp;
- fp = mkdecl(src, Darg, tint);
- fp->sym = idf->sym;
- (*last)->next = fp;
- *last = fp;
- }
- }
- }
- void
- addfnptrs(Decl *d, int link)
- {
- Decl *fps, *last, *polys;
- if(debug['U'])
- print("addfnptrs %s %d\n", d->sym->name, link);
- polys = encpolys(d);
- if(d->ty->flags&FULLARGS){
- if(link)
- adjfnptrs(d, d->ty->polys, polys);
- if(0 && debug['U']){
- for(d = d->ty->ids; d != nil; d = d->next)
- print("%s=%ld(%d) ", d->sym->name, d->offset, tattr[d->ty->kind].isptr);
- print("\n");
- }
- return;
- }
- d->ty->flags |= FULLARGS;
- fps = last = nil;
- addptrs(d->ty->polys, &fps, &last, link, &d->src);
- addptrs(polys, &fps, &last, link, &d->src);
- for(last = d->ty->ids; last != nil && last->next != nil; last = last->next)
- ;
- if(last != nil)
- last->next = fps;
- else
- d->ty->ids = fps;
- d->offset = idoffsets(d->ty->ids, MaxTemp, IBY2WD);
- if(0 && debug['U']){
- for(d = d->ty->ids; d != nil; d = d->next)
- print("%s=%ld(%d) ", d->sym->name, d->offset, tattr[d->ty->kind].isptr);
- print("\n");
- }
- }
- void
- rmfnptrs(Decl *d)
- {
- int n;
- Decl *id, *idt, *idf;
- if(debug['U'])
- print("rmfnptrs %s\n", d->sym->name);
- if(!(d->ty->flags&FULLARGS))
- return;
- d->ty->flags &= ~FULLARGS;
- n = 0;
- for(id = d->ty->ids; id != nil; id = id->next)
- n++;
- for(idt = d->ty->polys; idt != nil; idt = idt->next)
- for(idf = idt->ty->ids; idf != nil; idf = idf->next)
- n -= 2;
- for(idt = encpolys(d); idt != nil; idt = idt->next)
- for(idf = idt->ty->ids; idf != nil; idf = idf->next)
- n -= 2;
- if(n == 0){
- d->ty->ids = nil;
- return;
- }
- for(id = d->ty->ids; --n > 0; id = id->next)
- ;
- id->next = nil;
- d->offset = idoffsets(d->ty->ids, MaxTemp, IBY2WD);
- }
- int
- local(Decl *d)
- {
- for(d = d->dot; d != nil; d = d->dot)
- if(d->store == Dtype && d->ty->kind == Tmodule)
- return 0;
- return 1;
- }
- Decl*
- module(Decl *d)
- {
- for(d = d->dot; d != nil; d = d->dot)
- if(d->store == Dtype && d->ty->kind == Tmodule)
- return d;
- return nil;
- }
- Decl*
- outerpolys(Node *n)
- {
- Decl *d;
- if(n->op == Odot){
- d = n->right->decl;
- if(d == nil)
- fatal("decl() outeradt nil");
- d = d->dot;
- if(d != nil && d->store == Dtype && d->ty->kind == Tadt)
- return d->ty->polys;
- }
- return nil;
- }
- Decl*
- encpolys(Decl *d)
- {
- if((d = d->dot) == nil)
- return nil;
- return d->ty->polys;
- }
- Decl*
- fnlookup(Sym *s, Type *t, Node **m)
- {
- Decl *id;
- Node *mod;
- id = nil;
- mod = nil;
- if(t->kind == Tpoly || t->kind == Tmodule)
- id = namedot(t->ids, s);
- else if(t->kind == Tref){
- t = t->tof;
- if(t->kind == Tadt){
- id = namedot(t->ids, s);
- if(t->decl != nil && t->decl->timport != nil)
- mod = t->decl->timport->eimport;
- }
- else if(t->kind == Tadtpick){
- id = namedot(t->ids, s);
- if(t->decl != nil && t->decl->timport != nil)
- mod = t->decl->timport->eimport;
- t = t->decl->dot->ty;
- if(id == nil)
- id = namedot(t->ids, s);
- if(t->decl != nil && t->decl->timport != nil)
- mod = t->decl->timport->eimport;
- }
- }
- if(id == nil){
- id = lookup(s);
- if(id != nil)
- mod = id->eimport;
- }
- if(m != nil)
- *m = mod;
- return id;
- }
- int
- isimpmod(Sym *s)
- {
- Decl *d;
- for(d = impmods; d != nil; d = d->next)
- if(d->sym == s)
- return 1;
- return 0;
- }
- int
- dequal(Decl *d1, Decl *d2, int full)
- {
- return d1->sym == d2->sym &&
- d1->store == d2->store &&
- d1->implicit == d2->implicit &&
- d1->cyc == d2->cyc &&
- (!full || tequal(d1->ty, d2->ty)) &&
- (!full || d1->store == Dfn || sametree(d1->init, d2->init));
- }
- static int
- tzero(Type *t)
- {
- return t->kind == Texception || tmustzero(t);
- }
- static int
- isptr(Type *t)
- {
- return t->kind == Texception || tattr[t->kind].isptr;
- }
- /* can d share the same stack location as another local ? */
- void
- shareloc(Decl *d)
- {
- int z;
- Type *t, *tt;
- Decl *dd, *res;
- if(d->store != Dlocal || d->nid != 1)
- return;
- t = d->ty;
- res = nil;
- for(dd = fndecls; dd != nil; dd = dd->next){
- if(d == dd)
- fatal("d==dd in shareloc");
- if(dd->store != Dlocal || dd->nid != 1 || dd->link != nil || dd->tref != 0)
- continue;
- tt = dd->ty;
- if(t->size != tt->size || t->align != tt->align)
- continue;
- z = tzero(t)+tzero(tt);
- if(z > 0)
- continue; /* for now */
- if(t == tt || tequal(t, tt))
- res = dd;
- else{
- if(z == 1)
- continue;
- if(z == 0 || isptr(t) || isptr(tt) || mktdesc(t) == mktdesc(tt))
- res = dd;
- }
- if(res != nil){
- /* print("%L %K share %L %K\n", d->src.start, d, res->src.start, res); */
- d->link = res;
- res->tref = 1;
- return;
- }
- }
- return;
- }
- static void
- freeloc(Decl *d)
- {
- if(d->link != nil)
- d->link->tref = 0;
- }
|