summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-03-30 21:31:29 -0700
committerRuss Cox <rsc@golang.org>2009-03-30 21:31:29 -0700
commitb9334f573c4f5a170e65bb7085129befa894b06b (patch)
tree8d1ab31c6b7e903abc62d44808d5198241702af1
parentdd1ccb897369eef6766d0c83d837cbf4bb2e1f8d (diff)
downloadgolang-b9334f573c4f5a170e65bb7085129befa894b06b.tar.gz
move portable object routines (especially
signature generation) into gc. R=ken OCL=26933 CL=26933
-rw-r--r--src/cmd/6g/Makefile2
-rw-r--r--src/cmd/6g/align.c4
-rw-r--r--src/cmd/6g/gg.h25
-rw-r--r--src/cmd/6g/gsubr.c31
-rw-r--r--src/cmd/6g/obj.c863
-rw-r--r--src/cmd/gc/Makefile1
-rw-r--r--src/cmd/gc/go.h47
-rw-r--r--src/cmd/gc/lex.c12
-rw-r--r--src/cmd/gc/obj.c585
-rw-r--r--src/cmd/gc/subr.c96
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;