summaryrefslogtreecommitdiff
path: root/src/cmd/gc/subr.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
committerMichael Stapelberg <stapelberg@debian.org>2013-12-03 09:43:15 +0100
commit64d2a7c8945ba05af859901f5e248f1befdd8621 (patch)
tree013fcb7e9e3296ecdda876012252c36bd6bcb063 /src/cmd/gc/subr.c
parentb901efe83e212f0c34c769c079e41373da12d723 (diff)
downloadgolang-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.c84
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);
}