* give genwrapper and genembedtramp the same signature.
* move duint8, duint16, duint32, duint64, duintptr into gc.
* tidy genwrapper.
* bug involving struct field symbols in signature list.
(hash-order dependent so hard to trigger)
* new Type print format %#-T like %#T but omits
names on function arguments.
R=ken
OCL=31237
CL=31237
}
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)
+dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.sym = x;
- p->to.offset = 0;
+ p->to.offset = xoff;
off += widthptr;
return off;
}
-
void
-genembedtramp(Type *t, Sig *b)
+genembedtramp(Type *rcvr, Type *method, Sym *newnam)
{
Sym *e;
- int c, d, o, loaded;
+ int c, d, o, mov, add, loaded;
Prog *p;
Type *f;
- e = lookup(b->name);
+ if(debug['r'])
+ print("genembedtramp %T %T %S\n", rcvr, method, newnam);
+
+ e = method->sym;
for(d=0; d<nelem(dotlist); d++) {
- c = adddot1(e, t, d, nil);
+ c = adddot1(e, rcvr, d, nil);
if(c == 1)
goto out;
}
- fatal("genembedtramp %T.%s", t, b->name);
+ fatal("genembedtramp %T.%S", rcvr, method->sym);
out:
-// print("genembedtramp %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);
-
- newplist()->name = newname(b->sym);
+ newplist()->name = newname(newnam);
//TEXT main·S_test2(SB),7,$0
p = pc;
gins(ATEXT, N, N);
p->from.type = D_EXTERN;
- p->from.sym = b->sym;
+ p->from.sym = newnam;
p->to.type = D_CONST;
p->to.offset = 0;
p->from.scale = 7;
//print("1. %P\n", p);
+ mov = AMOVQ;
+ add = AADDQ;
loaded = 0;
o = 0;
for(c=d-1; c>=0; c--) {
loaded = 1;
//MOVQ 8(SP), AX
p = pc;
- gins(AMOVQ, N, N);
+ gins(mov, N, N);
p->from.type = D_INDIR+D_SP;
- p->from.offset = 8;
+ p->from.offset = widthptr;
p->to.type = D_AX;
//print("2. %P\n", p);
}
//MOVQ o(AX), AX
p = pc;
- gins(AMOVQ, N, N);
+ gins(mov, N, N);
p->from.type = D_INDIR+D_AX;
p->from.offset = o;
p->to.type = D_AX;
if(o != 0) {
//ADDQ $XX, AX
p = pc;
- gins(AADDQ, N, N);
+ gins(add, N, N);
p->from.type = D_CONST;
p->from.offset = o;
if(loaded)
p->to.type = D_AX;
else {
p->to.type = D_INDIR+D_SP;
- p->to.offset = 8;
+ p->to.offset = widthptr;
}
//print("4. %P\n", p);
}
//MOVQ AX, 8(SP)
if(loaded) {
p = pc;
- gins(AMOVQ, N, N);
+ gins(mov, N, N);
p->from.type = D_AX;
p->to.type = D_INDIR+D_SP;
- p->to.offset = 8;
+ p->to.offset = widthptr;
//print("5. %P\n", p);
} else {
// TODO(rsc): obviously this is unnecessary,
p = pc;
gins(AJMP, N, N);
p->to.type = D_EXTERN;
- p->to.sym = methodsym(lookup(b->name), ptrto(f->type));
+ p->to.sym = methodsym(method->sym, ptrto(f->type));
//print("6. %P\n", p);
pc->as = ARET; // overwrite AEND
}
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, 4);
-}
-
-int
-dsymptr(Sym *s, int off, Sym *x)
+dsymptr(Sym *s, int off, Sym *x, int xoff)
{
Prog *p;
p->to.type = D_ADDR;
p->to.index = D_EXTERN;
p->to.sym = x;
- p->to.offset = 0;
+ p->to.offset = xoff;
off += widthptr;
return off;
}
-
void
-genembedtramp(Type *t, Sig *b)
+genembedtramp(Type *rcvr, Type *method, Sym *newnam)
{
Sym *e;
- int c, d, o;
+ int c, d, o, mov, add, loaded;
Prog *p;
Type *f;
- e = lookup(b->name);
+ e = method->sym;
for(d=0; d<nelem(dotlist); d++) {
- c = adddot1(e, t, d, nil);
+ c = adddot1(e, rcvr, d, nil);
if(c == 1)
goto out;
}
- fatal("genembedtramp %T.%s", t, b->name);
+ fatal("genembedtramp %T.%S", rcvr, method->sym);
out:
- if(d == 0)
- return;
-
-// print("genembedtramp %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);
-
- newplist()->name = newname(b->sym);
+ newplist()->name = newname(newnam);
//TEXT main·S_test2(SB),7,$0
p = pc;
gins(ATEXT, N, N);
p->from.type = D_EXTERN;
- p->from.sym = b->sym;
+ p->from.sym = newnam;
p->to.type = D_CONST;
p->to.offset = 0;
p->from.scale = 7;
//print("1. %P\n", p);
- //MOVL 4(SP), AX
- p = pc;
- gins(AMOVL, N, N);
- p->from.type = D_INDIR+D_SP;
- p->from.offset = widthptr;
- p->to.type = D_AX;
-//print("2. %P\n", p);
+ mov = AMOVL;
+ add = AADDL;
+ loaded = 0;
o = 0;
for(c=d-1; c>=0; c--) {
f = dotlist[c].field;
o += f->width;
if(!isptr[f->type->etype])
continue;
+ if(!loaded) {
+ loaded = 1;
+ //MOVL 4(SP), AX
+ p = pc;
+ gins(mov, N, N);
+ p->from.type = D_INDIR+D_SP;
+ p->from.offset = widthptr;
+ p->to.type = D_AX;
+//print("2. %P\n", p);
+ }
+
//MOVL o(AX), AX
p = pc;
- gins(AMOVL, N, N);
+ gins(mov, N, N);
p->from.type = D_INDIR+D_AX;
p->from.offset = o;
p->to.type = D_AX;
if(o != 0) {
//ADDL $XX, AX
p = pc;
- gins(AADDL, N, N);
+ gins(add, N, N);
p->from.type = D_CONST;
p->from.offset = o;
- p->to.type = D_AX;
+ if(loaded)
+ p->to.type = D_AX;
+ else {
+ p->to.type = D_INDIR+D_SP;
+ p->to.offset = widthptr;
+ }
//print("4. %P\n", p);
}
//MOVL AX, 4(SP)
- p = pc;
- gins(AMOVL, N, N);
- p->from.type = D_AX;
- p->to.type = D_INDIR+D_SP;
- p->to.offset = widthptr;
+ if(loaded) {
+ p = pc;
+ gins(mov, N, N);
+ p->from.type = D_AX;
+ p->to.type = D_INDIR+D_SP;
+ p->to.offset = widthptr;
//print("5. %P\n", p);
+ } else {
+ // TODO(rsc): obviously this is unnecessary,
+ // but 6l has a bug, and it can't handle
+ // JMP instructions too close to the top of
+ // a new function.
+ p = pc;
+ gins(ANOP, N, N);
+ }
f = dotlist[0].field;
//JMP main·*Sub_test2(SB)
p = pc;
gins(AJMP, N, N);
p->to.type = D_EXTERN;
- p->to.sym = methodsym(lookup(b->name), ptrto(f->type));
+ p->to.sym = methodsym(method->sym, ptrto(f->type));
//print("6. %P\n", p);
pc->as = ARET; // overwrite AEND
// TARRAY
int32 bound; // negative is dynamic array
-
+
int32 maplineno; // first use of TFORW as map key
};
#define T ((Type*)0)
EXTERN Type* types[NTYPE];
EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE];
+EXTERN uchar isforw[NTYPE];
EXTERN uchar isint[NTYPE];
EXTERN uchar isfloat[NTYPE];
EXTERN uchar issigned[NTYPE];
EXTERN int32 thunk;
EXTERN int exporting;
+EXTERN int noargnames;
EXTERN int funcdepth;
void zname(Biobuf *b, Sym *s, int t);
void nopout(Prog*);
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 dgostringptr(Sym*, int off, char *str);
+int dgostrlitptr(Sym*, int off, Strlit*);
+int dsymptr(Sym *s, int off, Sym *x, int xoff);
+int duint8(Sym *s, int off, uint8 v);
+int duint16(Sym *s, int off, uint16 v);
int duint32(Sym *s, int off, uint32 v);
-int duintptr(Sym *s, int off, uint32 v);
+int duint64(Sym *s, int off, uint64 v);
+int duintptr(Sym *s, int off, uint64 v);
int duintxx(Sym *s, int off, uint64 v, int wid);
-void genembedtramp(Type*, Sig*);
+void genembedtramp(Type*, Type*, Sym*);
int gen_as_init(Node*, Node*);
*ieee = ((uint64)h << 32) | l;
}
+int
+duint8(Sym *s, int off, uint8 v)
+{
+ return duintxx(s, off, v, 1);
+}
+
+int
+duint16(Sym *s, int off, uint16 v)
+{
+ return duintxx(s, off, v, 2);
+}
+
+int
+duint32(Sym *s, int off, uint32 v)
+{
+ return duintxx(s, off, v, 4);
+}
+
+int
+duint64(Sym *s, int off, uint64 v)
+{
+ return duintxx(s, off, v, 8);
+}
+
+int
+duintptr(Sym *s, int off, uint64 v)
+{
+ return duintxx(s, off, v, widthptr);
+}
+
static int
sigcmp(Sig *a, Sig *b)
{
// using genembedtramp if all that is necessary
// is a pointer adjustment and a JMP.
if(f->embedded && isptr[ifacet->etype] && !isifacemethod(f))
- genembedtramp(ifacet, a);
+ genembedtramp(ifacet, f, a->sym);
else
genwrapper(ifacet, f, a->sym);
}
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
+ ot = dsymptr(s, ot, b->sym, 0); // &method
}
// nil field name at end
fmtprint(fp, "func");
fmtprint(fp, "(");
for(t1=getinargx(t)->type; t1; t1=t1->down) {
- fmtprint(fp, "%T", t1);
+ if(noargnames && t1->etype == TFIELD)
+ fmtprint(fp, "%T", t1->type);
+ else
+ fmtprint(fp, "%T", t1);
if(t1->down)
fmtprint(fp, ", ");
}
t1 = getoutargx(t)->type;
fmtprint(fp, " (");
for(; t1; t1=t1->down) {
- fmtprint(fp, "%T", t1);
+ if(noargnames && t1->etype == TFIELD)
+ fmtprint(fp, "%T", t1->type);
+ else
+ fmtprint(fp, "%T", t1);
if(t1->down)
fmtprint(fp, ", ");
}
{
char buf[500], buf1[500];
Type *t, *t1;
- int et, exp;
+ int r, et, sharp, minus;
+
+ sharp = (fp->flags & FmtSharp);
+ minus = (fp->flags & FmtLeft);
+ fp->flags &= ~(FmtSharp|FmtLeft);
t = va_arg(fp->args, Type*);
if(t == T)
}
if(!debug['t']) {
- exp = (fp->flags & FmtSharp);
- if(exp)
+ if(sharp)
exporting++;
- if(Tpretty(fp, t) >= 0) {
+ if(minus)
+ noargnames++;
+ r = Tpretty(fp, t);
+ if(sharp)
+ exporting--;
+ if(minus)
+ noargnames--;
+ if(r >= 0) {
t->trecur--;
- if(exp)
- exporting--;
return 0;
}
- if(exp)
- exporting--;
}
et = t->etype;
case TFUNC:
t = at->type;
- // skip this argument
+ // skip this (receiver) argument
if(t != T)
t = t->down;
for(; t!=T; t=t->down)
if(t == T)
return;
-//print("s=%S t=%lT\n", s, t);
-
// generate all reachable methods
slist = nil;
expand1(t, nelem(dotlist)-1, 0);
c = adddot1(sl->field->sym, t, d, &f);
if(c == 0)
continue;
- if(c == 1 && f == sl->field)
+ if(c == 1) {
sl->good = 1;
+ sl->field = f;
+ }
break;
}
}
for(sl=slist; sl!=nil; sl=sl->link) {
if(sl->good) {
-//print(" %lT\n", sl->field);
// add it to the base type method list
f = typ(TFIELD);
*f = *sl->field;
* and calls the T.M method.
* The resulting function is for use in method tables.
*
- * rcvrtype - U
+ * rcvr - U
* method - M func (t T)(), a TFIELD type struct
* newnam - the eventual mangled name of this function
*/
void
-genwrapper(Type *rcvrtype, Type *method, Sym *newnam)
+genwrapper(Type *rcvr, Type *method, Sym *newnam)
{
Node *this, *in, *out, *fn, *args, *call;
Node *l;
Iter savel;
- if(debug['r']) {
+ if(debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
- rcvrtype, method, newnam);
- }
+ rcvr, method, newnam);
dclcontext = PEXTERN;
markdcl();
- this = nametodcl(newname(lookup(".this")), rcvrtype);
+ this = nametodcl(newname(lookup(".this")), rcvr);
in = structargs(getinarg(method->type), 1);
out = structargs(getoutarg(method->type), 0);