diff options
author | Russ Cox <rsc@golang.org> | 2009-03-30 21:31:29 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-03-30 21:31:29 -0700 |
commit | b9334f573c4f5a170e65bb7085129befa894b06b (patch) | |
tree | 8d1ab31c6b7e903abc62d44808d5198241702af1 | |
parent | dd1ccb897369eef6766d0c83d837cbf4bb2e1f8d (diff) | |
download | golang-b9334f573c4f5a170e65bb7085129befa894b06b.tar.gz |
move portable object routines (especially
signature generation) into gc.
R=ken
OCL=26933
CL=26933
-rw-r--r-- | src/cmd/6g/Makefile | 2 | ||||
-rw-r--r-- | src/cmd/6g/align.c | 4 | ||||
-rw-r--r-- | src/cmd/6g/gg.h | 25 | ||||
-rw-r--r-- | src/cmd/6g/gsubr.c | 31 | ||||
-rw-r--r-- | src/cmd/6g/obj.c | 863 | ||||
-rw-r--r-- | src/cmd/gc/Makefile | 1 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 47 | ||||
-rw-r--r-- | src/cmd/gc/lex.c | 12 | ||||
-rw-r--r-- | src/cmd/gc/obj.c | 585 | ||||
-rw-r--r-- | src/cmd/gc/subr.c | 96 |
10 files changed, 858 insertions, 808 deletions
diff --git a/src/cmd/6g/Makefile b/src/cmd/6g/Makefile index 9a59858d7..4d2b6ab97 100644 --- a/src/cmd/6g/Makefile +++ b/src/cmd/6g/Makefile @@ -15,11 +15,11 @@ HFILES=\ OFILES=\ list.$O\ + obj.$O\ align.$O\ gen.$O\ cgen.$O\ gsubr.$O\ - obj.$O\ peep.$O\ reg.$O\ ../6l/enam.$O\ diff --git a/src/cmd/6g/align.c b/src/cmd/6g/align.c index 209ac324f..fa7315057 100644 --- a/src/cmd/6g/align.c +++ b/src/cmd/6g/align.c @@ -4,6 +4,10 @@ #include "gg.h" +int thechar = '6'; +char* thestring = "amd64"; + + /* * go declares several platform-specific type aliases: * int, uint, float, and uintptr diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index af1e2c2cc..b3eddb3d3 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -41,18 +41,6 @@ struct Prog void* reg; // pointer to containing Reg struct }; -typedef struct Plist Plist; -struct Plist -{ - Node* name; - Dcl* locals; - Prog* firstpc; - int recur; - Plist* link; -}; - -EXTERN Plist* plist; -EXTERN Plist* plast; EXTERN Biobuf* bout; EXTERN int32 dynloc; EXTERN uchar reg[D_NONE]; @@ -146,18 +134,5 @@ int Rconv(Fmt*); int Yconv(Fmt*); void listinit(void); -/* - * obj - */ -void zname(Biobuf*, Sym*, int); void zaddr(Biobuf*, Addr*, int); -void ieeedtod(Ieee*, double); -void dumpstrings(void); -void dumpsignatures(void); -void outhist(Biobuf*); -/* - * align - */ -void dowidth(Type*); -uint32 rnd(uint32, uint32); diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index ab4979a34..e47731309 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -1938,10 +1938,39 @@ Prog* gjmp(Prog *to) { Prog *p; - + p = gbranch(AJMP, T); if(to != P) patch(p, to); return p; } +void +ggloblnod(Node *nam, int32 width) +{ + Prog *p; + + p = gins(AGLOBL, nam, N); + p->lineno = nam->lineno; + p->to.sym = S; + p->to.type = D_CONST; + p->to.offset = width; +} + +void +ggloblsym(Sym *s, int32 width, int dupok) +{ + Prog *p; + + p = gins(AGLOBL, N, N); + p->from.type = D_EXTERN; + if(s == symstringo) + p->from.type = D_STATIC; + p->from.index = D_NONE; + p->from.sym = s; + p->to.type = D_CONST; + p->to.index = D_NONE; + p->to.offset = width; + if(dupok) + p->from.scale = DUPOK; +} diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c index af375a1d4..26c2d929c 100644 --- a/src/cmd/6g/obj.c +++ b/src/cmd/6g/obj.c @@ -31,156 +31,6 @@ #include "gg.h" void -dumpobj(void) -{ - Plist *pl; - Prog *p; - Dcl *d; - Sym *s; - Node *n; - struct { Sym *sym; short type; } h[NSYM]; - int sf, st, t, sym; - Node n1; - - // add nil plist w AEND - newplist(); - - bout = Bopen(outfile, OWRITE); - if(bout == nil) - fatal("cant open %s", outfile); - - Bprint(bout, "amd64\n"); - Bprint(bout, " exports automatically generated from\n"); - Bprint(bout, " %s in package \"%s\"\n", curio.infile, package); - dumpexport(); - Bprint(bout, "\n!\n"); - - outhist(bout); - - // add globals - nodconst(&n1, types[TINT32], 0); - for(d=externdcl; d!=D; d=d->forw) { - if(d->op != ONAME) - continue; - - s = d->dsym; - if(s == S) - fatal("external nil"); - n = d->dnode; - if(n == N || n->type == T) - fatal("external %S nil\n", s); - - if(n->class == PFUNC) - continue; - - dowidth(n->type); - mpmovecfix(n1.val.u.xval, n->type->width); - - p = pc; - gins(AGLOBL, s->oname, &n1); - p->lineno = s->oname->lineno; - } - - dumpstrings(); - dumpsignatures(); - - for(sym=0; sym<NSYM; sym++) { - h[sym].sym = S; - h[sym].type = 0; - } - sym = 1; - - // fix up pc - pcloc = 0; - for(pl=plist; pl!=nil; pl=pl->link) { - for(p=pl->firstpc; p!=P; p=p->link) { - p->loc = pcloc; - pcloc++; - } - } - - // put out functions - for(pl=plist; pl!=nil; pl=pl->link) { - - if(debug['S']) { - s = S; - if(pl->name != N) - s = pl->name->sym; - print("\n--- prog list \"%S\" ---\n", s); - for(p=pl->firstpc; p!=P; p=p->link) - print("%P\n", p); - } - - for(p=pl->firstpc; p!=P; p=p->link) { - jackpot: - sf = 0; - s = p->from.sym; - while(s != S) { - sf = s->sym; - if(sf < 0 || sf >= NSYM) - sf = 0; - t = p->from.type; - if(t == D_ADDR) - t = p->from.index; - if(h[sf].type == t) - if(h[sf].sym == s) - break; - s->sym = sym; - zname(bout, s, t); - h[sym].sym = s; - h[sym].type = t; - sf = sym; - sym++; - if(sym >= NSYM) - sym = 1; - break; - } - st = 0; - s = p->to.sym; - while(s != S) { - st = s->sym; - if(st < 0 || st >= NSYM) - st = 0; - t = p->to.type; - if(t == D_ADDR) - t = p->to.index; - if(h[st].type == t) - if(h[st].sym == s) - break; - s->sym = sym; - zname(bout, s, t); - h[sym].sym = s; - h[sym].type = t; - st = sym; - sym++; - if(sym >= NSYM) - sym = 1; - if(st == sf) - goto jackpot; - break; - } - Bputc(bout, p->as); - Bputc(bout, p->as>>8); - Bputc(bout, p->lineno); - Bputc(bout, p->lineno>>8); - Bputc(bout, p->lineno>>16); - Bputc(bout, p->lineno>>24); - zaddr(bout, &p->from, sf); - zaddr(bout, &p->to, st); - } - } - Bterm(bout); -} - -void -Bputdot(Biobuf *b) -{ - // put out middle dot · - Bputc(b, 0xc2); - Bputc(b, 0xb7); -} - -void zname(Biobuf *b, Sym *s, int t) { char *n; @@ -199,12 +49,44 @@ zname(Biobuf *b, Sym *s, int t) } void +zfile(Biobuf *b, char *p, int n) +{ + Bputc(b, ANAME); + Bputc(b, ANAME>>8); + Bputc(b, D_FILE); + Bputc(b, 1); + Bputc(b, '<'); + Bwrite(b, p, n); + Bputc(b, 0); +} + +void +zhist(Biobuf *b, int line, vlong offset) +{ + Addr a; + + Bputc(b, AHISTORY); + Bputc(b, AHISTORY>>8); + Bputc(b, line); + Bputc(b, line>>8); + Bputc(b, line>>16); + Bputc(b, line>>24); + zaddr(b, &zprog.from, 0); + a = zprog.to; + if(offset != 0) { + a.offset = offset; + a.type = D_CONST; + } + zaddr(b, &a, 0); +} + +void zaddr(Biobuf *b, Addr *a, int s) { int32 l; + uint64 e; int i, t; char *n; - Ieee e; t = 0; if(a->index != D_NONE || a->scale != 0) @@ -259,12 +141,12 @@ zaddr(Biobuf *b, Addr *a, int s) Bputc(b, s); if(t & T_FCONST) { ieeedtod(&e, a->dval); - l = e.l; + l = e; Bputc(b, l); Bputc(b, l>>8); Bputc(b, l>>16); Bputc(b, l>>24); - l = e.h; + l = e >> 32; Bputc(b, l); Bputc(b, l>>8); Bputc(b, l>>16); @@ -284,95 +166,99 @@ zaddr(Biobuf *b, Addr *a, int s) } void -outhist(Biobuf *b) +dumpfuncs(void) { - Hist *h; - char *p, *q, *op; - Prog pg; - int n; - - pg = zprog; - pg.as = AHISTORY; - for(h = hist; h != H; h = h->link) { - p = h->name; - op = 0; - - if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') { - op = p; - p = pathname; - } + Plist *pl; + int sf, st, t, sym; + struct { Sym *sym; short type; } h[NSYM]; + Sym *s; + Prog *p; - while(p) { - q = utfrune(p, '/'); - if(q) { - n = q-p; - if(n == 0) - n = 1; // leading "/" - q++; - } else { - n = strlen(p); - q = 0; - } - if(n) { - Bputc(b, ANAME); - Bputc(b, ANAME>>8); - Bputc(b, D_FILE); - Bputc(b, 1); - Bputc(b, '<'); - Bwrite(b, p, n); - Bputc(b, 0); - } - p = q; - if(p == 0 && op) { - p = op; - op = 0; - } - } + for(sym=0; sym<NSYM; sym++) { + h[sym].sym = S; + h[sym].type = 0; + } + sym = 1; - pg.lineno = h->line; - pg.to.type = zprog.to.type; - pg.to.offset = h->offset; - if(h->offset) - pg.to.type = D_CONST; - - Bputc(b, pg.as); - Bputc(b, pg.as>>8); - Bputc(b, pg.lineno); - Bputc(b, pg.lineno>>8); - Bputc(b, pg.lineno>>16); - Bputc(b, pg.lineno>>24); - zaddr(b, &pg.from, 0); - zaddr(b, &pg.to, 0); + // fix up pc + pcloc = 0; + for(pl=plist; pl!=nil; pl=pl->link) { + for(p=pl->firstpc; p!=P; p=p->link) { + p->loc = pcloc; + pcloc++; + } } -} -void -ieeedtod(Ieee *ieee, double native) -{ - double fr, ho, f; - int exp; + // put out functions + for(pl=plist; pl!=nil; pl=pl->link) { - if(native < 0) { - ieeedtod(ieee, -native); - ieee->h |= 0x80000000L; - return; - } - if(native == 0) { - ieee->l = 0; - ieee->h = 0; - return; + if(debug['S']) { + s = S; + if(pl->name != N) + s = pl->name->sym; + print("\n--- prog list \"%S\" ---\n", s); + for(p=pl->firstpc; p!=P; p=p->link) + print("%P\n", p); + } + + for(p=pl->firstpc; p!=P; p=p->link) { + jackpot: + sf = 0; + s = p->from.sym; + while(s != S) { + sf = s->sym; + if(sf < 0 || sf >= NSYM) + sf = 0; + t = p->from.type; + if(t == D_ADDR) + t = p->from.index; + if(h[sf].type == t) + if(h[sf].sym == s) + break; + s->sym = sym; + zname(bout, s, t); + h[sym].sym = s; + h[sym].type = t; + sf = sym; + sym++; + if(sym >= NSYM) + sym = 1; + break; + } + st = 0; + s = p->to.sym; + while(s != S) { + st = s->sym; + if(st < 0 || st >= NSYM) + st = 0; + t = p->to.type; + if(t == D_ADDR) + t = p->to.index; + if(h[st].type == t) + if(h[st].sym == s) + break; + s->sym = sym; + zname(bout, s, t); + h[sym].sym = s; + h[sym].type = t; + st = sym; + sym++; + if(sym >= NSYM) + sym = 1; + if(st == sf) + goto jackpot; + break; + } + Bputc(bout, p->as); + Bputc(bout, p->as>>8); + Bputc(bout, p->lineno); + Bputc(bout, p->lineno>>8); + Bputc(bout, p->lineno>>16); + Bputc(bout, p->lineno>>24); + zaddr(bout, &p->from, sf); + zaddr(bout, &p->to, st); + } } - fr = frexp(native, &exp); - f = 2097152L; /* shouldnt use fp constants here */ - fr = modf(fr*f, &ho); - ieee->h = ho; - ieee->h &= 0xfffffL; - ieee->h |= (exp+1022L) << 20; - f = 65536L; - fr = modf(fr*f, &ho); - ieee->l = ho; - ieee->l <<= 16; - ieee->l |= (int32)(fr*f); } void @@ -463,66 +349,91 @@ dumpstrings(void) } } -static int -sigcmp(Sig *a, Sig *b) +int +dstringptr(Sym *s, int off, char *str) { - return strcmp(a->name, b->name); -} + Prog *p; -static Addr at, ao, ac, ad; -static int wi, ws, ot; + off = rnd(off, widthptr); + p = gins(ADATA, N, N); + p->from.type = D_EXTERN; + p->from.index = D_NONE; + p->from.sym = s; + p->from.offset = off; + p->from.scale = widthptr; + p->to.type = D_ADDR; + p->to.index = D_STATIC; + p->to.etype = TINT32; + p->to.sym = symstringo; + p->to.offset = stringo; + off += widthptr; + + datastring(str, strlen(str)+1); + return off; +} -void -ginsatoa(int fscale, int toffset) +int +duintxx(Sym *s, int off, uint64 v, int wid) { Prog *p; - p = pc; - ot = rnd(ot, fscale); - - gins(ADATA, N, N); - p->from = at; - p->from.offset = ot; - p->from.scale = fscale; - p->to = ao; - p->to.offset = toffset; - ot += fscale; + off = rnd(off, wid); + + p = gins(ADATA, N, N); + p->from.type = D_EXTERN; + p->from.index = D_NONE; + p->from.sym = s; + p->from.offset = off; + p->from.scale = wid; + p->to.type = D_CONST; + p->to.index = D_NONE; + p->to.offset = v; + off += wid; + + return off; } -void -gensatac(int fscale, int toffset) +int +duint32(Sym *s, int off, uint32 v) { - Prog *p; + return duintxx(s, off, v, 4); +} - p = pc; - ot = rnd(ot, fscale); - - gins(ADATA, N, N); - p->from = at; - p->from.offset = ot; - p->from.scale = fscale; - p->to = ac; - p->to.offset = toffset; - ot += fscale; +int +duint16(Sym *s, int off, uint32 v) +{ + return duintxx(s, off, v, 2); } -void -gensatad(Sym *s) +int +duintptr(Sym *s, int off, uint32 v) +{ + return duintxx(s, off, v, 8); +} + +int +dsymptr(Sym *s, int off, Sym *x) { Prog *p; - p = pc; - ot = rnd(ot, widthptr); + off = rnd(off, widthptr); - gins(ADATA, N, N); - p->from = at; - p->from.offset = ot; + p = gins(ADATA, N, N); + p->from.type = D_EXTERN; + p->from.index = D_NONE; + p->from.sym = s; + p->from.offset = off; p->from.scale = widthptr; - p->to = ad; - p->to.sym = s; - ot += widthptr; + p->to.type = D_ADDR; + p->to.index = D_EXTERN; + p->to.sym = x; + p->to.offset = 0; + off += widthptr; + + return off; } + void genembedtramp(Type *t, Sig *b) { @@ -615,405 +526,9 @@ out: pc->as = ARET; // overwrite AEND } -/* - * Add DATA for signature s. - * progt - type in program - * ifacet - type stored in interface (==progt if small, ==ptrto(progt) if large) - * rcvrt - type used as method interface. eqtype(ifacet, rcvrt) is always true, - * but ifacet might have a name that rcvrt does not. - * methodt - type with methods hanging off it (progt==*methodt sometimes) - * - * memory layout is Sigt struct from iface.c: - * struct Sigt - * { - * byte* name; // name of basic type - * Sigt* link; // for linking into hash tables - * uint32 thash; // hash of type - * uint32 mhash; // hash of methods - * uint16 width; // width of base type in bytes - * uint16 alg; // algorithm - * uint32 pad; - * struct { - * byte* fname; - * uint32 fhash; // hash of type - * uint32 offset; // offset of substruct - * void (*fun)(void); - * } meth[1]; // one or more - last name is nil - * }; - */ - void -dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s) +nopout(Prog *p) { - Type *f; - int o; - Sig *a, *b; - Prog *p; - char buf[NSYMB]; - Type *this; - Iter savet; - Prog *oldlist; - Sym *method; - uint32 sighash; - - at.sym = s; - - a = nil; - o = 0; - oldlist = nil; - sighash = typehash(progt, 1, 0); - for(f=methodt->method; f!=T; f=f->down) { - if(f->type->etype != TFUNC) - continue; - - if(f->etype != TFIELD) - fatal("dumpsignatures: not field"); - - method = f->sym; - if(method == nil) - continue; - - b = mal(sizeof(*b)); - b->link = a; - a = b; - - a->name = method->name; - a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0); - if(!exportname(a->name)) - a->hash += PRIME10*stringhash(package); - a->perm = o; - a->sym = methodsym(method, rcvrt); - - sighash = sighash*100003 + a->hash; - - if(!a->sym->siggen) { - a->sym->siggen = 1; - // TODO(rsc): This test is still not quite right. - - this = structfirst(&savet, getthis(f->type))->type; - if(isptr[this->etype] != isptr[ifacet->etype]) { - if(oldlist == nil) - oldlist = pc; - - // indirect vs direct mismatch - Sym *oldname, *newname; - Type *oldthis, *newthis; - - newthis = ifacet; - if(isptr[newthis->etype]) - oldthis = ifacet->type; - else - oldthis = ptrto(ifacet); - newname = a->sym; - oldname = methodsym(method, oldthis); - genptrtramp(method, oldname, oldthis, f->type, newname, newthis); - } else - if(f->embedded) { - // TODO(rsc): only works for pointer receivers - if(oldlist == nil) - oldlist = pc; - genembedtramp(ifacet, a); - } - } - o++; - } - - // restore data output - if(oldlist) { - // old list ended with AEND; change to ANOP - // so that the trampolines that follow can be found. - oldlist->as = ANOP; - - // start new data list - newplist(); - } - - a = lsort(a, sigcmp); - ot = 0; - ot = rnd(ot, maxround); // base structure - - // base of type signature contains parameters - ginsatoa(widthptr, stringo); // name - ot = rnd(ot, widthptr)+widthptr; // skip link - gensatac(wi, typehash(progt, 1, 0)); // thash - gensatac(wi, sighash); // mhash - gensatac(ws, progt->width); // width - gensatac(ws, algtype(progt)); // algorithm - - snprint(buf, sizeof buf, "%#T", progt); - datastring(buf, strlen(buf)+1); - - for(b=a; b!=nil; b=b->link) { - ot = rnd(ot, maxround); // base of substructure - ginsatoa(widthptr, stringo); // field name - gensatac(wi, b->hash); // hash - gensatac(wi, 0); // offset - gensatad(b->sym); // &method - - datastring(b->name, strlen(b->name)+1); - } - - // nil field name at end - ot = rnd(ot, maxround); - gensatac(widthptr, 0); - - // set DUPOK to allow other .6s to contain - // the same signature. only one will be chosen. - // should only happen for empty signatures - p = pc; - gins(AGLOBL, N, N); - p->from = at; - if(a == nil) - p->from.scale = DUPOK; - p->to = ac; - p->to.offset = ot; -} - -/* - * memory layout is Sigi struct from iface.c: - * struct Sigi - * { - * byte* name; - * uint32 hash; - * uint32 size; // number of methods - * struct { - * byte* fname; - * uint32 fhash; - * uint32 perm; // location of fun in Sigt - * } meth[1]; // [size+1] - last name is nil - * }; - */ -void -dumpsigi(Type *t, Sym *s) -{ - Type *f; - Sym *s1; - int o; - Sig *a, *b; - Prog *p; - char buf[NSYMB]; - uint32 sighash; - - at.sym = s; - - a = nil; - o = 0; - sighash = 0; - for(f=t->type; f!=T; f=f->down) { - if(f->type->etype != TFUNC) - continue; - - if(f->etype != TFIELD) - fatal("dumpsignatures: not field"); - - s1 = f->sym; - if(s1 == nil) - continue; - - b = mal(sizeof(*b)); - b->link = a; - a = b; - - a->name = s1->name; - a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0); - if(!exportname(a->name)) - a->hash += PRIME10*stringhash(package); - a->perm = o; - a->sym = methodsym(f->sym, t); - a->offset = 0; - - sighash = sighash*100003 + a->hash; - - o++; - } - - a = lsort(a, sigcmp); - ot = 0; - ot = rnd(ot, maxround); // base structure - - // sigi[0].name = "" - ginsatoa(widthptr, stringo); - - // save type name for runtime error message. - snprint(buf, sizeof buf, "%#T", t); - datastring(buf, strlen(buf)+1); - - // first field of an interface signature - // contains the count and is not a real entry - - // sigi[0].hash = sighash - gensatac(wi, sighash); - - // sigi[0].offset = count - o = 0; - for(b=a; b!=nil; b=b->link) - o++; - gensatac(wi, o); - - for(b=a; b!=nil; b=b->link) { -//print(" %s\n", b->name); - ot = rnd(ot, maxround); // base structure - - // sigx[++].name = "fieldname" - ginsatoa(widthptr, stringo); - - // sigx[++].hash = hashcode - gensatac(wi, b->hash); - - // sigi[++].perm = mapped offset of method - gensatac(wi, b->perm); - - datastring(b->name, strlen(b->name)+1); - } - - // nil field name at end - ot = rnd(ot, maxround); - gensatac(widthptr, 0); - - p = pc; - gins(AGLOBL, N, N); - p->from = at; - p->from.scale = DUPOK; - p->to = ac; - p->to.offset = ot; + p->as = ANOP; } -void -dumpsignatures(void) -{ - int et; - Dcl *d, *x; - Type *t, *progt, *methodt, *ifacet, *rcvrt; - Sym *s; - Prog *p; - - memset(&at, 0, sizeof(at)); - memset(&ao, 0, sizeof(ao)); - memset(&ac, 0, sizeof(ac)); - memset(&ad, 0, sizeof(ad)); - - wi = types[TINT32]->width; - ws = types[TINT16]->width; - - // sig structure - at.type = D_EXTERN; - at.index = D_NONE; - at.sym = S; // fill in - at.offset = 0; // fill in - - // $string - ao.type = D_ADDR; - ao.index = D_STATIC; - ao.etype = TINT32; - ao.sym = symstringo; - ao.offset = 0; // fill in - - // constant - ac.type = D_CONST; - ac.index = D_NONE; - ac.offset = 0; // fill in - - // $method - ad.type = D_ADDR; - ad.index = D_EXTERN; - ad.sym = S; // fill in - ad.offset = 0; - - // copy externdcl list to signatlist - for(d=externdcl; d!=D; d=d->forw) { - if(d->op != OTYPE) - continue; - - t = d->dtype; - if(t == T) - continue; - - s = signame(t); - if(s == S) - continue; - - x = mal(sizeof(*d)); - x->op = OTYPE; - if(t->etype == TINTER) - x->dtype = t; - else - x->dtype = ptrto(t); - x->forw = signatlist; - x->block = 0; - signatlist = x; -//print("SIG = %lS %lS %lT\n", d->dsym, s, t); - } - - // process signatlist - for(d=signatlist; d!=D; d=d->forw) { - if(d->op != OTYPE) - continue; - t = d->dtype; - et = t->etype; - s = signame(t); - if(s == S) - continue; - - // only emit one - if(s->siggen) - continue; - s->siggen = 1; - - // interface is easy - if(et == TINTER || et == TDDD) { - if(t->sym && !t->local) - continue; - dumpsigi(t, s); - continue; - } - - // non-interface is more complex - progt = t; - methodt = t; - ifacet = t; - rcvrt = t; - - // if there's a pointer, methods are on base. - if(isptr[methodt->etype] && methodt->type->sym != S) { - methodt = methodt->type; - expandmeth(methodt->sym, methodt); - - // if methodt had a name, we don't want to see - // it in the method names that go into the sigt. - // e.g., if - // type item *rat - // then item needs its own sigt distinct from *rat, - // but it needs to have all of *rat's methods, using - // the *rat (not item) in the method names. - if(rcvrt->sym != S) - rcvrt = ptrto(methodt); - } - - // and if ifacet is too wide, the methods - // will see a pointer anyway. - if(ifacet->width > 8) { - ifacet = ptrto(progt); - rcvrt = ptrto(progt); - } - - // don't emit non-trivial signatures for types defined outside this file. - // non-trivial signatures might also drag in generated trampolines, - // and ar can't handle duplicates of the trampolines. - // only pay attention to types with symbols, because - // the ... structs and maybe other internal structs - // don't get marked as local. - if(methodt->method && methodt->sym && !methodt->local) - continue; - -//print("s=%S\n", s); - dumpsigt(progt, ifacet, rcvrt, methodt, s); - } - - if(stringo > 0) { - p = pc; - gins(AGLOBL, N, N); - p->from = ao; - p->to = ac; - p->to.offset = stringo; - } -} diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile index 2f79f31cb..0fc15deaa 100644 --- a/src/cmd/gc/Makefile +++ b/src/cmd/gc/Makefile @@ -31,6 +31,7 @@ OFILES=\ bits.$O\ align.$O\ gen.$O\ + obj.$O\ $(LIB): $(OFILES) ar rsc $(LIB) $(OFILES) diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 2654d48cc..62fd95a12 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -592,8 +592,8 @@ EXTERN Node* typeswvar; EXTERN char* context; EXTERN char* pkgcontext; -EXTERN int thechar; -EXTERN char* thestring; +extern int thechar; +extern char* thestring; EXTERN char* hunk; EXTERN int32 nhunk; EXTERN int32 thunk; @@ -979,6 +979,19 @@ struct Label EXTERN Label* labellist; EXTERN Label* findlab(Sym*); +typedef struct Plist Plist; +struct Plist +{ + Node* name; + Dcl* locals; + Prog* firstpc; + int recur; + Plist* link; +}; + +EXTERN Plist* plist; +EXTERN Plist* plast; + EXTERN Prog* continpc; EXTERN Prog* breakpc; EXTERN Prog* pc; @@ -994,10 +1007,20 @@ Label* findlab(Sym *s); void gen(Node *n); void newlab(int op, Sym *s); Node* sysfunc(char *name); +Plist* newplist(void); +/* + * obj.c + */ +void Bputdot(Biobuf *b); +void dumpfuncs(void); +void dumpglobls(void); +void dumpobj(void); +void ieeedtod(uint64 *ieee, double native); +void outhist(Biobuf *b); /* - * gen.c/gsubr.c/obj.c + * arch-specific gen.c/gsubr.c/obj.c */ void betypeinit(void); vlong convvtox(vlong, int); @@ -1021,3 +1044,21 @@ int isfat(Type*); void clearfat(Node *n); void cgen(Node*, Node*); void gused(Node*); +void dumpstrings(void); +void dumpsignatures(void); +void dumpfuncs(void); +void ggloblnod(Node *nam, int32 width); +void ggloblsym(Sym *s, int32 width, int dupok); +void zfile(Biobuf *b, char *p, int n); +void zhist(Biobuf *b, int line, vlong offset); +void zname(Biobuf *b, Sym *s, int t); +void dumpstrings(void); +void nopout(Prog*); +void datastring(char *s, int len); +int dstringptr(Sym *s, int off, char *str); +int dsymptr(Sym *s, int off, Sym *x); +int duint16(Sym *s, int off, uint32 v); +int duint32(Sym *s, int off, uint32 v); +int duintptr(Sym *s, int off, uint32 v); +int duintxx(Sym *s, int off, uint64 v, int wid); +void genembedtramp(Type*, Sig*); diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index ab7ced376..c186058b4 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -213,8 +213,6 @@ findpkg(String *name) goroot = getenv("GOROOT"); } - // BOTCH need to get .6 from backend - // try .a before .6. important for building libraries: // if there is an array.6 in the array.a library, // want to find all of array.a, not just array.6. @@ -222,7 +220,7 @@ findpkg(String *name) snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name); if(access(namebuf, 0) >= 0) return 1; - snprint(namebuf, sizeof(namebuf), "%s/%Z.6", p->dir, name); + snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, thechar); if(access(namebuf, 0) >= 0) return 1; } @@ -230,14 +228,14 @@ findpkg(String *name) snprint(namebuf, sizeof(namebuf), "%Z.a", name); if(access(namebuf, 0) >= 0) return 1; - snprint(namebuf, sizeof(namebuf), "%Z.6", name); + snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar); if(access(namebuf, 0) >= 0) return 1; if(goroot != nil) { snprint(namebuf, sizeof(namebuf), "%s/pkg/%Z.a", goroot, name); if(access(namebuf, 0) >= 0) return 1; - snprint(namebuf, sizeof(namebuf), "%s/pkg/%Z.6", goroot, name); + snprint(namebuf, sizeof(namebuf), "%s/pkg/%Z.%c", goroot, name, thechar); if(access(namebuf, 0) >= 0) return 1; } @@ -1300,7 +1298,6 @@ mkpackage(char* pkg) lookup(package)->lexical = LPACK; if(outfile == nil) { - // BOTCH need to get .6 from backend p = strrchr(infile, '/'); if(p == nil) p = infile; @@ -1310,7 +1307,6 @@ mkpackage(char* pkg) p = strrchr(namebuf, '.'); if(p != nil) *p = 0; - strncat(namebuf, ".6", sizeof(namebuf)); - outfile = strdup(namebuf); + outfile = smprint("%s.%c", namebuf, thechar); } } diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c new file mode 100644 index 000000000..7c80ee22a --- /dev/null +++ b/src/cmd/gc/obj.c @@ -0,0 +1,585 @@ +// 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" + +/* + * architecture-independent object file output + */ + +void +dumpobj(void) +{ + bout = Bopen(outfile, OWRITE); + if(bout == nil) + fatal("cant open %s", outfile); + + Bprint(bout, "%s\n", thestring); + Bprint(bout, " exports automatically generated from\n"); + Bprint(bout, " %s in package \"%s\"\n", curio.infile, package); + dumpexport(); + Bprint(bout, "\n!\n"); + + outhist(bout); + + // add nil plist w AEND to catch + // auto-generated trampolines, data + newplist(); + + dumpglobls(); + dumpstrings(); + dumpsignatures(); + dumpfuncs(); + + Bterm(bout); +} + +void +dumpglobls(void) +{ + Dcl *d; + Sym *s; + Node *n; + + // add globals + for(d=externdcl; d!=D; d=d->forw) { + if(d->op != ONAME) + continue; + + s = d->dsym; + if(s == S) + fatal("external nil"); + n = d->dnode; + if(n == N || n->type == T) + fatal("external %S nil\n", s); + + if(n->class == PFUNC) + continue; + + dowidth(n->type); + ggloblnod(s->oname, n->type->width); + } +} + +void +Bputdot(Biobuf *b) +{ + // put out middle dot · + Bputc(b, 0xc2); + Bputc(b, 0xb7); +} + +void +outhist(Biobuf *b) +{ + Hist *h; + char *p, *q, *op; + int n; + + for(h = hist; h != H; h = h->link) { + p = h->name; + op = 0; + + if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') { + op = p; + p = pathname; + } + + while(p) { + q = utfrune(p, '/'); + if(q) { + n = q-p; + if(n == 0) + n = 1; // leading "/" + q++; + } else { + n = strlen(p); + q = 0; + } + if(n) + zfile(b, p, n); + p = q; + if(p == 0 && op) { + p = op; + op = 0; + } + } + + zhist(b, h->line, h->offset); + } +} + +void +ieeedtod(uint64 *ieee, double native) +{ + double fr, ho, f; + int exp; + uint32 h, l; + + if(native < 0) { + ieeedtod(ieee, -native); + *ieee |= 1ULL<<63; + return; + } + if(native == 0) { + *ieee = 0; + return; + } + fr = frexp(native, &exp); + f = 2097152L; /* shouldnt use fp constants here */ + fr = modf(fr*f, &ho); + h = ho; + h &= 0xfffffL; + h |= (exp+1022L) << 20; + f = 65536L; + fr = modf(fr*f, &ho); + l = ho; + l <<= 16; + l |= (int32)(fr*f); + *ieee = ((uint64)h << 32) | l; +} + +/* + * Add DATA for signature s. + * progt - type in program + * ifacet - type stored in interface (==progt if small, ==ptrto(progt) if large) + * rcvrt - type used as method interface. eqtype(ifacet, rcvrt) is always true, + * but ifacet might have a name that rcvrt does not. + * methodt - type with methods hanging off it (progt==*methodt sometimes) + * + * memory layout is Sigt struct from iface.c: + * struct Sigt + * { + * byte* name; // name of basic type + * Sigt* link; // for linking into hash tables + * uint32 thash; // hash of type + * uint32 mhash; // hash of methods + * uint16 width; // width of base type in bytes + * uint16 alg; // algorithm + * struct { + * byte* fname; + * uint32 fhash; // hash of type + * uint32 offset; // offset of substruct + * void (*fun)(void); + * } meth[1]; // one or more - last name is nil + * }; + */ + +static int +sigcmp(Sig *a, Sig *b) +{ + return strcmp(a->name, b->name); +} + +void +dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s) +{ + Type *f; + int o; + Sig *a, *b; + char buf[NSYMB]; + Type *this; + Iter savet; + Prog *oldlist; + Sym *method; + uint32 sighash; + int ot; + + a = nil; + o = 0; + oldlist = nil; + sighash = typehash(progt, 1, 0); + for(f=methodt->method; f!=T; f=f->down) { + if(f->type->etype != TFUNC) + continue; + + if(f->etype != TFIELD) + fatal("dumpsignatures: not field"); + + method = f->sym; + if(method == nil) + continue; + + b = mal(sizeof(*b)); + b->link = a; + a = b; + + a->name = method->name; + a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0); + if(!exportname(a->name)) + a->hash += PRIME10*stringhash(package); + a->perm = o; + a->sym = methodsym(method, rcvrt); + + sighash = sighash*100003 + a->hash; + + if(!a->sym->siggen) { + a->sym->siggen = 1; + // TODO(rsc): This test is still not quite right. + + this = structfirst(&savet, getthis(f->type))->type; + if(isptr[this->etype] != isptr[ifacet->etype]) { + if(oldlist == nil) + oldlist = pc; + + // indirect vs direct mismatch + Sym *oldname, *newname; + Type *oldthis, *newthis; + + newthis = ifacet; + if(isptr[newthis->etype]) + oldthis = ifacet->type; + else + oldthis = ptrto(ifacet); + newname = a->sym; + oldname = methodsym(method, oldthis); + genptrtramp(method, oldname, oldthis, f->type, newname, newthis); + } else + if(f->embedded) { + // TODO(rsc): only works for pointer receivers + if(oldlist == nil) + oldlist = pc; + genembedtramp(ifacet, a); + } + } + o++; + } + + // restore data output + if(oldlist) { + // old list ended with AEND; change to ANOP + // so that the trampolines that follow can be found. + nopout(oldlist); + + // start new data list + newplist(); + } + + a = lsort(a, sigcmp); + ot = 0; + ot = rnd(ot, maxround); // base structure + + // base of type signature contains parameters + snprint(buf, sizeof buf, "%#T", progt); + ot = dstringptr(s, ot, buf); // name + ot = duintptr(s, ot, 0); // skip link + ot = duint32(s, ot, typehash(progt, 1, 0)); // thash + ot = duint32(s, ot, sighash); // mhash + ot = duint16(s, ot, progt->width); // width + ot = duint16(s, ot, algtype(progt)); // algorithm + + for(b=a; b!=nil; b=b->link) { + ot = rnd(ot, maxround); // base of substructure + ot = dstringptr(s, ot, b->name); // field name + ot = duint32(s, ot, b->hash); // hash + ot = duint32(s, ot, 0); // offset + ot = dsymptr(s, ot, b->sym); // &method + } + + // nil field name at end + ot = rnd(ot, maxround); + ot = duintptr(s, ot, 0); + + // set DUPOK to allow other .6s to contain + // the same signature. only one will be chosen. + // should only happen for empty signatures + ggloblsym(s, ot, a == nil); +} + +/* + * memory layout is Sigi struct from iface.c: + * struct Sigi + * { + * byte* name; + * uint32 hash; + * uint32 size; // number of methods + * struct { + * byte* fname; + * uint32 fhash; + * uint32 perm; // location of fun in Sigt + * } meth[1]; // [size+1] - last name is nil + * }; + */ +void +dumpsigi(Type *t, Sym *s) +{ + Type *f; + Sym *s1; + int o; + Sig *a, *b; + char buf[NSYMB]; + uint32 sighash; + int ot; + + a = nil; + o = 0; + sighash = 0; + for(f=t->type; f!=T; f=f->down) { + if(f->type->etype != TFUNC) + continue; + + if(f->etype != TFIELD) + fatal("dumpsignatures: not field"); + + s1 = f->sym; + if(s1 == nil) + continue; + + b = mal(sizeof(*b)); + b->link = a; + a = b; + + a->name = s1->name; + a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0, 0); + if(!exportname(a->name)) + a->hash += PRIME10*stringhash(package); + a->perm = o; + a->sym = methodsym(f->sym, t); + a->offset = 0; + + sighash = sighash*100003 + a->hash; + + o++; + } + + a = lsort(a, sigcmp); + ot = 0; + ot = rnd(ot, maxround); // base structure + + // sigi[0].name = type name, for runtime error message + snprint(buf, sizeof buf, "%#T", t); + ot = dstringptr(s, ot, buf); + + // first field of an interface signature + // contains the count and is not a real entry + + // sigi[0].hash = sighash + ot = duint32(s, ot, sighash); + + // sigi[0].offset = count + o = 0; + for(b=a; b!=nil; b=b->link) + o++; + ot = duint32(s, ot, o); + + for(b=a; b!=nil; b=b->link) { +//print(" %s\n", b->name); + ot = rnd(ot, maxround); // base structure + + // sigx[++].name = "fieldname" + // sigx[++].hash = hashcode + // sigi[++].perm = mapped offset of method + ot = dstringptr(s, ot, b->name); + ot = duint32(s, ot, b->hash); + ot = duint32(s, ot, b->perm); + } + + // nil field name at end + ot = rnd(ot, maxround); + ot = duintptr(s, ot, 0); + + // TODO(rsc): DUPOK should not be necessary here, + // and I am a bit worried that it is. If I turn it off, + // I get multiple definitions for sigi.dotdotdot. + ggloblsym(s, ot, 1); +} + +void +dumpsignatures(void) +{ + int et; + Dcl *d, *x; + Type *t, *progt, *methodt, *ifacet, *rcvrt; + Sym *s; + + // copy externdcl list to signatlist + for(d=externdcl; d!=D; d=d->forw) { + if(d->op != OTYPE) + continue; + + t = d->dtype; + if(t == T) + continue; + + s = signame(t); + if(s == S) + continue; + + x = mal(sizeof(*d)); + x->op = OTYPE; + if(t->etype == TINTER) + x->dtype = t; + else + x->dtype = ptrto(t); + x->forw = signatlist; + x->block = 0; + signatlist = x; +//print("SIG = %lS %lS %lT\n", d->dsym, s, t); + } + + // process signatlist + for(d=signatlist; d!=D; d=d->forw) { + if(d->op != OTYPE) + continue; + t = d->dtype; + et = t->etype; + s = signame(t); + if(s == S) + continue; + + // only emit one + if(s->siggen) + continue; + s->siggen = 1; + + // interface is easy + if(et == TINTER || et == TDDD) { + if(t->sym && !t->local) + continue; + dumpsigi(t, s); + continue; + } + + // non-interface is more complex + progt = t; + methodt = t; + ifacet = t; + rcvrt = t; + + // if there's a pointer, methods are on base. + if(isptr[methodt->etype] && methodt->type->sym != S) { + methodt = methodt->type; + expandmeth(methodt->sym, methodt); + + // if methodt had a name, we don't want to see + // it in the method names that go into the sigt. + // e.g., if + // type item *rat + // then item needs its own sigt distinct from *rat, + // but it needs to have all of *rat's methods, using + // the *rat (not item) in the method names. + if(rcvrt->sym != S) + rcvrt = ptrto(methodt); + } + + // and if ifacet is too wide, the methods + // will see a pointer anyway. + if(ifacet->width > 8) { + ifacet = ptrto(progt); + rcvrt = ptrto(progt); + } + + // don't emit non-trivial signatures for types defined outside this file. + // non-trivial signatures might also drag in generated trampolines, + // and ar can't handle duplicates of the trampolines. + // only pay attention to types with symbols, because + // the ... structs and maybe other internal structs + // don't get marked as local. + if(methodt->method && methodt->sym && !methodt->local) + continue; + +//print("s=%S\n", s); + dumpsigt(progt, ifacet, rcvrt, methodt, s); + } + + if(stringo > 0) + ggloblsym(symstringo, stringo, 0); +} + +void +stringpool(Node *n) +{ + Pool *p; + int w; + + if(n->op != OLITERAL || n->val.ctype != CTSTR) { + if(n->val.ctype == CTNIL) + return; + fatal("stringpool: not string %N", n); + } + + p = mal(sizeof(*p)); + + p->sval = n->val.u.sval; + p->link = nil; + + if(poolist == nil) + poolist = p; + else + poolast->link = p; + poolast = p; + + w = types[TINT32]->width; + symstringo->offset += w; // len + symstringo->offset += p->sval->len; // str[len] + symstringo->offset = rnd(symstringo->offset, w); +} + +Sig* +lsort(Sig *l, int(*f)(Sig*, Sig*)) +{ + Sig *l1, *l2, *le; + + if(l == 0 || l->link == 0) + return l; + + l1 = l; + l2 = l; + for(;;) { + l2 = l2->link; + if(l2 == 0) + break; + l2 = l2->link; + if(l2 == 0) + break; + l1 = l1->link; + } + + l2 = l1->link; + l1->link = 0; + l1 = lsort(l, f); + l2 = lsort(l2, f); + + /* set up lead element */ + if((*f)(l1, l2) < 0) { + l = l1; + l1 = l1->link; + } else { + l = l2; + l2 = l2->link; + } + le = l; + + for(;;) { + if(l1 == 0) { + while(l2) { + le->link = l2; + le = l2; + l2 = l2->link; + } + le->link = 0; + break; + } + if(l2 == 0) { + while(l1) { + le->link = l1; + le = l1; + l1 = l1->link; + } + break; + } + if((*f)(l1, l2) < 0) { + le->link = l1; + le = l1; + l1 = l1->link; + } else { + le->link = l2; + le = l2; + l2 = l2->link; + } + } + le->link = 0; + return l; +} + diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 403f3dd28..d6414f7eb 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -2404,102 +2404,6 @@ tempname(Node *n, Type *t) } void -stringpool(Node *n) -{ - Pool *p; - int w; - - if(n->op != OLITERAL || n->val.ctype != CTSTR) { - if(n->val.ctype == CTNIL) - return; - fatal("stringpool: not string %N", n); - } - - p = mal(sizeof(*p)); - - p->sval = n->val.u.sval; - p->link = nil; - - if(poolist == nil) - poolist = p; - else - poolast->link = p; - poolast = p; - - w = types[TINT32]->width; - symstringo->offset += w; // len - symstringo->offset += p->sval->len; // str[len] - symstringo->offset = rnd(symstringo->offset, w); -} - -Sig* -lsort(Sig *l, int(*f)(Sig*, Sig*)) -{ - Sig *l1, *l2, *le; - - if(l == 0 || l->link == 0) - return l; - - l1 = l; - l2 = l; - for(;;) { - l2 = l2->link; - if(l2 == 0) - break; - l2 = l2->link; - if(l2 == 0) - break; - l1 = l1->link; - } - - l2 = l1->link; - l1->link = 0; - l1 = lsort(l, f); - l2 = lsort(l2, f); - - /* set up lead element */ - if((*f)(l1, l2) < 0) { - l = l1; - l1 = l1->link; - } else { - l = l2; - l2 = l2->link; - } - le = l; - - for(;;) { - if(l1 == 0) { - while(l2) { - le->link = l2; - le = l2; - l2 = l2->link; - } - le->link = 0; - break; - } - if(l2 == 0) { - while(l1) { - le->link = l1; - le = l1; - l1 = l1->link; - } - break; - } - if((*f)(l1, l2) < 0) { - le->link = l1; - le = l1; - l1 = l1->link; - } else { - le->link = l2; - le = l2; - l2 = l2->link; - } - } - le->link = 0; - return l; -} - -void setmaxarg(Type *t) { int32 w; |