diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-08-03 16:54:30 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-08-03 16:54:30 +0200 |
commit | 28592ee1ea1f5cdffcf85472f9de0285d928cf12 (patch) | |
tree | 32944e18b23f7fe4a0818a694aa2a6dfb1835463 /src/cmd/gc | |
parent | e836bee4716dc0d4d913537ad3ad1925a7ac32d0 (diff) | |
download | golang-28592ee1ea1f5cdffcf85472f9de0285d928cf12.tar.gz |
Imported Upstream version 59upstream/59
Diffstat (limited to 'src/cmd/gc')
-rw-r--r-- | src/cmd/gc/builtin.c.boot | 10 | ||||
-rw-r--r-- | src/cmd/gc/closure.c | 78 | ||||
-rw-r--r-- | src/cmd/gc/dcl.c | 26 | ||||
-rw-r--r-- | src/cmd/gc/gen.c | 214 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 29 | ||||
-rw-r--r-- | src/cmd/gc/go.y | 59 | ||||
-rw-r--r-- | src/cmd/gc/lex.c | 18 | ||||
-rw-r--r-- | src/cmd/gc/pgen.c | 32 | ||||
-rw-r--r-- | src/cmd/gc/runtime.go | 1 | ||||
-rw-r--r-- | src/cmd/gc/subr.c | 41 | ||||
-rw-r--r-- | src/cmd/gc/typecheck.c | 7 | ||||
-rw-r--r-- | src/cmd/gc/unsafe.c | 2 | ||||
-rw-r--r-- | src/cmd/gc/unsafe.go | 8 | ||||
-rw-r--r-- | src/cmd/gc/walk.c | 15 |
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); |