From ed139c1e372d5b02e6a4f05edbbf08894082b359 Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Thu, 2 Oct 2008 20:51:10 -0700 Subject: [PATCH] more on arbitrary receiver types this CL passes the tests, but should be considered unstable R=r OCL=16390 CL=16390 --- src/cmd/6g/gg.h | 3 +++ src/cmd/6g/obj.c | 47 +++++++++++++++++++++++++++++-------- src/cmd/gc/dcl.c | 38 +++++++----------------------- src/cmd/gc/go.h | 2 +- src/cmd/gc/subr.c | 59 +++++++++++++++++++++++++++++++++++++++-------- src/cmd/gc/walk.c | 22 ++++++++++++------ 6 files changed, 114 insertions(+), 57 deletions(-) diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index 5a45aca873e..a6b9bcaf222 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -58,7 +58,10 @@ struct Sig char* name; Sym* sym; uint32 hash; + int32 perm; int32 offset; + int32 width; + int32 elemalg; Sig* link; }; diff --git a/src/cmd/6g/obj.c b/src/cmd/6g/obj.c index 5b16e716d0f..a44ebdf3624 100644 --- a/src/cmd/6g/obj.c +++ b/src/cmd/6g/obj.c @@ -580,10 +580,13 @@ dumpsignatures(void) a->name = sp+1; a->hash = PRIME8*stringhash(a->name) + PRIME9*typehash(f->type, 0); - a->offset = o; + a->perm = o; snprint(namebuf, sizeof(namebuf), "%s_%s", at.sym->name+5, f->sym->name); a->sym = lookup(namebuf); + a->offset = 0; + a->elemalg = 0; + a->width = 0; o++; } @@ -660,7 +663,18 @@ dumpsignatures(void) ot += wi; if(et == TINTER) { - // sigi[++].offset = offset of method + // 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); @@ -670,17 +684,30 @@ dumpsignatures(void) p->to = ac; p->to.offset = b->offset; ot += wi; - } else { - // leave space for 3 ints - // offset, algorithm and width - ot = rnd(ot, wi); - ot += wi; - ot = rnd(ot, wi); - ot += wi; + + // sigt[++].width = type size 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->width; ot += wi; - // sigs[++].fun = &method + // sigt[++].elemalg = type algorithm + 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->elemalg; + ot += wi; + + // sigt[++].fun = &method ot = rnd(ot, widthptr); p = pc; gins(ADATA, N, N); diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 5839d4abef3..d6f1b144247 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -250,7 +250,6 @@ addmethod(Node *n, Type *t, int local) { Type *f, *d, *pa; Sym *st, *sf; - int ptr; // get field sym if(n == N) @@ -272,29 +271,11 @@ addmethod(Node *n, Type *t, int local) if(pa == T) goto bad; - switch(algtype(pa)) { - default: - goto bad; - case ASIMP: - case APTR: - case ASTRING: - break; - } - - // optionally rip off ptr to type - ptr = 0; - if(isptr[pa->etype]) { - if(pa->sym == S || pa->sym->name[0] == '_') { - ptr = 1; - pa = pa->type; - if(pa == T) - goto bad; - } - } - if(pa->etype == TINTER) - yyerror("no methods on interfaces"); - // and finally the receiver sym + f = ismethod(pa); + if(f == T) + goto bad; + pa = f; st = pa->sym; if(st == S) goto bad; @@ -306,11 +287,6 @@ addmethod(Node *n, Type *t, int local) n = nod(ODCLFIELD, newname(sf), N); n->type = t; - if(pa->method == T) - pa->methptr = ptr; - if(pa->methptr != ptr) - yyerror("combination of direct and ptr receivers of: %S", st); - d = T; // last found for(f=pa->method; f!=T; f=f->down) { if(f->etype != TFIELD) @@ -331,7 +307,7 @@ addmethod(Node *n, Type *t, int local) stotype(n, &d->down); if(dflag()) - print("method %S of type %s%S\n", sf, (ptr? "*":""), st); + print("method %S of type %T\n", sf, pa); return; bad: @@ -450,8 +426,10 @@ funcargs(Type *ft) all |= 2; t = structnext(&save); } + + // this test is remarkedly similar to checkarglist if(all == 3) - yyerror("output parameters are all named or not named"); + yyerror("cannot mix anonymous and named output arguments"); ft->outnamed = 0; if(all == 1) diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index d38c8cb38fb..28a2a626da1 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -571,7 +571,7 @@ int isptrto(Type*, int); int isptrarray(Type*); int isptrdarray(Type*); int isinter(Type*); -int ismethod(Type*); +Type* ismethod(Type*); Sym* signame(Type*); int bytearraysz(Type*); int eqtype(Type*, Type*, int); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 4514f39140c..d2c6a13ce61 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -1357,18 +1357,59 @@ isinter(Type *t) return 0; } -int +Type* ismethod(Type *t) { - // OLD WAY - if(isptrto(t, TSTRUCT)) - return 1; - return 0; + int a; + Sym *s; - // NEW WAY - but doesnt work yet - if(t != T && t->method != T) - return 1; - return 0; + if(t == T) + return T; + + a = algtype(t); + + // direct receiver + s = t->sym; + if(s != S && s->name[0] != '_') { + if(t->methptr == 2) + goto both; + t->methptr |= 1; + goto out; + } + + // pointer receiver + if(!isptr[t->etype]) + return T; + + t = t->type; + if(t == T) + return T; + + s = t->sym; + if(s != S && s->name[0] != '_') { + if(t->methptr == 1) + goto both; + t->methptr |= 2; + goto out; + } + + return T; + +both: + yyerror("type %T used as both direct and indirect method", t); + t->methptr = 3; + +out: + switch(a) { + default: + yyerror("type %T cannot be used as a method", t); + case ASIMP: + case APTR: + case ASTRING: + break; + } + + return t; } Sym* diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index cc06abc6e5f..f3aafc4aad7 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -1598,9 +1598,12 @@ ascompat(Type *t1, Type *t2) // if(eqtype(t2, nilptr, 0)) // return 1; - if(isinter(t1)) - if(ismethod(t2) || isinter(t2)) + if(isinter(t1)) { + if(isinter(t2)) return 1; + if(ismethod(t2)) + return 1; + } if(isinter(t2)) if(ismethod(t1)) @@ -2445,15 +2448,20 @@ isandss(Type *lt, Node *r) rt = r->type; if(isinter(lt)) { - if(ismethod(rt)) + if(isinter(rt)) { + if(!eqtype(rt, lt, 0)) + return I2I; + return Inone; + } + if(ismethod(rt) != T) return T2I; - if(isinter(rt) && !eqtype(rt, lt, 0)) - return I2I; + return Inone; } - if(ismethod(lt)) { - if(isinter(rt)) + if(isinter(rt)) { + if(ismethod(lt) != T) return I2T; + return Inone; } return Inone;