summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/align.c7
-rw-r--r--src/cmd/gc/builtin.c7
-rw-r--r--src/cmd/gc/closure.c194
-rw-r--r--src/cmd/gc/const.c36
-rw-r--r--src/cmd/gc/cplx.c8
-rw-r--r--src/cmd/gc/dcl.c56
-rw-r--r--src/cmd/gc/esc.c13
-rw-r--r--src/cmd/gc/fmt.c11
-rw-r--r--src/cmd/gc/gen.c7
-rw-r--r--src/cmd/gc/go.h26
-rw-r--r--src/cmd/gc/go.y8
-rw-r--r--src/cmd/gc/inl.c32
-rw-r--r--src/cmd/gc/lex.c11
-rwxr-xr-xsrc/cmd/gc/mkbuiltin1
-rw-r--r--src/cmd/gc/obj.c14
-rw-r--r--src/cmd/gc/pgen.c13
-rw-r--r--src/cmd/gc/racewalk.c162
-rw-r--r--src/cmd/gc/range.c6
-rw-r--r--src/cmd/gc/reflect.c46
-rw-r--r--src/cmd/gc/runtime.go6
-rw-r--r--src/cmd/gc/sinit.c8
-rw-r--r--src/cmd/gc/subr.c54
-rw-r--r--src/cmd/gc/swt.c6
-rw-r--r--src/cmd/gc/typecheck.c204
-rw-r--r--src/cmd/gc/unsafe.c42
-rw-r--r--src/cmd/gc/walk.c185
-rw-r--r--src/cmd/gc/y.tab.c594
27 files changed, 1216 insertions, 541 deletions
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index be9f552f6..80c65387b 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -46,7 +46,8 @@ static vlong
widstruct(Type *errtype, Type *t, vlong o, int flag)
{
Type *f;
- int32 w, maxalign;
+ int64 w;
+ int32 maxalign;
maxalign = flag;
if(maxalign < 1)
@@ -643,7 +644,7 @@ argsize(Type *t)
{
Iter save;
Type *fp;
- int w, x;
+ int64 w, x;
w = 0;
@@ -664,5 +665,7 @@ argsize(Type *t)
}
w = (w+widthptr-1) & ~(widthptr-1);
+ if((int)w != w)
+ fatal("argsize too big");
return w;
}
diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c
index 7de448d1e..9053dfe10 100644
--- a/src/cmd/gc/builtin.c
+++ b/src/cmd/gc/builtin.c
@@ -1,3 +1,4 @@
+// AUTO-GENERATED by mkbuiltin; DO NOT EDIT
char *runtimeimport =
"package runtime\n"
"import runtime \"runtime\"\n"
@@ -63,7 +64,13 @@ char *runtimeimport =
"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"
+ "func @\"\".mapaccess1_fast64 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
+ "func @\"\".mapaccess1_faststr (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n"
"func @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast32 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_fast64 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
+ "func @\"\".mapaccess2_faststr (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n"
"func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any, @\"\".val·4 any)\n"
"func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n"
"func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any)\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index 4e029ef83..d81c5281d 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -60,6 +60,7 @@ closurebody(NodeList *body)
func = curfn;
func->nbody = body;
+ func->endlineno = lineno;
funcbody(func);
// closure-specific variables are hanging off the
@@ -75,7 +76,7 @@ closurebody(NodeList *body)
return func;
}
-static Node* makeclosure(Node *func, int nowrap);
+static Node* makeclosure(Node *func);
void
typecheckclosure(Node *func, int top)
@@ -124,17 +125,17 @@ typecheckclosure(Node *func, int top)
}
// Create top-level function
- xtop = list(xtop, makeclosure(func, func->cvars==nil || (top&Ecall)));
+ xtop = list(xtop, makeclosure(func));
}
static Node*
-makeclosure(Node *func, int nowrap)
+makeclosure(Node *func)
{
Node *xtype, *v, *addr, *xfunc, *cv;
NodeList *l, *body;
static int closgen;
char *p;
- int offset;
+ vlong offset;
/*
* wrap body in external function
@@ -154,6 +155,7 @@ makeclosure(Node *func, int nowrap)
declare(xfunc->nname, PFUNC);
xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth;
+ xfunc->endlineno = func->endlineno;
// declare variables holding addresses taken from closure
// and initialize in entry prologue.
@@ -255,26 +257,174 @@ walkclosure(Node *func, NodeList **init)
return clos;
}
-// Special case for closures that get called in place.
-// Optimize runtime.closure(X, __func__xxxx_, .... ) away
-// to __func__xxxx_(Y ....).
-// On entry, expect n->op == OCALL, n->left->op == OCLOSURE.
+static Node *makepartialcall(Node*, Type*, Node*);
+
void
-walkcallclosure(Node *n, NodeList **init)
+typecheckpartialcall(Node *fn, Node *sym)
+{
+ switch(fn->op) {
+ case ODOTINTER:
+ case ODOTMETH:
+ break;
+ default:
+ fatal("invalid typecheckpartialcall");
+ }
+
+ // Create top-level function.
+ fn->nname = makepartialcall(fn, fn->type, sym);
+ fn->right = sym;
+ fn->op = OCALLPART;
+ fn->type = fn->nname->type;
+}
+
+static Node*
+makepartialcall(Node *fn, Type *t0, Node *meth)
+{
+ Node *ptr, *n, *fld, *call, *xtype, *xfunc, *cv;
+ Type *rcvrtype, *basetype, *t;
+ NodeList *body, *l, *callargs, *retargs;
+ char *p;
+ Sym *sym;
+ int i, ddd;
+
+ // TODO: names are not right
+ rcvrtype = fn->left->type;
+ if(exportname(meth->sym->name))
+ p = smprint("%-hT.%s·fm", rcvrtype, meth->sym->name);
+ else
+ p = smprint("%-hT.(%-S)·fm", rcvrtype, meth->sym);
+ basetype = rcvrtype;
+ if(isptr[rcvrtype->etype])
+ basetype = basetype->type;
+ if(basetype->sym == S)
+ fatal("missing base type for %T", rcvrtype);
+
+ sym = pkglookup(p, basetype->sym->pkg);
+ free(p);
+ if(sym->flags & SymUniq)
+ return sym->def;
+ sym->flags |= SymUniq;
+
+ xtype = nod(OTFUNC, N, N);
+ i = 0;
+ l = nil;
+ callargs = nil;
+ ddd = 0;
+ xfunc = nod(ODCLFUNC, N, N);
+ for(t = getinargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "a%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAM;
+ xfunc->dcl = list(xfunc->dcl, n);
+ callargs = list(callargs, n);
+ fld = nod(ODCLFIELD, n, typenod(t->type));
+ if(t->isddd) {
+ fld->isddd = 1;
+ ddd = 1;
+ }
+ l = list(l, fld);
+ }
+ xtype->list = l;
+ i = 0;
+ l = nil;
+ retargs = nil;
+ for(t = getoutargx(t0)->type; t; t = t->down) {
+ snprint(namebuf, sizeof namebuf, "r%d", i++);
+ n = newname(lookup(namebuf));
+ n->class = PPARAMOUT;
+ xfunc->dcl = list(xfunc->dcl, n);
+ retargs = list(retargs, n);
+ l = list(l, nod(ODCLFIELD, n, typenod(t->type)));
+ }
+ xtype->rlist = l;
+
+ xfunc->dupok = 1;
+ xfunc->nname = newname(sym);
+ xfunc->nname->sym->flags |= SymExported; // disable export
+ xfunc->nname->ntype = xtype;
+ xfunc->nname->defn = xfunc;
+ declare(xfunc->nname, PFUNC);
+
+ // Declare and initialize variable holding receiver.
+ body = nil;
+ cv = nod(OCLOSUREVAR, N, N);
+ cv->xoffset = widthptr;
+ cv->type = rcvrtype;
+ ptr = nod(ONAME, N, N);
+ ptr->sym = lookup("rcvr");
+ ptr->class = PAUTO;
+ ptr->addable = 1;
+ ptr->ullman = 1;
+ ptr->used = 1;
+ ptr->curfn = xfunc;
+ xfunc->dcl = list(xfunc->dcl, ptr);
+ if(isptr[rcvrtype->etype] || isinter(rcvrtype)) {
+ ptr->ntype = typenod(rcvrtype);
+ body = list(body, nod(OAS, ptr, cv));
+ } else {
+ ptr->ntype = typenod(ptrto(rcvrtype));
+ body = list(body, nod(OAS, ptr, nod(OADDR, cv, N)));
+ }
+
+ call = nod(OCALL, nod(OXDOT, ptr, meth), N);
+ call->list = callargs;
+ call->isddd = ddd;
+ if(t0->outtuple == 0) {
+ body = list(body, call);
+ } else {
+ n = nod(OAS2, N, N);
+ n->list = retargs;
+ n->rlist = list1(call);
+ body = list(body, n);
+ n = nod(ORETURN, N, N);
+ body = list(body, n);
+ }
+
+ xfunc->nbody = body;
+
+ typecheck(&xfunc, Etop);
+ sym->def = xfunc;
+ xtop = list(xtop, xfunc);
+
+ return xfunc;
+}
+
+Node*
+walkpartialcall(Node *n, NodeList **init)
{
- USED(init);
- if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
- dump("walkcallclosure", n);
- fatal("abuse of walkcallclosure");
+ Node *clos, *typ;
+
+ // Create closure in the form of a composite literal.
+ // For x.M with receiver (x) type T, the generated code looks like:
+ //
+ // clos = &struct{F uintptr; R T}{M.T·f, x}
+ //
+ // Like walkclosure above.
+
+ if(isinter(n->left->type)) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
}
- // New arg list for n. First the closure-args
- // and then the original parameter list.
- n->list = concat(n->left->enter, n->list);
- n->left = n->left->closure->nname;
- dowidth(n->left->type);
- n->type = getoutargx(n->left->type);
- // for a single valued function, pull the field type out of the struct
- if (n->type && n->type->type && !n->type->type->down)
- n->type = n->type->type->type;
+ typ = nod(OTSTRUCT, N, N);
+ typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR])));
+ typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup("R")), typenod(n->left->type)));
+
+ clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
+ clos->esc = n->esc;
+ clos->right->implicit = 1;
+ clos->list = list1(nod(OCFUNC, n->nname->nname, N));
+ clos->list = list(clos->list, n->left);
+
+ // Force type conversion from *struct to the func type.
+ clos = nod(OCONVNOP, clos, N);
+ clos->type = n->type;
+
+ typecheck(&clos, Erv);
+ // typecheck will insert a PTRLIT node under CONVNOP,
+ // tag it with escape analysis result.
+ clos->left->esc = n->esc;
+ walkexpr(&clos, init);
+
+ return clos;
}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 4f1ff6778..e9d99df18 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -119,6 +119,27 @@ convlit1(Node **np, Type *t, int explicit)
}
n->type = t;
return;
+ case OCOMPLEX:
+ if(n->type->etype == TIDEAL) {
+ switch(t->etype) {
+ default:
+ // If trying to convert to non-complex type,
+ // leave as complex128 and let typechecker complain.
+ t = types[TCOMPLEX128];
+ //fallthrough
+ case TCOMPLEX128:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT64]);
+ convlit(&n->right, types[TFLOAT64]);
+ break;
+ case TCOMPLEX64:
+ n->type = t;
+ convlit(&n->left, types[TFLOAT32]);
+ convlit(&n->right, types[TFLOAT32]);
+ break;
+ }
+ }
+ return;
}
// avoided repeated calculations, errors
@@ -1068,6 +1089,11 @@ idealkind(Node *n)
return k1;
else
return k2;
+ case OREAL:
+ case OIMAG:
+ return CTFLT;
+ case OCOMPLEX:
+ return CTCPLX;
case OADDSTR:
return CTSTR;
case OANDAND:
@@ -1110,7 +1136,6 @@ defaultlit(Node **np, Type *t)
lno = setlineno(n);
ctype = idealkind(n);
- t1 = T;
switch(ctype) {
default:
if(t != T) {
@@ -1185,6 +1210,7 @@ void
defaultlit2(Node **lp, Node **rp, int force)
{
Node *l, *r;
+ int lkind, rkind;
l = *lp;
r = *rp;
@@ -1204,18 +1230,20 @@ defaultlit2(Node **lp, Node **rp, int force)
convlit(lp, types[TBOOL]);
convlit(rp, types[TBOOL]);
}
- if(isconst(l, CTCPLX) || isconst(r, CTCPLX)) {
+ lkind = idealkind(l);
+ rkind = idealkind(r);
+ if(lkind == CTCPLX || rkind == CTCPLX) {
convlit(lp, types[TCOMPLEX128]);
convlit(rp, types[TCOMPLEX128]);
return;
}
- if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
+ if(lkind == CTFLT || rkind == CTFLT) {
convlit(lp, types[TFLOAT64]);
convlit(rp, types[TFLOAT64]);
return;
}
- if(isconst(l, CTRUNE) || isconst(r, CTRUNE)) {
+ if(lkind == CTRUNE || rkind == CTRUNE) {
convlit(lp, runetype);
convlit(rp, runetype);
return;
diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c
index e0127fc59..c9bab7a76 100644
--- a/src/cmd/gc/cplx.c
+++ b/src/cmd/gc/cplx.c
@@ -36,7 +36,7 @@ void
complexmove(Node *f, Node *t)
{
int ft, tt;
- Node n1, n2, n3, n4;
+ Node n1, n2, n3, n4, tmp;
if(debug['g']) {
dump("\ncomplexmove-f", f);
@@ -62,9 +62,9 @@ complexmove(Node *f, Node *t)
// make f addable.
// also use temporary if possible stack overlap.
if(!f->addable || overlap(f, t)) {
- tempname(&n1, f->type);
- complexmove(f, &n1);
- f = &n1;
+ tempname(&tmp, f->type);
+ complexmove(f, &tmp);
+ f = &tmp;
}
subnode(&n1, &n2, f);
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index aa2489d9a..d3759efde 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -225,8 +225,12 @@ declare(Node *n, int ctxt)
if(ctxt == PAUTO)
n->xoffset = 0;
- if(s->block == block)
- redeclare(s, "in this block");
+ if(s->block == block) {
+ // functype will print errors about duplicate function arguments.
+ // Don't repeat the error here.
+ if(ctxt != PPARAM && ctxt != PPARAMOUT)
+ redeclare(s, "in this block");
+ }
s->block = block;
s->lastlineno = parserline();
@@ -824,22 +828,24 @@ structfield(Node *n)
return f;
}
+static uint32 uniqgen;
+
static void
checkdupfields(Type *t, char* what)
{
- Type* t1;
int lno;
lno = lineno;
- for( ; t; t=t->down)
- if(t->sym && t->nname && !isblank(t->nname))
- for(t1=t->down; t1; t1=t1->down)
- if(t1->sym == t->sym) {
- lineno = t->nname->lineno;
- yyerror("duplicate %s %s", what, t->sym->name);
- break;
- }
+ for( ; t; t=t->down) {
+ if(t->sym && t->nname && !isblank(t->nname)) {
+ if(t->sym->uniqgen == uniqgen) {
+ lineno = t->nname->lineno;
+ yyerror("duplicate %s %s", what, t->sym->name);
+ } else
+ t->sym->uniqgen = uniqgen;
+ }
+ }
lineno = lno;
}
@@ -865,6 +871,7 @@ tostruct(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "field");
if (!t->broke)
@@ -897,7 +904,6 @@ tofunargs(NodeList *l)
if(f->broke)
t->broke = 1;
- checkdupfields(t->type, "argument");
return t;
}
@@ -1004,6 +1010,7 @@ tointerface(NodeList *l)
if(f->broke)
t->broke = 1;
+ uniqgen++;
checkdupfields(t->type, "method");
t = sortinter(t);
checkwidth(t);
@@ -1187,6 +1194,11 @@ functype(Node *this, NodeList *in, NodeList *out)
t->type->down = tofunargs(out);
t->type->down->down = tofunargs(in);
+ uniqgen++;
+ checkdupfields(t->type->type, "argument");
+ checkdupfields(t->type->down->type, "argument");
+ checkdupfields(t->type->down->down->type, "argument");
+
if (t->type->broke || t->type->down->broke || t->type->down->down->broke)
t->broke = 1;
@@ -1327,6 +1339,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
f = methtype(pa, 1);
if(f == T) {
t = pa;
+ if(t == T) // rely on typecheck having complained before
+ return;
if(t != T) {
if(isptr[t->etype]) {
if(t->sym != S) {
@@ -1335,10 +1349,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
}
t = t->type;
}
- }
- if(t->broke) // rely on typecheck having complained before
- return;
- if(t != T) {
+ if(t->broke) // rely on typecheck having complained before
+ return;
if(t->sym == S) {
yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t);
return;
@@ -1368,6 +1380,12 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
}
}
+ if(local && !pa->local) {
+ // defining method on non-local type.
+ yyerror("cannot define new methods on non-local type %T", pa);
+ return;
+ }
+
n = nod(ODCLFIELD, newname(sf), N);
n->type = t;
@@ -1383,12 +1401,6 @@ addmethod(Sym *sf, Type *t, int local, int nointerface)
return;
}
- if(local && !pa->local) {
- // defining method on non-local type.
- yyerror("cannot define new methods on non-local type %T", pa);
- return;
- }
-
f = structfield(n);
f->nointerface = nointerface;
diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c
index 46c06d10e..df273e392 100644
--- a/src/cmd/gc/esc.c
+++ b/src/cmd/gc/esc.c
@@ -596,6 +596,14 @@ esc(EscState *e, Node *n)
// Contents make it to memory, lose track.
escassign(e, &e->theSink, n->left);
break;
+
+ case OCALLPART:
+ n->esc = EscNone; // until proven otherwise
+ e->noesc = list(e->noesc, n);
+ n->escloopdepth = e->loopdepth;
+ // Contents make it to memory, lose track.
+ escassign(e, &e->theSink, n->left);
+ break;
case OMAPLIT:
n->esc = EscNone; // until proven otherwise
@@ -667,6 +675,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OCONVNOP:
case OMAPLIT:
case OSTRUCTLIT:
+ case OCALLPART:
break;
case ONAME:
@@ -713,6 +722,7 @@ escassign(EscState *e, Node *dst, Node *src)
case OMAKESLICE:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
escflows(e, dst, src);
break;
@@ -1033,7 +1043,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
switch(src->op) {
case ONAME:
- if(src->class == PPARAM && leaks && src->esc != EscHeap) {
+ if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) {
src->esc = EscScope;
if(debug['m'])
warnl(src->lineno, "leaking param: %hN", src);
@@ -1073,6 +1083,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
case OMAPLIT:
case ONEW:
case OCLOSURE:
+ case OCALLPART:
if(leaks) {
src->esc = EscHeap;
if(debug['m'])
diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c
index ab81e6c88..35f01a5c2 100644
--- a/src/cmd/gc/fmt.c
+++ b/src/cmd/gc/fmt.c
@@ -168,7 +168,7 @@ Lconv(Fmt *fp)
lno = a[i].incl->line - 1; // now print out start of this file
}
if(n == 0)
- fmtprint(fp, "<epoch>");
+ fmtprint(fp, "<unknown line number>");
return 0;
}
@@ -443,6 +443,9 @@ Zconv(Fmt *fp)
fmtrune(fp, '\\');
fmtrune(fp, r);
break;
+ case 0xFEFF: // BOM, basically disallowed in source code
+ fmtstrcpy(fp, "\\uFEFF");
+ break;
}
}
return 0;
@@ -630,7 +633,7 @@ typefmt(Fmt *fp, Type *t)
case TARRAY:
if(t->bound >= 0)
- return fmtprint(fp, "[%d]%T", (int)t->bound, t->type);
+ return fmtprint(fp, "[%lld]%T", t->bound, t->type);
if(t->bound == -100)
return fmtprint(fp, "[...]%T", t->type);
return fmtprint(fp, "[]%T", t->type);
@@ -1022,6 +1025,7 @@ static int opprec[] = {
[ODOTTYPE] = 8,
[ODOT] = 8,
[OXDOT] = 8,
+ [OCALLPART] = 8,
[OPLUS] = 7,
[ONOT] = 7,
@@ -1269,9 +1273,10 @@ exprfmt(Fmt *f, Node *n, int prec)
case ODOTPTR:
case ODOTINTER:
case ODOTMETH:
+ case OCALLPART:
exprfmt(f, n->left, nprec);
if(n->right == N || n->right->sym == S)
- fmtstrcpy(f, ".<nil>");
+ return fmtstrcpy(f, ".<nil>");
return fmtprint(f, ".%hhS", n->right->sym);
case ODOTTYPE:
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 5f03d9476..955ec2c5b 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -491,6 +491,9 @@ gen(Node *n)
case ORETURN:
cgen_ret(n);
break;
+
+ case OCHECKNOTNIL:
+ checkref(n->left, 1);
}
ret:
@@ -807,7 +810,7 @@ cgen_slice(Node *n, Node *res)
if(n->op == OSLICEARR) {
if(!isptr[n->left->type->etype])
fatal("slicearr is supposed to work on pointer: %+N\n", n);
- checkref(n->left);
+ checkref(n->left, 0);
}
if(isnil(n->left)) {
@@ -833,7 +836,7 @@ cgen_slice(Node *n, Node *res)
* <0 is pointer to next field (+1)
*/
int
-dotoffset(Node *n, int *oary, Node **nn)
+dotoffset(Node *n, int64 *oary, Node **nn)
{
int i;
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f86c152f2..48bcf0233 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -155,10 +155,10 @@ struct Type
Type* orig; // original type (type literal or predefined type)
int lineno;
- // TFUNCT
- uchar thistuple;
- uchar outtuple;
- uchar intuple;
+ // TFUNC
+ int thistuple;
+ int outtuple;
+ int intuple;
uchar outnamed;
Type* method;
@@ -252,9 +252,7 @@ struct Node
uchar embedded; // ODCLFIELD embedded type
uchar colas; // OAS resulting from :=
uchar diag; // already printed error about this
- uchar esc; // EscXXX
uchar noescape; // func arguments do not escape
- uchar funcdepth;
uchar builtin; // built-in name, like len or close
uchar walkdef;
uchar typecheck;
@@ -268,6 +266,9 @@ struct Node
uchar addrtaken; // address taken, even if not moved to heap
uchar dupok; // duplicate definitions ok (for func)
schar likely; // likeliness of if statement
+ uchar hasbreak; // has break statement
+ uint esc; // EscXXX
+ int funcdepth;
// most nodes
Type* type;
@@ -368,6 +369,7 @@ struct Sym
uchar sym; // huffman encoding in object file
Sym* link;
int32 npkg; // number of imported packages with this name
+ uint32 uniqgen;
// saved and restored by dcopy
Pkg* pkg;
@@ -392,6 +394,7 @@ struct Pkg
uchar imported; // export data of this package was parsed
char exported; // import line written in export data
char direct; // imported directly
+ char safe; // whether the package is marked as safe
};
typedef struct Iter Iter;
@@ -450,6 +453,7 @@ enum
OCALLFUNC, // f()
OCALLMETH, // t.Method()
OCALLINTER, // err.Error()
+ OCALLPART, // t.Method (without ())
OCAP, // cap
OCLOSE, // close
OCLOSURE, // f = func() { etc }
@@ -562,6 +566,7 @@ enum
OITAB, // itable word of an interface value.
OCLOSUREVAR, // variable reference at beginning of closure function
OCFUNC, // reference to c function pointer (not go func value)
+ OCHECKNOTNIL, // emit code to ensure pointer/interface not nil
// arch-specific registers
OREGISTER, // a register, such as AX.
@@ -987,7 +992,8 @@ Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
void typecheckclosure(Node *func, int top);
Node* walkclosure(Node *func, NodeList **init);
-void walkcallclosure(Node *n, NodeList **init);
+void typecheckpartialcall(Node*, Node*);
+Node* walkpartialcall(Node*, NodeList**);
/*
* const.c
@@ -1097,7 +1103,7 @@ void cgen_eface(Node* n, Node* res);
void cgen_slice(Node* n, Node* res);
void clearlabels(void);
void checklabels(void);
-int dotoffset(Node *n, int *oary, Node **nn);
+int dotoffset(Node *n, int64 *oary, Node **nn);
void gen(Node *n);
void genlist(NodeList *l);
Node* sysfunc(char *name);
@@ -1363,6 +1369,7 @@ Node* typecheck(Node **np, int top);
void typechecklist(NodeList *l, int top);
Node* typecheckdef(Node *n);
void copytype(Node *n, Type *t);
+void checkreturn(Node*);
void queuemethod(Node *n);
/*
@@ -1416,7 +1423,8 @@ EXTERN Node* nodfp;
int anyregalloc(void);
void betypeinit(void);
void bgen(Node *n, int true, int likely, Prog *to);
-void checkref(Node*);
+void checkref(Node *n, int force);
+void checknotnil(Node*, NodeList**);
void cgen(Node*, Node*);
void cgen_asop(Node *n);
void cgen_call(Node *n, int proc);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 794961e8e..29cd37008 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -251,7 +251,8 @@ import_package:
} else if(strcmp(importpkg->name, $2->name) != 0)
yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, $2->name, importpkg->path);
importpkg->direct = 1;
-
+ importpkg->safe = curio.importsafe;
+
if(safemode && !curio.importsafe)
yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
}
@@ -536,7 +537,10 @@ compound_stmt:
}
stmt_list '}'
{
- $$ = liststmt($3);
+ if($3 == nil)
+ $$ = nod(OEMPTY, N, N);
+ else
+ $$ = liststmt($3);
popdcl();
}
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
index 1cc13a304..f77b51d70 100644
--- a/src/cmd/gc/inl.c
+++ b/src/cmd/gc/inl.c
@@ -188,6 +188,7 @@ ishairy(Node *n, int *budget)
break;
case OCLOSURE:
+ case OCALLPART:
case ORANGE:
case OFOR:
case OSELECT:
@@ -357,7 +358,7 @@ inlnode(Node **np)
}
case OCLOSURE:
- // TODO do them here (or earlier) instead of in walkcallclosure,
+ // TODO do them here (or earlier),
// so escape analysis can avoid more heapmoves.
return;
}
@@ -565,24 +566,31 @@ mkinlcall1(Node **np, Node *fn, int isddd)
inlretvars = nil;
i = 0;
// Make temp names to use instead of the originals
- for(ll = dcl; ll; ll=ll->next)
+ for(ll = dcl; ll; ll=ll->next) {
+ if(ll->n->class == PPARAMOUT) // return values handled below.
+ continue;
if(ll->n->op == ONAME) {
ll->n->inlvar = inlvar(ll->n);
// Typecheck because inlvar is not necessarily a function parameter.
typecheck(&ll->n->inlvar, Erv);
if ((ll->n->class&~PHEAP) != PAUTO)
ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs
- if (ll->n->class == PPARAMOUT) // we rely on the order being correct here
- inlretvars = list(inlretvars, ll->n->inlvar);
}
+ }
- // anonymous return values, synthesize names for use in assignment that replaces return
- if(inlretvars == nil && fn->type->outtuple > 0)
- for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ // temporaries for return values.
+ for(t = getoutargx(fn->type)->type; t; t = t->down) {
+ if(t != T && t->nname != N && !isblank(t->nname)) {
+ m = inlvar(t->nname);
+ typecheck(&m, Erv);
+ t->nname->inlvar = m;
+ } else {
+ // anonymous return values, synthesize names for use in assignment that replaces return
m = retvar(t, i++);
- ninit = list(ninit, nod(ODCL, m, N));
- inlretvars = list(inlretvars, m);
}
+ ninit = list(ninit, nod(ODCL, m, N));
+ inlretvars = list(inlretvars, m);
+ }
// assign receiver.
if(fn->type->thistuple && n->left->op == ODOTMETH) {
@@ -790,6 +798,12 @@ inlvar(Node *var)
n->class = PAUTO;
n->used = 1;
n->curfn = curfn; // the calling function, not the called one
+
+ // esc pass wont run if we're inlining into a iface wrapper
+ // luckily, we can steal the results from the target func
+ if(var->esc == EscHeap)
+ addrescapes(n);
+
curfn->dcl = list(curfn->dcl, n);
return n;
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 68ae6864d..b7f71d553 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -376,6 +376,7 @@ main(int argc, char *argv[])
curfn = l->n;
saveerrors();
typechecklist(l->n->nbody, Etop);
+ checkreturn(l->n);
if(nerrors != 0)
l->n->nbody = nil; // type errors; do not compile
}
@@ -601,7 +602,7 @@ void
importfile(Val *f, int line)
{
Biobuf *imp;
- char *file, *p, *q;
+ char *file, *p, *q, *tag;
int32 c;
int len;
Strlit *path;
@@ -609,8 +610,6 @@ importfile(Val *f, int line)
USED(line);
- // TODO(rsc): don't bother reloading imports more than once?
-
if(f->ctype != CTSTR) {
yyerror("import statement not a string");
fakeimport();
@@ -685,7 +684,11 @@ importfile(Val *f, int line)
// to the lexer to avoid parsing export data twice.
if(importpkg->imported) {
file = strdup(namebuf);
- p = smprint("package %s\n$$\n", importpkg->name);
+ tag = "";
+ if(importpkg->safe) {
+ tag = "safe";
+ }
+ p = smprint("package %s %s\n$$\n", importpkg->name, tag);
cannedimports(file, p);
return;
}
diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin
index 2f76e6f06..1dab1c9a0 100755
--- a/src/cmd/gc/mkbuiltin
+++ b/src/cmd/gc/mkbuiltin
@@ -19,6 +19,7 @@ fi
GC=${GOCHAR}g
gcc -o mkbuiltin1 mkbuiltin1.c
rm -f _builtin.c
+echo "// AUTO-GENERATED by mkbuiltin; DO NOT EDIT" >>_builtin.c
for i in runtime unsafe
do
go tool $GC -A $i.go
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index b87d35b7b..e4bcd1170 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -16,6 +16,8 @@ static void dumpglobls(void);
void
dumpobj(void)
{
+ NodeList *externs, *tmp;
+
bout = Bopen(outfile, OWRITE);
if(bout == nil) {
flusherrors();
@@ -31,8 +33,20 @@ dumpobj(void)
outhist(bout);
+ externs = nil;
+ if(externdcl != nil)
+ externs = externdcl->end;
+
dumpglobls();
dumptypestructs();
+
+ // Dump extra globals.
+ tmp = externdcl;
+ if(externs != nil)
+ externdcl = externs->next;
+ dumpglobls();
+ externdcl = tmp;
+
dumpdata();
dumpfuncs();
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index df8903baf..82d8186b0 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -177,8 +177,13 @@ cmpstackvar(Node *a, Node *b)
{
if (a->class != b->class)
return (a->class == PAUTO) ? 1 : -1;
- if (a->class != PAUTO)
- return a->xoffset - b->xoffset;
+ if (a->class != PAUTO) {
+ if (a->xoffset < b->xoffset)
+ return -1;
+ if (a->xoffset > b->xoffset)
+ return 1;
+ return 0;
+ }
if ((a->used == 0) != (b->used == 0))
return b->used - a->used;
return b->type->align - a->type->align;
@@ -240,6 +245,10 @@ allocauto(Prog* ptxt)
stksize = rnd(stksize, n->type->align);
if(thechar == '5')
stksize = rnd(stksize, widthptr);
+ if(stksize >= (1ULL<<31)) {
+ setlineno(curfn);
+ yyerror("stack frame too large (>2GB)");
+ }
n->stkdelta = -stksize - n->xoffset;
}
diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c
index bae98ec1b..5d4f62e76 100644
--- a/src/cmd/gc/racewalk.c
+++ b/src/cmd/gc/racewalk.c
@@ -26,6 +26,7 @@ static Node* uintptraddr(Node *n);
static Node* basenod(Node *n);
static void foreach(Node *n, void(*f)(Node*, void*), void *c);
static void hascallspred(Node *n, void *c);
+static void appendinit(Node **np, NodeList *init);
static Node* detachexpr(Node *n, NodeList **init);
// Do not instrument the following packages at all,
@@ -132,14 +133,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OASOP:
case OAS:
case OAS2:
- case OAS2DOTTYPE:
case OAS2RECV:
case OAS2FUNC:
case OAS2MAPR:
racewalknode(&n->left, init, 1, 0);
racewalknode(&n->right, init, 0, 0);
goto ret;
-
+
case OCFUNC:
// can't matter
goto ret;
@@ -185,17 +185,12 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->left, init, 0, 0);
goto ret;
- case OSWITCH:
- if(n->ntest->op == OTYPESW)
- // TODO(dvyukov): the expression can contain calls or reads.
- return;
- goto ret;
-
case ONOT:
case OMINUS:
case OPLUS:
case OREAL:
case OIMAG:
+ case OCOM:
racewalknode(&n->left, init, wr, 0);
goto ret;
@@ -222,29 +217,24 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OCAP:
racewalknode(&n->left, init, 0, 0);
if(istype(n->left->type, TMAP)) {
- // crashes on len(m[0]) or len(f())
- SET(n1);
- USED(n1);
- /*
- n1 = nod(OADDR, n->left, N);
- n1 = conv(n1, types[TUNSAFEPTR]);
- n1 = conv(n1, ptrto(ptrto(types[TINT8])));
- n1 = nod(OIND, n1, N);
+ n1 = nod(OCONVNOP, n->left, N);
+ n1->type = ptrto(types[TUINT8]);
n1 = nod(OIND, n1, N);
typecheck(&n1, Erv);
callinstr(&n1, init, 0, skip);
- */
}
goto ret;
case OLSH:
case ORSH:
+ case OLROT:
case OAND:
case OANDNOT:
case OOR:
case OXOR:
case OSUB:
case OMUL:
+ case OHMUL:
case OEQ:
case ONE:
case OLT:
@@ -260,9 +250,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OANDAND:
case OOROR:
racewalknode(&n->left, init, wr, 0);
- // It requires more complex tree transformation,
- // because we don't know whether it will be executed or not.
- //racewalknode(&n->right, init, wr, 0);
+ // walk has ensured the node has moved to a location where
+ // side effects are safe.
+ // n->right may not be executed,
+ // so instrumentation goes to n->right->ninit, not init.
+ l = nil;
+ racewalknode(&n->right, &l, wr, 0);
+ appendinit(&n->right, l);
goto ret;
case ONAME:
@@ -279,7 +273,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case ODIV:
case OMOD:
- // TODO(dvyukov): add a test for this
racewalknode(&n->left, init, wr, 0);
racewalknode(&n->right, init, wr, 0);
goto ret;
@@ -313,6 +306,14 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->right, init, 0, 0);
goto ret;
+ case OITAB:
+ racewalknode(&n->left, init, 0, 0);
+ goto ret;
+
+ case OTYPESW:
+ racewalknode(&n->right, init, 0, 0);
+ goto ret;
+
// should not appear in AST by now
case OSEND:
case ORECV:
@@ -324,67 +325,69 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPANIC:
case ORECOVER:
case OCONVIFACE:
+ case OCMPIFACE:
+ case OMAKECHAN:
+ case OMAKEMAP:
+ case OMAKESLICE:
+ case OCALL:
+ case OCOPY:
+ case OAPPEND:
+ case ORUNESTR:
+ case OARRAYBYTESTR:
+ case OARRAYRUNESTR:
+ case OSTRARRAYBYTE:
+ case OSTRARRAYRUNE:
+ case OINDEXMAP: // lowered to call
+ case OCMPSTR:
+ case OADDSTR:
+ case ODOTTYPE:
+ case ODOTTYPE2:
+ case OAS2DOTTYPE:
+ case OCALLPART: // lowered to PTRLIT
+ case OCLOSURE: // lowered to PTRLIT
+ case ORANGE: // lowered to ordinary for loop
+ case OARRAYLIT: // lowered to assignments
+ case OMAPLIT:
+ case OSTRUCTLIT:
yyerror("racewalk: %O must be lowered by now", n->op);
goto ret;
+ // impossible nodes: only appear in backend.
+ case ORROTC:
+ case OEXTEND:
+ yyerror("racewalk: %O cannot exist now", n->op);
+ goto ret;
+
// just do generic traversal
case OFOR:
case OIF:
case OCALLMETH:
case ORETURN:
+ case OSWITCH:
case OSELECT:
case OEMPTY:
+ case OBREAK:
+ case OCONTINUE:
+ case OFALL:
+ case OGOTO:
+ case OLABEL:
goto ret;
// does not require instrumentation
- case OINDEXMAP: // implemented in runtime
case OPRINT: // don't bother instrumenting it
case OPRINTN: // don't bother instrumenting it
+ case OCHECKNOTNIL: // always followed by a read.
case OPARAM: // it appears only in fn->exit to copy heap params back
- goto ret;
-
- // unimplemented
- case OCMPSTR:
- case OADDSTR:
- case OSLICESTR:
- case OAPPEND:
- case OCOPY:
- case OMAKECHAN:
- case OMAKEMAP:
- case OMAKESLICE:
- case ORUNESTR:
- case OARRAYBYTESTR:
- case OARRAYRUNESTR:
- case OSTRARRAYBYTE:
- case OSTRARRAYRUNE:
- case OCMPIFACE:
- case OARRAYLIT:
- case OMAPLIT:
- case OSTRUCTLIT:
- case OCLOSURE:
- case ODOTTYPE:
- case ODOTTYPE2:
- case OCALL:
- case OBREAK:
- case ODCL:
- case OCONTINUE:
- case OFALL:
- case OGOTO:
- case OLABEL:
+ case OCLOSUREVAR:// immutable pointer to captured variable
+ case ODOTMETH: // either part of CALLMETH or CALLPART (lowered to PTRLIT)
+ case OINDREG: // at this stage, only n(SP) nodes from nodarg
+ case ODCL: // declarations (without value) cannot be races
case ODCLCONST:
case ODCLTYPE:
- case OLITERAL:
- case ORANGE:
case OTYPE:
case ONONAME:
- case OINDREG:
- case OCOM:
- case ODOTMETH:
- case OITAB:
- case OEXTEND:
- case OHMUL:
- case OLROT:
- case ORROTC:
+ case OLITERAL:
+ case OSLICESTR: // always preceded by bounds checking, avoid double instrumentation.
goto ret;
}
@@ -400,7 +403,6 @@ ret:
racewalklist(n->nbody, nil);
racewalklist(n->nelse, nil);
racewalklist(n->rlist, nil);
-
*np = n;
}
@@ -442,6 +444,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
if(isartificial(n))
return 0;
if(t->etype == TSTRUCT) {
+ // TODO: instrument arrays similarly.
// PARAMs w/o PHEAP are not interesting.
if(n->class == PPARAM || n->class == PPARAMOUT)
return 0;
@@ -478,7 +481,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip)
// that has got a pointer inside. Whether it points to
// the heap or not is impossible to know at compile time
if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
- || b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
+ || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
hascalls = 0;
foreach(n, hascallspred, &hascalls);
if(hascalls) {
@@ -504,6 +507,8 @@ uintptraddr(Node *n)
return r;
}
+// basenod returns the simplest child node of n pointing to the same
+// memory area.
static Node*
basenod(Node *n)
{
@@ -512,7 +517,7 @@ basenod(Node *n)
n = n->left;
continue;
}
- if(n->op == OINDEX) {
+ if(n->op == OINDEX && isfixedarray(n->type)) {
n = n->left;
continue;
}
@@ -577,3 +582,30 @@ hascallspred(Node *n, void *c)
(*(int*)c)++;
}
}
+
+// appendinit is like addinit in subr.c
+// but appends rather than prepends.
+static void
+appendinit(Node **np, NodeList *init)
+{
+ Node *n;
+
+ if(init == nil)
+ return;
+
+ n = *np;
+ switch(n->op) {
+ case ONAME:
+ case OLITERAL:
+ // There may be multiple refs to this node;
+ // introduce OCONVNOP to hold init list.
+ n = nod(OCONVNOP, n, N);
+ n->type = n->left->type;
+ n->typecheck = 1;
+ *np = n;
+ break;
+ }
+ n->ninit = concat(n->ninit, init);
+ n->ullman = UINF;
+}
+
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 50c4617c0..8af45b9d2 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -181,9 +181,9 @@ walkrange(Node *n)
case TMAP:
th = typ(TARRAY);
th->type = ptrto(types[TUINT8]);
- // see ../../pkg/runtime/hashmap.h:/hash_iter
- // Size in words.
- th->bound = 5 + 4*3 + 4*4/widthptr;
+ // see ../../pkg/runtime/hashmap.c:/hash_iter
+ // Size of hash_iter in # of pointers.
+ th->bound = 11;
hit = temp(th);
fn = syslook("mapiterinit", 1);
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b8eb79938..fc182b03e 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1026,13 +1026,29 @@ dalgsym(Type *t)
}
static int
+gcinline(Type *t) {
+ switch(t->etype) {
+ case TARRAY:
+ if(t->bound == 1)
+ return 1;
+ if(t->width <= 4*widthptr)
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+static int
dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
{
Type *t1;
- vlong o, off2, fieldoffset;
+ vlong o, off2, fieldoffset, i;
if(t->align > 0 && (*off % t->align) != 0)
fatal("dgcsym1: invalid initial alignment, %T", t);
+
+ if(t->width == BADWIDTH)
+ dowidth(t);
switch(t->etype) {
case TINT8:
@@ -1056,6 +1072,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
case TPTR32:
case TPTR64:
+ // NOTE: Any changes here need to be made to reflect.PtrTo as well.
if(*off % widthptr != 0)
fatal("dgcsym1: invalid alignment, %T", t);
if(!haspointers(t->type) || t->type->etype == TUINT8) {
@@ -1069,7 +1086,6 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
- case TCHAN:
case TUNSAFEPTR:
case TFUNC:
if(*off % widthptr != 0)
@@ -1079,8 +1095,20 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
*off += t->width;
break;
+ // struct Hchan*
+ case TCHAN:
+ // NOTE: Any changes here need to be made to reflect.ChanOf as well.
+ if(*off % widthptr != 0)
+ fatal("dgcsym1: invalid alignment, %T", t);
+ ot = duintptr(s, ot, GC_CHAN_PTR);
+ ot = duintptr(s, ot, *off);
+ ot = dsymptr(s, ot, dtypesym(t), 0);
+ *off += t->width;
+ break;
+
// struct Hmap*
case TMAP:
+ // NOTE: Any changes here need to be made to reflect.MapOf as well.
if(*off % widthptr != 0)
fatal("dgcsym1: invalid alignment, %T", t);
ot = duintptr(s, ot, GC_MAP_PTR);
@@ -1116,7 +1144,10 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
case TARRAY:
if(t->bound < -1)
fatal("dgcsym1: invalid bound, %T", t);
+ if(t->type->width == BADWIDTH)
+ dowidth(t->type);
if(isslice(t)) {
+ // NOTE: Any changes here need to be made to reflect.SliceOf as well.
// struct { byte* array; uint32 len; uint32 cap; }
if(*off % widthptr != 0)
fatal("dgcsym1: invalid alignment, %T", t);
@@ -1130,10 +1161,14 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size)
}
*off += t->width;
} else {
+ // NOTE: Any changes here need to be made to reflect.ArrayOf as well,
+ // at least once ArrayOf's gc info is implemented and ArrayOf is exported.
+ // struct { byte* array; uint32 len; uint32 cap; }
if(t->bound < 1 || !haspointers(t->type)) {
*off += t->width;
- } else if(t->bound == 1) {
- ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
+ } else if(gcinline(t)) {
+ for(i=0; i<t->bound; i++)
+ ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1
} else {
if(stack_size < GC_STACK_CAPACITY) {
ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC
@@ -1184,6 +1219,9 @@ dgcsym(Type *t)
return s;
s->flags |= SymGcgen;
+ if(t->width == BADWIDTH)
+ dowidth(t);
+
ot = 0;
off = 0;
ot = duintptr(s, ot, t->width);
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index c49d05c5c..2139a95d9 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -89,7 +89,13 @@ 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)
+func mapaccess1_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
+func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
+func mapaccess1_faststr(mapType *byte, hmap map[any]any, key any) (val *any)
func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
+func mapaccess2_fast32(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
+func mapaccess2_fast64(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
+func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pres bool)
func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
func mapdelete(mapType *byte, hmap map[any]any, key any)
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 353fc00ce..f8c61828c 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -801,7 +801,8 @@ maplit(int ctxt, Node *n, Node *var, NodeList **init)
{
Node *r, *a;
NodeList *l;
- int nerr, b;
+ int nerr;
+ int64 b;
Type *t, *tk, *tv, *t1;
Node *vstat, *index, *value;
Sym *syma, *symb;
@@ -1142,7 +1143,10 @@ stataddr(Node *nam, Node *n)
l = getlit(n->right);
if(l < 0)
break;
- nam->xoffset += l*n->type->width;
+ // Check for overflow.
+ if(n->type->width != 0 && MAXWIDTH/n->type->width <= l)
+ break;
+ nam->xoffset += l*n->type->width;
nam->type = n->type;
return 1;
}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index c53eaf285..20a15bc71 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -548,6 +548,12 @@ algtype1(Type *t, Type **bad)
*bad = T;
switch(t->etype) {
+ case TANY:
+ case TFORW:
+ // will be defined later.
+ *bad = t;
+ return -1;
+
case TINT8:
case TUINT8:
case TINT16:
@@ -665,11 +671,14 @@ Type*
maptype(Type *key, Type *val)
{
Type *t;
+ Type *bad;
+ int atype;
if(key != nil) {
- switch(key->etype) {
+ atype = algtype1(key, &bad);
+ switch(bad == T ? key->etype : bad->etype) {
default:
- if(algtype1(key, nil) == ANOEQ)
+ if(atype == ANOEQ)
yyerror("invalid map key type %T", key);
break;
case TANY:
@@ -714,6 +723,12 @@ methcmp(const void *va, const void *vb)
a = *(Type**)va;
b = *(Type**)vb;
+ if(a->sym == S && b->sym == S)
+ return 0;
+ if(a->sym == S)
+ return -1;
+ if(b->sym == S)
+ return 1;
i = strcmp(a->sym->name, b->sym->name);
if(i != 0)
return i;
@@ -824,7 +839,7 @@ Type*
aindex(Node *b, Type *t)
{
Type *r;
- int bound;
+ int64 bound;
bound = -1; // open bound
typecheck(&b, Erv);
@@ -1393,7 +1408,7 @@ assignconv(Node *n, Type *t, char *context)
Node *r, *old;
char *why;
- if(n == N || n->type == T)
+ if(n == N || n->type == T || n->type->broke)
return n;
old = n;
@@ -1759,6 +1774,13 @@ ullmancalc(Node *n)
case OCALLINTER:
ul = UINF;
goto out;
+ case OANDAND:
+ case OOROR:
+ // hard with race detector
+ if(flag_race) {
+ ul = UINF;
+ goto out;
+ }
}
ul = 1;
if(n->left != N)
@@ -1772,6 +1794,8 @@ ullmancalc(Node *n)
ul = ur;
out:
+ if(ul > 200)
+ ul = 200; // clamp to uchar with room to grow
n->ullman = ul;
}
@@ -2096,7 +2120,7 @@ localexpr(Node *n, Type *t, NodeList **init)
void
setmaxarg(Type *t)
{
- int32 w;
+ int64 w;
dowidth(t);
w = t->argwid;
@@ -2565,6 +2589,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
fn->dupok = 1;
typecheck(&fn, Etop);
typechecklist(fn->nbody, Etop);
+ inlcalls(fn);
curfn = nil;
funccompile(fn, 0);
}
@@ -3273,11 +3298,14 @@ liststmt(NodeList *l)
int
count(NodeList *l)
{
- int n;
+ vlong n;
n = 0;
for(; l; l=l->next)
n++;
+ if((int)n != n) { // Overflow.
+ yyerror("too many elements in list");
+ }
return n;
}
@@ -3722,3 +3750,17 @@ isbadimport(Strlit *path)
}
return 0;
}
+
+void
+checknotnil(Node *x, NodeList **init)
+{
+ Node *n;
+
+ if(isinter(x->type)) {
+ x = nod(OITAB, x, N);
+ typecheck(&x, Erv);
+ }
+ n = nod(OCHECKNOTNIL, x, N);
+ n->typecheck = 1;
+ *init = list(*init, n);
+}
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
index a497b8622..3ad5f02a5 100644
--- a/src/cmd/gc/swt.c
+++ b/src/cmd/gc/swt.c
@@ -322,6 +322,10 @@ casebody(Node *sw, Node *typeswvar)
setlineno(last);
yyerror("cannot fallthrough in type switch");
}
+ if(l->next == nil) {
+ setlineno(last);
+ yyerror("cannot fallthrough final case in switch");
+ }
last->op = OFALL;
} else
stat = list(stat, br);
@@ -354,6 +358,8 @@ mkcaselist(Node *sw, int arg)
c = c1;
ord++;
+ if((uint16)ord != ord)
+ fatal("too many cases in switch");
c->ordinal = ord;
c->node = n;
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index fbab85d03..40eecd337 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -276,6 +276,29 @@ callrecvlist(NodeList *l)
return 0;
}
+// indexlit implements typechecking of untyped values as
+// array/slice indexes. It is equivalent to defaultlit
+// except for constants of numerical kind, which are acceptable
+// whenever they can be represented by a value of type int.
+static void
+indexlit(Node **np)
+{
+ Node *n;
+
+ n = *np;
+ if(n == N || !isideal(n->type))
+ return;
+ switch(consttype(n)) {
+ case CTINT:
+ case CTRUNE:
+ case CTFLT:
+ case CTCPLX:
+ defaultlit(np, types[TINT]);
+ break;
+ }
+ defaultlit(np, T);
+}
+
static void
typecheck1(Node **np, int top)
{
@@ -732,6 +755,7 @@ reswitch:
yyerror("rhs of . must be a name"); // impossible
goto error;
}
+ r = n->right;
if(n->left->op == OTYPE) {
if(!looktypedot(n, t, 0)) {
@@ -775,7 +799,12 @@ reswitch:
switch(n->op) {
case ODOTINTER:
case ODOTMETH:
- ok |= Ecall;
+ if(top&Ecall)
+ ok |= Ecall;
+ else {
+ typecheckpartialcall(n, r);
+ ok |= Erv;
+ }
break;
default:
ok |= Erv;
@@ -839,7 +868,7 @@ reswitch:
case TSTRING:
case TARRAY:
- defaultlit(&n->right, T);
+ indexlit(&n->right);
if(t->etype == TSTRING)
n->type = types[TUINT8];
else
@@ -855,8 +884,8 @@ reswitch:
yyerror("non-integer %s index %N", why, n->right);
break;
}
- if(n->right->op == OLITERAL) {
- if(mpgetfix(n->right->val.u.xval) < 0)
+ if(isconst(n->right, CTINT)) {
+ if(mpgetfix(n->right->val.u.xval) < 0)
yyerror("invalid %s index %N (index must be non-negative)", why, n->right);
else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound)
yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound);
@@ -932,8 +961,8 @@ reswitch:
typecheck(&n->right->left, Erv);
typecheck(&n->right->right, Erv);
defaultlit(&n->left, T);
- defaultlit(&n->right->left, T);
- defaultlit(&n->right->right, T);
+ indexlit(&n->right->left);
+ indexlit(&n->right->right);
l = n->left;
if(isfixedarray(l->type)) {
if(!islvalue(n->left)) {
@@ -1180,16 +1209,18 @@ reswitch:
if(l->type == T || r->type == T)
goto error;
defaultlit2(&l, &r, 0);
+ if(l->type == T || r->type == T)
+ goto error;
n->left = l;
n->right = r;
- if(l->type->etype != r->type->etype) {
- badcmplx:
- yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type);
+ if(!eqtype(l->type, r->type)) {
+ yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
goto error;
}
switch(l->type->etype) {
default:
- goto badcmplx;
+ yyerror("invalid operation: %N (arguments have type %T, expected floating-point)", n, l->type, r->type);
+ goto error;
case TIDEAL:
t = types[TIDEAL];
break;
@@ -1692,10 +1723,6 @@ ret:
yyerror("%N is not a type", n);
goto error;
}
- if((ok & Ecall) && !(top & Ecall)) {
- yyerror("method %N is not an expression, must be called", n);
- goto error;
- }
// TODO(rsc): simplify
if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
yyerror("%N used as value", n);
@@ -2323,7 +2350,8 @@ pushtype(Node *n, Type *t)
static void
typecheckcomplit(Node **np)
{
- int bad, i, len, nerr;
+ int bad, i, nerr;
+ int64 len;
Node *l, *n, *norig, *r, **hash;
NodeList *ll;
Type *t, *f;
@@ -2558,6 +2586,7 @@ islvalue(Node *n)
// fall through
case OIND:
case ODOTPTR:
+ case OCLOSUREVAR:
return 1;
case ODOT:
return islvalue(n->left);
@@ -3144,3 +3173,148 @@ checkmake(Type *t, char *arg, Node *n)
}
return 0;
}
+
+static void markbreaklist(NodeList*, Node*);
+
+static void
+markbreak(Node *n, Node *implicit)
+{
+ Label *lab;
+
+ if(n == N)
+ return;
+
+ switch(n->op) {
+ case OBREAK:
+ if(n->left == N) {
+ if(implicit)
+ implicit->hasbreak = 1;
+ } else {
+ lab = n->left->sym->label;
+ if(lab != L)
+ lab->def->hasbreak = 1;
+ }
+ break;
+
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ implicit = n;
+ // fall through
+
+ default:
+ markbreak(n->left, implicit);
+ markbreak(n->right, implicit);
+ markbreak(n->ntest, implicit);
+ markbreak(n->nincr, implicit);
+ markbreaklist(n->ninit, implicit);
+ markbreaklist(n->nbody, implicit);
+ markbreaklist(n->nelse, implicit);
+ markbreaklist(n->list, implicit);
+ markbreaklist(n->rlist, implicit);
+ break;
+ }
+}
+
+static void
+markbreaklist(NodeList *l, Node *implicit)
+{
+ Node *n;
+ Label *lab;
+
+ for(; l; l=l->next) {
+ n = l->n;
+ if(n->op == OLABEL && l->next && n->defn == l->next->n) {
+ switch(n->defn->op) {
+ case OFOR:
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ case ORANGE:
+ lab = mal(sizeof *lab);
+ lab->def = n->defn;
+ n->left->sym->label = lab;
+ markbreak(n->defn, n->defn);
+ n->left->sym->label = L;
+ l = l->next;
+ continue;
+ }
+ }
+ markbreak(n, implicit);
+ }
+}
+
+static int
+isterminating(NodeList *l, int top)
+{
+ int def;
+ Node *n;
+
+ if(l == nil)
+ return 0;
+ if(top) {
+ while(l->next && l->n->op != OLABEL)
+ l = l->next;
+ markbreaklist(l, nil);
+ }
+ while(l->next)
+ l = l->next;
+ n = l->n;
+
+ if(n == N)
+ return 0;
+
+ switch(n->op) {
+ // NOTE: OLABEL is treated as a separate statement,
+ // not a separate prefix, so skipping to the last statement
+ // in the block handles the labeled statement case by
+ // skipping over the label. No case OLABEL here.
+
+ case OBLOCK:
+ return isterminating(n->list, 0);
+
+ case OGOTO:
+ case ORETURN:
+ case OPANIC:
+ case OXFALL:
+ return 1;
+
+ case OFOR:
+ if(n->ntest != N)
+ return 0;
+ if(n->hasbreak)
+ return 0;
+ return 1;
+
+ case OIF:
+ return isterminating(n->nbody, 0) && isterminating(n->nelse, 0);
+
+ case OSWITCH:
+ case OTYPESW:
+ case OSELECT:
+ if(n->hasbreak)
+ return 0;
+ def = 0;
+ for(l=n->list; l; l=l->next) {
+ if(!isterminating(l->n->nbody, 0))
+ return 0;
+ if(l->n->list == nil) // default
+ def = 1;
+ }
+ if(n->op != OSELECT && !def)
+ return 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+checkreturn(Node *fn)
+{
+ if(fn->type->outtuple && fn->nbody != nil)
+ if(!isterminating(fn->nbody, 1))
+ yyerrorl(fn->endlineno, "missing return at end of function");
+}
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 95200ad41..ff08c0eef 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -16,10 +16,10 @@
Node*
unsafenmagic(Node *nn)
{
- Node *r, *n;
+ Node *r, *n, *base, *r1;
Sym *s;
Type *t, *tr;
- long v;
+ vlong v;
Val val;
Node *fn;
NodeList *args;
@@ -49,11 +49,43 @@ unsafenmagic(Node *nn)
goto yes;
}
if(strcmp(s->name, "Offsetof") == 0) {
- typecheck(&r, Erv);
- if(r->op != ODOT && r->op != ODOTPTR)
+ // must be a selector.
+ if(r->op != OXDOT)
goto bad;
+ // Remember base of selector to find it back after dot insertion.
+ // Since r->left may be mutated by typechecking, check it explicitly
+ // first to track it correctly.
+ typecheck(&r->left, Erv);
+ base = r->left;
typecheck(&r, Erv);
- v = r->xoffset;
+ switch(r->op) {
+ case ODOT:
+ case ODOTPTR:
+ break;
+ case OCALLPART:
+ yyerror("invalid expression %N: argument is a method value", nn);
+ v = 0;
+ goto ret;
+ default:
+ goto bad;
+ }
+ v = 0;
+ // add offsets for inserted dots.
+ for(r1=r; r1->left!=base; r1=r1->left) {
+ switch(r1->op) {
+ case ODOT:
+ v += r1->xoffset;
+ break;
+ case ODOTPTR:
+ yyerror("invalid expression %N: selector implies indirection of embedded %N", nn, r1->left);
+ goto ret;
+ default:
+ dump("unsafenmagic", r);
+ fatal("impossible %#O node after dot insertion", r1->op);
+ goto bad;
+ }
+ }
+ v += r1->xoffset;
goto yes;
}
if(strcmp(s->name, "Alignof") == 0) {
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index de2105ed3..d9c6341b4 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -29,40 +29,6 @@ static void walkdiv(Node**, NodeList**);
static int bounded(Node*, int64);
static Mpint mpzero;
-// can this code branch reach the end
-// without an unconditional RETURN
-// this is hard, so it is conservative
-static int
-walkret(NodeList *l)
-{
- Node *n;
-
-loop:
- while(l && l->next)
- l = l->next;
- if(l == nil)
- return 1;
-
- // at this point, we have the last
- // statement of the function
- n = l->n;
- switch(n->op) {
- case OBLOCK:
- l = n->list;
- goto loop;
-
- case OGOTO:
- case ORETURN:
- case OPANIC:
- return 0;
- break;
- }
-
- // all other statements
- // will flow to the end
- return 1;
-}
-
void
walk(Node *fn)
{
@@ -76,9 +42,6 @@ walk(Node *fn)
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody);
}
- if(curfn->type->outtuple)
- if(walkret(curfn->nbody))
- yyerror("function ends without a return statement");
lno = lineno;
@@ -221,6 +184,7 @@ walkstmt(Node **np)
case OLABEL:
case ODCLCONST:
case ODCLTYPE:
+ case OCHECKNOTNIL:
break;
case OBLOCK:
@@ -433,13 +397,28 @@ walkexpr(Node **np, NodeList **init)
case OIMAG:
case ODOTMETH:
case ODOTINTER:
+ walkexpr(&n->left, init);
+ goto ret;
+
case OIND:
+ if(n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
case ODOT:
+ usefield(n);
+ walkexpr(&n->left, init);
+ goto ret;
+
case ODOTPTR:
usefield(n);
+ if(n->op == ODOTPTR && n->left->type->type->width == 0) {
+ n->left = cheapexpr(n->left, init);
+ checknotnil(n->left, init);
+ }
walkexpr(&n->left, init);
goto ret;
@@ -561,13 +540,6 @@ walkexpr(Node **np, NodeList **init)
if(n->list && n->list->n->op == OAS)
goto ret;
- /*
- if(n->left->op == OCLOSURE) {
- walkcallclosure(n, init);
- t = n->left->type;
- }
- */
-
walkexpr(&n->left, init);
walkexprlist(n->list, init);
@@ -673,8 +645,48 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
- fn = mapfn("mapaccess2", r->left->type);
- r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
+ t = r->left->type;
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess2_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess2_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess2_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // from:
+ // a,b = m[i]
+ // to:
+ // var,b = mapaccess2_fast*(t, m, i)
+ // a = *var
+ a = n->list->n;
+ var = temp(ptrto(t->type));
+ var->typecheck = 1;
+
+ fn = mapfn(p, t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
+ n->rlist = list1(r);
+ n->op = OAS2FUNC;
+ n->list->n = var;
+ walkexpr(&n, init);
+ *init = list(*init, n);
+
+ n = nod(OAS, a, nod(OIND, var, N));
+ typecheck(&n, Etop);
+ walkexpr(&n, init);
+ goto ret;
+ }
+ fn = mapfn("mapaccess2", t);
+ r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right);
n->rlist = list1(r);
n->op = OAS2FUNC;
goto as2func;
@@ -1041,7 +1053,33 @@ walkexpr(Node **np, NodeList **init)
goto ret;
t = n->left->type;
- n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ p = nil;
+ if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing.
+ switch(simsimtype(t->down)) {
+ case TINT32:
+ case TUINT32:
+ p = "mapaccess1_fast32";
+ break;
+ case TINT64:
+ case TUINT64:
+ p = "mapaccess1_fast64";
+ break;
+ case TSTRING:
+ p = "mapaccess1_faststr";
+ break;
+ }
+ }
+ if(p != nil) {
+ // use fast version. The fast versions return a pointer to the value - we need
+ // to dereference it to get the result.
+ n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, n->right);
+ n = nod(OIND, n, N);
+ n->type = t->type;
+ n->typecheck = 1;
+ } else {
+ // no fast version for this key
+ n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
+ }
goto ret;
case ORECV:
@@ -1292,6 +1330,10 @@ walkexpr(Node **np, NodeList **init)
case OCLOSURE:
n = walkclosure(n, init);
goto ret;
+
+ case OCALLPART:
+ n = walkpartialcall(n, init);
+ goto ret;
}
fatal("missing switch %O", n->op);
@@ -2814,11 +2856,19 @@ walkcompare(Node **np, NodeList **init)
typecheck(&call, Etop);
walkstmt(&call);
*init = list(*init, call);
-
- if(n->op == OEQ)
- r = tempbool;
- else
- r = nod(ONOT, tempbool, N);
+
+ // 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);
+
+ if(n->op != OEQ)
+ r = nod(ONOT, r, N);
typecheck(&r, Erv);
walkexpr(&r, init);
*np = r;
@@ -2847,14 +2897,29 @@ hard:
static int
samecheap(Node *a, Node *b)
{
- if(a == N || b == N || a->op != b->op)
- return 0;
-
- switch(a->op) {
- case ONAME:
- return a == b;
- // TODO: Could do more here, but maybe this is enough.
- // It's all cheapexpr does.
+ Node *ar, *br;
+ while(a != N && b != N && a->op == b->op) {
+ switch(a->op) {
+ default:
+ return 0;
+ case ONAME:
+ return a == b;
+ case ODOT:
+ case ODOTPTR:
+ ar = a->right;
+ br = b->right;
+ if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym)
+ return 0;
+ break;
+ case OINDEX:
+ ar = a->right;
+ br = b->right;
+ if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0)
+ return 0;
+ break;
+ }
+ a = a->left;
+ b = b->left;
}
return 0;
}
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 75175455e..21c67e805 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -658,39 +658,39 @@ static const yytype_uint16 yyrline[] =
{
0, 124, 124, 133, 140, 151, 151, 166, 167, 170,
171, 172, 175, 208, 219, 220, 223, 230, 237, 246,
- 259, 260, 267, 267, 280, 284, 285, 289, 294, 300,
- 304, 308, 312, 318, 324, 330, 335, 339, 343, 349,
- 355, 359, 363, 369, 373, 379, 380, 384, 390, 399,
- 405, 423, 428, 440, 456, 461, 468, 488, 506, 515,
- 534, 533, 545, 544, 575, 578, 585, 584, 595, 601,
- 610, 621, 627, 630, 638, 637, 648, 654, 666, 670,
- 675, 665, 696, 695, 708, 711, 717, 720, 732, 736,
- 731, 754, 753, 769, 770, 774, 778, 782, 786, 790,
- 794, 798, 802, 806, 810, 814, 818, 822, 826, 830,
- 834, 838, 842, 847, 853, 854, 858, 869, 873, 877,
- 881, 886, 890, 900, 904, 909, 917, 921, 922, 933,
- 937, 941, 945, 949, 950, 956, 963, 969, 976, 979,
- 986, 992, 1009, 1016, 1017, 1024, 1025, 1044, 1045, 1048,
- 1051, 1055, 1066, 1075, 1081, 1084, 1087, 1094, 1095, 1101,
- 1116, 1124, 1136, 1141, 1147, 1148, 1149, 1150, 1151, 1152,
- 1158, 1159, 1160, 1161, 1167, 1168, 1169, 1170, 1171, 1177,
- 1178, 1181, 1184, 1185, 1186, 1187, 1188, 1191, 1192, 1205,
- 1209, 1214, 1219, 1224, 1228, 1229, 1232, 1238, 1245, 1251,
- 1258, 1264, 1275, 1289, 1318, 1358, 1383, 1401, 1410, 1413,
- 1421, 1425, 1429, 1436, 1442, 1447, 1459, 1462, 1472, 1473,
- 1479, 1480, 1486, 1490, 1496, 1497, 1503, 1507, 1513, 1536,
- 1541, 1547, 1553, 1560, 1569, 1578, 1593, 1599, 1604, 1608,
- 1615, 1628, 1629, 1635, 1641, 1644, 1648, 1654, 1657, 1666,
- 1669, 1670, 1674, 1675, 1681, 1682, 1683, 1684, 1685, 1687,
- 1686, 1701, 1706, 1710, 1714, 1718, 1722, 1727, 1746, 1752,
- 1760, 1764, 1770, 1774, 1780, 1784, 1790, 1794, 1803, 1807,
- 1811, 1815, 1821, 1824, 1832, 1833, 1835, 1836, 1839, 1842,
- 1845, 1848, 1851, 1854, 1857, 1860, 1863, 1866, 1869, 1872,
- 1875, 1878, 1884, 1888, 1892, 1896, 1900, 1904, 1924, 1931,
- 1942, 1943, 1944, 1947, 1948, 1951, 1955, 1965, 1969, 1973,
- 1977, 1981, 1985, 1989, 1995, 2001, 2009, 2017, 2023, 2030,
- 2046, 2064, 2068, 2074, 2077, 2080, 2084, 2094, 2098, 2113,
- 2121, 2122, 2134, 2135, 2138, 2142, 2148, 2152, 2158, 2162
+ 260, 261, 268, 268, 281, 285, 286, 290, 295, 301,
+ 305, 309, 313, 319, 325, 331, 336, 340, 344, 350,
+ 356, 360, 364, 370, 374, 380, 381, 385, 391, 400,
+ 406, 424, 429, 441, 457, 462, 469, 489, 507, 516,
+ 535, 534, 549, 548, 579, 582, 589, 588, 599, 605,
+ 614, 625, 631, 634, 642, 641, 652, 658, 670, 674,
+ 679, 669, 700, 699, 712, 715, 721, 724, 736, 740,
+ 735, 758, 757, 773, 774, 778, 782, 786, 790, 794,
+ 798, 802, 806, 810, 814, 818, 822, 826, 830, 834,
+ 838, 842, 846, 851, 857, 858, 862, 873, 877, 881,
+ 885, 890, 894, 904, 908, 913, 921, 925, 926, 937,
+ 941, 945, 949, 953, 954, 960, 967, 973, 980, 983,
+ 990, 996, 1013, 1020, 1021, 1028, 1029, 1048, 1049, 1052,
+ 1055, 1059, 1070, 1079, 1085, 1088, 1091, 1098, 1099, 1105,
+ 1120, 1128, 1140, 1145, 1151, 1152, 1153, 1154, 1155, 1156,
+ 1162, 1163, 1164, 1165, 1171, 1172, 1173, 1174, 1175, 1181,
+ 1182, 1185, 1188, 1189, 1190, 1191, 1192, 1195, 1196, 1209,
+ 1213, 1218, 1223, 1228, 1232, 1233, 1236, 1242, 1249, 1255,
+ 1262, 1268, 1279, 1293, 1322, 1362, 1387, 1405, 1414, 1417,
+ 1425, 1429, 1433, 1440, 1446, 1451, 1463, 1466, 1476, 1477,
+ 1483, 1484, 1490, 1494, 1500, 1501, 1507, 1511, 1517, 1540,
+ 1545, 1551, 1557, 1564, 1573, 1582, 1597, 1603, 1608, 1612,
+ 1619, 1632, 1633, 1639, 1645, 1648, 1652, 1658, 1661, 1670,
+ 1673, 1674, 1678, 1679, 1685, 1686, 1687, 1688, 1689, 1691,
+ 1690, 1705, 1710, 1714, 1718, 1722, 1726, 1731, 1750, 1756,
+ 1764, 1768, 1774, 1778, 1784, 1788, 1794, 1798, 1807, 1811,
+ 1815, 1819, 1825, 1828, 1836, 1837, 1839, 1840, 1843, 1846,
+ 1849, 1852, 1855, 1858, 1861, 1864, 1867, 1870, 1873, 1876,
+ 1879, 1882, 1888, 1892, 1896, 1900, 1904, 1908, 1928, 1935,
+ 1946, 1947, 1948, 1951, 1952, 1955, 1959, 1969, 1973, 1977,
+ 1981, 1985, 1989, 1993, 1999, 2005, 2013, 2021, 2027, 2034,
+ 2050, 2068, 2072, 2078, 2081, 2084, 2088, 2098, 2102, 2117,
+ 2125, 2126, 2138, 2139, 2142, 2146, 2152, 2156, 2162, 2166
};
#endif
@@ -2494,14 +2494,15 @@ yyreduce:
} else if(strcmp(importpkg->name, (yyvsp[(2) - (4)].sym)->name) != 0)
yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, (yyvsp[(2) - (4)].sym)->name, importpkg->path);
importpkg->direct = 1;
-
+ importpkg->safe = curio.importsafe;
+
if(safemode && !curio.importsafe)
yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
}
break;
case 21:
-#line 261 "go.y"
+#line 262 "go.y"
{
if(strcmp((yyvsp[(1) - (1)].sym)->name, "safe") == 0)
curio.importsafe = 1;
@@ -2509,14 +2510,14 @@ yyreduce:
break;
case 22:
-#line 267 "go.y"
+#line 268 "go.y"
{
defercheckwidth();
}
break;
case 23:
-#line 271 "go.y"
+#line 272 "go.y"
{
resumecheckwidth();
unimportfile();
@@ -2524,7 +2525,7 @@ yyreduce:
break;
case 24:
-#line 280 "go.y"
+#line 281 "go.y"
{
yyerror("empty top-level declaration");
(yyval.list) = nil;
@@ -2532,14 +2533,14 @@ yyreduce:
break;
case 26:
-#line 286 "go.y"
+#line 287 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 27:
-#line 290 "go.y"
+#line 291 "go.y"
{
yyerror("non-declaration statement outside function body");
(yyval.list) = nil;
@@ -2547,35 +2548,35 @@ yyreduce:
break;
case 28:
-#line 295 "go.y"
+#line 296 "go.y"
{
(yyval.list) = nil;
}
break;
case 29:
-#line 301 "go.y"
+#line 302 "go.y"
{
(yyval.list) = (yyvsp[(2) - (2)].list);
}
break;
case 30:
-#line 305 "go.y"
+#line 306 "go.y"
{
(yyval.list) = (yyvsp[(3) - (5)].list);
}
break;
case 31:
-#line 309 "go.y"
+#line 310 "go.y"
{
(yyval.list) = nil;
}
break;
case 32:
-#line 313 "go.y"
+#line 314 "go.y"
{
(yyval.list) = (yyvsp[(2) - (2)].list);
iota = -100000;
@@ -2584,7 +2585,7 @@ yyreduce:
break;
case 33:
-#line 319 "go.y"
+#line 320 "go.y"
{
(yyval.list) = (yyvsp[(3) - (5)].list);
iota = -100000;
@@ -2593,7 +2594,7 @@ yyreduce:
break;
case 34:
-#line 325 "go.y"
+#line 326 "go.y"
{
(yyval.list) = concat((yyvsp[(3) - (7)].list), (yyvsp[(5) - (7)].list));
iota = -100000;
@@ -2602,7 +2603,7 @@ yyreduce:
break;
case 35:
-#line 331 "go.y"
+#line 332 "go.y"
{
(yyval.list) = nil;
iota = -100000;
@@ -2610,84 +2611,84 @@ yyreduce:
break;
case 36:
-#line 336 "go.y"
+#line 337 "go.y"
{
(yyval.list) = list1((yyvsp[(2) - (2)].node));
}
break;
case 37:
-#line 340 "go.y"
+#line 341 "go.y"
{
(yyval.list) = (yyvsp[(3) - (5)].list);
}
break;
case 38:
-#line 344 "go.y"
+#line 345 "go.y"
{
(yyval.list) = nil;
}
break;
case 39:
-#line 350 "go.y"
+#line 351 "go.y"
{
iota = 0;
}
break;
case 40:
-#line 356 "go.y"
+#line 357 "go.y"
{
(yyval.list) = variter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
}
break;
case 41:
-#line 360 "go.y"
+#line 361 "go.y"
{
(yyval.list) = variter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
}
break;
case 42:
-#line 364 "go.y"
+#line 365 "go.y"
{
(yyval.list) = variter((yyvsp[(1) - (3)].list), nil, (yyvsp[(3) - (3)].list));
}
break;
case 43:
-#line 370 "go.y"
+#line 371 "go.y"
{
(yyval.list) = constiter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list));
}
break;
case 44:
-#line 374 "go.y"
+#line 375 "go.y"
{
(yyval.list) = constiter((yyvsp[(1) - (3)].list), N, (yyvsp[(3) - (3)].list));
}
break;
case 46:
-#line 381 "go.y"
+#line 382 "go.y"
{
(yyval.list) = constiter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil);
}
break;
case 47:
-#line 385 "go.y"
+#line 386 "go.y"
{
(yyval.list) = constiter((yyvsp[(1) - (1)].list), N, nil);
}
break;
case 48:
-#line 391 "go.y"
+#line 392 "go.y"
{
// different from dclname because the name
// becomes visible right here, not at the end
@@ -2697,14 +2698,14 @@ yyreduce:
break;
case 49:
-#line 400 "go.y"
+#line 401 "go.y"
{
(yyval.node) = typedcl1((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node), 1);
}
break;
case 50:
-#line 406 "go.y"
+#line 407 "go.y"
{
(yyval.node) = (yyvsp[(1) - (1)].node);
@@ -2725,7 +2726,7 @@ yyreduce:
break;
case 51:
-#line 424 "go.y"
+#line 425 "go.y"
{
(yyval.node) = nod(OASOP, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
(yyval.node)->etype = (yyvsp[(2) - (3)].i); // rathole to pass opcode
@@ -2733,7 +2734,7 @@ yyreduce:
break;
case 52:
-#line 429 "go.y"
+#line 430 "go.y"
{
if((yyvsp[(1) - (3)].list)->next == nil && (yyvsp[(3) - (3)].list)->next == nil) {
// simple
@@ -2748,7 +2749,7 @@ yyreduce:
break;
case 53:
-#line 441 "go.y"
+#line 442 "go.y"
{
if((yyvsp[(3) - (3)].list)->n->op == OTYPESW) {
(yyval.node) = nod(OTYPESW, N, (yyvsp[(3) - (3)].list)->n->right);
@@ -2767,7 +2768,7 @@ yyreduce:
break;
case 54:
-#line 457 "go.y"
+#line 458 "go.y"
{
(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
(yyval.node)->etype = OADD;
@@ -2775,7 +2776,7 @@ yyreduce:
break;
case 55:
-#line 462 "go.y"
+#line 463 "go.y"
{
(yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1));
(yyval.node)->etype = OSUB;
@@ -2783,7 +2784,7 @@ yyreduce:
break;
case 56:
-#line 469 "go.y"
+#line 470 "go.y"
{
Node *n, *nn;
@@ -2806,7 +2807,7 @@ yyreduce:
break;
case 57:
-#line 489 "go.y"
+#line 490 "go.y"
{
Node *n;
@@ -2827,7 +2828,7 @@ yyreduce:
break;
case 58:
-#line 507 "go.y"
+#line 508 "go.y"
{
// will be converted to OCASE
// right will point to next case
@@ -2839,7 +2840,7 @@ yyreduce:
break;
case 59:
-#line 516 "go.y"
+#line 517 "go.y"
{
Node *n, *nn;
@@ -2858,22 +2859,25 @@ yyreduce:
break;
case 60:
-#line 534 "go.y"
+#line 535 "go.y"
{
markdcl();
}
break;
case 61:
-#line 538 "go.y"
+#line 539 "go.y"
{
- (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
+ if((yyvsp[(3) - (4)].list) == nil)
+ (yyval.node) = nod(OEMPTY, N, N);
+ else
+ (yyval.node) = liststmt((yyvsp[(3) - (4)].list));
popdcl();
}
break;
case 62:
-#line 545 "go.y"
+#line 549 "go.y"
{
// If the last token read by the lexer was consumed
// as part of the case, clear it (parser has cleared yychar).
@@ -2886,7 +2890,7 @@ yyreduce:
break;
case 63:
-#line 555 "go.y"
+#line 559 "go.y"
{
int last;
@@ -2908,28 +2912,28 @@ yyreduce:
break;
case 64:
-#line 575 "go.y"
+#line 579 "go.y"
{
(yyval.list) = nil;
}
break;
case 65:
-#line 579 "go.y"
+#line 583 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
}
break;
case 66:
-#line 585 "go.y"
+#line 589 "go.y"
{
markdcl();
}
break;
case 67:
-#line 589 "go.y"
+#line 593 "go.y"
{
(yyval.list) = (yyvsp[(3) - (4)].list);
popdcl();
@@ -2937,7 +2941,7 @@ yyreduce:
break;
case 68:
-#line 596 "go.y"
+#line 600 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2946,7 +2950,7 @@ yyreduce:
break;
case 69:
-#line 602 "go.y"
+#line 606 "go.y"
{
(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2956,7 +2960,7 @@ yyreduce:
break;
case 70:
-#line 611 "go.y"
+#line 615 "go.y"
{
// init ; test ; incr
if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -2970,7 +2974,7 @@ yyreduce:
break;
case 71:
-#line 622 "go.y"
+#line 626 "go.y"
{
// normal test
(yyval.node) = nod(OFOR, N, N);
@@ -2979,7 +2983,7 @@ yyreduce:
break;
case 73:
-#line 631 "go.y"
+#line 635 "go.y"
{
(yyval.node) = (yyvsp[(1) - (2)].node);
(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -2987,14 +2991,14 @@ yyreduce:
break;
case 74:
-#line 638 "go.y"
+#line 642 "go.y"
{
markdcl();
}
break;
case 75:
-#line 642 "go.y"
+#line 646 "go.y"
{
(yyval.node) = (yyvsp[(3) - (3)].node);
popdcl();
@@ -3002,7 +3006,7 @@ yyreduce:
break;
case 76:
-#line 649 "go.y"
+#line 653 "go.y"
{
// test
(yyval.node) = nod(OIF, N, N);
@@ -3011,7 +3015,7 @@ yyreduce:
break;
case 77:
-#line 655 "go.y"
+#line 659 "go.y"
{
// init ; test
(yyval.node) = nod(OIF, N, N);
@@ -3022,14 +3026,14 @@ yyreduce:
break;
case 78:
-#line 666 "go.y"
+#line 670 "go.y"
{
markdcl();
}
break;
case 79:
-#line 670 "go.y"
+#line 674 "go.y"
{
if((yyvsp[(3) - (3)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3037,14 +3041,14 @@ yyreduce:
break;
case 80:
-#line 675 "go.y"
+#line 679 "go.y"
{
(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
}
break;
case 81:
-#line 679 "go.y"
+#line 683 "go.y"
{
Node *n;
NodeList *nn;
@@ -3062,14 +3066,14 @@ yyreduce:
break;
case 82:
-#line 696 "go.y"
+#line 700 "go.y"
{
markdcl();
}
break;
case 83:
-#line 700 "go.y"
+#line 704 "go.y"
{
if((yyvsp[(4) - (5)].node)->ntest == N)
yyerror("missing condition in if statement");
@@ -3079,28 +3083,28 @@ yyreduce:
break;
case 84:
-#line 708 "go.y"
+#line 712 "go.y"
{
(yyval.list) = nil;
}
break;
case 85:
-#line 712 "go.y"
+#line 716 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
}
break;
case 86:
-#line 717 "go.y"
+#line 721 "go.y"
{
(yyval.list) = nil;
}
break;
case 87:
-#line 721 "go.y"
+#line 725 "go.y"
{
NodeList *node;
@@ -3112,14 +3116,14 @@ yyreduce:
break;
case 88:
-#line 732 "go.y"
+#line 736 "go.y"
{
markdcl();
}
break;
case 89:
-#line 736 "go.y"
+#line 740 "go.y"
{
Node *n;
n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3130,7 +3134,7 @@ yyreduce:
break;
case 90:
-#line 744 "go.y"
+#line 748 "go.y"
{
(yyval.node) = (yyvsp[(3) - (7)].node);
(yyval.node)->op = OSWITCH;
@@ -3141,14 +3145,14 @@ yyreduce:
break;
case 91:
-#line 754 "go.y"
+#line 758 "go.y"
{
typesw = nod(OXXX, typesw, N);
}
break;
case 92:
-#line 758 "go.y"
+#line 762 "go.y"
{
(yyval.node) = nod(OSELECT, N, N);
(yyval.node)->lineno = typesw->lineno;
@@ -3158,154 +3162,154 @@ yyreduce:
break;
case 94:
-#line 771 "go.y"
+#line 775 "go.y"
{
(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 95:
-#line 775 "go.y"
+#line 779 "go.y"
{
(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 96:
-#line 779 "go.y"
+#line 783 "go.y"
{
(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 97:
-#line 783 "go.y"
+#line 787 "go.y"
{
(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 98:
-#line 787 "go.y"
+#line 791 "go.y"
{
(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 99:
-#line 791 "go.y"
+#line 795 "go.y"
{
(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 100:
-#line 795 "go.y"
+#line 799 "go.y"
{
(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 101:
-#line 799 "go.y"
+#line 803 "go.y"
{
(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 102:
-#line 803 "go.y"
+#line 807 "go.y"
{
(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 103:
-#line 807 "go.y"
+#line 811 "go.y"
{
(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 104:
-#line 811 "go.y"
+#line 815 "go.y"
{
(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 105:
-#line 815 "go.y"
+#line 819 "go.y"
{
(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 106:
-#line 819 "go.y"
+#line 823 "go.y"
{
(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 107:
-#line 823 "go.y"
+#line 827 "go.y"
{
(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 108:
-#line 827 "go.y"
+#line 831 "go.y"
{
(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 109:
-#line 831 "go.y"
+#line 835 "go.y"
{
(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 110:
-#line 835 "go.y"
+#line 839 "go.y"
{
(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 111:
-#line 839 "go.y"
+#line 843 "go.y"
{
(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 112:
-#line 843 "go.y"
+#line 847 "go.y"
{
(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 113:
-#line 848 "go.y"
+#line 852 "go.y"
{
(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 115:
-#line 855 "go.y"
+#line 859 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 116:
-#line 859 "go.y"
+#line 863 "go.y"
{
if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
// Special case for &T{...}: turn into (*T){...}.
@@ -3319,28 +3323,28 @@ yyreduce:
break;
case 117:
-#line 870 "go.y"
+#line 874 "go.y"
{
(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 118:
-#line 874 "go.y"
+#line 878 "go.y"
{
(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
}
break;
case 119:
-#line 878 "go.y"
+#line 882 "go.y"
{
(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
}
break;
case 120:
-#line 882 "go.y"
+#line 886 "go.y"
{
yyerror("the bitwise complement operator is ^");
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
@@ -3348,28 +3352,28 @@ yyreduce:
break;
case 121:
-#line 887 "go.y"
+#line 891 "go.y"
{
(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
}
break;
case 122:
-#line 891 "go.y"
+#line 895 "go.y"
{
(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
}
break;
case 123:
-#line 901 "go.y"
+#line 905 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
}
break;
case 124:
-#line 905 "go.y"
+#line 909 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3377,7 +3381,7 @@ yyreduce:
break;
case 125:
-#line 910 "go.y"
+#line 914 "go.y"
{
(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3386,14 +3390,14 @@ yyreduce:
break;
case 126:
-#line 918 "go.y"
+#line 922 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 128:
-#line 923 "go.y"
+#line 927 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3407,35 +3411,35 @@ yyreduce:
break;
case 129:
-#line 934 "go.y"
+#line 938 "go.y"
{
(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
}
break;
case 130:
-#line 938 "go.y"
+#line 942 "go.y"
{
(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
}
break;
case 131:
-#line 942 "go.y"
+#line 946 "go.y"
{
(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
}
break;
case 132:
-#line 946 "go.y"
+#line 950 "go.y"
{
(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
}
break;
case 134:
-#line 951 "go.y"
+#line 955 "go.y"
{
// conversion
(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3444,7 +3448,7 @@ yyreduce:
break;
case 135:
-#line 957 "go.y"
+#line 961 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3454,7 +3458,7 @@ yyreduce:
break;
case 136:
-#line 964 "go.y"
+#line 968 "go.y"
{
(yyval.node) = (yyvsp[(3) - (5)].node);
(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3463,7 +3467,7 @@ yyreduce:
break;
case 137:
-#line 970 "go.y"
+#line 974 "go.y"
{
yyerror("cannot parenthesize type in composite literal");
(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3473,7 +3477,7 @@ yyreduce:
break;
case 139:
-#line 979 "go.y"
+#line 983 "go.y"
{
// composite expression.
// make node early so we get the right line number.
@@ -3482,14 +3486,14 @@ yyreduce:
break;
case 140:
-#line 987 "go.y"
+#line 991 "go.y"
{
(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
}
break;
case 141:
-#line 993 "go.y"
+#line 997 "go.y"
{
// These nodes do not carry line numbers.
// Since a composite literal commonly spans several lines,
@@ -3509,7 +3513,7 @@ yyreduce:
break;
case 142:
-#line 1010 "go.y"
+#line 1014 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3517,7 +3521,7 @@ yyreduce:
break;
case 144:
-#line 1018 "go.y"
+#line 1022 "go.y"
{
(yyval.node) = (yyvsp[(2) - (4)].node);
(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3525,7 +3529,7 @@ yyreduce:
break;
case 146:
-#line 1026 "go.y"
+#line 1030 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
@@ -3545,21 +3549,21 @@ yyreduce:
break;
case 150:
-#line 1052 "go.y"
+#line 1056 "go.y"
{
(yyval.i) = LBODY;
}
break;
case 151:
-#line 1056 "go.y"
+#line 1060 "go.y"
{
(yyval.i) = '{';
}
break;
case 152:
-#line 1067 "go.y"
+#line 1071 "go.y"
{
if((yyvsp[(1) - (1)].sym) == S)
(yyval.node) = N;
@@ -3569,21 +3573,21 @@ yyreduce:
break;
case 153:
-#line 1076 "go.y"
+#line 1080 "go.y"
{
(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
}
break;
case 154:
-#line 1081 "go.y"
+#line 1085 "go.y"
{
(yyval.node) = N;
}
break;
case 156:
-#line 1088 "go.y"
+#line 1092 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3593,14 +3597,14 @@ yyreduce:
break;
case 158:
-#line 1096 "go.y"
+#line 1100 "go.y"
{
(yyval.sym) = S;
}
break;
case 159:
-#line 1102 "go.y"
+#line 1106 "go.y"
{
Pkg *p;
@@ -3616,7 +3620,7 @@ yyreduce:
break;
case 160:
-#line 1117 "go.y"
+#line 1121 "go.y"
{
(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
if((yyval.node)->pack != N)
@@ -3625,7 +3629,7 @@ yyreduce:
break;
case 162:
-#line 1137 "go.y"
+#line 1141 "go.y"
{
yyerror("final argument in variadic function missing type");
(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
@@ -3633,35 +3637,35 @@ yyreduce:
break;
case 163:
-#line 1142 "go.y"
+#line 1146 "go.y"
{
(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
}
break;
case 169:
-#line 1153 "go.y"
+#line 1157 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 173:
-#line 1162 "go.y"
+#line 1166 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 178:
-#line 1172 "go.y"
+#line 1176 "go.y"
{
(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
}
break;
case 188:
-#line 1193 "go.y"
+#line 1197 "go.y"
{
if((yyvsp[(1) - (3)].node)->op == OPACK) {
Sym *s;
@@ -3675,14 +3679,14 @@ yyreduce:
break;
case 189:
-#line 1206 "go.y"
+#line 1210 "go.y"
{
(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
}
break;
case 190:
-#line 1210 "go.y"
+#line 1214 "go.y"
{
// array literal of nelem
(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
@@ -3690,7 +3694,7 @@ yyreduce:
break;
case 191:
-#line 1215 "go.y"
+#line 1219 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
(yyval.node)->etype = Cboth;
@@ -3698,7 +3702,7 @@ yyreduce:
break;
case 192:
-#line 1220 "go.y"
+#line 1224 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Csend;
@@ -3706,21 +3710,21 @@ yyreduce:
break;
case 193:
-#line 1225 "go.y"
+#line 1229 "go.y"
{
(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
}
break;
case 196:
-#line 1233 "go.y"
+#line 1237 "go.y"
{
(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
}
break;
case 197:
-#line 1239 "go.y"
+#line 1243 "go.y"
{
(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
(yyval.node)->etype = Crecv;
@@ -3728,7 +3732,7 @@ yyreduce:
break;
case 198:
-#line 1246 "go.y"
+#line 1250 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3737,7 +3741,7 @@ yyreduce:
break;
case 199:
-#line 1252 "go.y"
+#line 1256 "go.y"
{
(yyval.node) = nod(OTSTRUCT, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3745,7 +3749,7 @@ yyreduce:
break;
case 200:
-#line 1259 "go.y"
+#line 1263 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3754,7 +3758,7 @@ yyreduce:
break;
case 201:
-#line 1265 "go.y"
+#line 1269 "go.y"
{
(yyval.node) = nod(OTINTER, N, N);
fixlbrace((yyvsp[(2) - (3)].i));
@@ -3762,7 +3766,7 @@ yyreduce:
break;
case 202:
-#line 1276 "go.y"
+#line 1280 "go.y"
{
(yyval.node) = (yyvsp[(2) - (3)].node);
if((yyval.node) == N)
@@ -3777,7 +3781,7 @@ yyreduce:
break;
case 203:
-#line 1290 "go.y"
+#line 1294 "go.y"
{
Node *t;
@@ -3809,7 +3813,7 @@ yyreduce:
break;
case 204:
-#line 1319 "go.y"
+#line 1323 "go.y"
{
Node *rcvr, *t;
@@ -3850,7 +3854,7 @@ yyreduce:
break;
case 205:
-#line 1359 "go.y"
+#line 1363 "go.y"
{
Sym *s;
Type *t;
@@ -3878,7 +3882,7 @@ yyreduce:
break;
case 206:
-#line 1384 "go.y"
+#line 1388 "go.y"
{
(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right);
(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3897,7 +3901,7 @@ yyreduce:
break;
case 207:
-#line 1402 "go.y"
+#line 1406 "go.y"
{
(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
(yyval.node) = nod(OTFUNC, N, N);
@@ -3907,14 +3911,14 @@ yyreduce:
break;
case 208:
-#line 1410 "go.y"
+#line 1414 "go.y"
{
(yyval.list) = nil;
}
break;
case 209:
-#line 1414 "go.y"
+#line 1418 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
if((yyval.list) == nil)
@@ -3923,21 +3927,21 @@ yyreduce:
break;
case 210:
-#line 1422 "go.y"
+#line 1426 "go.y"
{
(yyval.list) = nil;
}
break;
case 211:
-#line 1426 "go.y"
+#line 1430 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
}
break;
case 212:
-#line 1430 "go.y"
+#line 1434 "go.y"
{
(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
(yyval.list) = (yyvsp[(2) - (3)].list);
@@ -3945,14 +3949,14 @@ yyreduce:
break;
case 213:
-#line 1437 "go.y"
+#line 1441 "go.y"
{
closurehdr((yyvsp[(1) - (1)].node));
}
break;
case 214:
-#line 1443 "go.y"
+#line 1447 "go.y"
{
(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
fixlbrace((yyvsp[(2) - (4)].i));
@@ -3960,21 +3964,21 @@ yyreduce:
break;
case 215:
-#line 1448 "go.y"
+#line 1452 "go.y"
{
(yyval.node) = closurebody(nil);
}
break;
case 216:
-#line 1459 "go.y"
+#line 1463 "go.y"
{
(yyval.list) = nil;
}
break;
case 217:
-#line 1463 "go.y"
+#line 1467 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
if(nsyntaxerrors == 0)
@@ -3985,56 +3989,56 @@ yyreduce:
break;
case 219:
-#line 1474 "go.y"
+#line 1478 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 221:
-#line 1481 "go.y"
+#line 1485 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 222:
-#line 1487 "go.y"
+#line 1491 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 223:
-#line 1491 "go.y"
+#line 1495 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 225:
-#line 1498 "go.y"
+#line 1502 "go.y"
{
(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
}
break;
case 226:
-#line 1504 "go.y"
+#line 1508 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 227:
-#line 1508 "go.y"
+#line 1512 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 228:
-#line 1514 "go.y"
+#line 1518 "go.y"
{
NodeList *l;
@@ -4060,7 +4064,7 @@ yyreduce:
break;
case 229:
-#line 1537 "go.y"
+#line 1541 "go.y"
{
(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
(yyval.list) = list1((yyvsp[(1) - (2)].node));
@@ -4068,7 +4072,7 @@ yyreduce:
break;
case 230:
-#line 1542 "go.y"
+#line 1546 "go.y"
{
(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4077,7 +4081,7 @@ yyreduce:
break;
case 231:
-#line 1548 "go.y"
+#line 1552 "go.y"
{
(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4086,7 +4090,7 @@ yyreduce:
break;
case 232:
-#line 1554 "go.y"
+#line 1558 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4096,7 +4100,7 @@ yyreduce:
break;
case 233:
-#line 1561 "go.y"
+#line 1565 "go.y"
{
(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4106,7 +4110,7 @@ yyreduce:
break;
case 234:
-#line 1570 "go.y"
+#line 1574 "go.y"
{
Node *n;
@@ -4118,7 +4122,7 @@ yyreduce:
break;
case 235:
-#line 1579 "go.y"
+#line 1583 "go.y"
{
Pkg *pkg;
@@ -4134,14 +4138,14 @@ yyreduce:
break;
case 236:
-#line 1594 "go.y"
+#line 1598 "go.y"
{
(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
}
break;
case 237:
-#line 1600 "go.y"
+#line 1604 "go.y"
{
(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
ifacedcl((yyval.node));
@@ -4149,14 +4153,14 @@ yyreduce:
break;
case 238:
-#line 1605 "go.y"
+#line 1609 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
}
break;
case 239:
-#line 1609 "go.y"
+#line 1613 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
yyerror("cannot parenthesize embedded type");
@@ -4164,7 +4168,7 @@ yyreduce:
break;
case 240:
-#line 1616 "go.y"
+#line 1620 "go.y"
{
// without func keyword
(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4175,7 +4179,7 @@ yyreduce:
break;
case 242:
-#line 1630 "go.y"
+#line 1634 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4184,7 +4188,7 @@ yyreduce:
break;
case 243:
-#line 1636 "go.y"
+#line 1640 "go.y"
{
(yyval.node) = nod(ONONAME, N, N);
(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4193,56 +4197,56 @@ yyreduce:
break;
case 245:
-#line 1645 "go.y"
+#line 1649 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 246:
-#line 1649 "go.y"
+#line 1653 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 247:
-#line 1654 "go.y"
+#line 1658 "go.y"
{
(yyval.list) = nil;
}
break;
case 248:
-#line 1658 "go.y"
+#line 1662 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 249:
-#line 1666 "go.y"
+#line 1670 "go.y"
{
(yyval.node) = N;
}
break;
case 251:
-#line 1671 "go.y"
+#line 1675 "go.y"
{
(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
}
break;
case 253:
-#line 1676 "go.y"
+#line 1680 "go.y"
{
(yyval.node) = N;
}
break;
case 259:
-#line 1687 "go.y"
+#line 1691 "go.y"
{
(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
(yyvsp[(1) - (2)].node)->sym = dclstack; // context, for goto restrictions
@@ -4250,7 +4254,7 @@ yyreduce:
break;
case 260:
-#line 1692 "go.y"
+#line 1696 "go.y"
{
NodeList *l;
@@ -4263,7 +4267,7 @@ yyreduce:
break;
case 261:
-#line 1702 "go.y"
+#line 1706 "go.y"
{
// will be converted to OFALL
(yyval.node) = nod(OXFALL, N, N);
@@ -4271,35 +4275,35 @@ yyreduce:
break;
case 262:
-#line 1707 "go.y"
+#line 1711 "go.y"
{
(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
}
break;
case 263:
-#line 1711 "go.y"
+#line 1715 "go.y"
{
(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
}
break;
case 264:
-#line 1715 "go.y"
+#line 1719 "go.y"
{
(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
}
break;
case 265:
-#line 1719 "go.y"
+#line 1723 "go.y"
{
(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
}
break;
case 266:
-#line 1723 "go.y"
+#line 1727 "go.y"
{
(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
(yyval.node)->sym = dclstack; // context, for goto restrictions
@@ -4307,7 +4311,7 @@ yyreduce:
break;
case 267:
-#line 1728 "go.y"
+#line 1732 "go.y"
{
(yyval.node) = nod(ORETURN, N, N);
(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4327,7 +4331,7 @@ yyreduce:
break;
case 268:
-#line 1747 "go.y"
+#line 1751 "go.y"
{
(yyval.list) = nil;
if((yyvsp[(1) - (1)].node) != N)
@@ -4336,7 +4340,7 @@ yyreduce:
break;
case 269:
-#line 1753 "go.y"
+#line 1757 "go.y"
{
(yyval.list) = (yyvsp[(1) - (3)].list);
if((yyvsp[(3) - (3)].node) != N)
@@ -4345,189 +4349,189 @@ yyreduce:
break;
case 270:
-#line 1761 "go.y"
+#line 1765 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 271:
-#line 1765 "go.y"
+#line 1769 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 272:
-#line 1771 "go.y"
+#line 1775 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 273:
-#line 1775 "go.y"
+#line 1779 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 274:
-#line 1781 "go.y"
+#line 1785 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 275:
-#line 1785 "go.y"
+#line 1789 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 276:
-#line 1791 "go.y"
+#line 1795 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 277:
-#line 1795 "go.y"
+#line 1799 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 278:
-#line 1804 "go.y"
+#line 1808 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 279:
-#line 1808 "go.y"
+#line 1812 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 280:
-#line 1812 "go.y"
+#line 1816 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 281:
-#line 1816 "go.y"
+#line 1820 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 282:
-#line 1821 "go.y"
+#line 1825 "go.y"
{
(yyval.list) = nil;
}
break;
case 283:
-#line 1825 "go.y"
+#line 1829 "go.y"
{
(yyval.list) = (yyvsp[(1) - (2)].list);
}
break;
case 288:
-#line 1839 "go.y"
+#line 1843 "go.y"
{
(yyval.node) = N;
}
break;
case 290:
-#line 1845 "go.y"
+#line 1849 "go.y"
{
(yyval.list) = nil;
}
break;
case 292:
-#line 1851 "go.y"
+#line 1855 "go.y"
{
(yyval.node) = N;
}
break;
case 294:
-#line 1857 "go.y"
+#line 1861 "go.y"
{
(yyval.list) = nil;
}
break;
case 296:
-#line 1863 "go.y"
+#line 1867 "go.y"
{
(yyval.list) = nil;
}
break;
case 298:
-#line 1869 "go.y"
+#line 1873 "go.y"
{
(yyval.list) = nil;
}
break;
case 300:
-#line 1875 "go.y"
+#line 1879 "go.y"
{
(yyval.val).ctype = CTxxx;
}
break;
case 302:
-#line 1885 "go.y"
+#line 1889 "go.y"
{
importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
}
break;
case 303:
-#line 1889 "go.y"
+#line 1893 "go.y"
{
importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
}
break;
case 304:
-#line 1893 "go.y"
+#line 1897 "go.y"
{
importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
}
break;
case 305:
-#line 1897 "go.y"
+#line 1901 "go.y"
{
importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
}
break;
case 306:
-#line 1901 "go.y"
+#line 1905 "go.y"
{
importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
}
break;
case 307:
-#line 1905 "go.y"
+#line 1909 "go.y"
{
if((yyvsp[(2) - (4)].node) == N) {
dclcontext = PEXTERN; // since we skip the funcbody below
@@ -4548,7 +4552,7 @@ yyreduce:
break;
case 308:
-#line 1925 "go.y"
+#line 1929 "go.y"
{
(yyval.sym) = (yyvsp[(1) - (1)].sym);
structpkg = (yyval.sym)->pkg;
@@ -4556,7 +4560,7 @@ yyreduce:
break;
case 309:
-#line 1932 "go.y"
+#line 1936 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
importsym((yyvsp[(1) - (1)].sym), OTYPE);
@@ -4564,14 +4568,14 @@ yyreduce:
break;
case 315:
-#line 1952 "go.y"
+#line 1956 "go.y"
{
(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
}
break;
case 316:
-#line 1956 "go.y"
+#line 1960 "go.y"
{
// predefined name like uint8
(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4584,49 +4588,49 @@ yyreduce:
break;
case 317:
-#line 1966 "go.y"
+#line 1970 "go.y"
{
(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
}
break;
case 318:
-#line 1970 "go.y"
+#line 1974 "go.y"
{
(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
}
break;
case 319:
-#line 1974 "go.y"
+#line 1978 "go.y"
{
(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
}
break;
case 320:
-#line 1978 "go.y"
+#line 1982 "go.y"
{
(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
}
break;
case 321:
-#line 1982 "go.y"
+#line 1986 "go.y"
{
(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
}
break;
case 322:
-#line 1986 "go.y"
+#line 1990 "go.y"
{
(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
}
break;
case 323:
-#line 1990 "go.y"
+#line 1994 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4635,7 +4639,7 @@ yyreduce:
break;
case 324:
-#line 1996 "go.y"
+#line 2000 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4644,7 +4648,7 @@ yyreduce:
break;
case 325:
-#line 2002 "go.y"
+#line 2006 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4653,7 +4657,7 @@ yyreduce:
break;
case 326:
-#line 2010 "go.y"
+#line 2014 "go.y"
{
(yyval.type) = typ(TCHAN);
(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4662,14 +4666,14 @@ yyreduce:
break;
case 327:
-#line 2018 "go.y"
+#line 2022 "go.y"
{
(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
}
break;
case 328:
-#line 2024 "go.y"
+#line 2028 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
if((yyvsp[(1) - (3)].sym))
@@ -4679,7 +4683,7 @@ yyreduce:
break;
case 329:
-#line 2031 "go.y"
+#line 2035 "go.y"
{
Type *t;
@@ -4696,7 +4700,7 @@ yyreduce:
break;
case 330:
-#line 2047 "go.y"
+#line 2051 "go.y"
{
Sym *s;
@@ -4715,49 +4719,49 @@ yyreduce:
break;
case 331:
-#line 2065 "go.y"
+#line 2069 "go.y"
{
(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
}
break;
case 332:
-#line 2069 "go.y"
+#line 2073 "go.y"
{
(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
}
break;
case 333:
-#line 2074 "go.y"
+#line 2078 "go.y"
{
(yyval.list) = nil;
}
break;
case 335:
-#line 2081 "go.y"
+#line 2085 "go.y"
{
(yyval.list) = (yyvsp[(2) - (3)].list);
}
break;
case 336:
-#line 2085 "go.y"
+#line 2089 "go.y"
{
(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
}
break;
case 337:
-#line 2095 "go.y"
+#line 2099 "go.y"
{
(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
}
break;
case 338:
-#line 2099 "go.y"
+#line 2103 "go.y"
{
(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
switch((yyval.node)->val.ctype){
@@ -4775,7 +4779,7 @@ yyreduce:
break;
case 339:
-#line 2114 "go.y"
+#line 2118 "go.y"
{
(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
if((yyval.node)->op != OLITERAL)
@@ -4784,7 +4788,7 @@ yyreduce:
break;
case 341:
-#line 2123 "go.y"
+#line 2127 "go.y"
{
if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4798,42 +4802,42 @@ yyreduce:
break;
case 344:
-#line 2139 "go.y"
+#line 2143 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 345:
-#line 2143 "go.y"
+#line 2147 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 346:
-#line 2149 "go.y"
+#line 2153 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 347:
-#line 2153 "go.y"
+#line 2157 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
break;
case 348:
-#line 2159 "go.y"
+#line 2163 "go.y"
{
(yyval.list) = list1((yyvsp[(1) - (1)].node));
}
break;
case 349:
-#line 2163 "go.y"
+#line 2167 "go.y"
{
(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
}
@@ -4841,7 +4845,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 4846 "y.tab.c"
+#line 4850 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5055,7 +5059,7 @@ yyreturn:
}
-#line 2167 "go.y"
+#line 2171 "go.y"
static void