diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/cmd/gc/subr.c | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/cmd/gc/subr.c')
-rw-r--r-- | src/cmd/gc/subr.c | 193 |
1 files changed, 123 insertions, 70 deletions
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 72a9ac20c..c3bc5af3b 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -529,7 +529,8 @@ algtype1(Type *t, Type **bad) if(bad) *bad = T; - + if(t->broke) + return AMEM; if(t->noalg) return ANOEQ; @@ -656,11 +657,15 @@ maptype(Type *key, Type *val) { Type *t; Type *bad; - int atype; + int atype, mtype; if(key != nil) { atype = algtype1(key, &bad); - switch(bad == T ? key->etype : bad->etype) { + if(bad == T) + mtype = key->etype; + else + mtype = bad->etype; + switch(mtype) { default: if(atype == ANOEQ) yyerror("invalid map key type %T", key); @@ -2625,9 +2630,10 @@ hashmem(Type *t) n = newname(sym); n->class = PFUNC; tfn = nod(OTFUNC, N, N); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR])))); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); typecheck(&tfn, Etype); n->type = tfn->type; return n; @@ -2673,9 +2679,10 @@ hashfor(Type *t) n = newname(sym); n->class = PFUNC; tfn = nod(OTFUNC, N, N); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(types[TUINTPTR])))); - tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(ptrto(t)))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->list = list(tfn->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); + tfn->rlist = list(tfn->rlist, nod(ODCLFIELD, N, typenod(types[TUINTPTR]))); typecheck(&tfn, Etype); n->type = tfn->type; return n; @@ -2687,7 +2694,7 @@ hashfor(Type *t) void genhash(Sym *sym, Type *t) { - Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn; + Node *n, *fn, *np, *nh, *ni, *call, *nx, *na, *tfn, *r; Node *hashel; Type *first, *t1; int old_safemode; @@ -2700,21 +2707,23 @@ genhash(Sym *sym, Type *t) dclcontext = PEXTERN; markdcl(); - // func sym(h *uintptr, s uintptr, p *T) + // func sym(p *T, s uintptr, h uintptr) uintptr fn = nod(ODCLFUNC, N, N); fn->nname = newname(sym); fn->nname->class = PFUNC; tfn = nod(OTFUNC, N, N); fn->nname->ntype = tfn; - n = nod(ODCLFIELD, newname(lookup("h")), typenod(ptrto(types[TUINTPTR]))); + n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); - nh = n->left; + np = n->left; n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); tfn->list = list(tfn->list, n); - n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); + n = nod(ODCLFIELD, newname(lookup("h")), typenod(types[TUINTPTR])); tfn->list = list(tfn->list, n); - np = n->left; + nh = n->left; + n = nod(ODCLFIELD, N, typenod(types[TUINTPTR])); // return value + tfn->rlist = list(tfn->rlist, n); funchdr(fn); typecheck(&fn->nname->ntype, Etype); @@ -2740,15 +2749,17 @@ genhash(Sym *sym, Type *t) colasdefn(n->list, n); ni = n->list->n; - // *h = *h<<3 | *h>>61 + // TODO: with aeshash we don't need these shift/mul parts + + // h = h<<3 | h>>61 n->nbody = list(n->nbody, nod(OAS, - nod(OIND, nh, N), + nh, nod(OOR, - nod(OLSH, nod(OIND, nh, N), nodintconst(3)), - nod(ORSH, nod(OIND, nh, N), nodintconst(widthptr*8-3))))); + nod(OLSH, nh, nodintconst(3)), + nod(ORSH, nh, nodintconst(widthptr*8-3))))); - // *h *= mul + // h *= mul // Same multipliers as in runtime.memhash. if(widthptr == 4) mul = 3267000013LL; @@ -2756,19 +2767,19 @@ genhash(Sym *sym, Type *t) mul = 23344194077549503LL; n->nbody = list(n->nbody, nod(OAS, - nod(OIND, nh, N), - nod(OMUL, nod(OIND, nh, N), nodintconst(mul)))); + nh, + nod(OMUL, nh, nodintconst(mul)))); - // hashel(h, sizeof(p[i]), &p[i]) + // h = hashel(&p[i], sizeof(p[i]), h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(t->type->width)); nx = nod(OINDEX, np, ni); nx->bounded = 1; na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - n->nbody = list(n->nbody, call); + call->list = list(call->list, nodintconst(t->type->width)); + call->list = list(call->list, nh); + n->nbody = list(n->nbody, nod(OAS, nh, call)); fn->nbody = list(fn->nbody, n); break; @@ -2793,15 +2804,15 @@ genhash(Sym *sym, Type *t) if(first != T) { size = offend - first->width; // first->width is offset hashel = hashmem(first->type); - // hashel(h, size, &p.first) + // h = hashel(&p.first, size, h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(size)); nx = nod(OXDOT, np, newname(first->sym)); // TODO: fields from other packages? na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - fn->nbody = list(fn->nbody, call); + call->list = list(call->list, nodintconst(size)); + call->list = list(call->list, nh); + fn->nbody = list(fn->nbody, nod(OAS, nh, call)); first = T; } @@ -2812,20 +2823,21 @@ genhash(Sym *sym, Type *t) // Run hash for this field. hashel = hashfor(t1->type); - // hashel(h, size, &p.t1) + // h = hashel(&p.t1, size, h) call = nod(OCALL, hashel, N); - call->list = list(call->list, nh); - call->list = list(call->list, nodintconst(t1->type->width)); nx = nod(OXDOT, np, newname(t1->sym)); // TODO: fields from other packages? na = nod(OADDR, nx, N); na->etype = 1; // no escape to heap call->list = list(call->list, na); - fn->nbody = list(fn->nbody, call); + call->list = list(call->list, nodintconst(t1->type->width)); + call->list = list(call->list, nh); + fn->nbody = list(fn->nbody, nod(OAS, nh, call)); } - // make sure body is not empty. - fn->nbody = list(fn->nbody, nod(ORETURN, N, N)); break; } + r = nod(ORETURN, N, N); + r->list = list(r->list, nh); + fn->nbody = list(fn->nbody, r); if(debug['r']) dumplist("genhash body", fn->nbody); @@ -2849,18 +2861,19 @@ genhash(Sym *sym, Type *t) } // Return node for -// if p.field != q.field { *eq = false; return } +// if p.field != q.field { return false } static Node* -eqfield(Node *p, Node *q, Node *field, Node *eq) +eqfield(Node *p, Node *q, Node *field) { - Node *nif, *nx, *ny; + Node *nif, *nx, *ny, *r; nx = nod(OXDOT, p, field); ny = nod(OXDOT, q, field); nif = nod(OIF, N, N); nif->ntest = nod(ONE, nx, ny); - nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, eq, N), nodbool(0))); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); return nif; } @@ -2889,11 +2902,11 @@ eqmemfunc(vlong size, Type *type) } // Return node for -// if memequal(size, &p.field, &q.field, eq); !*eq { return } +// if !memequal(&p.field, &q.field, size) { return false } static Node* -eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) +eqmem(Node *p, Node *q, Node *field, vlong size) { - Node *nif, *nx, *ny, *call; + Node *nif, *nx, *ny, *call, *r; nx = nod(OADDR, nod(OXDOT, p, field), N); nx->etype = 1; // does not escape @@ -2903,15 +2916,16 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) typecheck(&ny, Erv); call = nod(OCALL, eqmemfunc(size, nx->type->type), N); - call->list = list(call->list, eq); - call->list = list(call->list, nodintconst(size)); call->list = list(call->list, nx); call->list = list(call->list, ny); + call->list = list(call->list, nodintconst(size)); nif = nod(OIF, N, N); nif->ninit = list(nif->ninit, call); - nif->ntest = nod(ONOT, nod(OIND, eq, N), N); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + nif->ntest = nod(ONOT, call, N); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); return nif; } @@ -2921,7 +2935,7 @@ eqmem(Node *p, Node *q, Node *field, vlong size, Node *eq) void geneq(Sym *sym, Type *t) { - Node *n, *fn, *np, *neq, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange; + Node *n, *fn, *np, *nq, *tfn, *nif, *ni, *nx, *ny, *nrange, *r; Type *t1, *first; int old_safemode; int64 size; @@ -2934,24 +2948,23 @@ geneq(Sym *sym, Type *t) dclcontext = PEXTERN; markdcl(); - // func sym(eq *bool, s uintptr, p, q *T) + // func sym(p, q *T, s uintptr) bool fn = nod(ODCLFUNC, N, N); fn->nname = newname(sym); fn->nname->class = PFUNC; tfn = nod(OTFUNC, N, N); fn->nname->ntype = tfn; - n = nod(ODCLFIELD, newname(lookup("eq")), typenod(ptrto(types[TBOOL]))); - tfn->list = list(tfn->list, n); - neq = n->left; - n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); - tfn->list = list(tfn->list, n); n = nod(ODCLFIELD, newname(lookup("p")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); np = n->left; n = nod(ODCLFIELD, newname(lookup("q")), typenod(ptrto(t))); tfn->list = list(tfn->list, n); nq = n->left; + n = nod(ODCLFIELD, newname(lookup("s")), typenod(types[TUINTPTR])); + tfn->list = list(tfn->list, n); + n = nod(ODCLFIELD, N, typenod(types[TBOOL])); + tfn->rlist = list(tfn->rlist, n); funchdr(fn); @@ -2977,7 +2990,7 @@ geneq(Sym *sym, Type *t) colasdefn(nrange->list, nrange); ni = nrange->list->n; - // if p[i] != q[i] { *eq = false; return } + // if p[i] != q[i] { return false } nx = nod(OINDEX, np, ni); nx->bounded = 1; ny = nod(OINDEX, nq, ni); @@ -2985,13 +2998,11 @@ geneq(Sym *sym, Type *t) nif = nod(OIF, N, N); nif->ntest = nod(ONE, nx, ny); - nif->nbody = list(nif->nbody, nod(OAS, nod(OIND, neq, N), nodbool(0))); - nif->nbody = list(nif->nbody, nod(ORETURN, N, N)); + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(0)); + nif->nbody = list(nif->nbody, r); nrange->nbody = list(nrange->nbody, nif); fn->nbody = list(fn->nbody, nrange); - - // *eq = true; - fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1))); break; case TSTRUCT: @@ -3016,16 +3027,16 @@ geneq(Sym *sym, Type *t) // cross-package unexported fields. if(first != T) { if(first->down == t1) { - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); } else if(first->down->down == t1) { - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); first = first->down; if(!isblanksym(first->sym)) - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(first->sym))); } else { // More than two fields: use memequal. size = offend - first->width; // first->width is offset - fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size, neq)); + fn->nbody = list(fn->nbody, eqmem(np, nq, newname(first->sym), size)); } first = T; } @@ -3035,14 +3046,17 @@ geneq(Sym *sym, Type *t) continue; // Check this field, which is not just memory. - fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym), neq)); + fn->nbody = list(fn->nbody, eqfield(np, nq, newname(t1->sym))); } - // *eq = true; - fn->nbody = list(fn->nbody, nod(OAS, nod(OIND, neq, N), nodbool(1))); break; } + // return true + r = nod(ORETURN, N, N); + r->list = list(r->list, nodbool(1)); + fn->nbody = list(fn->nbody, r); + if(debug['r']) dumplist("geneq body", fn->nbody); @@ -3445,7 +3459,7 @@ smagic(Magic *m) mask = 0xffffffffLL; break; case 64: - mask = 0xffffffffffffffffLL; + mask = 0xffffffffffffffffULL; break; } two31 = mask ^ (mask>>1); @@ -3453,7 +3467,7 @@ smagic(Magic *m) p = m->w-1; ad = m->sd; if(m->sd < 0) - ad = -m->sd; + ad = -(uvlong)m->sd; // bad denominators if(ad == 0 || ad == 1 || ad == two31) { @@ -3543,7 +3557,7 @@ umagic(Magic *m) mask = 0xffffffffLL; break; case 64: - mask = 0xffffffffffffffffLL; + mask = 0xffffffffffffffffULL; break; } two31 = mask ^ (mask>>1); @@ -3628,7 +3642,7 @@ ngotype(Node *n) * users if we escape that as little as possible. * * If you edit this, edit ../ld/lib.c:/^pathtoprefix too. - * If you edit this, edit ../../pkg/debug/goobj/read.go:/importPathToPrefix too. + * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too. */ static char* pathtoprefix(char *s) @@ -3785,3 +3799,42 @@ checknil(Node *x, NodeList **init) n->typecheck = 1; *init = list(*init, n); } + +/* + * Can this type be stored directly in an interface word? + */ +int +isdirectiface(Type *t) +{ + // Setting IfacePointerOnly = 1 changes the + // interface representation so that the data word + // in an interface value must always be a pointer. + // Setting it to 0 uses the original representation, + // where the data word can hold a pointer or any + // non-pointer value no bigger than a pointer. + enum { + IfacePointerOnly = 1, + }; + + if(IfacePointerOnly) { + switch(t->etype) { + case TPTR32: + case TPTR64: + case TCHAN: + case TMAP: + case TFUNC: + case TUNSAFEPTR: + return 1; + case TARRAY: + // Array of 1 direct iface type can be direct. + return t->bound == 1 && isdirectiface(t->type); + case TSTRUCT: + // Struct with 1 field of direct iface type can be direct. + return t->type != T && t->type->down == T && isdirectiface(t->type->type); + } + return 0; + } + + dowidth(t); + return t->width <= widthptr; +} |