mirror of
https://github.com/golang/go
synced 2024-11-26 06:57:56 -07:00
move portable object routines (especially
signature generation) into gc. R=ken OCL=26933 CL=26933
This commit is contained in:
parent
941ed00b1d
commit
5e792b6c09
@ -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\
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
925
src/cmd/6g/obj.c
925
src/cmd/6g/obj.c
@ -31,58 +31,148 @@
|
||||
#include "gg.h"
|
||||
|
||||
void
|
||||
dumpobj(void)
|
||||
zname(Biobuf *b, Sym *s, int t)
|
||||
{
|
||||
char *n;
|
||||
|
||||
Bputc(b, ANAME); /* as */
|
||||
Bputc(b, ANAME>>8); /* as */
|
||||
Bputc(b, t); /* type */
|
||||
Bputc(b, s->sym); /* sym */
|
||||
|
||||
for(n=s->opackage; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputdot(b);
|
||||
for(n=s->name; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputc(b, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
t = 0;
|
||||
if(a->index != D_NONE || a->scale != 0)
|
||||
t |= T_INDEX;
|
||||
if(s != 0)
|
||||
t |= T_SYM;
|
||||
|
||||
switch(a->type) {
|
||||
|
||||
case D_BRANCH:
|
||||
a->offset = a->branch->loc;
|
||||
|
||||
default:
|
||||
t |= T_TYPE;
|
||||
|
||||
case D_NONE:
|
||||
if(a->offset != 0) {
|
||||
t |= T_OFFSET;
|
||||
l = a->offset;
|
||||
if((vlong)l != a->offset)
|
||||
t |= T_64;
|
||||
}
|
||||
break;
|
||||
case D_FCONST:
|
||||
t |= T_FCONST;
|
||||
break;
|
||||
case D_SCONST:
|
||||
t |= T_SCONST;
|
||||
break;
|
||||
}
|
||||
Bputc(b, t);
|
||||
|
||||
if(t & T_INDEX) { /* implies index, scale */
|
||||
Bputc(b, a->index);
|
||||
Bputc(b, a->scale);
|
||||
}
|
||||
if(t & T_OFFSET) { /* implies offset */
|
||||
l = a->offset;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
if(t & T_64) {
|
||||
l = a->offset>>32;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
}
|
||||
}
|
||||
if(t & T_SYM) /* implies sym */
|
||||
Bputc(b, s);
|
||||
if(t & T_FCONST) {
|
||||
ieeedtod(&e, a->dval);
|
||||
l = e;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
l = e >> 32;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
return;
|
||||
}
|
||||
if(t & T_SCONST) {
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(t & T_TYPE)
|
||||
Bputc(b, a->type);
|
||||
}
|
||||
|
||||
void
|
||||
dumpfuncs(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();
|
||||
struct { Sym *sym; short type; } h[NSYM];
|
||||
Sym *s;
|
||||
Prog *p;
|
||||
|
||||
for(sym=0; sym<NSYM; sym++) {
|
||||
h[sym].sym = S;
|
||||
@ -169,210 +259,6 @@ dumpobj(void)
|
||||
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;
|
||||
|
||||
Bputc(b, ANAME); /* as */
|
||||
Bputc(b, ANAME>>8); /* as */
|
||||
Bputc(b, t); /* type */
|
||||
Bputc(b, s->sym); /* sym */
|
||||
|
||||
for(n=s->opackage; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputdot(b);
|
||||
for(n=s->name; *n; n++)
|
||||
Bputc(b, *n);
|
||||
Bputc(b, 0);
|
||||
}
|
||||
|
||||
void
|
||||
zaddr(Biobuf *b, Addr *a, int s)
|
||||
{
|
||||
int32 l;
|
||||
int i, t;
|
||||
char *n;
|
||||
Ieee e;
|
||||
|
||||
t = 0;
|
||||
if(a->index != D_NONE || a->scale != 0)
|
||||
t |= T_INDEX;
|
||||
if(s != 0)
|
||||
t |= T_SYM;
|
||||
|
||||
switch(a->type) {
|
||||
|
||||
case D_BRANCH:
|
||||
a->offset = a->branch->loc;
|
||||
|
||||
default:
|
||||
t |= T_TYPE;
|
||||
|
||||
case D_NONE:
|
||||
if(a->offset != 0) {
|
||||
t |= T_OFFSET;
|
||||
l = a->offset;
|
||||
if((vlong)l != a->offset)
|
||||
t |= T_64;
|
||||
}
|
||||
break;
|
||||
case D_FCONST:
|
||||
t |= T_FCONST;
|
||||
break;
|
||||
case D_SCONST:
|
||||
t |= T_SCONST;
|
||||
break;
|
||||
}
|
||||
Bputc(b, t);
|
||||
|
||||
if(t & T_INDEX) { /* implies index, scale */
|
||||
Bputc(b, a->index);
|
||||
Bputc(b, a->scale);
|
||||
}
|
||||
if(t & T_OFFSET) { /* implies offset */
|
||||
l = a->offset;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
if(t & T_64) {
|
||||
l = a->offset>>32;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
}
|
||||
}
|
||||
if(t & T_SYM) /* implies sym */
|
||||
Bputc(b, s);
|
||||
if(t & T_FCONST) {
|
||||
ieeedtod(&e, a->dval);
|
||||
l = e.l;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
l = e.h;
|
||||
Bputc(b, l);
|
||||
Bputc(b, l>>8);
|
||||
Bputc(b, l>>16);
|
||||
Bputc(b, l>>24);
|
||||
return;
|
||||
}
|
||||
if(t & T_SCONST) {
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(b, *n);
|
||||
n++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(t & T_TYPE)
|
||||
Bputc(b, a->type);
|
||||
}
|
||||
|
||||
void
|
||||
outhist(Biobuf *b)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ieeedtod(Ieee *ieee, double native)
|
||||
{
|
||||
double fr, ho, f;
|
||||
int exp;
|
||||
|
||||
if(native < 0) {
|
||||
ieeedtod(ieee, -native);
|
||||
ieee->h |= 0x80000000L;
|
||||
return;
|
||||
}
|
||||
if(native == 0) {
|
||||
ieee->l = 0;
|
||||
ieee->h = 0;
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static Addr at, ao, ac, ad;
|
||||
static int wi, ws, ot;
|
||||
|
||||
void
|
||||
ginsatoa(int fscale, int toffset)
|
||||
int
|
||||
dstringptr(Sym *s, int off, char *str)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
gensatac(int fscale, int toffset)
|
||||
{
|
||||
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 = ac;
|
||||
p->to.offset = toffset;
|
||||
ot += fscale;
|
||||
}
|
||||
|
||||
void
|
||||
gensatad(Sym *s)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
p = pc;
|
||||
ot = rnd(ot, widthptr);
|
||||
|
||||
gins(ADATA, N, N);
|
||||
p->from = at;
|
||||
p->from.offset = 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 = ad;
|
||||
p->to.sym = s;
|
||||
ot += 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;
|
||||
}
|
||||
|
||||
int
|
||||
duintxx(Sym *s, int off, uint64 v, int wid)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int
|
||||
duint32(Sym *s, int off, uint32 v)
|
||||
{
|
||||
return duintxx(s, off, v, 4);
|
||||
}
|
||||
|
||||
int
|
||||
duint16(Sym *s, int off, uint32 v)
|
||||
{
|
||||
return duintxx(s, off, v, 2);
|
||||
}
|
||||
|
||||
int
|
||||
duintptr(Sym *s, int off, uint32 v)
|
||||
{
|
||||
return duintxx(s, off, v, 8);
|
||||
}
|
||||
|
||||
int
|
||||
dsymptr(Sym *s, int off, Sym *x)
|
||||
{
|
||||
Prog *p;
|
||||
|
||||
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_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;
|
||||
p->as = ANOP;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ OFILES=\
|
||||
bits.$O\
|
||||
align.$O\
|
||||
gen.$O\
|
||||
obj.$O\
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
ar rsc $(LIB) $(OFILES)
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
* gen.c/gsubr.c/obj.c
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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*);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
585
src/cmd/gc/obj.c
Normal file
585
src/cmd/gc/obj.c
Normal file
@ -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;
|
||||
}
|
||||
|
@ -2403,102 +2403,6 @@ tempname(Node *n, Type *t)
|
||||
n->xoffset = -stksize;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user