summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-08-03 16:54:30 +0200
committerOndřej Surý <ondrej@sury.org>2011-08-03 16:54:30 +0200
commit28592ee1ea1f5cdffcf85472f9de0285d928cf12 (patch)
tree32944e18b23f7fe4a0818a694aa2a6dfb1835463 /src/cmd/gc
parente836bee4716dc0d4d913537ad3ad1925a7ac32d0 (diff)
downloadgolang-28592ee1ea1f5cdffcf85472f9de0285d928cf12.tar.gz
Imported Upstream version 59upstream/59
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/builtin.c.boot10
-rw-r--r--src/cmd/gc/closure.c78
-rw-r--r--src/cmd/gc/dcl.c26
-rw-r--r--src/cmd/gc/gen.c214
-rw-r--r--src/cmd/gc/go.h29
-rw-r--r--src/cmd/gc/go.y59
-rw-r--r--src/cmd/gc/lex.c18
-rw-r--r--src/cmd/gc/pgen.c32
-rw-r--r--src/cmd/gc/runtime.go1
-rw-r--r--src/cmd/gc/subr.c41
-rw-r--r--src/cmd/gc/typecheck.c7
-rw-r--r--src/cmd/gc/unsafe.c2
-rw-r--r--src/cmd/gc/unsafe.go8
-rw-r--r--src/cmd/gc/walk.c15
14 files changed, 332 insertions, 208 deletions
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index c9bf501d1..95098c8af 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -6,6 +6,7 @@ char *runtimeimport =
"func \"\".panicslice ()\n"
"func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n"
+ "func \"\".panicwrap (? string, ? string, ? string)\n"
"func \"\".panic (? interface { })\n"
"func \"\".recover (? *int32) interface { }\n"
"func \"\".printbool (? bool)\n"
@@ -22,6 +23,7 @@ char *runtimeimport =
"func \"\".printsp ()\n"
"func \"\".goprintf ()\n"
"func \"\".concatstring ()\n"
+ "func \"\".append ()\n"
"func \"\".appendslice (typ *uint8, x any, y []any) any\n"
"func \"\".cmpstring (? string, ? string) int\n"
"func \"\".slicestring (? string, ? int, ? int) string\n"
@@ -81,7 +83,7 @@ char *runtimeimport =
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
"func \"\".makeslice (typ *uint8, nel int64, cap int64) []any\n"
- "func \"\".growslice (typ *uint8, old []any, cap int64) []any\n"
+ "func \"\".growslice (typ *uint8, old []any, n int64) []any\n"
"func \"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func \"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func \"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
@@ -101,9 +103,9 @@ char *unsafeimport =
"package unsafe\n"
"import runtime \"runtime\"\n"
"type \"\".Pointer uintptr\n"
- "func \"\".Offsetof (? any) int\n"
- "func \"\".Sizeof (? any) int\n"
- "func \"\".Alignof (? any) int\n"
+ "func \"\".Offsetof (? any) uintptr\n"
+ "func \"\".Sizeof (? any) uintptr\n"
+ "func \"\".Alignof (? any) uintptr\n"
"func \"\".Typeof (i interface { }) interface { }\n"
"func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n"
"func \"\".Unreflect (typ interface { }, addr \"\".Pointer) interface { }\n"
diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c
index 906dadbc9..7e7b40526 100644
--- a/src/cmd/gc/closure.c
+++ b/src/cmd/gc/closure.c
@@ -116,12 +116,11 @@ typecheckclosure(Node *func, int top)
}
}
-Node*
-walkclosure(Node *func, NodeList **init)
+static Node*
+makeclosure(Node *func, NodeList **init, int nowrap)
{
- int narg;
- Node *xtype, *v, *addr, *xfunc, *call, *clos;
- NodeList *l, *in;
+ Node *xtype, *v, *addr, *xfunc;
+ NodeList *l;
static int closgen;
char *p;
@@ -133,7 +132,6 @@ walkclosure(Node *func, NodeList **init)
// each closure variable has a corresponding
// address parameter.
- narg = 0;
for(l=func->cvars; l; l=l->next) {
v = l->n;
if(v->op == 0)
@@ -146,7 +144,6 @@ walkclosure(Node *func, NodeList **init)
addr->class = PPARAM;
addr->addable = 1;
addr->ullman = 1;
- narg++;
v->heapaddr = addr;
@@ -154,7 +151,8 @@ walkclosure(Node *func, NodeList **init)
}
// then a dummy arg where the closure's caller pc sits
- xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
+ if (!nowrap)
+ xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
// then the function arguments
xtype->list = concat(xtype->list, func->list);
@@ -176,15 +174,36 @@ walkclosure(Node *func, NodeList **init)
typecheck(&xfunc, Etop);
closures = list(closures, xfunc);
+ return xfunc;
+}
+
+Node*
+walkclosure(Node *func, NodeList **init)
+{
+ int narg;
+ Node *xtype, *xfunc, *call, *clos;
+ NodeList *l, *in;
+
+ /*
+ * wrap body in external function
+ * with extra closure parameters.
+ */
+
+ // create the function
+ xfunc = makeclosure(func, init, 0);
+ xtype = xfunc->nname->ntype;
+
// prepare call of sys.closure that turns external func into func literal value.
clos = syslook("closure", 1);
clos->type = T;
clos->ntype = nod(OTFUNC, N, N);
in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // siz
in = list(in, nod(ODCLFIELD, N, xtype));
+ narg = 0;
for(l=func->cvars; l; l=l->next) {
if(l->n->op == 0)
continue;
+ narg++;
in = list(in, nod(ODCLFIELD, N, l->n->heapaddr->ntype));
}
clos->ntype->list = in;
@@ -211,33 +230,18 @@ walkclosure(Node *func, NodeList **init)
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);
+ if (n->op != OCALLFUNC || n->left->op != OCLOSURE) {
+ dump("walkcallclosure", n);
+ fatal("abuse of walkcallclosure");
+ }
+
+ // 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 = makeclosure(n->left, init, 1)->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;
}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 335d056a0..7290f9d3b 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -39,6 +39,7 @@ push(void)
Sym *d;
d = mal(sizeof(*d));
+ d->lastlineno = lineno;
d->link = dclstack;
dclstack = d;
return d;
@@ -60,6 +61,7 @@ void
popdcl(void)
{
Sym *d, *s;
+ int lno;
// if(dflag())
// print("revert\n");
@@ -68,7 +70,9 @@ popdcl(void)
if(d->name == nil)
break;
s = pkglookup(d->name, d->pkg);
+ lno = s->lastlineno;
dcopy(s, d);
+ d->lastlineno = lno;
if(dflag())
print("\t%L pop %S %p\n", lineno, s, s->def);
}
@@ -81,19 +85,12 @@ popdcl(void)
void
poptodcl(void)
{
- Sym *d, *s;
-
- for(d=dclstack; d!=S; d=d->link) {
- if(d->name == nil)
- break;
- s = pkglookup(d->name, d->pkg);
- dcopy(s, d);
- if(dflag())
- print("\t%L pop %S\n", lineno, s);
- }
- if(d == S)
- fatal("poptodcl: no mark");
- dclstack = d;
+ // pop the old marker and push a new one
+ // (cannot reuse the existing one)
+ // because we use the markers to identify blocks
+ // for the goto restriction checks.
+ popdcl();
+ markdcl();
}
void
@@ -1241,10 +1238,7 @@ funccompile(Node *n, int isclosure)
stksize = 0;
dclcontext = PAUTO;
funcdepth = n->funcdepth + 1;
- hasgoto = 0;
compile(n);
- if(hasgoto)
- clearstk();
curfn = nil;
funcdepth = 0;
dclcontext = PEXTERN;
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index ad7b65b30..cb66921ba 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -11,6 +11,10 @@
static void cgen_dcl(Node *n);
static void cgen_proc(Node *n, int proc);
+static void checkgoto(Node*, Node*);
+
+static Label *labellist;
+static Label *lastlabel;
Node*
sysfunc(char *name)
@@ -80,71 +84,122 @@ clearlabels(void)
lastlabel = L;
}
-static void
-newlab(int op, Node *nlab, Node *stmt)
+static Label*
+newlab(Node *n)
{
- Label *lab;
Sym *s;
- int32 lno;
+ Label *lab;
+
+ s = n->left->sym;
+ if((lab = s->label) == L) {
+ lab = mal(sizeof(*lab));
+ if(lastlabel == nil)
+ labellist = lab;
+ else
+ lastlabel->link = lab;
+ lastlabel = lab;
+ lab->sym = s;
+ s->label = lab;
+ }
- s = nlab->left->sym;
- lno = nlab->left->lineno;
-
- lab = mal(sizeof(*lab));
- if(lastlabel == nil)
- labellist = lab;
- else
- lastlabel->link = lab;
- lastlabel = lab;
-
- lab->lineno = lno;
- lab->sym = s;
- lab->op = op;
- lab->label = pc;
- lab->stmt = stmt;
- if(op == OLABEL) {
- if(s->label != L) {
- lineno = lno;
- yyerror("label %S already defined at %L", s, s->label->lineno);
- } else
- s->label = lab;
- }
+ if(n->op == OLABEL) {
+ if(lab->def != N)
+ yyerror("label %S already defined at %L", s, lab->def->lineno);
+ else
+ lab->def = n;
+ } else
+ lab->use = list(lab->use, n);
+
+ return lab;
}
void
checklabels(void)
{
- Label *l;
- Sym *s;
- int lno;
+ Label *lab;
+ NodeList *l;
- lno = lineno;
-
- // resolve goto using syms
- for(l=labellist; l!=L; l=l->link) {
- switch(l->op) {
- case OGOTO:
- s = l->sym;
- if(s->label == L) {
- lineno = l->lineno;
- yyerror("label %S not defined", s);
- break;
- }
- s->label->used = 1;
- patch(l->label, s->label->label);
- break;
+ for(lab=labellist; lab!=L; lab=lab->link) {
+ if(lab->def == N) {
+ for(l=lab->use; l; l=l->next)
+ yyerrorl(l->n->lineno, "label %S not defined", lab->sym);
+ continue;
}
+ if(lab->use == nil && !lab->used) {
+ yyerrorl(lab->def->lineno, "label %S defined and not used", lab->sym);
+ continue;
+ }
+ if(lab->gotopc != P)
+ fatal("label %S never resolved", lab->sym);
+ for(l=lab->use; l; l=l->next)
+ checkgoto(l->n, lab->def);
}
-
- // diagnose unused labels
- for(l=labellist; l!=L; l=l->link) {
- if(l->op == OLABEL && !l->used) {
- lineno = l->lineno;
- yyerror("label %S defined and not used", l->sym);
+}
+
+static void
+checkgoto(Node *from, Node *to)
+{
+ int nf, nt;
+ Sym *block, *dcl, *fs, *ts;
+ int lno;
+
+ if(from->sym == to->sym)
+ return;
+
+ nf = 0;
+ for(fs=from->sym; fs; fs=fs->link)
+ nf++;
+ nt = 0;
+ for(fs=to->sym; fs; fs=fs->link)
+ nt++;
+ fs = from->sym;
+ for(; nf > nt; nf--)
+ fs = fs->link;
+ if(fs != to->sym) {
+ lno = lineno;
+ setlineno(from);
+
+ // decide what to complain about.
+ // prefer to complain about 'into block' over declarations,
+ // so scan backward to find most recent block or else dcl.
+ block = S;
+ dcl = S;
+ ts = to->sym;
+ for(; nt > nf; nt--) {
+ if(ts->pkg == nil)
+ block = ts;
+ else
+ dcl = ts;
+ ts = ts->link;
}
+ while(ts != fs) {
+ if(ts->pkg == nil)
+ block = ts;
+ else
+ dcl = ts;
+ ts = ts->link;
+ fs = fs->link;
+ }
+
+ if(block)
+ yyerror("goto %S jumps into block starting at %L", from->left->sym, block->lastlineno);
+ else
+ yyerror("goto %S jumps over declaration of %S at %L", from->left->sym, dcl, dcl->lastlineno);
+ lineno = lno;
}
-
- lineno = lno;
+}
+
+static Label*
+stmtlabel(Node *n)
+{
+ Label *lab;
+
+ if(n->sym != S)
+ if((lab = n->sym->label) != L)
+ if(lab->def != N)
+ if(lab->def->right == n)
+ return lab;
+ return L;
}
/*
@@ -193,11 +248,6 @@ gen(Node *n)
break;
case OEMPTY:
- // insert no-op so that
- // L:; for { }
- // does not treat L as a label for the loop.
- if(lastlabel != L && lastlabel->label == p3)
- gused(N);
break;
case OBLOCK:
@@ -205,13 +255,41 @@ gen(Node *n)
break;
case OLABEL:
- newlab(OLABEL, n, n->right);
+ lab = newlab(n);
+
+ // if there are pending gotos, resolve them all to the current pc.
+ for(p1=lab->gotopc; p1; p1=p2) {
+ p2 = unpatch(p1);
+ patch(p1, pc);
+ }
+ lab->gotopc = P;
+ if(lab->labelpc == P)
+ lab->labelpc = pc;
+
+ if(n->right) {
+ switch(n->right->op) {
+ case OFOR:
+ case OSWITCH:
+ case OSELECT:
+ // so stmtlabel can find the label
+ n->right->sym = lab->sym;
+ }
+ }
break;
case OGOTO:
- hasgoto = 1;
- newlab(OGOTO, n, N);
- gjmp(P);
+ // if label is defined, emit jump to it.
+ // otherwise save list of pending gotos in lab->gotopc.
+ // the list is linked through the normal jump target field
+ // to avoid a second list. (the jumps are actually still
+ // valid code, since they're just going to another goto
+ // to the same label. we'll unwind it when we learn the pc
+ // of the label in the OLABEL case above.)
+ lab = newlab(n);
+ if(lab->labelpc != P)
+ gjmp(lab->labelpc);
+ else
+ lab->gotopc = gjmp(lab->gotopc);
break;
case OBREAK:
@@ -266,12 +344,10 @@ gen(Node *n)
continpc = pc;
// define break and continue labels
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n) {
+ if((lab = stmtlabel(n)) != L) {
lab->breakpc = breakpc;
lab->continpc = continpc;
- } else
- lab = L;
-
+ }
gen(n->nincr); // contin: incr
patch(p1, pc); // test:
bgen(n->ntest, 0, breakpc); // if(!test) goto break
@@ -304,10 +380,8 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- else
- lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
@@ -323,10 +397,8 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = stmtlabel(n)) != L)
lab->breakpc = breakpc;
- else
- lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // select() body
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index c16903e77..8ca086ee0 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -278,6 +278,7 @@ struct Node
int32 iota;
};
#define N ((Node*)0)
+EXTERN int32 walkgen;
struct NodeList
{
@@ -301,6 +302,7 @@ struct Sym
uchar flags;
uchar sym; // huffman encoding in object file
Sym* link;
+ int32 npkg; // number of imported packages with this name
// saved and restored by dcopy
Pkg* pkg;
@@ -632,21 +634,20 @@ typedef struct Prog Prog;
struct Label
{
- uchar op; // OGOTO/OLABEL
uchar used;
Sym* sym;
- Node* stmt;
- Prog* label; // pointer to code
+ Node* def;
+ NodeList* use;
+ Label* link;
+
+ // for use during gen
+ Prog* gotopc; // pointer to unresolved gotos
+ Prog* labelpc; // pointer to code
Prog* breakpc; // pointer to code
Prog* continpc; // pointer to code
- Label* link;
- int32 lineno;
};
#define L ((Label*)0)
-EXTERN Label* labellist;
-EXTERN Label* lastlabel;
-
/*
* note this is the runtime representation
* of the compilers arrays.
@@ -691,6 +692,7 @@ EXTERN char* infile;
EXTERN char* outfile;
EXTERN Biobuf* bout;
EXTERN int nerrors;
+EXTERN int nsavederrors;
EXTERN int nsyntaxerrors;
EXTERN int safemode;
EXTERN char namebuf[NSYMB];
@@ -776,6 +778,7 @@ EXTERN int32 nhunk;
EXTERN int32 thunk;
EXTERN int exporting;
+EXTERN int erroring;
EXTERN int noargnames;
EXTERN int funcdepth;
@@ -913,8 +916,8 @@ Type* pkgtype(Sym *s);
void allocparams(void);
void cgen_as(Node *nl, Node *nr);
void cgen_callmeth(Node *n, int proc);
-void checklabels(void);
void clearlabels(void);
+void checklabels(void);
int dotoffset(Node *n, int *oary, Node **nn);
void gen(Node *n);
void genlist(NodeList *l);
@@ -1132,6 +1135,7 @@ Type* ptrto(Type *t);
void* remal(void *p, int32 on, int32 n);
Sym* restrictlookup(char *name, Pkg *pkg);
Node* safeexpr(Node *n, NodeList **init);
+void saveerrors(void);
Node* cheapexpr(Node *n, NodeList **init);
int32 setlineno(Node *n);
void setmaxarg(Type *t);
@@ -1195,7 +1199,7 @@ void walkstmt(Node **np);
void walkstmtlist(NodeList *l);
/*
- * arch-specific ggen.c/gsubr.c/gobj.c
+ * arch-specific ggen.c/gsubr.c/gobj.c/pgen.c
*/
#define P ((Prog*)0)
@@ -1237,6 +1241,7 @@ int dsymptr(Sym *s, int off, Sym *x, int xoff);
int duintxx(Sym *s, int off, uint64 v, int wid);
void dumpdata(void);
void dumpfuncs(void);
+void fixautoused(Prog*);
void gdata(Node*, Node*, int);
void gdatacomplex(Node*, Mpcplx*);
void gdatastring(Node*, Strlit*);
@@ -1246,15 +1251,15 @@ void ggloblsym(Sym *s, int32 width, int dupok);
Prog* gjmp(Prog*);
void gused(Node*);
int isfat(Type*);
+void markautoused(Prog*);
Plist* newplist(void);
Node* nodarg(Type*, int);
void nopout(Prog*);
void patch(Prog*, Prog*);
+Prog* unpatch(Prog*);
void zfile(Biobuf *b, char *p, int n);
void zhist(Biobuf *b, int line, vlong offset);
void zname(Biobuf *b, Sym *s, int t);
void data(void);
void text(void);
-EXTERN int hasgoto;
-void clearstk(void);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 1278c2586..01a4e822f 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -66,7 +66,7 @@ static void fixlbrace(int);
%type <node> switch_stmt uexpr
%type <node> xfndcl typedcl
-%type <list> xdcl fnbody fnres switch_body loop_body dcl_name_list
+%type <list> xdcl fnbody fnres loop_body dcl_name_list
%type <list> new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
%type <list> oexpr_list caseblock_list stmt_list oarg_type_list_ocomma arg_type_list
%type <list> interfacedcl_list vardcl vardcl_list structdcl structdcl_list
@@ -237,7 +237,11 @@ import_here:
import_package:
LPACKAGE sym import_safety ';'
{
- importpkg->name = $2->name;
+ if(importpkg->name == nil) {
+ importpkg->name = $2->name;
+ pkglookup($2->name, nil)->npkg++;
+ } 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;
if(safemode && !curio.importsafe)
@@ -449,7 +453,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
$$->list = $2;
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
@@ -468,7 +472,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
if($2->next == nil)
n = nod(OAS, $2->n, $4);
@@ -484,7 +488,7 @@ case:
// will be converted to OCASE
// right will point to next case
// done in casebody()
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
$$->list = list1(colas($2, list1($4)));
}
@@ -492,7 +496,7 @@ case:
{
Node *n;
- poptodcl();
+ markdcl();
$$ = nod(OXCASE, N, N);
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
// type switch - declare variable
@@ -514,17 +518,6 @@ compound_stmt:
popdcl();
}
-switch_body:
- LBODY
- {
- markdcl();
- }
- caseblock_list '}'
- {
- $$ = $3;
- popdcl();
- }
-
caseblock:
case
{
@@ -553,6 +546,7 @@ caseblock:
yyerror("missing statement after label");
$$ = $1;
$$->nbody = $3;
+ popdcl();
}
caseblock_list:
@@ -674,11 +668,11 @@ switch_stmt:
n = N;
typesw = nod(OXXX, typesw, n);
}
- switch_body
+ LBODY caseblock_list '}'
{
$$ = $3;
$$->op = OSWITCH;
- $$->list = $5;
+ $$->list = $6;
typesw = typesw->left;
popdcl();
}
@@ -686,15 +680,13 @@ switch_stmt:
select_stmt:
LSELECT
{
- markdcl();
typesw = nod(OXXX, typesw, N);
}
- switch_body
+ LBODY caseblock_list '}'
{
$$ = nod(OSELECT, N, N);
- $$->list = $3;
+ $$->list = $4;
typesw = typesw->left;
- popdcl();
}
/*
@@ -1474,13 +1466,19 @@ non_dcl_stmt:
$$ = $1;
$$->nelse = list1($3);
}
-| labelname ':' stmt
+| labelname ':'
+ {
+ $1 = nod(OLABEL, $1, N);
+ $1->sym = dclstack; // context, for goto restrictions
+ }
+ stmt
{
NodeList *l;
- l = list1(nod(OLABEL, $1, $3));
- if($3)
- l = list(l, $3);
+ $1->right = $4;
+ l = list1($1);
+ if($4)
+ l = list(l, $4);
$$ = liststmt(l);
}
| LFALL
@@ -1507,6 +1505,7 @@ non_dcl_stmt:
| LGOTO new_name
{
$$ = nod(OGOTO, $2, N);
+ $$->sym = dclstack; // context, for goto restrictions
}
| LRETURN oexpr_list
{
@@ -1662,7 +1661,11 @@ hidden_import:
Pkg *p;
p = mkpkg($3.u.sval);
- p->name = $2->name;
+ if(p->name == nil) {
+ p->name = $2->name;
+ pkglookup($2->name, nil)->npkg++;
+ } else if(strcmp(p->name, $2->name) != 0)
+ yyerror("conflicting names %s and %s for package %Z", p->name, $2->name, p->path);
}
| LVAR hidden_pkg_importsym hidden_type ';'
{
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 88acb60af..5c642375a 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -97,7 +97,7 @@ fault(int s)
// in the program, don't bother complaining
// about the seg fault too; let the user clean up
// the code and try again.
- if(nerrors > 0)
+ if(nsavederrors + nerrors > 0)
errorexit();
fatal("fault");
}
@@ -256,7 +256,10 @@ main(int argc, char *argv[])
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC) {
curfn = l->n;
+ saveerrors();
typechecklist(l->n->nbody, Etop);
+ if(nerrors != 0)
+ l->n->nbody = nil; // type errors; do not compile
}
curfn = nil;
@@ -264,7 +267,7 @@ main(int argc, char *argv[])
if(l->n->op == ODCLFUNC)
funccompile(l->n, 0);
- if(nerrors == 0)
+ if(nsavederrors+nerrors == 0)
fninit(xtop);
while(closures) {
@@ -278,12 +281,12 @@ main(int argc, char *argv[])
if(l->n->op == ONAME)
typecheck(&l->n, Erv);
- if(nerrors)
+ if(nerrors+nsavederrors)
errorexit();
dumpobj();
- if(nerrors)
+ if(nerrors+nsavederrors)
errorexit();
flusherrors();
@@ -291,6 +294,13 @@ main(int argc, char *argv[])
return 0;
}
+void
+saveerrors(void)
+{
+ nsavederrors += nerrors;
+ nerrors = 0;
+}
+
static int
arsize(Biobuf *b, char *name)
{
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index ab6186697..552e405d8 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -30,6 +30,8 @@ compile(Node *fn)
if(fn->nbody == nil)
return;
+ saveerrors();
+
// set up domain for labels
clearlabels();
@@ -53,7 +55,7 @@ compile(Node *fn)
hasdefer = 0;
walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
+ if(nerrors != 0)
goto ret;
allocparams();
@@ -67,7 +69,7 @@ compile(Node *fn)
setlineno(curfn);
nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
+ ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
afunclit(&ptxt->from);
ginit();
@@ -111,8 +113,7 @@ compile(Node *fn)
}
oldstksize = stksize;
- if(thechar != '5')
- compactframe(ptxt);
+ compactframe(ptxt);
if(0)
print("compactframe: %ld to %ld\n", oldstksize, stksize);
@@ -142,12 +143,12 @@ cmpstackvar(Node *a, Node *b)
}
+// TODO(lvd) find out where the PAUTO/OLITERAL nodes come from.
static void
compactframe(Prog* ptxt)
{
NodeList *ll;
Node* n;
- Prog *p;
uint32 w;
if (stksize == 0)
@@ -155,17 +156,10 @@ compactframe(Prog* ptxt)
// Mark the PAUTO's unused.
for(ll=curfn->dcl; ll != nil; ll=ll->next)
- if (ll->n->class == PAUTO && ll->n->op == ONAME)
+ if (ll->n->class == PAUTO)
ll->n->used = 0;
- // Sweep the prog list to mark any used nodes.
- for (p = ptxt; p; p = p->link) {
- if (p->from.type == D_AUTO && p->from.node)
- p->from.node->used++;
-
- if (p->to.type == D_AUTO && p->to.node)
- p->to.node->used++;
- }
+ markautoused(ptxt);
listsort(&curfn->dcl, cmpstackvar);
@@ -191,7 +185,6 @@ compactframe(Prog* ptxt)
stksize = 0;
for(ll = curfn->dcl; ll != nil; ll=ll->next) {
n = ll->n;
- // TODO find out where the literal autos come from
if (n->class != PAUTO || n->op != ONAME)
continue;
@@ -205,14 +198,7 @@ compactframe(Prog* ptxt)
n->stkdelta = -stksize - n->xoffset;
}
- // Fixup instructions.
- for (p = ptxt; p; p = p->link) {
- if (p->from.type == D_AUTO && p->from.node)
- p->from.offset += p->from.node->stkdelta;
-
- if (p->to.type == D_AUTO && p->to.node)
- p->to.offset += p->to.node->stkdelta;
- }
+ fixautoused(ptxt);
// The debug information needs accurate offsets on the symbols.
for(ll = curfn->dcl ;ll != nil; ll=ll->next) {
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 00fc720b8..e13c95db9 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -15,6 +15,7 @@ func panicindex()
func panicslice()
func throwreturn()
func throwinit()
+func panicwrap(string, string, string)
func panic(interface{})
func recover(*int32) interface{}
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 49797f9df..40b0c4fd1 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -45,10 +45,12 @@ adderr(int line, char *fmt, va_list arg)
Fmt f;
Error *p;
+ erroring++;
fmtstrinit(&f);
fmtprint(&f, "%L: ", line);
fmtvprint(&f, fmt, arg);
fmtprint(&f, "\n");
+ erroring--;
if(nerr >= merr) {
if(merr == 0)
@@ -1122,7 +1124,14 @@ Sconv(Fmt *fp)
return 0;
}
- if(s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) {
+ if(s->pkg && s->pkg != localpkg || longsymnames || (fp->flags & FmtLong)) {
+ // This one is for the user. If the package name
+ // was used by multiple packages, give the full
+ // import path to disambiguate.
+ if(erroring && pkglookup(s->pkg->name, nil)->npkg > 1) {
+ fmtprint(fp, "\"%Z\".%s", s->pkg->path, s->name);
+ return 0;
+ }
fmtprint(fp, "%s.%s", s->pkg->name, s->name);
return 0;
}
@@ -3131,8 +3140,9 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
NodeList *l, *args, *in, *out;
Type *tpad;
int isddd;
+ Val v;
- if(0 && debug['r'])
+ if(debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
rcvr, method, newnam);
@@ -3174,17 +3184,38 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
args = list(args, l->n->left);
isddd = l->n->left->isddd;
}
+
+ // generate nil pointer check for better error
+ if(isptr[rcvr->etype] && rcvr->type == getthisx(method->type)->type->type) {
+ // generating wrapper from *T to T.
+ n = nod(OIF, N, N);
+ n->ntest = nod(OEQ, this->left, nodnil());
+ // these strings are already in the reflect tables,
+ // so no space cost to use them here.
+ l = nil;
+ v.ctype = CTSTR;
+ v.u.sval = strlit(rcvr->type->sym->pkg->name); // package name
+ l = list(l, nodlit(v));
+ v.u.sval = strlit(rcvr->type->sym->name); // type name
+ l = list(l, nodlit(v));
+ v.u.sval = strlit(method->sym->name);
+ l = list(l, nodlit(v)); // method name
+ call = nod(OCALL, syslook("panicwrap", 0), N);
+ call->list = l;
+ n->nbody = list1(call);
+ fn->nbody = list(fn->nbody, n);
+ }
// generate call
call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N);
call->list = args;
call->isddd = isddd;
- fn->nbody = list1(call);
if(method->type->outtuple > 0) {
n = nod(ORETURN, N, N);
- n->list = fn->nbody;
- fn->nbody = list1(n);
+ n->list = list1(call);
+ call = n;
}
+ fn->nbody = list(fn->nbody, call);
if(0 && debug['r'])
dumplist("genwrapper body", fn->nbody);
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 04dc1a507..dfe0f30f7 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -2716,6 +2716,11 @@ typecheckdef(Node *n)
default:
fatal("typecheckdef %O", n->op);
+ case OGOTO:
+ case OLABEL:
+ // not really syms
+ break;
+
case OLITERAL:
if(n->ntype != N) {
typecheck(&n->ntype, Etype);
@@ -2772,7 +2777,7 @@ typecheckdef(Node *n)
if(n->defn == N) {
if(n->etype != 0) // like OPRINTN
break;
- if(nerrors > 0) {
+ if(nsavederrors+nerrors > 0) {
// Can have undefined variables in x := foo
// that make x have an n->ndefn == nil.
// If there are other errors anyway, don't
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
index 540994ddd..d304077c8 100644
--- a/src/cmd/gc/unsafe.c
+++ b/src/cmd/gc/unsafe.c
@@ -92,6 +92,6 @@ ret:
mpmovecfix(val.u.xval, v);
n = nod(OLITERAL, N, N);
n->val = val;
- n->type = types[TINT];
+ n->type = types[TUINTPTR];
return n;
}
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
index b2a341d39..db27d7425 100644
--- a/src/cmd/gc/unsafe.go
+++ b/src/cmd/gc/unsafe.go
@@ -10,9 +10,11 @@ package PACKAGE
type Pointer uintptr // not really; filled in by compiler
-func Offsetof(any) int
-func Sizeof(any) int
-func Alignof(any) int
+// return types here are ignored; see unsafe.c
+func Offsetof(any) uintptr
+func Sizeof(any) uintptr
+func Alignof(any) uintptr
+
func Typeof(i interface{}) (typ interface{})
func Reflect(i interface{}) (typ interface{}, addr Pointer)
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 65a504bff..c9ca9b3b3 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -243,7 +243,16 @@ walkstmt(Node **np)
break;
case OPROC:
- walkexpr(&n->left, &n->ninit);
+ switch(n->left->op) {
+ case OPRINT:
+ case OPRINTN:
+ walkexprlist(n->left->list, &n->ninit);
+ n->left = walkprint(n->left, &n->ninit, 1);
+ break;
+ default:
+ walkexpr(&n->left, &n->ninit);
+ break;
+ }
break;
case ORETURN:
@@ -485,9 +494,9 @@ walkexpr(Node **np, NodeList **init)
if(n->left->op == OCLOSURE) {
walkcallclosure(n, init);
t = n->left->type;
- } else
- walkexpr(&n->left, init);
+ }
+ walkexpr(&n->left, init);
walkexprlist(n->list, init);
ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);