summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-01-20 15:36:43 -0800
committerRuss Cox <rsc@golang.org>2009-01-20 15:36:43 -0800
commitbe323cab54e32b56ff7c58ce0828a486bb328d3f (patch)
treed32b7a674c46e005de789ff680eec98f5e729fca
parent8498cd2641a58da02b38cab7a7ea9efb1064f243 (diff)
downloadgolang-be323cab54e32b56ff7c58ce0828a486bb328d3f.tar.gz
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
-rw-r--r--src/cmd/6l/go.c32
-rw-r--r--src/cmd/6l/l.h9
-rw-r--r--src/cmd/6l/obj.c25
-rw-r--r--src/cmd/6l/pass.c25
4 files changed, 73 insertions, 18 deletions
diff --git a/src/cmd/6l/go.c b/src/cmd/6l/go.c
index 10ebe3fdb..07a0f21d5 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 e6ce0e7b2..4a2c456f2 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 a250f1c45..d6af049d9 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 e5316fe46..45617ac56 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 : "<nil>");
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)
{