// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "go.h" #include "y.tab.h" void addexportsym(Sym *s) { Dcl *d, *r; d = mal(sizeof(*d)); d->dsym = s; d->dnode = N; d->lineno = lineno; r = exportlist; d->back = r->back; r->back->forw = d; r->back = d; } void exportsym(Sym *s) { if(s == S) return; if(s->export != 0) return; s->export = 1; addexportsym(s); } void makeexportsym(Type *t) { Sym *s; if(t->sym == S) { exportgen++; snprint(namebuf, sizeof(namebuf), "_e%s_%.3ld", filename, exportgen); s = lookup(namebuf); s->lexical = LATYPE; s->otype = t; t->sym = s; } } void reexport(Type *t) { if(t == T) fatal("reexport: type nil"); makeexportsym(t); dumpexporttype(t->sym); } void dumpexportconst(Sym *s) { Node *n; Type *t; if(s->exported != 0) return; s->exported = 1; n = s->oconst; if(n == N || n->op != OLITERAL) fatal("dumpexportconst: oconst nil: %S", s); t = n->type; // may or may not be specified if(t != T) reexport(t); Bprint(bout, "\tconst "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS ", s); if(t != T) Bprint(bout, "%lS ", t->sym); switch(n->val.ctype) { default: fatal("dumpexportconst: unknown ctype: %S", s); case CTINT: case CTSINT: case CTUINT: Bprint(bout, "%B\n", n->val.u.xval); break; case CTBOOL: Bprint(bout, "0x%llux\n", n->val.u.bval); break; case CTFLT: Bprint(bout, "%.17e\n", mpgetflt(n->val.u.fval)); break; case CTSTR: Bprint(bout, "\"%Z\"\n", n->val.u.sval); break; } } void dumpexportvar(Sym *s) { Node *n; Type *t; if(s->exported != 0) return; s->exported = 1; n = s->oname; if(n == N || n->type == T) { yyerror("variable exported but not defined: %S", s); return; } t = n->type; reexport(t); Bprint(bout, "\tvar "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS %lS\n", s, t->sym); } void dumpexporttype(Sym *s) { Type *t, *f; Sym *ts; int et, forw; if(s->exported != 0) return; s->exported = 1; t = s->otype; if(t == T) { yyerror("type exported but not defined: %S", s); return; } if(t->sym != s) fatal("dumpexporttype: cross reference: %S", s); et = t->etype; switch(et) { default: if(et < 0 || et >= nelem(types) || types[et] == T) fatal("dumpexporttype: basic type: %S %E", s, et); /* type 5 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS %d\n", s, et); break; case TARRAY: reexport(t->type); /* type 2 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); if(t->bound >= 0) Bprint(bout, "%lS [%lud] %lS\n", s, t->bound, t->type->sym); else Bprint(bout, "%lS [] %lS\n", s, t->type->sym); break; case TPTR32: case TPTR64: if(t->type == T) fatal("dumpexporttype: ptr %S", s); makeexportsym(t->type); ts = t->type->sym; if(ts->exported == 0) addexportsym(ts); /* type 6 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS *%lS\n", s, ts); break; case TFUNC: for(f=t->type; f!=T; f=f->down) { if(f->etype != TSTRUCT) fatal("dumpexporttype: funct not field: %T", f); reexport(f); } /* type 3 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS (", s); for(f=t->type; f!=T; f=f->down) { if(f != t->type) Bprint(bout, " "); Bprint(bout, "%lS", f->sym); } Bprint(bout, ")\n"); break; case TSTRUCT: case TINTER: for(f=t->type; f!=T; f=f->down) { if(f->etype != TFIELD) fatal("dumpexporttype: funct not field: %lT", f); reexport(f->type); } /* type 4 */ Bprint(bout, "\ttype "); if(s->export) Bprint(bout, "!"); Bprint(bout, "%lS %c", s, (et==TSTRUCT)? '{': '<'); for(f=t->type; f!=T; f=f->down) { ts = f->type->sym; if(f != t->type) Bprint(bout, " "); Bprint(bout, "%s %lS", f->sym->name, ts); } Bprint(bout, "%c\n", (et==TSTRUCT)? '}': '>'); break; case TMAP: reexport(t->type); reexport(t->down); /* type 1 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS [%lS] %lS\n", s, t->down->sym, t->type->sym); break; case TCHAN: reexport(t->type); /* type 8 */ Bprint(bout, "\ttype "); if(s->export != 0) Bprint(bout, "!"); Bprint(bout, "%lS %d %lS\n", s, t->chan, t->type->sym); break; } } void dumpe(Sym *s) { switch(s->lexical) { default: yyerror("unknown export symbol: %S", s, s->lexical); break; case LPACK: yyerror("package export symbol: %S", s); break; case LATYPE: case LBASETYPE: //print("TYPE %S\n", s); dumpexporttype(s); break; case LNAME: //print("VAR %S\n", s); dumpexportvar(s); break; case LACONST: //print("CONST %S\n", s); dumpexportconst(s); break; } } void dumpm(Sym *s) { Type *t, *f; switch(s->lexical) { default: return; case LATYPE: case LBASETYPE: break; } t = s->otype; if(t == T) { yyerror("type exported but not defined: %S", s); return; } for(f=t->method; f!=T; f=f->down) { if(f->etype != TFIELD) fatal("dumpexporttype: method not field: %lT", f); reexport(f->type); Bprint(bout, "\tfunc %S %lS\n", f->sym, f->type->sym); } } void dumpexport(void) { Dcl *d; int32 lno; lno = lineno; Bprint(bout, " import\n"); Bprint(bout, " ((\n"); Bprint(bout, " package %s\n", package); // first pass dump vars/types depth first for(d=exportlist->forw; d!=D; d=d->forw) { lineno = d->lineno; dumpe(d->dsym); } // second pass dump methods for(d=exportlist->forw; d!=D; d=d->forw) { lineno = d->lineno; dumpm(d->dsym); } // third pass pick up redefs from previous passes for(d=exportlist->forw; d!=D; d=d->forw) { lineno = d->lineno; dumpe(d->dsym); } Bprint(bout, " ))\n"); lineno = lno; } /* * ******* import ******* */ void checkimports(void) { Sym *s; Type *t, *t1; uint32 h; int et; return; for(h=0; hlink) { t = s->otype; if(t == T) continue; et = t->etype; switch(t->etype) { case TFORW: print("ci-1: %S %lT\n", s, t); break; case TPTR32: case TPTR64: if(t->type == T) { print("ci-2: %S %lT\n", s, t); break; } t1 = t->type; if(t1 == T) { print("ci-3: %S %lT\n", s, t1); break; } et = t1->etype; if(et == TFORW) { print("%L: ci-4: %S %lT\n", lineno, s, t); break; } break; } } } void renamepkg(Node *n) { if(n->psym == pkgimportname) if(pkgmyname != S) n->psym = pkgmyname; } Sym* getimportsym(Node *ss) { char *pkg; Sym *s; if(ss->op != OIMPORT) fatal("getimportsym: oops1 %N", ss); pkg = ss->psym->name; s = pkglookup(ss->sym->name, pkg); /* botch - need some diagnostic checking for the following assignment */ s->opackage = ss->osym->name; return s; } Type* importlooktype(Node *n) { Sym *s; s = getimportsym(n); if(s->otype == T) fatal("importlooktype: oops2 %S", s); return s->otype; } Type** importstotype(Node *fl, Type **t, Type *uber) { Type *f; Iter save; Node *n; n = listfirst(&save, &fl); loop: if(n == N) { *t = T; return t; } f = typ(TFIELD); f->type = importlooktype(n); if(n->fsym != S) { f->nname = newname(n->fsym); } else { vargen++; snprint(namebuf, sizeof(namebuf), "_m%.3ld", vargen); f->nname = newname(lookup(namebuf)); } f->sym = f->nname->sym; *t = f; t = &f->down; n = listnext(&save); goto loop; } int importcount(Type *t) { int i; Type *f; if(t == T || t->etype != TSTRUCT) fatal("importcount: not a struct: %N", t); i = 0; for(f=t->type; f!=T; f=f->down) i = i+1; return i; } void importfuncnam(Type *t) { Node *n; Type *t1; if(t->etype != TFUNC) fatal("importfuncnam: not func %T", t); if(t->thistuple > 0) { t1 = t->type; if(t1->sym == S) fatal("importfuncnam: no this"); n = newname(t1->sym); vargen++; n->vargen = vargen; t1->nname = n; } if(t->outtuple > 0) { t1 = t->type->down; if(t1->sym == S) fatal("importfuncnam: no output"); n = newname(t1->sym); vargen++; n->vargen = vargen; t1->nname = n; } if(t->intuple > 0) { t1 = t->type->down->down; if(t1->sym == S) fatal("importfuncnam: no input"); n = newname(t1->sym); vargen++; n->vargen = vargen; t1->nname = n; } } void importaddtyp(Node *ss, Type *t) { Sym *s; s = getimportsym(ss); if(s->otype != T) { // here we should try to discover if // the new type is the same as the old type if(eqtype(t, s->otype, 0)) return; if(isptrto(t, TFORW)) { return; // hard part } warn("redeclare import %S from %lT to %lT", s, s->otype, t); return; } addtyp(newtype(s), t, PEXTERN); } /* * LCONST importsym LITERAL * untyped constant */ void doimportc1(Node *ss, Val *v) { Node *n; Sym *s; n = nod(OLITERAL, N, N); n->val = *v; s = getimportsym(ss); if(s->oconst == N) { // botch sould ask if already declared the same dodclconst(newname(s), n); } } /* * LCONST importsym importsym LITERAL * typed constant */ void doimportc2(Node *ss, Node *st, Val *v) { Node *n; Type *t; Sym *s; n = nod(OLITERAL, N, N); n->val = *v; t = importlooktype(st); n->type = t; s = getimportsym(ss); if(s->oconst == N) { // botch sould ask if already declared the same dodclconst(newname(s), n); } } /* * LVAR importsym importsym * variable */ void doimportv1(Node *ss, Node *st) { Type *t; Sym *s; t = importlooktype(st); s = getimportsym(ss); if(s->oname == N || !eqtype(t, s->oname->type, 0)) { addvar(newname(s), t, dclcontext); } } /* * LTYPE importsym [ importsym ] importsym * array type */ void doimport1(Node *ss, Node *si, Node *st) { Type *t; Sym *s; t = typ(TMAP); s = pkglookup(si->sym->name, si->psym->name); t->down = s->otype; s = pkglookup(st->sym->name, st->psym->name); t->type = s->otype; importaddtyp(ss, t); } /* * LTYPE importsym [ LLITERAL ] importsym * array type */ void doimport2(Node *ss, Val *b, Node *st) { Type *t; Sym *s; t = typ(TARRAY); t->bound = -1; if(b != nil) t->bound = mpgetfix(b->u.xval); s = pkglookup(st->sym->name, st->psym->name); t->type = s->otype; importaddtyp(ss, t); } /* * LTYPE importsym '(' importsym_list ')' * function/method type */ void doimport3(Node *ss, Node *n) { Type *t; t = typ(TFUNC); t->type = importlooktype(n->left); t->type->down = importlooktype(n->right->left); t->type->down->down = importlooktype(n->right->right); t->thistuple = importcount(t->type); t->outtuple = importcount(t->type->down); t->intuple = importcount(t->type->down->down); dowidth(t); importfuncnam(t); importaddtyp(ss, t); } /* * LTYPE importsym '{' importsym_list '}' * structure type */ void doimport4(Node *ss, Node *n) { Type *t; t = typ(TSTRUCT); importstotype(n, &t->type, t); dowidth(t); importaddtyp(ss, t); } /* * LTYPE importsym LLITERAL * basic type */ void doimport5(Node *ss, Val *v) { int et; Type *t; et = mpgetfix(v->u.xval); if(et <= 0 || et >= nelem(types) || types[et] == T) fatal("doimport5: bad type index: %E", et); t = typ(et); t->sym = S; importaddtyp(ss, t); } /* * LTYPE importsym * importsym * pointer type */ void doimport6(Node *ss, Node *st) { Type *t; Sym *s; s = pkglookup(st->sym->name, st->psym->name); t = s->otype; if(t == T) t = forwdcl(s); else t = ptrto(t); importaddtyp(ss, t); } /* * LTYPE importsym '<' importsym '>' * interface type */ void doimport7(Node *ss, Node *n) { Type *t; t = typ(TINTER); importstotype(n, &t->type, t); dowidth(t); importaddtyp(ss, t); } /* * LTYPE importsym chdir importsym * interface type */ void doimport8(Node *ss, Val *v, Node *st) { Type *t; Sym *s; int dir; s = pkglookup(st->sym->name, st->psym->name); dir = mpgetfix(v->u.xval); t = typ(TCHAN); s = pkglookup(st->sym->name, st->psym->name); t->type = s->otype; t->chan = dir; importaddtyp(ss, t); } /* * LFUNC importsym sym * method type */ void doimport9(Sym *sf, Node *ss) { Sym *sfun; sfun = getimportsym(ss); addmethod(newname(sf), sfun->otype, 0); }