From a3c4faf83f1849198b5431aa050793124a2fc91d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 20 Jan 2009 15:36:43 -0800 Subject: [PATCH] 6l: do not link in objects from an archive just for init functions. (makes go libraries behave more like c libraries.) R=r DELTA=85 (67 added, 12 deleted, 6 changed) OCL=23133 CL=23139 --- src/cmd/6l/go.c | 32 ++++++++++++++++++++++++++++++++ src/cmd/6l/l.h | 9 ++++++++- src/cmd/6l/obj.c | 25 +++++++++---------------- src/cmd/6l/pass.c | 25 ++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/cmd/6l/go.c b/src/cmd/6l/go.c index 10ebe3fdbb..07a0f21d54 100644 --- a/src/cmd/6l/go.c +++ b/src/cmd/6l/go.c @@ -489,3 +489,35 @@ definetypesigs(void) if(debug['v']) Bprint(&bso, "%5.2f typesigs %d\n", cputime(), n); } + +int +isinitfunc(Sym *s) +{ + char *p; + + p = utfrune(s->name, 0xb7); // 0xb7 = '·' + if(p == nil) + return 0; + if(memcmp(p, "·Init·", 8) == 0 || memcmp(p, "·init·", 8) == 0) + return 1; + return 0; +} + +void +ignoreoptfuncs(void) +{ + Prog *p; + + // nop out calls to optional functions + // that were not pulled in from libraries. + for(p=firstp; p != P; p=p->link) { + if(p->to.sym != S && p->to.sym->type == SOPT) { + if(p->as != ACALL) + diag("bad use of optional function: %P", p); + p->as = ANOP; + p->from.type = D_NONE; + p->to.type = D_NONE; + } + } +} + diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h index e6ce0e7b23..4a2c456f2d 100644 --- a/src/cmd/6l/l.h +++ b/src/cmd/6l/l.h @@ -112,12 +112,14 @@ struct Sym short version; short become; short frame; + ushort file; uchar subtype; uchar dupok; - ushort file; + uchar reachable; vlong value; int32 sig; Sym* link; + Prog* text; }; struct Optab { @@ -146,6 +148,7 @@ enum SFILE, SCONST, SUNDEF, + SOPT, SIMPORT, SEXPORT, @@ -381,8 +384,10 @@ void ckoff(Sym*, int32); Prog* copyp(Prog*); double cputime(void); void datblk(int32, int32); +void ignoreoptfuncs(void); void definetypestrings(void); void definetypesigs(void); +void deadcode(void); void diag(char*, ...); void dodata(void); void doinit(void); @@ -415,6 +420,7 @@ void main(int, char*[]); void mkfwd(void); void* mysbrk(uint32); Prog* newdata(Sym*, int, int, int); +Prog* newtext(Prog*, Sym*); void nuxiinit(void); void objfile(char*); int opsize(Prog*); @@ -434,6 +440,7 @@ void xdefine(char*, int, vlong); void xfol(Prog*); void zaddr(Biobuf*, Adr*, Sym*[]); void zerosig(char*); +int isinitfunc(Sym*); void machseg(char*, vlong, vlong, vlong, vlong, uint32, uint32, uint32, uint32); void machsymseg(uint32, uint32); diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c index a250f1c45c..d6af049d9a 100644 --- a/src/cmd/6l/obj.c +++ b/src/cmd/6l/obj.c @@ -368,6 +368,8 @@ main(int argc, char *argv[]) sprint(a, "%s/lib/lib_%s_%s.a", goroot, goarch, goos); objfile(a); } + ignoreoptfuncs(); + // TODO(rsc): remove unused code and data definetypestrings(); definetypesigs(); @@ -945,8 +947,11 @@ loop: if(debug['W']) print(" ANAME %s\n", s->name); h[o] = s; - if((v == D_EXTERN || v == D_STATIC) && s->type == 0) + if((v == D_EXTERN || v == D_STATIC) && s->type == 0) { s->type = SXREF; + if(isinitfunc(s)) + s->type = SOPT; // optional function; don't pull in an object file just for s. + } if(v == D_FILE) { if(s->type != SFILE) { histgen++; @@ -1083,7 +1088,7 @@ loop: case ATEXT: s = p->from.sym; - if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { + if(ntext++ == 0 && s->type != 0 && s->type != SXREF && s->type != SOPT) { /* redefinition, so file has probably been seen before */ if(debug['v']) Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); @@ -1100,26 +1105,14 @@ loop: diag("%s: no TEXT symbol: %P", pn, p); errorexit(); } - if(s->type != 0 && s->type != SXREF) { + if(s->type != 0 && s->type != SXREF && s->type != SOPT) { if(p->from.scale & DUPOK) { skip = 1; goto casdef; } diag("%s: redefinition: %s\n%P", pn, s->name, p); } - s->type = STEXT; - s->value = pc; - lastp->link = p; - lastp = p; - p->pc = pc; - pc++; - if(textp == P) { - textp = p; - etextp = p; - goto loop; - } - etextp->pcond = p; - etextp = p; + newtext(p, s); goto loop; case AMODE: diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c index e5316fe467..45617ac561 100644 --- a/src/cmd/6l/pass.c +++ b/src/cmd/6l/pass.c @@ -398,7 +398,8 @@ patch(void) q = q->link; } if(q == P) { - diag("branch out of range in %s\n%P", TNAME, p); + diag("branch out of range in %s\n%P [%s]", + TNAME, p, p->to.sym ? p->to.sym->name : ""); p->to.type = D_NONE; } p->pcond = q; @@ -853,6 +854,28 @@ newdata(Sym *s, int o, int w, int t) return p; } +Prog* +newtext(Prog *p, Sym *s) +{ + if(p == P) { + p = prg(); + p->as = ATEXT; + p->from.sym = s; + } + s->type = STEXT; + s->text = p; + s->value = pc; + lastp->link = p; + lastp = p; + p->pc = pc++; + if(textp == P) + textp = p; + else + etextp->pcond = p; + etextp = p; + return p; +} + void export(void) { -- 2.48.1