diff options
author | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
---|---|---|
committer | Michael Stapelberg <stapelberg@debian.org> | 2013-12-03 09:43:15 +0100 |
commit | 64d2a7c8945ba05af859901f5e248f1befdd8621 (patch) | |
tree | 013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/gc/subr.c | |
parent | b901efe83e212f0c34c769c079e41373da12d723 (diff) | |
download | golang-64d2a7c8945ba05af859901f5e248f1befdd8621.tar.gz |
Imported Upstream version 1.2upstream/1.2
Diffstat (limited to 'src/cmd/gc/subr.c')
-rw-r--r-- | src/cmd/gc/subr.c | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 20a15bc71..bea90b87b 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -322,7 +322,7 @@ setlineno(Node *n) uint32 stringhash(char *p) { - int32 h; + uint32 h; int c; h = 0; @@ -333,9 +333,9 @@ stringhash(char *p) h = h*PRIME1 + c; } - if(h < 0) { + if((int32)h < 0) { h = -h; - if(h < 0) + if((int32)h < 0) h = 0; } return h; @@ -525,7 +525,7 @@ saveorignode(Node *n) n->orig = norig; } -// ispaddedfield returns whether the given field +// ispaddedfield reports whether the given field // is followed by padding. For the case where t is // the last field, total gives the size of the enclosing struct. static int @@ -547,6 +547,9 @@ algtype1(Type *t, Type **bad) if(bad) *bad = T; + if(t->noalg) + return ANOEQ; + switch(t->etype) { case TANY: case TFORW: @@ -615,23 +618,23 @@ algtype1(Type *t, Type **bad) return -1; // needs special compare case TSTRUCT: - if(t->type != T && t->type->down == T) { + if(t->type != T && t->type->down == T && !isblanksym(t->type->sym)) { // One-field struct is same as that one field alone. return algtype1(t->type->type, bad); } ret = AMEM; for(t1=t->type; t1!=T; t1=t1->down) { - // Blank fields and padding must be ignored, - // so need special compare. - if(isblanksym(t1->sym) || ispaddedfield(t1, t->width)) { + // All fields must be comparable. + a = algtype1(t1->type, bad); + if(a == ANOEQ) + return ANOEQ; + + // Blank fields, padded fields, fields with non-memory + // equality need special compare. + if(a != AMEM || isblanksym(t1->sym) || ispaddedfield(t1, t->width)) { ret = -1; continue; } - a = algtype1(t1->type, bad); - if(a == ANOEQ) - return ANOEQ; // not comparable - if(a != AMEM) - ret = -1; // needs special compare } return ret; } @@ -1260,7 +1263,7 @@ assignop(Type *src, Type *dst, char **why) "\t\thave %S%hhT\n\t\twant %S%hhT", src, dst, missing->sym, have->sym, have->type, missing->sym, missing->type); else if(ptr) - *why = smprint(":\n\t%T does not implement %T (%S method requires pointer receiver)", + *why = smprint(":\n\t%T does not implement %T (%S method has pointer receiver)", src, dst, missing->sym); else if(have) *why = smprint(":\n\t%T does not implement %T (missing %S method)\n" @@ -1411,6 +1414,9 @@ assignconv(Node *n, Type *t, char *context) if(n == N || n->type == T || n->type->broke) return n; + if(t->etype == TBLANK && n->type->etype == TNIL) + yyerror("use of untyped nil"); + old = n; old->diag++; // silence errors about n; we'll issue one below defaultlit(&n, t); @@ -2177,7 +2183,7 @@ lookdot0(Sym *s, Type *t, Type **save, int ignorecase) c = 0; if(u->etype == TSTRUCT || u->etype == TINTER) { for(f=u->type; f!=T; f=f->down) - if(f->sym == s || (ignorecase && ucistrcmp(f->sym->name, s->name) == 0)) { + if(f->sym == s || (ignorecase && f->type->etype == TFUNC && f->type->thistuple > 0 && ucistrcmp(f->sym->name, s->name) == 0)) { if(save) *save = f; c++; @@ -2495,13 +2501,13 @@ structargs(Type **tl, int mustname) void genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) { - Node *this, *fn, *call, *n, *t, *pad; + Node *this, *fn, *call, *n, *t, *pad, *dot, *as; NodeList *l, *args, *in, *out; - Type *tpad; + Type *tpad, *methodrcvr; int isddd; Val v; - if(debug['r']) + if(0 && debug['r']) print("genwrapper rcvrtype=%T method=%T newnam=%S\n", rcvr, method, newnam); @@ -2547,8 +2553,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) isddd = l->n->left->isddd; } + methodrcvr = getthisx(method->type)->type->type; + // generate nil pointer check for better error - if(isptr[rcvr->etype] && rcvr->type == getthisx(method->type)->type->type) { + if(isptr[rcvr->etype] && rcvr->type == methodrcvr) { // generating wrapper from *T to T. n = nod(OIF, N, N); n->ntest = nod(OEQ, this->left, nodnil()); @@ -2567,17 +2575,33 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) n->nbody = list1(call); fn->nbody = list(fn->nbody, n); } - + + dot = adddot(nod(OXDOT, this->left, newname(method->sym))); + // generate call - call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N); - call->list = args; - call->isddd = isddd; - if(method->type->outtuple > 0) { - n = nod(ORETURN, N, N); - n->list = list1(call); - call = n; + if(!flag_race && isptr[rcvr->etype] && isptr[methodrcvr->etype] && method->embedded && !isifacemethod(method->type)) { + // generate tail call: adjust pointer receiver and jump to embedded method. + dot = dot->left; // skip final .M + if(!isptr[dotlist[0].field->type->etype]) + dot = nod(OADDR, dot, N); + as = nod(OAS, this->left, nod(OCONVNOP, dot, N)); + as->right->type = rcvr; + fn->nbody = list(fn->nbody, as); + n = nod(ORETJMP, N, N); + n->left = newname(methodsym(method->sym, methodrcvr, 0)); + fn->nbody = list(fn->nbody, n); + } else { + fn->wrapper = 1; // ignore frame for panic+recover matching + call = nod(OCALL, dot, N); + call->list = args; + call->isddd = isddd; + if(method->type->outtuple > 0) { + n = nod(ORETURN, N, N); + n->list = list1(call); + call = n; + } + fn->nbody = list(fn->nbody, call); } - fn->nbody = list(fn->nbody, call); if(0 && debug['r']) dumplist("genwrapper body", fn->nbody); @@ -3752,7 +3776,7 @@ isbadimport(Strlit *path) } void -checknotnil(Node *x, NodeList **init) +checknil(Node *x, NodeList **init) { Node *n; @@ -3760,7 +3784,7 @@ checknotnil(Node *x, NodeList **init) x = nod(OITAB, x, N); typecheck(&x, Erv); } - n = nod(OCHECKNOTNIL, x, N); + n = nod(OCHECKNIL, x, N); n->typecheck = 1; *init = list(*init, n); } |