aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/6g/obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6g/obj.c')
-rw-r--r--src/cmd/6g/obj.c506
1 files changed, 316 insertions, 190 deletions
diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c
index 39e0b95574..8070af4b48 100644
--- a/src/cmd/6g/obj.c
+++ b/src/cmd/6g/obj.c
@@ -455,84 +455,268 @@ sigcmp(Sig *a, Sig *b)
return strcmp(a->name, b->name);
}
+static Addr at, ao, ac, ad;
+static int wi, ot;
+
void
-dumpsignatures(void)
+ginsatoa(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 = 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;
+ p->from.scale = widthptr;
+ p->to = ad;
+ p->to.sym = s;
+ ot += widthptr;
+}
+
+void
+gentramp(Type *t, Sig *b)
+{
+ Sym *e;
+ int c, d;
+
+ e = lookup(b->name);
+ for(d=0; d<nelem(dotlist); d++) {
+ c = adddot1(e, t, d);
+ if(c == 1)
+ goto out;
+ }
+ fatal("gentramp");
+
+out:
+ print("gentramp %d\n", d);
+ print(" t = %lT\n", t);
+ print(" name = %s\n", b->name);
+ print(" sym = %S\n", b->sym);
+ print(" hash = 0x%ux\n", b->hash);
+
+ for(c=d-1; c>=0; c--) {
+ print(" %d %d %S\n",
+ dotlist[c].ptr,
+ dotlist[c].offset,
+ dotlist[c].sym);
+ }
+
+//TEXT main·S_test2(SB),7,$0
+// MOVQ 8(SP), AX
+// MOVQ XX(AX), AX
+// ADDQ $XX, AX
+// MOVQ AX, 8(SP)
+// JMP main·Sub_test2(SB)
+}
+
+void
+dumpsigt(void)
{
Dcl *d, *x;
Type *t, *f;
Sym *s1, *s;
- int et, o, wi, ot;
+ int et, o;
Sig *a, *b;
- Addr at, ao, ac, ad;
Prog *p;
char *sp;
char buf[NSYMB];
- // copy externdcl list to signatlist
- for(d=externdcl; d!=D; d=d->forw) {
+ /*
+ * put all the names into a linked
+ * list so that it may be generated in sorted order.
+ * the runtime will be linear rather than quadradic
+ */
+ for(d=signatlist; d!=D; d=d->forw) {
if(d->op != OTYPE)
continue;
t = d->dtype;
- if(t == T)
+ et = t->etype;
+ if(et == TINTER)
continue;
- s = signame(t, 0);
+ at.sym = signame(t, d->block);
+ if(at.sym == S)
+ continue;
+
+ // make unique
+ if(at.sym->local != 1)
+ continue;
+ at.sym->local = 2;
+
+ s = d->dsym;
if(s == S)
continue;
- x = mal(sizeof(*d));
- x->op = OTYPE;
- x->dsym = d->dsym;
- x->dtype = d->dtype;
- x->forw = signatlist;
- x->block = 0;
- signatlist = x;
-//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
- }
+ if(s->name[0] == '_')
+ continue;
- /*
- * put all the names into a linked
- * list so that it may be generated in sorted order.
- * the runtime will be linear rather than quadradic
- */
+ if(strcmp(s->opackage, package) != 0)
+ continue;
- memset(&at, 0, sizeof(at));
- memset(&ao, 0, sizeof(ao));
- memset(&ac, 0, sizeof(ac));
- memset(&ad, 0, sizeof(ad));
+ expandmeth(s, t);
- // sig structure
- at.type = D_EXTERN;
- at.index = D_NONE;
- at.sym = S; // fill in
- at.offset = 0; // fill in
+ a = nil;
+ o = 0;
+ for(f=t->method; f!=T; f=f->down) {
+ if(f->type->etype != TFUNC)
+ continue;
- // $string
- ao.type = D_ADDR;
- ao.index = D_STATIC;
- ao.etype = TINT32;
- ao.sym = symstringo;
- ao.offset = 0; // fill in
+ if(f->etype != TFIELD)
+ fatal("dumpsignatures: not field");
- // constant
- ac.type = D_CONST;
- ac.index = D_NONE;
- ac.offset = 0; // fill in
+ s1 = f->sym;
+ if(s1 == nil)
+ continue;
- // $method
- ad.type = D_ADDR;
- ad.index = D_EXTERN;
- ad.sym = S; // fill in
- ad.offset = 0;
+ b = mal(sizeof(*b));
+ b->link = a;
+ a = b;
- wi = types[TINT32]->width;
+ a->name = s1->name;
+ a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0);
+ a->perm = o;
+ snprint(namebuf, sizeof(namebuf), "%s_%s",
+ at.sym->name+5, f->sym->name);
+ a->sym = lookup(namebuf);
+ a->offset = f->embedded; // need trampoline
+
+ 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.
+ // TODO(rsc): the * is a botch but right more often than not.
+ snprint(buf, sizeof buf, "*%#T", t);
+ datastring(buf, strlen(buf)+1);
+
+ // first field of an type signature contains
+ // the element parameters and is not a real entry
+
+ t = d->dtype;
+ if(t->methptr & 2)
+ t = types[tptr];
+
+ // sigi[0].hash = elemalg
+ gensatac(wi, algtype(t));
+
+ // sigi[0].offset = width
+ gensatac(wi, t->width);
+
+ // skip the function
+ gensatac(widthptr, 0);
+
+ for(b=a; b!=nil; b=b->link) {
+ ot = rnd(ot, maxround); // base structure
+
+ // sigx[++].name = "fieldname"
+ ginsatoa(widthptr, stringo);
+
+ // sigx[++].hash = hashcode
+ gensatac(wi, b->hash);
+
+ // sigt[++].offset = of embeded struct
+ gensatac(wi, 0);
+
+ // sigt[++].fun = &method
+ gensatad(b->sym);
+
+ datastring(b->name, strlen(b->name)+1);
+
+ if(b->offset)
+ gentramp(d->dtype, b);
+ }
+
+ // nil field name at end
+ ot = rnd(ot, maxround);
+ gensatac(widthptr, 0);
+
+ p = pc;
+ gins(AGLOBL, N, N);
+ p->from = at;
+ p->to = ac;
+ p->to.offset = ot;
+ }
+
+ if(stringo > 0) {
+ p = pc;
+ gins(AGLOBL, N, N);
+ p->from = ao;
+ p->to = ac;
+ p->to.offset = stringo;
+ }
+
+}
+
+void
+dumpsigi(void)
+{
+ Dcl *d, *x;
+ Type *t, *f;
+ Sym *s1, *s;
+ int et, o;
+ Sig *a, *b;
+ Prog *p;
+ char *sp;
+ char buf[NSYMB];
+
+ /*
+ * put all the names into a linked
+ * list so that it may be generated in sorted order.
+ * the runtime will be linear rather than quadradic
+ */
for(d=signatlist; d!=D; d=d->forw) {
if(d->op != OTYPE)
continue;
t = d->dtype;
+ et = t->etype;
+ if(et != TINTER)
+ continue;
+
at.sym = signame(t, d->block);
if(at.sym == S)
continue;
@@ -542,10 +726,6 @@ dumpsignatures(void)
continue;
at.sym->local = 2;
-//print("SIGNAME = %lS\n", at.sym);
-
- et = t->etype;
-
s = d->dsym;
if(s == S)
continue;
@@ -556,14 +736,11 @@ dumpsignatures(void)
if(strcmp(s->opackage, package) != 0)
continue;
+//print("sigi: %S\n", s);
+
a = nil;
o = 0;
-
- f = t->method;
- if(et == TINTER)
- f = t->type;
-
- for(; f!=T; f=f->down) {
+ for(f=t->type; f!=T; f=f->down) {
if(f->type->etype != TFUNC)
continue;
@@ -597,162 +774,47 @@ dumpsignatures(void)
a = lsort(a, sigcmp);
ot = 0;
+ ot = rnd(ot, maxround); // base structure
// sigi[0].name = ""
- ot = rnd(ot, maxround); // array of structures
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = widthptr;
- p->to = ao;
- p->to.offset = stringo;
- ot += widthptr;
+ ginsatoa(widthptr, stringo);
// save type name for runtime error message.
// TODO(rsc): the * is a botch but right more often than not.
- if(et == TINTER)
- snprint(buf, sizeof buf, "%#T", t);
- else
- snprint(buf, sizeof buf, "*%#T", t);
+ snprint(buf, sizeof buf, "%#T", t);
datastring(buf, strlen(buf)+1);
- if(et == TINTER) {
- // first field of an interface signature
- // contains the count and is not a real entry
- o = 0;
- for(b=a; b!=nil; b=b->link)
- o++;
+ // first field of an interface signature
+ // contains the count and is not a real entry
- // sigi[0].hash = 0
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = 0;
- ot += wi;
+ // sigi[0].hash = 0
+ gensatac(wi, 0);
- // sigi[0].offset = count
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = o;
- ot += wi;
-
- } else {
- // first field of an type signature contains
- // the element parameters and is not a real entry
-
- t = d->dtype;
- if(t->methptr & 2)
- t = types[tptr];
-
- // sigi[0].hash = elemalg
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = algtype(t);
- ot += wi;
-
- // sigi[0].offset = width
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = t->width;
- ot += wi;
-
- // skip the function
- ot = rnd(ot, widthptr);
- ot += widthptr;
- }
+ // 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"
- ot = rnd(ot, maxround); // array of structures
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = widthptr;
- p->to = ao;
- p->to.offset = stringo;
- ot += widthptr;
+ ginsatoa(widthptr, stringo);
// sigx[++].hash = hashcode
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = b->hash;
- ot += wi;
+ gensatac(wi, b->hash);
- if(et == TINTER) {
- // sigi[++].perm = mapped offset of method
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = b->perm;
- ot += wi;
- } else {
- // sigt[++].offset = of embeded struct
- ot = rnd(ot, wi);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = wi;
- p->to = ac;
- p->to.offset = b->offset;
- ot += wi;
+ // sigi[++].perm = mapped offset of method
+ gensatac(wi, b->perm);
- // sigt[++].fun = &method
- ot = rnd(ot, widthptr);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = widthptr;
- p->to = ad;
- p->to.sym = b->sym;
- ot += widthptr;
- }
datastring(b->name, strlen(b->name)+1);
-
}
// nil field name at end
ot = rnd(ot, maxround);
- p = pc;
- gins(ADATA, N, N);
- p->from = at;
- p->from.offset = ot;
- p->from.scale = widthptr;
- p->to = ac;
- p->to.offset = 0;
- ot += widthptr;
+ gensatac(widthptr, 0);
p = pc;
gins(AGLOBL, N, N);
@@ -769,3 +831,67 @@ dumpsignatures(void)
p->to.offset = stringo;
}
}
+
+void
+dumpsignatures(void)
+{
+ Dcl *d, *x;
+ Type *t;
+ Sym *s;
+
+ memset(&at, 0, sizeof(at));
+ memset(&ao, 0, sizeof(ao));
+ memset(&ac, 0, sizeof(ac));
+ memset(&ad, 0, sizeof(ad));
+
+ wi = types[TINT32]->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, 0);
+ if(s == S)
+ continue;
+
+ x = mal(sizeof(*d));
+ x->op = OTYPE;
+ x->dsym = d->dsym;
+ x->dtype = d->dtype;
+ x->forw = signatlist;
+ x->block = 0;
+ signatlist = x;
+//print("SIG = %lS %lS %lT\n", d->dsym, s, t);
+ }
+ dumpsigi();
+ dumpsigt();
+}