summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-10-22 11:21:16 -0400
committerAustin Clements <austin@google.com>2014-10-22 11:21:16 -0400
commit2c586384223e980fd3303625ea6b02ed5d9fb9c0 (patch)
tree54aa72cd9d5eb1566f682d3b0770141a11b54fc2 /src/cmd/gc
parentebe8a09fb603d9510cb982a6c11a3e1638f7f8fb (diff)
parent45fcda1dc8d9b4d4a9b642faf8e78941873f508d (diff)
downloadgo-2c586384223e980fd3303625ea6b02ed5d9fb9c0.tar.gz
[dev.power64] build: merge default into dev.power64
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/160200044
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/builtin.c18
-rw-r--r--src/cmd/gc/bv.c5
-rw-r--r--src/cmd/gc/const.c8
-rw-r--r--src/cmd/gc/fmt.c2
-rw-r--r--src/cmd/gc/gen.c55
-rw-r--r--src/cmd/gc/go.h3
-rw-r--r--src/cmd/gc/mparith1.c2
-rw-r--r--src/cmd/gc/mparith3.c4
-rw-r--r--src/cmd/gc/order.c26
-rw-r--r--src/cmd/gc/plive.c7
-rw-r--r--src/cmd/gc/popt.c2
-rw-r--r--src/cmd/gc/racewalk.c6
-rw-r--r--src/cmd/gc/reflect.c40
-rw-r--r--src/cmd/gc/runtime.go19
-rw-r--r--src/cmd/gc/select.c6
-rw-r--r--src/cmd/gc/subr.c113
-rw-r--r--src/cmd/gc/typecheck.c15
-rw-r--r--src/cmd/gc/walk.c105
18 files changed, 244 insertions, 192 deletions
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index 4808269b7..60b7c2f97 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -9,11 +9,12 @@ char *runtimeimport =
"func @\"\".throwreturn ()\n"
"func @\"\".throwinit ()\n"
"func @\"\".panicwrap (? string, ? string, ? string)\n"
- "func @\"\".panic (? interface {})\n"
- "func @\"\".recover (? *int32) (? interface {})\n"
+ "func @\"\".gopanic (? interface {})\n"
+ "func @\"\".gorecover (? *int32) (? interface {})\n"
"func @\"\".printbool (? bool)\n"
"func @\"\".printfloat (? float64)\n"
"func @\"\".printint (? int64)\n"
+ "func @\"\".printhex (? uint64)\n"
"func @\"\".printuint (? uint64)\n"
"func @\"\".printcomplex (? complex128)\n"
"func @\"\".printstring (? string)\n"
@@ -64,7 +65,6 @@ char *runtimeimport =
"func @\"\".efaceeq (@\"\".i1·2 any, @\"\".i2·3 any) (@\"\".ret·1 bool)\n"
"func @\"\".ifacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
"func @\"\".efacethash (@\"\".i1·2 any) (@\"\".ret·1 uint32)\n"
- "func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n"
"func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n"
"func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 *any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
@@ -96,12 +96,12 @@ char *runtimeimport =
"func @\"\".makeslice (@\"\".typ·2 *byte, @\"\".nel·3 int64, @\"\".cap·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".growslice (@\"\".typ·2 *byte, @\"\".old·3 []any, @\"\".n·4 int64) (@\"\".ary·1 []any)\n"
"func @\"\".memmove (@\"\".to·1 *any, @\"\".frm·2 *any, @\"\".length·3 uintptr)\n"
- "func @\"\".memequal (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal8 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal16 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal32 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal64 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
- "func @\"\".memequal128 (@\"\".eq·1 *bool, @\"\".size·2 uintptr, @\"\".x·3 *any, @\"\".y·4 *any)\n"
+ "func @\"\".memequal (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal8 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal16 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal32 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal64 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
+ "func @\"\".memequal128 (@\"\".x·2 *any, @\"\".y·3 *any, @\"\".size·4 uintptr) (? bool)\n"
"func @\"\".int64div (? int64, ? int64) (? int64)\n"
"func @\"\".uint64div (? uint64, ? uint64) (? uint64)\n"
"func @\"\".int64mod (? int64, ? int64) (? int64)\n"
diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c
index 0e8f8d473..cfd1cd281 100644
--- a/src/cmd/gc/bv.c
+++ b/src/cmd/gc/bv.c
@@ -108,6 +108,9 @@ bvnext(Bvec *bv, int32 i)
{
uint32 w;
+ if(i >= bv->n)
+ return -1;
+
// Jump i ahead to next word with bits.
if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
i &= ~WORDMASK;
@@ -117,7 +120,7 @@ bvnext(Bvec *bv, int32 i)
}
if(i >= bv->n)
return -1;
-
+
// Find 1 bit.
w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
while((w&1) == 0) {
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index c01784a81..e418b9c56 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -1566,7 +1566,6 @@ isgoconst(Node *n)
case ORSH:
case OSUB:
case OXOR:
- case OCONV:
case OIOTA:
case OCOMPLEX:
case OREAL:
@@ -1574,7 +1573,12 @@ isgoconst(Node *n)
if(isgoconst(n->left) && (n->right == N || isgoconst(n->right)))
return 1;
break;
-
+
+ case OCONV:
+ if(okforconst[n->type->etype] && isgoconst(n->left))
+ return 1;
+ break;
+
case OLEN:
case OCAP:
l = n->left;
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index 951170aef..98556a658 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -1153,7 +1153,7 @@ exprfmt(Fmt *f, Node *n, int prec)
case Csend:
return fmtprint(f, "chan<- %N", n->left);
default:
- if(n->left != N && n->left->op == TCHAN && n->left->sym == S && n->left->etype == Crecv)
+ if(n->left != N && n->left->op == OTCHAN && n->left->sym == S && n->left->etype == Crecv)
return fmtprint(f, "chan (%N)", n->left);
else
return fmtprint(f, "chan %N", n->left);
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 908a5e53d..86acd8825 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -806,7 +806,8 @@ cgen_eface(Node *n, Node *res)
void
cgen_slice(Node *n, Node *res)
{
- Node src, dst, *cap, *len, *offs, *add, *base;
+ Node src, dst, *cap, *len, *offs, *add, *base, *tmpcap, *tmplen, *cmp, con;
+ Prog *p1, *p2;
cap = n->list->n;
len = n->list->next->n;
@@ -823,6 +824,11 @@ cgen_slice(Node *n, Node *res)
// garbage collector can see.
base = temp(types[TUINTPTR]);
+ tmplen = temp(types[TINT]);
+ if(n->op != OSLICESTR)
+ tmpcap = temp(types[TINT]);
+ else
+ tmpcap = tmplen;
if(isnil(n->left)) {
tempname(&src, n->left->type);
@@ -837,43 +843,62 @@ cgen_slice(Node *n, Node *res)
fatal("slicearr is supposed to work on pointer: %+N\n", n);
cgen(&src, base);
cgen_checknil(base);
- if(offs != N) {
- add = nod(OADD, base, offs);
- typecheck(&add, Erv);
- cgen(add, base);
- }
- } else if(offs == N) {
- src.type = types[tptr];
- cgen(&src, base);
} else {
src.type = types[tptr];
- add = nod(OADDPTR, &src, offs);
- typecheck(&add, Erv);
- cgen(add, base);
+ cgen(&src, base);
}
// committed to the update
gvardef(res);
+ // compute len and cap.
+ // len = n-i, cap = m-i, and offs = i*width.
+ // computing offs last lets the multiply overwrite i.
+ cgen(len, tmplen);
+ if(n->op != OSLICESTR)
+ cgen(cap, tmpcap);
+
+ // if new cap != 0 { base += add }
+ // This avoids advancing base past the end of the underlying array/string,
+ // so that it cannot point at the next object in memory.
+ // If cap == 0, the base doesn't matter except insofar as it is 0 or non-zero.
+ // In essence we are replacing x[i:j:k] where i == j == k
+ // or x[i:j] where i == j == cap(x) with x[0:0:0].
+ if(offs != N) {
+ p1 = gjmp(P);
+ p2 = gjmp(P);
+ patch(p1, pc);
+
+ nodconst(&con, tmpcap->type, 0);
+ cmp = nod(OEQ, tmpcap, &con);
+ typecheck(&cmp, Erv);
+ bgen(cmp, 1, -1, p2);
+
+ add = nod(OADD, base, offs);
+ typecheck(&add, Erv);
+ cgen(add, base);
+
+ patch(p2, pc);
+ }
+
// dst.array = src.array [ + lo *width ]
dst = *res;
dst.xoffset += Array_array;
dst.type = types[tptr];
-
cgen(base, &dst);
// dst.len = hi [ - lo ]
dst = *res;
dst.xoffset += Array_nel;
dst.type = types[simtype[TUINT]];
- cgen(len, &dst);
+ cgen(tmplen, &dst);
if(n->op != OSLICESTR) {
// dst.cap = cap [ - lo ]
dst = *res;
dst.xoffset += Array_cap;
dst.type = types[simtype[TUINT]];
- cgen(cap, &dst);
+ cgen(tmpcap, &dst);
}
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index c3da5f636..12c1e9853 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -447,7 +447,6 @@ enum
OSUB, // x - y
OOR, // x | y
OXOR, // x ^ y
- OADDPTR, // ptr + uintptr, inserted by compiler only, used to avoid unsafe type changes during codegen
OADDSTR, // s + "foo"
OADDR, // &x
OANDAND, // b0 && b1
@@ -1169,6 +1168,7 @@ void cgen_callmeth(Node *n, int proc);
void cgen_eface(Node* n, Node* res);
void cgen_slice(Node* n, Node* res);
void clearlabels(void);
+void clearslim(Node*);
void checklabels(void);
int dotoffset(Node *n, int64 *oary, Node **nn);
void gen(Node *n);
@@ -1363,6 +1363,7 @@ int is64(Type *t);
int isbadimport(Strlit *s);
int isblank(Node *n);
int isblanksym(Sym *s);
+int isdirectiface(Type*);
int isfixedarray(Type *t);
int isideal(Type *t);
int isinter(Type *t);
diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c
index 1519caec7..d33a81e09 100644
--- a/src/cmd/gc/mparith1.c
+++ b/src/cmd/gc/mparith1.c
@@ -591,7 +591,7 @@ Fconv(Fmt *fp)
d = mpgetflt(fvp);
if(d >= 0 && (fp->flags & FmtSign))
fmtprint(fp, "+");
- return fmtprint(fp, "%g", d, exp, fvp);
+ return fmtprint(fp, "%g", d);
}
// very out of range. compute decimal approximation by hand.
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
index 95618f1c6..6afd75c02 100644
--- a/src/cmd/gc/mparith3.c
+++ b/src/cmd/gc/mparith3.c
@@ -251,8 +251,8 @@ mpgetfltN(Mpflt *a, int prec, int bias)
s = minexp - e;
if(s > prec+1)
s = prec+1;
- if((v & ((1<<s)-1)) != 0)
- v |= 1<<s;
+ if((v & ((1ULL<<s)-1)) != 0)
+ v |= 1ULL<<s;
v >>= s;
e = minexp;
}
diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c
index 30dbc7dac..d11e9828c 100644
--- a/src/cmd/gc/order.c
+++ b/src/cmd/gc/order.c
@@ -593,7 +593,10 @@ orderstmt(Node *n, Order *order)
orderexpr(&n->rlist->n->left, order); // arg to recv
ch = n->rlist->n->left->type;
tmp1 = ordertemp(ch->type, order, haspointers(ch->type));
- tmp2 = ordertemp(types[TBOOL], order, 0);
+ if(!isblank(n->list->next->n))
+ tmp2 = ordertemp(n->list->next->n->type, order, 0);
+ else
+ tmp2 = ordertemp(types[TBOOL], order, 0);
order->out = list(order->out, n);
r = nod(OAS, n->list->n, tmp1);
typecheck(&r, Etop);
@@ -768,6 +771,12 @@ orderstmt(Node *n, Order *order)
// Special: clean case temporaries in each block entry.
// Select must enter one of its blocks, so there is no
// need for a cleaning at the end.
+ // Doubly special: evaluation order for select is stricter
+ // than ordinary expressions. Even something like p.c
+ // has to be hoisted into a temporary, so that it cannot be
+ // reordered after the channel evaluation for a different
+ // case (if p were nil, then the timing of the fault would
+ // give this away).
t = marktemp(order);
for(l=n->list; l; l=l->next) {
if(l->n->op != OXCASE)
@@ -810,6 +819,8 @@ orderstmt(Node *n, Order *order)
// r->left == N means 'case <-c'.
// c is always evaluated; x and ok are only evaluated when assigned.
orderexpr(&r->right->left, order);
+ if(r->right->left->op != ONAME)
+ r->right->left = ordercopyexpr(r->right->left, r->right->left->type, order, 0);
// Introduce temporary for receive and move actual copy into case body.
// avoids problems with target being addressed, as usual.
@@ -1055,6 +1066,19 @@ orderexpr(Node **np, Order *order)
orderexpr(&n->left, order);
n = ordercopyexpr(n, n->type, order, 1);
break;
+
+ case OEQ:
+ case ONE:
+ orderexpr(&n->left, order);
+ orderexpr(&n->right, order);
+ t = n->left->type;
+ if(t->etype == TSTRUCT || isfixedarray(t)) {
+ // for complex comparisons, we need both args to be
+ // addressable so we can pass them to the runtime.
+ orderaddrtemp(&n->left, order);
+ orderaddrtemp(&n->right, order);
+ }
+ break;
}
lineno = lno;
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index 716cdd108..dc4edad63 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -1113,8 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *str; intgo len; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 3:0 = multiword:string
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
*xoffset += t->width;
break;
@@ -1145,9 +1144,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *array; uintgo len; uintgo cap; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid TARRAY alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 0);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 2); // 3:1 = multiword/slice
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
*xoffset += t->width;
} else
for(i = 0; i < t->bound; i++)
diff --git a/src/cmd/gc/popt.c b/src/cmd/gc/popt.c
index 4c75e6c26..6e6db88ef 100644
--- a/src/cmd/gc/popt.c
+++ b/src/cmd/gc/popt.c
@@ -49,7 +49,7 @@ noreturn(Prog *p)
symlist[0] = pkglookup("panicindex", runtimepkg);
symlist[1] = pkglookup("panicslice", runtimepkg);
symlist[2] = pkglookup("throwinit", runtimepkg);
- symlist[3] = pkglookup("panic", runtimepkg);
+ symlist[3] = pkglookup("gopanic", runtimepkg);
symlist[4] = pkglookup("panicwrap", runtimepkg);
symlist[5] = pkglookup("throwreturn", runtimepkg);
symlist[6] = pkglookup("selectgo", runtimepkg);
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index 285bd78a2..27581702c 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -419,8 +419,10 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
ret:
if(n->op != OBLOCK) // OBLOCK is handled above in a special way.
racewalklist(n->list, init);
- racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
- racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
+ if(n->ntest != N)
+ racewalknode(&n->ntest, &n->ntest->ninit, 0, 0);
+ if(n->nincr != N)
+ racewalknode(&n->nincr, &n->nincr->ninit, 0, 0);
racewalklist(n->nbody, nil);
racewalklist(n->nelse, nil);
racewalklist(n->rlist, nil);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 8170c15b6..f227054ca 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -378,7 +378,7 @@ methods(Type *t)
// type stored in interface word
it = t;
- if(it->width > widthptr)
+ if(!isdirectiface(it))
it = ptrto(t);
// make list of methods for t,
@@ -724,7 +724,7 @@ dcommontype(Sym *s, int ot, Type *t)
if(ot != 0)
fatal("dcommontype %d", ot);
- sizeofAlg = 4*widthptr;
+ sizeofAlg = 2*widthptr;
if(algarray == nil)
algarray = pkglookup("algarray", runtimepkg);
alg = algtype(t);
@@ -785,6 +785,8 @@ dcommontype(Sym *s, int ot, Type *t)
i = KindSlice;
if(!haspointers(t))
i |= KindNoPointers;
+ if(isdirectiface(t))
+ i |= KindDirectIface;
if(gcprog)
i |= KindGCProg;
ot = duint8(s, ot, i); // kind
@@ -1239,8 +1241,7 @@ static Sym*
dalgsym(Type *t)
{
int ot;
- Sym *s, *hash, *hashfunc, *eq;
- char buf[100];
+ Sym *s, *hash, *hashfunc, *eq, *eqfunc;
// dalgsym is only called for a type that needs an algorithm table,
// which implies that the type is comparable (or else it would use ANOEQ).
@@ -1251,29 +1252,18 @@ dalgsym(Type *t)
eq = typesymprefix(".eq", t);
geneq(eq, t);
- // make Go func (a closure) for calling the hash function from Go
+ // make Go funcs (closures) for calling hash and equal from Go
hashfunc = typesymprefix(".hashfunc", t);
dsymptr(hashfunc, 0, hash, 0);
ggloblsym(hashfunc, widthptr, DUPOK|RODATA);
+ eqfunc = typesymprefix(".eqfunc", t);
+ dsymptr(eqfunc, 0, eq, 0);
+ ggloblsym(eqfunc, widthptr, DUPOK|RODATA);
- // ../../pkg/runtime/runtime.h:/Alg
+ // ../../pkg/runtime/alg.go:/typeAlg
ot = 0;
ot = dsymptr(s, ot, hashfunc, 0);
- ot = dsymptr(s, ot, eq, 0);
- ot = dsymptr(s, ot, pkglookup("memprint", runtimepkg), 0);
- switch(t->width) {
- default:
- ot = dsymptr(s, ot, pkglookup("memcopy", runtimepkg), 0);
- break;
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- snprint(buf, sizeof buf, "memcopy%d", (int)t->width*8);
- ot = dsymptr(s, ot, pkglookup(buf, runtimepkg), 0);
- break;
- }
+ ot = dsymptr(s, ot, eqfunc, 0);
ggloblsym(s, ot, DUPOK|RODATA);
return s;
@@ -1511,8 +1501,8 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
*xoffset += t->width;
break;
case TSTRING:
- proggendata(g, BitsMultiWord);
- proggendata(g, BitsString);
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsScalar);
*xoffset += t->width;
break;
case TINTER:
@@ -1525,8 +1515,8 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
break;
case TARRAY:
if(isslice(t)) {
- proggendata(g, BitsMultiWord);
- proggendata(g, BitsSlice);
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsScalar);
proggendata(g, BitsScalar);
} else {
t1 = t->type;
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 0257c3c7d..128fd1a31 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -20,12 +20,13 @@ func throwreturn()
func throwinit()
func panicwrap(string, string, string)
-func panic(interface{})
-func recover(*int32) interface{}
+func gopanic(interface{})
+func gorecover(*int32) interface{}
func printbool(bool)
func printfloat(float64)
func printint(int64)
+func printhex(uint64)
func printuint(uint64)
func printcomplex(complex128)
func printstring(string)
@@ -84,8 +85,6 @@ func efaceeq(i1 any, i2 any) (ret bool)
func ifacethash(i1 any) (ret uint32)
func efacethash(i1 any) (ret uint32)
-func equal(typ *byte, x1, x2 any) (ret bool)
-
// *byte is really *runtime.Type
func makemap(mapType *byte, hint int64) (hmap map[any]any)
func mapaccess1(mapType *byte, hmap map[any]any, key *any) (val *any)
@@ -124,12 +123,12 @@ func makeslice(typ *byte, nel int64, cap int64) (ary []any)
func growslice(typ *byte, old []any, n int64) (ary []any)
func memmove(to *any, frm *any, length uintptr)
-func memequal(eq *bool, size uintptr, x, y *any)
-func memequal8(eq *bool, size uintptr, x, y *any)
-func memequal16(eq *bool, size uintptr, x, y *any)
-func memequal32(eq *bool, size uintptr, x, y *any)
-func memequal64(eq *bool, size uintptr, x, y *any)
-func memequal128(eq *bool, size uintptr, x, y *any)
+func memequal(x, y *any, size uintptr) bool
+func memequal8(x, y *any, size uintptr) bool
+func memequal16(x, y *any, size uintptr) bool
+func memequal32(x, y *any, size uintptr) bool
+func memequal64(x, y *any, size uintptr) bool
+func memequal128(x, y *any, size uintptr) bool
// only used on 32-bit
func int64div(int64, int64) int64
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c
index 7168e6b80..ed23e4318 100644
--- a/src/cmd/gc/select.c
+++ b/src/cmd/gc/select.c
@@ -337,19 +337,23 @@ selecttype(int32 size)
sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("g")), typenod(ptrto(types[TUINT8]))));
sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("selectdone")), typenod(ptrto(types[TUINT8]))));
sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("link")), typenod(ptrto(types[TUINT8]))));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("prev")), typenod(ptrto(types[TUINT8]))));
sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64])));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("nrelease")), typenod(types[TINT32])));
+ sudog->list = list(sudog->list, nod(ODCLFIELD, newname(lookup("waitlink")), typenod(ptrto(types[TUINT8]))));
typecheck(&sudog, Etype);
sudog->type->noalg = 1;
sudog->type->local = 1;
scase = nod(OTSTRUCT, N, N);
- scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("sg")), sudog));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("elem")), typenod(ptrto(types[TUINT8]))));
scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("chan")), typenod(ptrto(types[TUINT8]))));
scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("pc")), typenod(types[TUINTPTR])));
scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("kind")), typenod(types[TUINT16])));
scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("so")), typenod(types[TUINT16])));
scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("receivedp")), typenod(ptrto(types[TUINT8]))));
+ scase->list = list(scase->list, nod(ODCLFIELD, newname(lookup("releasetime")), typenod(types[TUINT64])));
typecheck(&scase, Etype);
scase->type->noalg = 1;
scase->type->local = 1;
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 0195f3d62..d62d55e77 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -656,11 +656,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);
@@ -2856,18 +2860,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;
}
@@ -2896,11 +2901,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
@@ -2910,15 +2915,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;
}
@@ -2928,7 +2934,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;
@@ -2941,24 +2947,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);
@@ -2984,7 +2989,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);
@@ -2992,13 +2997,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:
@@ -3023,16 +3026,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;
}
@@ -3042,14 +3045,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);
@@ -3792,3 +3798,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;
+}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 92e9ad521..746feb4d1 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -525,19 +525,6 @@ reswitch:
op = n->etype;
goto arith;
- case OADDPTR:
- ok |= Erv;
- l = typecheck(&n->left, Erv);
- r = typecheck(&n->right, Erv);
- if(l->type == T || r->type == T)
- goto error;
- if(l->type->etype != tptr)
- fatal("bad OADDPTR left type %E for %N", l->type->etype, n->left);
- if(r->type->etype != TUINTPTR)
- fatal("bad OADDPTR right type %E for %N", r->type->etype, n->right);
- n->type = types[tptr];
- goto ret;
-
case OADD:
case OAND:
case OANDAND:
@@ -2965,7 +2952,7 @@ typecheckas2(Node *n)
if(l->defn == n)
l->type = r->type;
l = n->list->next->n;
- if(l->type != T)
+ if(l->type != T && l->type->etype != TBOOL)
checkassignto(types[TBOOL], l);
if(l->defn == n && l->ntype == N)
l->type = types[TBOOL];
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index cf25a3eac..365ece267 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -543,11 +543,11 @@ walkexpr(Node **np, NodeList **init)
goto ret;
case OPANIC:
- n = mkcall("panic", T, init, n->left);
+ n = mkcall("gopanic", T, init, n->left);
goto ret;
case ORECOVER:
- n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N));
+ n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N));
goto ret;
case OLITERAL:
@@ -673,7 +673,7 @@ walkexpr(Node **np, NodeList **init)
n1 = nod(OADDR, n->list->n, N);
n1->etype = 1; // addr does not escape
fn = chanfn("chanrecv2", 2, r->left->type);
- r = mkcall1(fn, types[TBOOL], init, typename(r->left->type), r->left, n1);
+ r = mkcall1(fn, n->list->next->n->type, init, typename(r->left->type), r->left, n1);
n = nod(OAS, n->list->next->n, r);
typecheck(&n, Etop);
goto ret;
@@ -723,6 +723,12 @@ walkexpr(Node **np, NodeList **init)
var->typecheck = 1;
fn = mapfn(p, t);
r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key);
+
+ // mapaccess2* returns a typed bool, but due to spec changes,
+ // the boolean result of i.(T) is now untyped so we make it the
+ // same type as the variable on the lhs.
+ if(!isblank(n->list->next->n))
+ r->type->type->down->type = n->list->next->n->type;
n->rlist = list1(r);
n->op = OAS2FUNC;
n->list->n = var;
@@ -770,6 +776,12 @@ walkexpr(Node **np, NodeList **init)
*p = '\0';
fn = syslook(buf, 1);
+
+ // runtime.assert(E|I)2TOK returns a typed bool, but due
+ // to spec changes, the boolean result of i.(T) is now untyped
+ // so we make it the same type as the variable on the lhs.
+ if(!isblank(n->list->next->n))
+ fn->type->type->down->type->type = n->list->next->n->type;
ll = list1(typename(r->type));
ll = list(ll, r->left);
argtype(fn, r->left->type);
@@ -822,9 +834,7 @@ walkexpr(Node **np, NodeList **init)
walkexpr(&n->left, init);
// Optimize convT2E as a two-word copy when T is uintptr-shaped.
- if(!isinter(n->left->type) && isnilinter(n->type) &&
- (n->left->type->width == widthptr) &&
- isint[simsimtype(n->left->type)]) {
+ if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
l = nod(OEFACE, typename(n->left->type), n->left);
l->type = n->type;
l->typecheck = n->typecheck;
@@ -872,8 +882,7 @@ walkexpr(Node **np, NodeList **init)
l->addable = 1;
ll = list(ll, l);
- if(n->left->type->width == widthptr &&
- isint[simsimtype(n->left->type)]) {
+ if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
/* For pointer types, we can make a special form of optimization
*
* These statements are put onto the expression init list:
@@ -1828,9 +1837,12 @@ walkprint(Node *nn, NodeList **init, int defer)
t = types[TINT64];
}
} else {
- if(et == TUINT64)
- on = syslook("printuint", 0);
- else
+ if(et == TUINT64) {
+ if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0)
+ on = syslook("printhex", 0);
+ else
+ on = syslook("printuint", 0);
+ } else
on = syslook("printint", 0);
}
} else if(isfloat[et]) {
@@ -2866,14 +2878,14 @@ sliceany(Node* n, NodeList **init)
lb = N;
}
- // dynamic checks convert all bounds to unsigned to save us the bound < 0 comparison
- // generate
- // if hb > bound || lb > hb { panicslice() }
+ // Checking src[lb:hb:cb] or src[lb:hb].
+ // if chk0 || chk1 || chk2 { panicslice() }
chk = N;
- chk0 = N;
- chk1 = N;
- chk2 = N;
+ chk0 = N; // cap(src) < cb
+ chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
+ chk2 = N; // hb < lb
+ // All comparisons are unsigned to avoid testing < 0.
bt = types[simtype[TUINT]];
if(cb != N && cb->type->width > 4)
bt = types[TUINT64];
@@ -3013,10 +3025,10 @@ eqfor(Type *t)
n = newname(sym);
n->class = PFUNC;
ntype = nod(OTFUNC, N, N);
- ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(types[TBOOL]))));
- ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
+ ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL])));
typecheck(&ntype, Etype);
n->type = ntype->type;
return n;
@@ -3037,10 +3049,9 @@ countfield(Type *t)
static void
walkcompare(Node **np, NodeList **init)
{
- Node *n, *l, *r, *fn, *call, *a, *li, *ri, *expr;
+ Node *n, *l, *r, *call, *a, *li, *ri, *expr;
int andor, i;
Type *t, *t1;
- static Node *tempbool;
n = *np;
@@ -3058,8 +3069,9 @@ walkcompare(Node **np, NodeList **init)
break;
}
- if(!islvalue(n->left) || !islvalue(n->right))
- goto hard;
+ if(!islvalue(n->left) || !islvalue(n->right)) {
+ fatal("arguments of comparison must be lvalues");
+ }
l = temp(ptrto(t));
a = nod(OAS, l, nod(OADDR, n->left, N));
@@ -3118,57 +3130,16 @@ walkcompare(Node **np, NodeList **init)
goto ret;
}
- // Chose not to inline, but still have addresses.
- // Call equality function directly.
- // The equality function requires a bool pointer for
- // storing its address, because it has to be callable
- // from C, and C can't access an ordinary Go return value.
- // To avoid creating many temporaries, cache one per function.
- if(tempbool == N || tempbool->curfn != curfn)
- tempbool = temp(types[TBOOL]);
-
+ // Chose not to inline. Call equality function directly.
call = nod(OCALL, eqfor(t), N);
- a = nod(OADDR, tempbool, N);
- a->etype = 1; // does not escape
- call->list = list(call->list, a);
- call->list = list(call->list, nodintconst(t->width));
call->list = list(call->list, l);
call->list = list(call->list, r);
- typecheck(&call, Etop);
- walkstmt(&call);
- *init = list(*init, call);
-
- // tempbool cannot be used directly as multiple comparison
- // expressions may exist in the same statement. Create another
- // temporary to hold the value (its address is not taken so it can
- // be optimized away).
- r = temp(types[TBOOL]);
- a = nod(OAS, r, tempbool);
- typecheck(&a, Etop);
- walkstmt(&a);
- *init = list(*init, a);
-
+ call->list = list(call->list, nodintconst(t->width));
+ r = call;
if(n->op != OEQ)
r = nod(ONOT, r, N);
goto ret;
-hard:
- // Cannot take address of one or both of the operands.
- // Instead, pass directly to runtime helper function.
- // Easier on the stack than passing the address
- // of temporary variables, because we are better at reusing
- // the argument space than temporary variable space.
- fn = syslook("equal", 1);
- l = n->left;
- r = n->right;
- argtype(fn, n->left->type);
- argtype(fn, n->left->type);
- r = mkcall1(fn, n->type, init, typename(n->left->type), l, r);
- if(n->op == ONE) {
- r = nod(ONOT, r, N);
- }
- goto ret;
-
ret:
typecheck(&r, Erv);
walkexpr(&r, init);