summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-05-06 13:47:40 -0700
committerRuss Cox <rsc@golang.org>2009-05-06 13:47:40 -0700
commit1bd3e3203f230c1f8ff2c21d3da14863f20ae09d (patch)
tree311039ca72c300e29c1161827219d51e7300a992
parent49aace720afdc145fc3abecbb438db5e7ad8b3da (diff)
downloadgolang-1bd3e3203f230c1f8ff2c21d3da14863f20ae09d.tar.gz
6g: generate string data as individual symbols,
so that 6l can discard strings used by dead code. also, for short strings, generate DUPOK global symbols so that references to, say, "%s: %s" in multiple files result in only a single symbol. R=ken OCL=28361 CL=28361
-rw-r--r--src/cmd/6g/gg.h1
-rw-r--r--src/cmd/6g/gsubr.c8
-rw-r--r--src/cmd/6g/obj.c190
-rw-r--r--src/cmd/gc/go.h20
-rw-r--r--src/cmd/gc/lex.c3
-rw-r--r--src/cmd/gc/obj.c38
6 files changed, 142 insertions, 118 deletions
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index ed2e703db..0cebfba46 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -122,6 +122,7 @@ int isfat(Type*);
void sudoclean(void);
int sudoaddable(int, Node*, Addr*);
void afunclit(Addr*);
+void datagostring(Strlit*, Addr*);
/*
* list.c
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index 25a16a20e..b29cab304 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -152,8 +152,6 @@ ggloblsym(Sym *s, int32 width, int dupok)
p = gins(AGLOBL, N, N);
p->from.type = D_EXTERN;
- if(s == symstringl || s == symstringc)
- p->from.type = D_STATIC;
p->from.index = D_NONE;
p->from.sym = s;
p->to.type = D_CONST;
@@ -1146,11 +1144,7 @@ naddr(Node *n, Addr *a)
a->offset = mpgetfix(n->val.u.xval);
break;
case CTSTR:
- a->etype = simtype[n->etype];
- a->sym = symstringl;
- a->type = D_STATIC;
- a->offset = symstringl->offset;
- stringpool(n);
+ datagostring(n->val.u.sval, a);
break;
case CTBOOL:
a->sym = S;
diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c
index ac249b6b6..bdbf5c767 100644
--- a/src/cmd/6g/obj.c
+++ b/src/cmd/6g/obj.c
@@ -261,23 +261,75 @@ dumpfuncs(void)
}
}
+/* deferred DATA output */
+static Prog *strdat;
+static Prog *estrdat;
+static int gflag;
+static Prog *savepc;
+
+static void
+data(void)
+{
+ gflag = debug['g'];
+ debug['g'] = 0;
+
+ if(estrdat == nil) {
+ strdat = mal(sizeof(*pc));
+ clearp(strdat);
+ estrdat = strdat;
+ }
+ if(savepc)
+ fatal("data phase error");
+ savepc = pc;
+ pc = estrdat;
+}
+
+static void
+text(void)
+{
+ if(!savepc)
+ fatal("text phase error");
+ debug['g'] = gflag;
+ estrdat = pc;
+ pc = savepc;
+ savepc = nil;
+}
+
+void
+dumpdata(void)
+{
+ Prog *p;
+
+ if(estrdat == nil)
+ return;
+ *pc = *strdat;
+ if(gflag)
+ for(p=pc; p!=estrdat; p=p->link)
+ print("%P\n", p);
+ pc = estrdat;
+}
+
/*
- * dump the characters of the string
- * pool into the array symstringc
+ * make a refer to the data s, s+len
+ * emitting DATA if needed.
*/
void
-datastring(char *s, int len)
+datastring(char *s, int len, Addr *a)
{
int w;
Prog *p;
Addr ac, ao;
-
+ static int gen;
+ struct {
+ Strlit lit;
+ char buf[100];
+ } tmp;
+
// string
memset(&ao, 0, sizeof(ao));
ao.type = D_STATIC;
ao.index = D_NONE;
ao.etype = TINT32;
- ao.sym = symstringc;
ao.offset = 0; // fill in
// constant
@@ -286,13 +338,37 @@ datastring(char *s, int len)
ac.index = D_NONE;
ac.offset = 0; // fill in
+ // huge strings are made static to avoid long names.
+ if(len > 100) {
+ snprint(namebuf, sizeof(namebuf), ".string.%d", gen++);
+ ao.sym = lookup(namebuf);
+ ao.type = D_STATIC;
+ } else {
+ if(len > 0 && s[len-1] == '\0')
+ len--;
+ tmp.lit.len = len;
+ memmove(tmp.lit.s, s, len);
+ tmp.lit.s[len] = '\0';
+ len++;
+ snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
+ ao.sym = pkglookup(namebuf, "string");
+ ao.type = D_EXTERN;
+ }
+ *a = ao;
+
+ // only generate data the first time.
+ if(ao.sym->uniq)
+ return;
+ ao.sym->uniq = 1;
+
+ data();
for(w=0; w<len; w+=8) {
p = pc;
gins(ADATA, N, N);
- // .stringo<>+oo, [NSNAME], $"xxx"
+ // DATA s+w, [NSNAME], $"xxx"
p->from = ao;
- p->from.offset = stringc;
+ p->from.offset = w;
p->from.scale = NSNAME;
if(w+8 > len)
@@ -302,25 +378,25 @@ datastring(char *s, int len)
p->to.type = D_SCONST;
p->to.offset = len;
memmove(p->to.sval, s+w, p->from.scale);
- stringc += p->from.scale;
}
+ p = pc;
+ ggloblsym(ao.sym, len, ao.type == D_EXTERN);
+ if(ao.type == D_STATIC)
+ p->from.type = D_STATIC;
+ text();
}
/*
- * dump the strings into thye pool
- * symstingl that consists of a pointer
- * to the characters and a count
+ * make a refer to the string sval,
+ * emitting DATA if needed.
*/
void
-dumpstrings(void)
+datagostring(Strlit *sval, Addr *a)
{
- Pool *l;
Prog *p;
Addr ac, ao, ap;
- int32 wi, wp, ws;
-
- if(poolist == nil)
- return;
+ int32 wi, wp;
+ static int gen;
memset(&ac, 0, sizeof(ac));
memset(&ao, 0, sizeof(ao));
@@ -332,49 +408,61 @@ dumpstrings(void)
ac.offset = 0; // fill in
// string len+ptr
- ao.type = D_STATIC;
+ ao.type = D_STATIC; // fill in
ao.index = D_NONE;
ao.etype = TINT32;
- ao.sym = symstringl;
- ao.offset = 0; // fill in
+ ao.sym = nil; // fill in
// $string len+ptr
+ datastring(sval->s, sval->len, &ap);
+ ap.index = ap.type;
ap.type = D_ADDR;
- ap.index = D_STATIC;
ap.etype = TINT32;
- ap.sym = symstringc;
- ap.offset = 0; // fill in
wi = types[TUINT32]->width;
wp = types[tptr]->width;
- ws = types[TSTRING]->width;
-
- // lay out (count+string)
- for(l=poolist; l!=nil; l=l->link) {
+
+ if(ap.index == D_STATIC) {
+ // huge strings are made static to avoid long names
+ snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
+ ao.sym = lookup(namebuf);
+ ao.type = D_STATIC;
+ } else {
+ // small strings get named by their contents,
+ // so that multiple modules using the same string
+ // can share it.
+ snprint(namebuf, sizeof(namebuf), "\"%Z\"", sval);
+ ao.sym = pkglookup(namebuf, "go.string");
+ ao.type = D_EXTERN;
+ }
- // .stringl<>+ol, wp, $.stringc<>+oc
- p = pc;
- gins(ADATA, N, N);
- p->from = ao;
- p->from.offset = stringl;
- p->from.scale = wp;
- p->to = ap;
- p->to.offset = stringc;
- stringl += wp;
+ *a = ao;
+ if(ao.sym->uniq)
+ return;
+ ao.sym->uniq = 1;
- // .stringl<>+ol, wi, $len
- p = pc;
- gins(ADATA, N, N);
- p->from = ao;
- p->from.offset = stringl;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = l->sval->len;
- stringl += wi;
+ data();
+ // DATA gostring, wp, $cstring
+ p = pc;
+ gins(ADATA, N, N);
+ p->from = ao;
+ p->from.scale = wp;
+ p->to = ap;
- stringl = rnd(stringl, ws);
- datastring(l->sval->s, l->sval->len);
- }
+ // DATA gostring+wp, wi, $len
+ p = pc;
+ gins(ADATA, N, N);
+ p->from = ao;
+ p->from.offset = wp;
+ p->from.scale = wi;
+ p->to = ac;
+ p->to.offset = sval->len;
+
+ p = pc;
+ ggloblsym(ao.sym, types[TSTRING]->width, ao.type == D_EXTERN);
+ if(ao.type == D_STATIC)
+ p->from.type = D_STATIC;
+ text();
}
int
@@ -390,14 +478,12 @@ dstringptr(Sym *s, int off, char *str)
p->from.offset = off;
p->from.scale = widthptr;
+ datastring(str, strlen(str)+1, &p->to);
+ p->to.index = p->to.type;
p->to.type = D_ADDR;
- p->to.index = D_STATIC;
p->to.etype = TINT32;
- p->to.sym = symstringc;
- p->to.offset = stringc;
off += widthptr;
- datastring(str, strlen(str)+1);
return off;
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index cdf2e2f1f..5b0da4cad 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -463,20 +463,6 @@ struct Sig
Sig* link;
};
-typedef struct Pool Pool;
-struct Pool
-{
- Strlit* sval;
- Pool* link;
-};
-
-EXTERN Pool* poolist;
-EXTERN Pool* poolast;
-EXTERN Sym* symstringl; // string literals
-EXTERN Sym* symstringc; // string characters
-EXTERN int32 stringl; // size of string literals
-EXTERN int32 stringc; // size of string characters
-
typedef struct Io Io;
struct Io
{
@@ -785,7 +771,6 @@ int brrev(int);
void setmaxarg(Type*);
Sig* lsort(Sig*, int(*)(Sig*, Sig*));
int dotoffset(Node*, int*, Node**);
-void stringpool(Node*);
void tempname(Node*, Type*);
int Econv(Fmt*);
@@ -1029,7 +1014,6 @@ Plist* newplist(void);
* obj.c
*/
void Bputdot(Biobuf *b);
-void dumpfuncs(void);
void dumpglobls(void);
void dumpobj(void);
void ieeedtod(uint64 *ieee, double native);
@@ -1060,17 +1044,15 @@ int isfat(Type*);
void clearfat(Node *n);
void cgen(Node*, Node*);
void gused(Node*);
-void dumpstrings(void);
void dumpsignatures(void);
void dumpfuncs(void);
+void dumpdata(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);
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 6457bf12a..b84d91ba7 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -66,9 +66,6 @@ main(int argc, char *argv[])
lexinit();
typeinit(LBASETYPE);
- symstringl = lookup(".stringl"); // string literals (ptr to char and count)
- symstringc = lookup(".stringc"); // string characters
-
lineno = 1;
block = 1;
blockgen = 1;
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 037cd4d48..6c67b6dfa 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -28,8 +28,8 @@ dumpobj(void)
newplist();
dumpglobls();
- dumpstrings();
dumpsignatures();
+ dumpdata();
dumpfuncs();
Bterm(bout);
@@ -483,42 +483,6 @@ dumpsignatures(void)
//print("s=%S\n", s);
dumpsigt(progt, ifacet, rcvrt, methodt, s);
}
-
- if(stringl > 0) {
- stringl = rnd(stringl, maxround);
- ggloblsym(symstringl, stringl, 0);
- if(stringc == 0)
- stringc = 1;
- }
- if(stringc > 0) {
- stringc = rnd(stringc, maxround);
- ggloblsym(symstringc, stringc, 0);
- }
-}
-
-void
-stringpool(Node *n)
-{
- Pool *p;
-
- 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;
-
- symstringl->offset += types[TSTRING]->width;
}
Sig*