summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/Makefile2
-rw-r--r--src/cmd/gc/align.c12
-rw-r--r--src/cmd/gc/closure.c44
-rw-r--r--src/cmd/gc/const.c4
-rw-r--r--src/cmd/gc/dcl.c28
-rw-r--r--src/cmd/gc/gen.c4
-rw-r--r--src/cmd/gc/go.h14
-rw-r--r--src/cmd/gc/go.y1
-rw-r--r--src/cmd/gc/init.c5
-rw-r--r--src/cmd/gc/lex.c16
-rw-r--r--src/cmd/gc/obj.c1
-rw-r--r--src/cmd/gc/pgen.c119
-rw-r--r--src/cmd/gc/sinit.c4
-rw-r--r--src/cmd/gc/subr.c3
-rw-r--r--src/cmd/gc/typecheck.c59
-rw-r--r--src/cmd/gc/walk.c18
16 files changed, 289 insertions, 45 deletions
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index dbfd86474..286618ec1 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -49,7 +49,7 @@ include ../../Make.clib
install: $(LIB)
y1.tab.c: y.tab.c # make yystate global, yytname mutable
- cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/' >y1.tab.c
+ cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c
yerr.h: bisonerrors go.errors y.tab.h # y.tab.h rule generates y.output too
awk -f bisonerrors y.output go.errors >yerr.h
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index a8454bf13..7fcac4833 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -234,9 +234,11 @@ dowidth(Type *t)
if(t->bound > cap)
yyerror("type %lT larger than address space", t);
w = t->bound * t->type->width;
- if(w == 0)
- w = 1;
t->align = t->type->align;
+ if(w == 0) {
+ w = 1;
+ t->align = 1;
+ }
}
else if(t->bound == -1) {
w = sizeof_Array;
@@ -253,10 +255,10 @@ dowidth(Type *t)
if(t->funarg)
fatal("dowidth fn struct %T", t);
w = widstruct(t, 0, 1);
- if(w == 0)
+ if(w == 0) {
w = 1;
- //if(t->align < widthptr)
- // warn("align %d: %T\n", t->align, t);
+ t->align = 1;
+ }
break;
case TFUNC:
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index eb7014366..906dadbc9 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -75,7 +75,7 @@ closurebody(NodeList *body)
}
void
-typecheckclosure(Node *func)
+typecheckclosure(Node *func, int top)
{
Node *oldfn;
NodeList *l;
@@ -106,6 +106,10 @@ typecheckclosure(Node *func)
v->op = 0;
continue;
}
+ // For a closure that is called in place, but not
+ // inside a go statement, avoid moving variables to the heap.
+ if ((top & (Ecall|Eproc)) == Ecall)
+ v->heapaddr->etype = 1;
typecheck(&v->heapaddr, Erv);
func->enter = list(func->enter, v->heapaddr);
v->heapaddr = N;
@@ -199,3 +203,41 @@ walkclosure(Node *func, NodeList **init)
walkexpr(&call, init);
return call;
}
+
+// 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.
+void
+walkcallclosure(Node *n, NodeList **init)
+{
+ Node *z;
+ NodeList *ll, *cargs;
+
+ walkexpr(&n->left, init);
+ cargs = n->left // FUNC runtime.closure
+ ->list // arguments
+ ->next // skip first
+ ->next; // skip second
+
+ n->left = n->left // FUNC runtime.closure
+ ->list // arguments
+ ->next // skip first
+ ->n // AS (to indreg)
+ ->right; // argument == the generated function
+
+ // New arg list for n. First the closure-args, stolen from
+ // runtime.closure's 3rd and following,
+ ll = nil;
+ for (; cargs; cargs = cargs->next)
+ ll = list(ll, cargs->n->right); // cargs->n is the OAS(INDREG, arg)
+
+ // then an extra zero, to fill the dummy return pointer slot,
+ z = nod(OXXX, N, N);
+ nodconst(z, types[TUINTPTR], 0);
+ z->typecheck = 1;
+ ll = list(ll, z);
+
+ // and finally the original parameter list.
+ n->list = concat(ll, n->list);
+}
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index a36ec68c0..8fe9072b2 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -103,6 +103,8 @@ convlit1(Node **np, Type *t, int explicit)
case ORSH:
convlit1(&n->left, t, explicit && isideal(n->left->type));
t = n->left->type;
+ if(t != T && t->etype == TIDEAL && n->val.ctype != CTINT)
+ n->val = toint(n->val);
if(t != T && !isint[t->etype]) {
yyerror("invalid operation: %#N (shift of type %T)", n, t);
t = T;
@@ -514,6 +516,8 @@ evconst(Node *n)
n->right = nr;
if(nr->type && (issigned[nr->type->etype] || !isint[nr->type->etype]))
goto illegal;
+ nl->val = toint(nl->val);
+ nr->val = toint(nr->val);
break;
}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 99af18d9f..78c676346 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -188,6 +188,7 @@ declare(Node *n, int ctxt)
else if(n->op == ONAME)
gen = ++vargen;
pushdcl(s);
+ n->curfn = curfn;
}
if(ctxt == PAUTO)
n->xoffset = BADWIDTH;
@@ -524,6 +525,30 @@ colas(NodeList *left, NodeList *right)
}
/*
+ * declare the arguments in an
+ * interface field declaration.
+ */
+void
+ifacedcl(Node *n)
+{
+ if(n->op != ODCLFIELD || n->right == N)
+ fatal("ifacedcl");
+
+ dclcontext = PAUTO;
+ markdcl();
+ funcdepth++;
+ n->outer = curfn;
+ curfn = n;
+ funcargs(n->right);
+
+ // funcbody is normally called after the parser has
+ // seen the body of a function but since an interface
+ // field declaration does not have a body, we must
+ // call it now to pop the current declaration context.
+ funcbody(n);
+}
+
+/*
* declare the function proper
* and declare the arguments.
* called in extern-declaration context
@@ -1226,9 +1251,6 @@ funccompile(Node *n, int isclosure)
if(curfn)
fatal("funccompile %S inside %S", n->nname->sym, curfn->nname->sym);
- curfn = n;
- typechecklist(n->nbody, Etop);
- curfn = nil;
stksize = 0;
dclcontext = PAUTO;
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 8ad6c437d..0b6f5bbd8 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -59,6 +59,8 @@ allocparams(void)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, n->type->align);
+ if(thechar == '5')
+ stksize = rnd(stksize, widthptr);
n->xoffset = -stksize;
}
lineno = lno;
@@ -698,6 +700,8 @@ tempname(Node *n, Type *t)
w = t->width;
stksize += w;
stksize = rnd(stksize, t->align);
+ if(thechar == '5')
+ stksize = rnd(stksize, widthptr);
n->xoffset = -stksize;
n->pun = anyregalloc();
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 359881e11..f5c0443f8 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -254,6 +254,7 @@ struct Node
Node* ntype;
Node* defn;
Node* pack; // real package for import . names
+ Node* curfn; // function for local variables
// ONAME func param with PHEAP
Node* heapaddr; // temp holding heap address of param
@@ -517,15 +518,16 @@ enum
enum
{
- Etop = 1<<1, // evaluated at statement level
- Erv = 1<<2, // evaluated in value context
+ Etop = 1<<1, // evaluated at statement level
+ Erv = 1<<2, // evaluated in value context
Etype = 1<<3,
- Ecall = 1<<4, // call-only expressions are ok
+ Ecall = 1<<4, // call-only expressions are ok
Efnstruct = 1<<5, // multivalue function returns are ok
Eiota = 1<<6, // iota is ok
Easgn = 1<<7, // assigning to expression
Eindir = 1<<8, // indirecting through expression
Eaddr = 1<<9, // taking address of expression
+ Eproc = 1<<10, // inside a go statement
};
#define BITS 5
@@ -815,8 +817,9 @@ int bset(Bits a, uint n);
*/
Node* closurebody(NodeList *body);
void closurehdr(Node *ntype);
-void typecheckclosure(Node *func);
+void typecheckclosure(Node *func, int top);
Node* walkclosure(Node *func, NodeList **init);
+void walkcallclosure(Node *n, NodeList **init);
/*
* const.c
@@ -870,6 +873,7 @@ void funcbody(Node *n);
void funccompile(Node *n, int isclosure);
void funchdr(Node *n);
Type* functype(Node *this, NodeList *in, NodeList *out);
+void ifacedcl(Node *n);
int isifacemethod(Type *f);
void markdcl(void);
Node* methodname(Node *n, Type *t);
@@ -1209,6 +1213,7 @@ EXTERN Prog* continpc;
EXTERN Prog* breakpc;
EXTERN Prog* pc;
EXTERN Prog* firstpc;
+EXTERN Prog* retpc;
EXTERN Node* nodfp;
@@ -1222,6 +1227,7 @@ void cgen_callinter(Node *n, Node *res, int proc);
void cgen_ret(Node *n);
void clearfat(Node *n);
void compile(Node*);
+void defframe(Prog*);
int dgostringptr(Sym*, int off, char *str);
int dgostrlitptr(Sym*, int off, Strlit*);
int dstringptr(Sym *s, int off, char *str);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 7adfd002a..fdaab4fa4 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1380,6 +1380,7 @@ interfacedcl:
new_name indcl
{
$$ = nod(ODCLFIELD, $1, $2);
+ ifacedcl($$);
}
| packname
{
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index af4eb0336..8818db08c 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -182,11 +182,14 @@ fninit(NodeList *n)
// (11)
a = nod(ORETURN, N, N);
r = list(r, a);
-
exportsym(fn->nname);
fn->nbody = r;
funcbody(fn);
+
+ curfn = fn;
typecheck(&fn, Etop);
+ typechecklist(r, Etop);
+ curfn = nil;
funccompile(fn, 0);
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 04dd0d5b9..5e2f73fc5 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -235,13 +235,14 @@ main(int argc, char *argv[])
if(debug['f'])
frame(1);
- // Process top-level declarations in three phases.
+ // Process top-level declarations in four phases.
// Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types
// and methods but doesn't depend on any of it.
// Phase 2: Variable assignments.
// To check interface assignments, depends on phase 1.
- // Phase 3: Function bodies.
+ // Phase 3: Type check function bodies.
+ // Phase 4: Compile function bodies.
defercheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op != ODCL && l->n->op != OAS)
@@ -251,17 +252,28 @@ main(int argc, char *argv[])
typecheck(&l->n, Etop);
resumetypecopy();
resumecheckwidth();
+
+ for(l=xtop; l; l=l->next)
+ if(l->n->op == ODCLFUNC) {
+ curfn = l->n;
+ typechecklist(l->n->nbody, Etop);
+ }
+ curfn = nil;
+
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
funccompile(l->n, 0);
+
if(nerrors == 0)
fninit(xtop);
+
while(closures) {
l = closures;
closures = nil;
for(; l; l=l->next)
funccompile(l->n, 1);
}
+
dclchecks();
if(nerrors)
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index 9f4b7b318..f34fc76c8 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -284,6 +284,7 @@ stringsym(char *s, int len)
off = dsname(sym, off, s+n, m);
}
off = duint8(sym, off, 0); // terminating NUL for runtime
+ off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
ggloblsym(sym, off, 1);
text();
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
new file mode 100644
index 000000000..9bd845dde
--- /dev/null
+++ b/src/cmd/gc/pgen.c
@@ -0,0 +1,119 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#undef EXTERN
+#define EXTERN
+#include "gg.h"
+#include "opt.h"
+
+void
+compile(Node *fn)
+{
+ Plist *pl;
+ Node nod1, *n;
+ Prog *ptxt;
+ int32 lno;
+ Type *t;
+ Iter save;
+
+ if(newproc == N) {
+ newproc = sysfunc("newproc");
+ deferproc = sysfunc("deferproc");
+ deferreturn = sysfunc("deferreturn");
+ panicindex = sysfunc("panicindex");
+ panicslice = sysfunc("panicslice");
+ throwreturn = sysfunc("throwreturn");
+ }
+
+ if(fn->nbody == nil)
+ return;
+
+ // set up domain for labels
+ clearlabels();
+
+ lno = setlineno(fn);
+
+ curfn = fn;
+ dowidth(curfn->type);
+
+ if(curfn->type->outnamed) {
+ // add clearing of the output parameters
+ t = structfirst(&save, getoutarg(curfn->type));
+ while(t != T) {
+ if(t->nname != N) {
+ n = nod(OAS, t->nname, N);
+ typecheck(&n, Etop);
+ curfn->nbody = concat(list1(n), curfn->nbody);
+ }
+ t = structnext(&save);
+ }
+ }
+
+ hasdefer = 0;
+ walk(curfn);
+ if(nerrors != 0 || isblank(curfn->nname))
+ goto ret;
+
+ allocparams();
+
+ continpc = P;
+ breakpc = P;
+
+ pl = newplist();
+ pl->name = curfn->nname;
+
+ setlineno(curfn);
+
+ nodconst(&nod1, types[TINT32], 0);
+ ptxt = gins(ATEXT, curfn->nname, &nod1);
+ afunclit(&ptxt->from);
+
+ ginit();
+ genlist(curfn->enter);
+
+ retpc = nil;
+ if(hasdefer || curfn->exit) {
+ Prog *p1;
+
+ p1 = gjmp(nil);
+ retpc = gjmp(nil);
+ patch(p1, pc);
+ }
+
+ genlist(curfn->nbody);
+ gclean();
+ checklabels();
+ if(nerrors != 0)
+ goto ret;
+ if(curfn->endlineno)
+ lineno = curfn->endlineno;
+
+ if(curfn->type->outtuple != 0)
+ ginscall(throwreturn, 0);
+
+ if(retpc)
+ patch(retpc, pc);
+ ginit();
+ if(hasdefer)
+ ginscall(deferreturn, 0);
+ if(curfn->exit)
+ genlist(curfn->exit);
+ gclean();
+ if(nerrors != 0)
+ goto ret;
+ pc->as = ARET; // overwrite AEND
+ pc->lineno = lineno;
+
+ if(!debug['N'] || debug['R'] || debug['P']) {
+ regopt(ptxt);
+ }
+
+ defframe(ptxt);
+
+ if(debug['f'])
+ frame(0);
+
+ret:
+ lineno = lno;
+}
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index be96a1477..eb7ef31ec 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -173,10 +173,10 @@ initfix(NodeList *l)
/*
* from here down is the walk analysis
- * of composit literals.
+ * of composite literals.
* most of the work is to generate
* data statements for the constant
- * part of the composit literal.
+ * part of the composite literal.
*/
static void structlit(int ctxt, int pass, Node *n, Node *var, NodeList **init);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 326a5ba74..4c0819cd8 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3170,7 +3170,10 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
dumplist("genwrapper body", fn->nbody);
funcbody(fn);
+ curfn = fn;
typecheck(&fn, Etop);
+ typechecklist(fn->nbody, Etop);
+ curfn = nil;
funccompile(fn, 0);
}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 9aaf3e6ef..44d08352d 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -29,8 +29,8 @@ static void typecheckfunc(Node*);
static void checklvalue(Node*, char*);
static void checkassign(Node*);
static void checkassignlist(NodeList*);
-static void stringtoarraylit(Node**);
-static Node* resolve(Node*);
+static void stringtoarraylit(Node**);
+static Node* resolve(Node*);
static Type* getforwtype(Node*);
/*
@@ -780,7 +780,7 @@ reswitch:
n = r;
goto reswitch;
}
- typecheck(&n->left, Erv | Etype | Ecall);
+ typecheck(&n->left, Erv | Etype | Ecall |(top&Eproc));
l = n->left;
if(l->op == ONAME && l->etype != 0) {
if(n->isddd && l->etype != OAPPEND)
@@ -794,7 +794,7 @@ reswitch:
defaultlit(&n->left, T);
l = n->left;
if(l->op == OTYPE) {
- if(n->isddd)
+ if(n->isddd || l->type->bound == -100)
yyerror("invalid use of ... in type conversion", l);
// pick off before type-checking arguments
ok |= Erv;
@@ -822,7 +822,13 @@ reswitch:
case ODOTMETH:
n->op = OCALLMETH;
- typecheckaste(OCALL, n->left, 0, getthisx(t), list1(l->left), "method receiver");
+ // typecheckaste was used here but there wasn't enough
+ // information further down the call chain to know if we
+ // were testing a method receiver for unexported fields.
+ // It isn't necessary, so just do a sanity check.
+ tp = getthisx(t)->type->type;
+ if(l->left == N || !eqtype(l->left->type, tp))
+ fatal("method receiver");
break;
default:
@@ -1021,9 +1027,9 @@ reswitch:
// copy([]byte, string)
if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
- if (n->left->type->type ==types[TUINT8])
- goto ret;
- yyerror("arguments to copy have different element types: %lT and string", n->left->type);
+ if (n->left->type->type == types[TUINT8])
+ goto ret;
+ yyerror("arguments to copy have different element types: %lT and string", n->left->type);
goto error;
}
@@ -1211,7 +1217,7 @@ reswitch:
case OCLOSURE:
ok |= Erv;
- typecheckclosure(n);
+ typecheckclosure(n, top);
if(n->type == T)
goto error;
goto ret;
@@ -1240,11 +1246,15 @@ reswitch:
goto ret;
case ODEFER:
- case OPROC:
ok |= Etop;
typecheck(&n->left, Etop);
goto ret;
+ case OPROC:
+ ok |= Etop;
+ typecheck(&n->left, Etop|Eproc);
+ goto ret;
+
case OFOR:
ok |= Etop;
typechecklist(n->ninit, Etop);
@@ -2159,7 +2169,9 @@ addrescapes(Node *n)
if(n->noescape)
break;
switch(n->class) {
- case PAUTO:
+ case PPARAMREF:
+ addrescapes(n->defn);
+ break;
case PPARAM:
case PPARAMOUT:
// if func param, need separate temporary
@@ -2167,16 +2179,17 @@ addrescapes(Node *n)
// the function type has already been checked
// (we're in the function body)
// so the param already has a valid xoffset.
- if(n->class == PPARAM || n->class == PPARAMOUT) {
- // expression to refer to stack copy
- n->stackparam = nod(OPARAM, n, N);
- n->stackparam->type = n->type;
- n->stackparam->addable = 1;
- if(n->xoffset == BADWIDTH)
- fatal("addrescapes before param assignment");
- n->stackparam->xoffset = n->xoffset;
- n->xoffset = 0;
- }
+
+ // expression to refer to stack copy
+ n->stackparam = nod(OPARAM, n, N);
+ n->stackparam->type = n->type;
+ n->stackparam->addable = 1;
+ if(n->xoffset == BADWIDTH)
+ fatal("addrescapes before param assignment");
+ n->stackparam->xoffset = n->xoffset;
+ n->xoffset = 0;
+ // fallthrough
+ case PAUTO:
n->class |= PHEAP;
n->addable = 0;
@@ -2189,7 +2202,9 @@ addrescapes(Node *n)
snprint(buf, sizeof buf, "&%S", n->sym);
n->heapaddr->sym = lookup(buf);
n->heapaddr->class = PHEAP-1; // defer tempname to allocparams
- curfn->dcl = list(curfn->dcl, n->heapaddr);
+ n->heapaddr->ullman = 1;
+ n->curfn->dcl = list(n->curfn->dcl, n->heapaddr);
+
break;
}
break;
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b3b400556..ccc65ff21 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -66,6 +66,7 @@ walk(Node *fn)
int lno;
curfn = fn;
+
if(debug['W']) {
snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
dumplist(s, curfn->nbody);
@@ -73,7 +74,7 @@ walk(Node *fn)
if(curfn->type->outtuple)
if(walkret(curfn->nbody))
yyerror("function ends without a return statement");
- typechecklist(curfn->nbody, Etop);
+
lno = lineno;
for(l=fn->dcl; l; l=l->next) {
n = l->n;
@@ -468,8 +469,10 @@ walkstmt(Node **np)
case OPANIC:
case OEMPTY:
case ORECOVER:
- if(n->typecheck == 0)
+ if(n->typecheck == 0) {
+ dump("missing typecheck:", n);
fatal("missing typecheck");
+ }
init = n->ninit;
n->ninit = nil;
walkexpr(&n, &init);
@@ -770,8 +773,15 @@ walkexpr(Node **np, NodeList **init)
t = n->left->type;
if(n->list && n->list->n->op == OAS)
goto ret;
- walkexpr(&n->left, init);
+
+ if(n->left->op == OCLOSURE) {
+ walkcallclosure(n, init);
+ t = n->left->type;
+ } else
+ walkexpr(&n->left, init);
+
walkexprlist(n->list, init);
+
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
n->list = reorder1(ll);
if(isselect(n)) {
@@ -1525,7 +1535,7 @@ ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
static int
fncall(Node *l, Type *rt)
{
- if(l->ullman >= UINF)
+ if(l->ullman >= UINF || l->op == OINDEXMAP)
return 1;
if(eqtype(l->type, rt))
return 0;