mirror of
https://github.com/golang/go
synced 2024-11-22 12:44:50 -07:00
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
This commit is contained in:
parent
0c3a43e7b2
commit
83cd4ee070
@ -122,6 +122,7 @@ int isfat(Type*);
|
||||
void sudoclean(void);
|
||||
int sudoaddable(int, Node*, Addr*);
|
||||
void afunclit(Addr*);
|
||||
void datagostring(Strlit*, Addr*);
|
||||
|
||||
/*
|
||||
* list.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;
|
||||
|
194
src/cmd/6g/obj.c
194
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) {
|
||||
|
||||
// .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;
|
||||
|
||||
// .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;
|
||||
|
||||
stringl = rnd(stringl, ws);
|
||||
datastring(l->sval->s, l->sval->len);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
*a = ao;
|
||||
if(ao.sym->uniq)
|
||||
return;
|
||||
ao.sym->uniq = 1;
|
||||
|
||||
data();
|
||||
// DATA gostring, wp, $cstring
|
||||
p = pc;
|
||||
gins(ADATA, N, N);
|
||||
p->from = ao;
|
||||
p->from.scale = wp;
|
||||
p->to = ap;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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*
|
||||
|
Loading…
Reference in New Issue
Block a user