summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/align.c12
-rw-r--r--src/cmd/gc/builtin.c.boot6
-rw-r--r--src/cmd/gc/const.c2
-rw-r--r--src/cmd/gc/dcl.c41
-rw-r--r--src/cmd/gc/export.c15
-rw-r--r--src/cmd/gc/gen.c157
-rw-r--r--src/cmd/gc/go.h32
-rw-r--r--src/cmd/gc/go.y20
-rw-r--r--src/cmd/gc/lex.c4
-rw-r--r--src/cmd/gc/obj.c54
-rw-r--r--src/cmd/gc/print.c2
-rw-r--r--src/cmd/gc/range.c4
-rw-r--r--src/cmd/gc/reflect.c65
-rw-r--r--src/cmd/gc/runtime.go4
-rw-r--r--src/cmd/gc/select.c70
-rw-r--r--src/cmd/gc/sinit.c2
-rw-r--r--src/cmd/gc/subr.c41
-rw-r--r--src/cmd/gc/typecheck.c21
-rw-r--r--src/cmd/gc/unsafe.go2
-rw-r--r--src/cmd/gc/walk.c15
20 files changed, 392 insertions, 177 deletions
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c
index 833eba19a..a01e2ea46 100644
--- a/src/cmd/gc/align.c
+++ b/src/cmd/gc/align.c
@@ -172,6 +172,9 @@ dowidth(Type *t)
w = 8;
checkwidth(t->type);
break;
+ case TUNSAFEPTR:
+ w = widthptr;
+ break;
case TINTER: // implemented as 2 pointers
w = 2*widthptr;
t->align = widthptr;
@@ -400,6 +403,13 @@ typeinit(void)
types[TPTR64] = typ(TPTR64);
dowidth(types[TPTR64]);
+
+ t = typ(TUNSAFEPTR);
+ types[TUNSAFEPTR] = t;
+ t->sym = pkglookup("Pointer", unsafepkg);
+ t->sym->def = typenod(t);
+
+ dowidth(types[TUNSAFEPTR]);
tptr = TPTR32;
if(widthptr == 8)
@@ -481,6 +491,7 @@ typeinit(void)
okforeq[TPTR32] = 1;
okforeq[TPTR64] = 1;
+ okforeq[TUNSAFEPTR] = 1;
okforeq[TINTER] = 1;
okforeq[TMAP] = 1;
okforeq[TCHAN] = 1;
@@ -570,6 +581,7 @@ typeinit(void)
simtype[TMAP] = tptr;
simtype[TCHAN] = tptr;
simtype[TFUNC] = tptr;
+ simtype[TUNSAFEPTR] = tptr;
/* pick up the backend typedefs */
for(i=0; typedefs[i].name; i++) {
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index 48f45293f..bdbca7f78 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -66,15 +66,17 @@ char *runtimeimport =
"func \"\".mapiter2 (hiter *any) (key any, val any)\n"
"func \"\".makechan (elem *uint8, hint int64) chan any\n"
"func \"\".chanrecv1 (hchan <-chan any) any\n"
- "func \"\".chanrecv3 (hchan <-chan any) (elem any, closed bool)\n"
+ "func \"\".chanrecv2 (hchan <-chan any) (elem any, received bool)\n"
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
"func \"\".closechan (hchan any)\n"
"func \"\".closedchan (hchan any) bool\n"
"func \"\".selectnbsend (hchan chan<- any, elem any) bool\n"
"func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n"
+ "func \"\".selectnbrecv2 (elem *any, received *bool, hchan <-chan any) bool\n"
"func \"\".newselect (size int) *uint8\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) bool\n"
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
+ "func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n"
"func \"\".selectdefault (sel *uint8) bool\n"
"func \"\".selectgo (sel *uint8)\n"
"func \"\".block ()\n"
@@ -96,7 +98,7 @@ char *runtimeimport =
"$$\n";
char *unsafeimport =
"package unsafe\n"
- "type \"\".Pointer *any\n"
+ "type \"\".Pointer uintptr\n"
"func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n"
"func \"\".Alignof (? any) int\n"
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index a54c40f6c..a36ec68c0 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -136,7 +136,6 @@ convlit1(Node **np, Type *t, int explicit)
case CTNIL:
switch(et) {
default:
- yyerror("cannot use nil as %T", t);
n->type = T;
goto bad;
@@ -155,6 +154,7 @@ convlit1(Node **np, Type *t, int explicit)
case TMAP:
case TCHAN:
case TFUNC:
+ case TUNSAFEPTR:
break;
}
break;
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index a71272aa2..3089a23b0 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -22,7 +22,6 @@ dflag(void)
/*
* declaration stack & operations
*/
-static Sym* dclstack;
static void
dcopy(Sym *a, Sym *b)
@@ -656,10 +655,19 @@ typedcl2(Type *pt, Type *t)
{
Node *n;
+ // override declaration in unsafe.go for Pointer.
+ // there is no way in Go code to define unsafe.Pointer
+ // so we have to supply it.
+ if(incannedimport &&
+ strcmp(importpkg->name, "unsafe") == 0 &&
+ strcmp(pt->nod->sym->name, "Pointer") == 0) {
+ t = types[TUNSAFEPTR];
+ }
+
if(pt->etype == TFORW)
goto ok;
if(!eqtype(pt->orig, t))
- yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t);
+ yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
return;
ok:
@@ -684,13 +692,13 @@ ok:
* turn a parsed struct into a type
*/
static Type**
-stotype(NodeList *l, int et, Type **t)
+stotype(NodeList *l, int et, Type **t, int funarg)
{
Type *f, *t1, *t2, **t0;
Strlit *note;
int lno;
NodeList *init;
- Node *n;
+ Node *n, *left;
char *what;
t0 = t;
@@ -707,15 +715,18 @@ stotype(NodeList *l, int et, Type **t)
if(n->op != ODCLFIELD)
fatal("stotype: oops %N\n", n);
+ left = n->left;
+ if(funarg && isblank(left))
+ left = N;
if(n->right != N) {
- if(et == TINTER && n->left != N) {
+ if(et == TINTER && left != N) {
// queue resolution of method type for later.
// right now all we need is the name list.
// avoids cycles for recursive interface types.
n->type = typ(TINTERMETH);
n->type->nname = n->right;
n->right = N;
- n->left->type = n->type;
+ left->type = n->type;
queuemethod(n);
} else {
typecheck(&n->right, Etype);
@@ -724,8 +735,8 @@ stotype(NodeList *l, int et, Type **t)
*t0 = T;
return t0;
}
- if(n->left != N)
- n->left->type = n->type;
+ if(left != N)
+ left->type = n->type;
n->right = N;
if(n->embedded && n->type != T) {
t1 = n->type;
@@ -763,7 +774,7 @@ stotype(NodeList *l, int et, Type **t)
break;
}
- if(et == TINTER && n->left == N) {
+ if(et == TINTER && left == N) {
// embedded interface - inline the methods
if(n->type->etype != TINTER) {
if(n->type->etype == TFORW)
@@ -796,8 +807,8 @@ stotype(NodeList *l, int et, Type **t)
f->width = BADWIDTH;
f->isddd = n->isddd;
- if(n->left != N && n->left->op == ONAME) {
- f->nname = n->left;
+ if(left != N && left->op == ONAME) {
+ f->nname = left;
f->embedded = n->embedded;
f->sym = f->nname->sym;
if(importpkg && !exportname(f->sym->name))
@@ -839,7 +850,7 @@ dostruct(NodeList *l, int et)
}
t = typ(et);
t->funarg = funarg;
- stotype(l, et, &t->type);
+ stotype(l, et, &t->type, funarg);
if(t->type == T && l != nil) {
t->broke = 1;
return t;
@@ -933,8 +944,6 @@ checkarglist(NodeList *all, int input)
t = n;
n = N;
}
- if(isblank(n))
- n = N;
if(n != N && n->sym == S) {
t = n;
n = N;
@@ -1151,9 +1160,9 @@ addmethod(Sym *sf, Type *t, int local)
}
if(d == T)
- stotype(list1(n), 0, &pa->method);
+ stotype(list1(n), 0, &pa->method, 0);
else
- stotype(list1(n), 0, &d->down);
+ stotype(list1(n), 0, &d->down, 0);
return;
}
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index 09b963f27..014f0c5f0 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -75,10 +75,15 @@ autoexport(Node *n, int ctxt)
static void
dumppkg(Pkg *p)
{
+ char *suffix;
+
if(p == nil || p == localpkg || p->exported)
return;
p->exported = 1;
- Bprint(bout, "\timport %s \"%Z\"\n", p->name, p->path);
+ suffix = "";
+ if(!p->direct)
+ suffix = " // indirect";
+ Bprint(bout, "\timport %s \"%Z\"%s\n", p->name, p->path, suffix);
}
static void
@@ -265,7 +270,8 @@ void
dumpexport(void)
{
NodeList *l;
- int32 lno;
+ int32 i, lno;
+ Pkg *p;
lno = lineno;
@@ -277,6 +283,11 @@ dumpexport(void)
Bprint(bout, " safe");
Bprint(bout, "\n");
+ for(i=0; i<nelem(phash); i++)
+ for(p=phash[i]; p; p=p->link)
+ if(p->direct)
+ dumppkg(p);
+
for(l=exportlist; l; l=l->next) {
lineno = l->n->lineno;
dumpsym(l->n->sym);
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 04af5a7bb..8ad6c437d 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -64,62 +64,83 @@ allocparams(void)
lineno = lno;
}
+void
+clearlabels(void)
+{
+ Label *l;
+
+ for(l=labellist; l!=L; l=l->link)
+ l->sym->label = L;
+
+ labellist = L;
+ lastlabel = L;
+}
+
static void
-newlab(int op, Sym *s, Node *stmt)
+newlab(int op, Node *nlab, Node *stmt)
{
Label *lab;
+ Sym *s;
+ int32 lno;
+
+ s = nlab->left->sym;
+ lno = nlab->left->lineno;
lab = mal(sizeof(*lab));
- lab->link = labellist;
- labellist = 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;
+ }
}
void
checklabels(void)
{
- Label *l, *m;
+ Label *l;
Sym *s;
+ int lno;
-// // print the label list
-// for(l=labellist; l!=L; l=l->link) {
-// print("lab %O %S\n", l->op, l->sym);
-// }
-
+ lno = lineno;
+
+ // resolve goto using syms
for(l=labellist; l!=L; l=l->link) {
- switch(l->op) {
- case OLABEL:
- // these are definitions -
+ switch(l->op) {
+ case OGOTO:
s = l->sym;
- for(m=labellist; m!=L; m=m->link) {
- if(m->sym != s)
- continue;
- switch(m->op) {
- case OLABEL:
- // these are definitions -
- // look for redefinitions
- if(l != m)
- yyerror("label %S redefined", s);
- break;
- case OGOTO:
- // these are references -
- // patch to definition
- patch(m->label, l->label);
- m->sym = S; // mark done
- break;
- }
+ 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;
}
}
-
- // diagnostic for all undefined references
- for(l=labellist; l!=L; l=l->link)
- if(l->op == OGOTO && l->sym != S)
- yyerror("label %S not defined", l->sym);
+
+ // 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);
+ }
+ }
+
+ lineno = lno;
}
/*
@@ -171,7 +192,7 @@ gen(Node *n)
// insert no-op so that
// L:; for { }
// does not treat L as a label for the loop.
- if(labellist && labellist->label == p3)
+ if(lastlabel != L && lastlabel->label == p3)
gused(N);
break;
@@ -180,26 +201,27 @@ gen(Node *n)
break;
case OLABEL:
- newlab(OLABEL, n->left->sym, n->right);
+ newlab(OLABEL, n, n->right);
break;
case OGOTO:
- newlab(OGOTO, n->left->sym, N);
+ newlab(OGOTO, n, N);
gjmp(P);
break;
case OBREAK:
if(n->left != N) {
- for(lab=labellist; lab!=L; lab=lab->link) {
- if(lab->sym == n->left->sym) {
- if(lab->breakpc == P)
- yyerror("invalid break label %S", n->left->sym);
- gjmp(lab->breakpc);
- goto donebreak;
- }
- }
- if(lab == L)
+ lab = n->left->sym->label;
+ if(lab == L) {
yyerror("break label not defined: %S", n->left->sym);
+ break;
+ }
+ lab->used = 1;
+ if(lab->breakpc == P) {
+ yyerror("invalid break label %S", n->left->sym);
+ break;
+ }
+ gjmp(lab->breakpc);
break;
}
if(breakpc == P) {
@@ -207,30 +229,28 @@ gen(Node *n)
break;
}
gjmp(breakpc);
- donebreak:
break;
case OCONTINUE:
if(n->left != N) {
- for(lab=labellist; lab!=L; lab=lab->link) {
- if(lab->sym == n->left->sym) {
- if(lab->continpc == P)
- yyerror("invalid continue label %S", n->left->sym);
- gjmp(lab->continpc);
- goto donecont;
- }
- }
- if(lab == L)
+ lab = n->left->sym->label;
+ if(lab == L) {
yyerror("continue label not defined: %S", n->left->sym);
+ break;
+ }
+ lab->used = 1;
+ if(lab->continpc == P) {
+ yyerror("invalid continue label %S", n->left->sym);
+ break;
+ }
+ gjmp(lab->continpc);
break;
}
-
if(continpc == P) {
yyerror("continue is not in a loop");
break;
}
gjmp(continpc);
- donecont:
break;
case OFOR:
@@ -241,10 +261,11 @@ gen(Node *n)
continpc = pc;
// define break and continue labels
- if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n) {
+ if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n) {
lab->breakpc = breakpc;
lab->continpc = continpc;
- }
+ } else
+ lab = L;
gen(n->nincr); // contin: incr
patch(p1, pc); // test:
@@ -254,6 +275,10 @@ gen(Node *n)
patch(breakpc, pc); // done:
continpc = scontin;
breakpc = sbreak;
+ if(lab) {
+ lab->breakpc = P;
+ lab->continpc = P;
+ }
break;
case OIF:
@@ -274,13 +299,17 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
lab->breakpc = breakpc;
+ else
+ lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // switch(test) body
patch(breakpc, pc); // done:
breakpc = sbreak;
+ if(lab != L)
+ lab->breakpc = P;
break;
case OSELECT:
@@ -289,13 +318,17 @@ gen(Node *n)
breakpc = gjmp(P); // break: goto done
// define break label
- if((lab = labellist) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
+ if((lab = lastlabel) != L && lab->label == p3 && lab->op == OLABEL && lab->stmt == n)
lab->breakpc = breakpc;
+ else
+ lab = L;
patch(p1, pc); // test:
genlist(n->nbody); // select() body
patch(breakpc, pc); // done:
breakpc = sbreak;
+ if(lab != L)
+ lab->breakpc = P;
break;
case OASOP:
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index bf84c12a1..bb258a193 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -138,6 +138,7 @@ typedef struct Sym Sym;
typedef struct Node Node;
typedef struct NodeList NodeList;
typedef struct Type Type;
+typedef struct Label Label;
struct Type
{
@@ -302,11 +303,14 @@ struct Sym
Pkg* pkg;
char* name; // variable name
Node* def; // definition: ONAME OTYPE OPACK or OLITERAL
+ Label* label; // corresponding label (ephemeral)
int32 block; // blocknumber to catch redeclaration
int32 lastlineno; // last declaration for diagnostic
};
#define S ((Sym*)0)
+EXTERN Sym* dclstack;
+
struct Pkg
{
char* name;
@@ -356,12 +360,11 @@ enum
OARRAY,
OARRAYBYTESTR, OARRAYRUNESTR,
OSTRARRAYBYTE, OSTRARRAYRUNE,
- OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECVCLOSED, OAS2MAPR, OAS2DOTTYPE, OASOP,
+ OAS, OAS2, OAS2MAPW, OAS2FUNC, OAS2RECV, OAS2MAPR, OAS2DOTTYPE, OASOP,
OBAD,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OCAP,
OCLOSE,
- OCLOSED,
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
@@ -389,6 +392,7 @@ enum
ORECV,
ORUNESTR,
OSELRECV,
+ OSELRECV2,
OIOTA,
OREAL, OIMAG, OCOMPLEX,
@@ -441,27 +445,28 @@ enum
TCOMPLEX64, // 12
TCOMPLEX128,
- TFLOAT32, // 15
+ TFLOAT32, // 14
TFLOAT64,
- TBOOL, // 18
+ TBOOL, // 16
- TPTR32, TPTR64, // 19
+ TPTR32, TPTR64, // 17
- TFUNC, // 21
+ TFUNC, // 19
TARRAY,
T_old_DARRAY,
- TSTRUCT, // 24
+ TSTRUCT, // 22
TCHAN,
TMAP,
- TINTER, // 27
+ TINTER, // 25
TFORW,
TFIELD,
TANY,
TSTRING,
+ TUNSAFEPTR,
// pseudo-types for literals
- TIDEAL, // 32
+ TIDEAL, // 31
TNIL,
TBLANK,
@@ -618,20 +623,22 @@ struct Magic
typedef struct Prog Prog;
-typedef struct Label Label;
struct Label
{
uchar op; // OGOTO/OLABEL
+ uchar used;
Sym* sym;
Node* stmt;
Prog* label; // 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
@@ -899,6 +906,7 @@ void allocparams(void);
void cgen_as(Node *nl, Node *nr);
void cgen_callmeth(Node *n, int proc);
void checklabels(void);
+void clearlabels(void);
int dotoffset(Node *n, int *oary, Node **nn);
void gen(Node *n);
void genlist(NodeList *l);
@@ -993,8 +1001,10 @@ int duint32(Sym *s, int off, uint32 v);
int duint64(Sym *s, int off, uint64 v);
int duint8(Sym *s, int off, uint8 v);
int duintptr(Sym *s, int off, uint64 v);
+int dsname(Sym *s, int off, char *dat, int ndat);
void dumpobj(void);
void ieeedtod(uint64 *ieee, double native);
+Sym* stringsym(char*, int);
/*
* print.c
@@ -1229,3 +1239,5 @@ void patch(Prog*, 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);
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 4b838a491..89899ae1e 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -461,23 +461,32 @@ case:
}
break;
}
-| LCASE expr '=' expr ':'
+| LCASE expr_or_type_list '=' expr ':'
{
+ Node *n;
+
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
- $$->list = list1(nod(OAS, $2, $4));
+ if($2->next == nil)
+ n = nod(OAS, $2->n, $4);
+ else {
+ n = nod(OAS2, N, N);
+ n->list = $2;
+ n->rlist = list1($4);
+ }
+ $$->list = list1(n);
}
-| LCASE name LCOLAS expr ':'
+| LCASE expr_or_type_list LCOLAS expr ':'
{
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
- $$->list = list1(colas(list1($2), list1($4)));
+ $$->list = list1(colas($2, list1($4)));
}
| LDEFAULT ':'
{
@@ -1230,9 +1239,10 @@ fnlitdcl:
}
fnliteral:
- fnlitdcl '{' stmt_list '}'
+ fnlitdcl lbrace stmt_list '}'
{
$$ = closurebody($3);
+ fixlbrace($2);
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index e79d3b0f8..bfd96274e 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -124,9 +124,6 @@ main(int argc, char *argv[])
runtimepkg = mkpkg(strlit("runtime"));
runtimepkg->name = "runtime";
- stringpkg = mkpkg(strlit("string"));
- stringpkg->name = "string";
-
typepkg = mkpkg(strlit("type"));
typepkg->name = "type";
@@ -1555,7 +1552,6 @@ static struct
"append", LNAME, Txxx, OAPPEND,
"cap", LNAME, Txxx, OCAP,
"close", LNAME, Txxx, OCLOSE,
- "closed", LNAME, Txxx, OCLOSED,
"complex", LNAME, Txxx, OCOMPLEX,
"copy", LNAME, Txxx, OCOPY,
"imag", LNAME, Txxx, OIMAG,
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index fbabe0d43..9f4b7b318 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -235,3 +235,57 @@ duintptr(Sym *s, int off, uint64 v)
{
return duintxx(s, off, v, widthptr);
}
+
+Sym*
+stringsym(char *s, int len)
+{
+ static int gen;
+ Sym *sym;
+ int off, n, m;
+ struct {
+ Strlit lit;
+ char buf[110];
+ } tmp;
+ Pkg *pkg;
+
+ if(len > 100) {
+ // huge strings are made static to avoid long names
+ snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
+ pkg = localpkg;
+ } else {
+ // small strings get named by their contents,
+ // so that multiple modules using the same string
+ // can share it.
+ tmp.lit.len = len;
+ memmove(tmp.lit.s, s, len);
+ tmp.lit.s[len] = '\0';
+ snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp);
+ pkg = gostringpkg;
+ }
+ sym = pkglookup(namebuf, pkg);
+
+ // SymUniq flag indicates that data is generated already
+ if(sym->flags & SymUniq)
+ return sym;
+ sym->flags |= SymUniq;
+
+ data();
+ off = 0;
+
+ // string header
+ off = dsymptr(sym, off, sym, widthptr+4);
+ off = duint32(sym, off, len);
+
+ // string data
+ for(n=0; n<len; n+=m) {
+ m = 8;
+ if(m > len-n)
+ m = len-n;
+ off = dsname(sym, off, s+n, m);
+ }
+ off = duint8(sym, off, 0); // terminating NUL for runtime
+ ggloblsym(sym, off, 1);
+ text();
+
+ return sym;
+}
diff --git a/src/cmd/gc/print.c b/src/cmd/gc/print.c
index 695a5a397..fee37f6d0 100644
--- a/src/cmd/gc/print.c
+++ b/src/cmd/gc/print.c
@@ -52,7 +52,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case OARRAYBYTESTR:
case OCAP:
case OCLOSE:
- case OCLOSED:
case OCOPY:
case OLEN:
case OMAKE:
@@ -405,7 +404,6 @@ exprfmt(Fmt *f, Node *n, int prec)
case OAPPEND:
case OCAP:
case OCLOSE:
- case OCLOSED:
case OLEN:
case OCOPY:
case OMAKE:
diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c
index 4ee8f39a7..dfb2b8efd 100644
--- a/src/cmd/gc/range.c
+++ b/src/cmd/gc/range.c
@@ -203,8 +203,8 @@ walkrange(Node *n)
hb = nod(OXXX, N, N);
tempname(hb, types[TBOOL]);
- n->ntest = nod(ONOT, hb, N);
- a = nod(OAS2RECVCLOSED, N, N);
+ n->ntest = nod(ONE, hb, nodbool(0));
+ a = nod(OAS2RECV, N, N);
a->typecheck = 1;
a->list = list(list1(hv1), hb);
a->rlist = list1(nod(ORECV, ha, N));
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 8129bf1ce..b98e820c6 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -348,17 +348,19 @@ dimportpath(Pkg *p)
* uncommonType
* ../../pkg/runtime/type.go:/uncommonType
*/
-static Sym*
-dextratype(Type *t)
+static int
+dextratype(Sym *sym, int off, Type *t, int ptroff)
{
int ot, n;
- char *p;
Sym *s;
Sig *a, *m;
m = methods(t);
if(t->sym == nil && m == nil)
- return nil;
+ return off;
+
+ // fill in *extraType pointer in header
+ dsymptr(sym, ptroff, sym, off);
n = 0;
for(a=m; a; a=a->link) {
@@ -366,9 +368,8 @@ dextratype(Type *t)
n++;
}
- p = smprint("_.%#T", t);
- s = pkglookup(p, typepkg);
- ot = 0;
+ ot = off;
+ s = sym;
if(t->sym) {
ot = dgostringptr(s, ot, t->sym->name);
if(t != types[t->etype])
@@ -402,9 +403,8 @@ dextratype(Type *t)
else
ot = duintptr(s, ot, 0);
}
- ggloblsym(s, ot, 0);
- return s;
+ return ot;
}
enum {
@@ -466,6 +466,7 @@ kinds[] =
[TFUNC] = KindFunc,
[TCOMPLEX64] = KindComplex64,
[TCOMPLEX128] = KindComplex128,
+ [TUNSAFEPTR] = KindUnsafePointer,
};
static char*
@@ -488,6 +489,7 @@ structnames[] =
[TFLOAT64] = "*runtime.FloatType",
[TBOOL] = "*runtime.BoolType",
[TSTRING] = "*runtime.StringType",
+ [TUNSAFEPTR] = "*runtime.UnsafePointerType",
[TPTR32] = "*runtime.PtrType",
[TPTR64] = "*runtime.PtrType",
@@ -514,9 +516,6 @@ typestruct(Type *t)
if(isslice(t))
name = "*runtime.SliceType";
- if(isptr[et] && t->type->etype == TANY)
- name = "*runtime.UnsafePointerType";
-
return pkglookup(name, typepkg);
}
@@ -553,6 +552,7 @@ haspointers(Type *t)
case TSTRING:
case TPTR32:
case TPTR64:
+ case TUNSAFEPTR:
case TINTER:
case TCHAN:
case TMAP:
@@ -570,7 +570,6 @@ static int
dcommontype(Sym *s, int ot, Type *t)
{
int i;
- Sym *s1;
Sym *sptr;
char *p;
@@ -582,8 +581,6 @@ dcommontype(Sym *s, int ot, Type *t)
else
sptr = weaktypesym(ptrto(t));
- s1 = dextratype(t);
-
// empty interface pointing at this type.
// all the references that we emit are *interface{};
// they point here.
@@ -612,8 +609,6 @@ dcommontype(Sym *s, int ot, Type *t)
i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0)
i = KindSlice;
- if(isptr[t->etype] && t->type->etype == TANY)
- i = KindUnsafePointer;
if(!haspointers(t))
i |= KindNoPointers;
ot = duint8(s, ot, i); // kind
@@ -622,11 +617,14 @@ dcommontype(Sym *s, int ot, Type *t)
longsymnames = 0;
ot = dgostringptr(s, ot, p); // string
free(p);
- if(s1)
- ot = dsymptr(s, ot, s1, 0); // extraType
- else
- ot = duintptr(s, ot, 0);
- ot = dsymptr(s, ot, sptr, 0); // ptr to type
+
+ // skip pointer to extraType,
+ // which follows the rest of this type structure.
+ // caller will fill in if needed.
+ // otherwise linker will assume 0.
+ ot += widthptr;
+
+ ot = dsymptr(s, ot, sptr, 0); // ptrto type
return ot;
}
@@ -693,7 +691,7 @@ weaktypesym(Type *t)
static Sym*
dtypesym(Type *t)
{
- int ot, n, isddd, dupok;
+ int ot, xt, n, isddd, dupok;
Sym *s, *s1, *s2;
Sig *a, *m;
Type *t1, *tbase;
@@ -714,12 +712,8 @@ dtypesym(Type *t)
tbase = t->type;
dupok = tbase->sym == S;
- if(compiling_runtime) {
- if(tbase == types[tbase->etype]) // int, float, etc
- goto ok;
- if(tbase->etype == tptr && tbase->type->etype == TANY) // unsafe.Pointer
- goto ok;
- }
+ if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
+ goto ok;
// named types from other files are defined only by those files
if(tbase->sym && !tbase->local)
@@ -729,15 +723,18 @@ dtypesym(Type *t)
ok:
ot = 0;
+ xt = 0;
switch(t->etype) {
default:
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
break;
case TARRAY:
// ../../pkg/runtime/type.go:/ArrayType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
if(t->bound < 0)
ot = duintptr(s, ot, -1);
@@ -749,6 +746,7 @@ ok:
// ../../pkg/runtime/type.go:/ChanType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
ot = duintptr(s, ot, t->chan);
break;
@@ -765,6 +763,7 @@ ok:
dtypesym(t1->type);
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = duint8(s, ot, isddd);
// two slice headers: in and out.
@@ -796,6 +795,7 @@ ok:
// ../../pkg/runtime/type.go:/InterfaceType
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s, ot+widthptr+2*4);
ot = duint32(s, ot, n);
ot = duint32(s, ot, n);
@@ -812,6 +812,7 @@ ok:
s1 = dtypesym(t->down);
s2 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
ot = dsymptr(s, ot, s2, 0);
break;
@@ -826,6 +827,7 @@ ok:
// ../../pkg/runtime/type.go:/PtrType
s1 = dtypesym(t->type);
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s1, 0);
break;
@@ -838,6 +840,7 @@ ok:
n++;
}
ot = dcommontype(s, ot, t);
+ xt = ot - 2*widthptr;
ot = dsymptr(s, ot, s, ot+widthptr+2*4);
ot = duint32(s, ot, n);
ot = duint32(s, ot, n);
@@ -859,7 +862,7 @@ ok:
}
break;
}
-
+ ot = dextratype(s, ot, t, xt);
ggloblsym(s, ot, dupok);
return s;
}
@@ -908,7 +911,7 @@ dumptypestructs(void)
for(i=1; i<=TBOOL; i++)
dtypesym(ptrto(types[i]));
dtypesym(ptrto(types[TSTRING]));
- dtypesym(ptrto(pkglookup("Pointer", unsafepkg)->def->type));
+ dtypesym(ptrto(types[TUNSAFEPTR]));
// add paths for runtime and main, which 6l imports implicitly.
dimportpath(runtimepkg);
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index bf7d045c0..35d11eca9 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -92,17 +92,19 @@ func mapiter2(hiter *any) (key any, val any)
// *byte is really *runtime.Type
func makechan(elem *byte, hint int64) (hchan chan any)
func chanrecv1(hchan <-chan any) (elem any)
-func chanrecv3(hchan <-chan any) (elem any, closed bool)
+func chanrecv2(hchan <-chan any) (elem any, received bool)
func chansend1(hchan chan<- any, elem any)
func closechan(hchan any)
func closedchan(hchan any) bool
func selectnbsend(hchan chan<- any, elem any) bool
func selectnbrecv(elem *any, hchan <-chan any) bool
+func selectnbrecv2(elem *any, received *bool, hchan <-chan any) bool
func newselect(size int) (sel *byte)
func selectsend(sel *byte, hchan chan<- any, elem any) (selected bool)
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
+func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
func selectdefault(sel *byte) (selected bool)
func selectgo(sel *byte)
func block()
diff --git a/src/cmd/gc/select.c b/src/cmd/gc/select.c
index 58a147745..91d4ebfd5 100644
--- a/src/cmd/gc/select.c
+++ b/src/cmd/gc/select.c
@@ -58,6 +58,18 @@ typecheckselect(Node *sel)
n->op = OSELRECV;
break;
+ case OAS2RECV:
+ // convert x, ok = <-c into OSELRECV(x, <-c) with ntest=ok
+ if(n->right->op != ORECV) {
+ yyerror("select assignment must have receive on right hand side");
+ break;
+ }
+ n->op = OSELRECV2;
+ n->left = n->list->n;
+ n->ntest = n->list->next->n;
+ n->right = n->rlist->n;
+ break;
+
case ORECV:
// convert <-c into OSELRECV(N, <-c)
n = nod(OSELRECV, N, n);
@@ -122,6 +134,18 @@ walkselect(Node *sel)
typecheck(&n, Etop);
}
break;
+
+ case OSELRECV2:
+ r = n->right;
+ ch = cheapexpr(r->left, &l);
+ r->left = ch;
+
+ a = nod(OAS2, N, N);
+ a->list = n->list;
+ a->rlist = n->rlist;
+ n = a;
+ typecheck(&n, Etop);
+ break;
}
// if ch == nil { block() }; n;
@@ -146,6 +170,7 @@ walkselect(Node *sel)
continue;
switch(n->op) {
case OSELRECV:
+ case OSELRECV2:
ch = n->right->left;
// If we can use the address of the target without
@@ -154,6 +179,28 @@ walkselect(Node *sel)
// Also introduce a temporary for := variables that escape,
// so that we can delay the heap allocation until the case
// is selected.
+ if(n->op == OSELRECV2) {
+ if(n->ntest == N || isblank(n->ntest))
+ n->ntest = nodnil();
+ else if(n->ntest->op == ONAME &&
+ (!n->colas || (n->ntest->class&PHEAP) == 0) &&
+ convertop(types[TBOOL], n->ntest->type, nil) == OCONVNOP) {
+ n->ntest = nod(OADDR, n->ntest, N);
+ n->ntest->etype = 1; // pointer does not escape
+ typecheck(&n->ntest, Erv);
+ } else {
+ tmp = nod(OXXX, N, N);
+ tempname(tmp, types[TBOOL]);
+ a = nod(OADDR, tmp, N);
+ a->etype = 1; // pointer does not escape
+ typecheck(&a, Erv);
+ r = nod(OAS, n->ntest, tmp);
+ typecheck(&r, Etop);
+ cas->nbody = concat(list1(r), cas->nbody);
+ n->ntest = a;
+ }
+ }
+
if(n->left == N || isblank(n->left))
n->left = nodnil();
else if(n->left->op == ONAME &&
@@ -171,10 +218,12 @@ walkselect(Node *sel)
r = nod(OAS, n->left, tmp);
typecheck(&r, Etop);
cas->nbody = concat(list1(r), cas->nbody);
- cas->nbody = concat(n->ninit, cas->nbody);
- n->ninit = nil;
n->left = a;
}
+
+ cas->nbody = concat(n->ninit, cas->nbody);
+ n->ninit = nil;
+ break;
}
}
@@ -212,6 +261,16 @@ walkselect(Node *sel)
mkcall1(chanfn("selectnbrecv", 2, ch->type),
types[TBOOL], &r->ninit, n->left, ch));
break;
+
+ case OSELRECV2:
+ // if c != nil && selectnbrecv2(&v, c) { body } else { default body }
+ r = nod(OIF, N, N);
+ r->ninit = cas->ninit;
+ ch = cheapexpr(n->right->left, &r->ninit);
+ r->ntest = nod(OANDAND, nod(ONE, ch, nodnil()),
+ mkcall1(chanfn("selectnbrecv2", 2, ch->type),
+ types[TBOOL], &r->ninit, n->left, n->ntest, ch));
+ break;
}
typecheck(&r->ntest, Erv);
r->nbody = cas->nbody;
@@ -254,11 +313,18 @@ walkselect(Node *sel)
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
&init, var, n->left, n->right);
break;
+
case OSELRECV:
// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
r->ntest = mkcall1(chanfn("selectrecv", 2, n->right->left->type), types[TBOOL],
&init, var, n->right->left, n->left);
break;
+
+ case OSELRECV2:
+ // selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
+ r->ntest = mkcall1(chanfn("selectrecv2", 2, n->right->left->type), types[TBOOL],
+ &init, var, n->right->left, n->left, n->ntest);
+ break;
}
}
r->nbody = concat(r->nbody, cas->nbody);
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 31781646d..be96a1477 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -94,7 +94,7 @@ init1(Node *n, NodeList **out)
case OAS2FUNC:
case OAS2MAPR:
case OAS2DOTTYPE:
- case OAS2RECVCLOSED:
+ case OAS2RECV:
if(n->defn->initorder)
break;
n->defn->initorder = 1;
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 142e5ba41..2098794a7 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -135,6 +135,7 @@ yyerror(char *fmt, ...)
int i;
static int lastsyntax;
va_list arg;
+ char buf[512], *p;
if(strncmp(fmt, "syntax error", 12) == 0) {
nsyntaxerrors++;
@@ -147,6 +148,16 @@ yyerror(char *fmt, ...)
return;
lastsyntax = lexlineno;
+ if(strstr(fmt, "{ or {")) {
+ // The grammar has { and LBRACE but both show up as {.
+ // Rewrite syntax error referring to "{ or {" to say just "{".
+ strecpy(buf, buf+sizeof buf, fmt);
+ p = strstr(buf, "{ or {");
+ if(p)
+ memmove(p+1, p+6, strlen(p+6)+1);
+ fmt = buf;
+ }
+
// look for parse state-specific errors in list (see go.errors).
for(i=0; i<nelem(yymsg); i++) {
if(yymsg[i].yystate == yystate && yymsg[i].yychar == yychar) {
@@ -834,7 +845,6 @@ goopnames[] =
[OCALL] = "function call",
[OCAP] = "cap",
[OCASE] = "case",
- [OCLOSED] = "closed",
[OCLOSE] = "close",
[OCOMPLEX] = "complex",
[OCOM] = "^",
@@ -1144,7 +1154,7 @@ Tpretty(Fmt *fp, Type *t)
&& t->sym != S
&& !(fp->flags&FmtLong)) {
s = t->sym;
- if(t == types[t->etype])
+ if(t == types[t->etype] && t->etype != TUNSAFEPTR)
return fmtprint(fp, "%s", s->name);
if(exporting) {
if(fp->flags & FmtShort)
@@ -1304,6 +1314,11 @@ Tpretty(Fmt *fp, Type *t)
if(t->sym)
return fmtprint(fp, "undefined %S", t->sym);
return fmtprint(fp, "undefined");
+
+ case TUNSAFEPTR:
+ if(exporting)
+ return fmtprint(fp, "\"unsafe\".Pointer");
+ return fmtprint(fp, "unsafe.Pointer");
}
// Don't know how to handle - fall back to detailed prints.
@@ -1346,6 +1361,9 @@ Tconv(Fmt *fp)
}
}
+ if(sharp || exporting)
+ fatal("missing %E case during export", t->etype);
+
et = t->etype;
fmtprint(fp, "%E ", et);
if(t->sym != S)
@@ -1663,6 +1681,9 @@ isselect(Node *n)
s = pkglookup("selectrecv", runtimepkg);
if(s == n->sym)
return 1;
+ s = pkglookup("selectrecv2", runtimepkg);
+ if(s == n->sym)
+ return 1;
s = pkglookup("selectdefault", runtimepkg);
if(s == n->sym)
return 1;
@@ -1864,7 +1885,7 @@ assignop(Type *src, Type *dst, char **why)
if(why != nil)
*why = "";
- if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) {
+ if(safemode && src != T && src->etype == TUNSAFEPTR) {
yyerror("cannot use unsafe.Pointer");
errorexit();
}
@@ -1879,8 +1900,9 @@ assignop(Type *src, Type *dst, char **why)
return OCONVNOP;
// 2. src and dst have identical underlying types
- // and either src or dst is not a named type.
- if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S))
+ // and either src or dst is not a named type or
+ // both are interface types.
+ if(eqtype(src->orig, dst->orig) && (src->sym == S || dst->sym == S || src->etype == TINTER))
return OCONVNOP;
// 3. dst is an interface type and src implements dst.
@@ -2028,11 +2050,11 @@ convertop(Type *src, Type *dst, char **why)
}
// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
- if((isptr[src->etype] || src->etype == TUINTPTR) && isptrto(dst, TANY))
+ if((isptr[src->etype] || src->etype == TUINTPTR) && dst->etype == TUNSAFEPTR)
return OCONVNOP;
// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
- if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR))
+ if(src->etype == TUNSAFEPTR && (isptr[dst->etype] || dst->etype == TUINTPTR))
return OCONVNOP;
return 0;
@@ -2043,13 +2065,16 @@ Node*
assignconv(Node *n, Type *t, char *context)
{
int op;
- Node *r;
+ Node *r, *old;
char *why;
if(n == N || n->type == T)
return n;
+ old = n;
+ old->diag++; // silence errors about n; we'll issue one below
defaultlit(&n, t);
+ old->diag--;
if(t->etype == TBLANK)
return n;
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 3e8f35877..1cc5abd5c 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -318,7 +318,7 @@ reswitch:
n->left = N;
goto ret;
}
- if(!isptr[t->etype] || (t->type != T && t->type->etype == TANY) /* unsafe.Pointer */) {
+ if(!isptr[t->etype]) {
yyerror("invalid indirect of %+N", n->left);
goto error;
}
@@ -921,7 +921,6 @@ reswitch:
n->type = t;
goto ret;
- case OCLOSED:
case OCLOSE:
if(onearg(n, "%#O", n->op) < 0)
goto error;
@@ -934,11 +933,7 @@ reswitch:
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error;
}
- if(n->op == OCLOSED) {
- n->type = types[TBOOL];
- ok |= Erv;
- } else
- ok |= Etop;
+ ok |= Etop;
goto ret;
case OAPPEND:
@@ -1316,7 +1311,7 @@ ret:
// TODO(rsc): should not need to check importpkg,
// but reflect mentions unsafe.Pointer.
- if(safemode && !incannedimport && !importpkg && isptrto(t, TANY))
+ if(safemode && !incannedimport && !importpkg && t && t->etype == TUNSAFEPTR)
yyerror("cannot use unsafe.Pointer");
evconst(n);
@@ -1639,11 +1634,6 @@ typecheckaste(int op, Node *call, int isddd, Type *tstruct, NodeList *nl, char *
for(tl=tstruct->type; tl; tl=tl->down) {
t = tl->type;
if(tl->isddd) {
- if(nl != nil && nl->n->op == ONAME && nl->n->isddd && !isddd) {
- // TODO(rsc): This is not actually illegal, but it will help catch bugs.
- yyerror("to pass '%#N' as ...%T, use '%#N...'", nl->n, t->type, nl->n);
- isddd = 1;
- }
if(isddd) {
if(nl == nil)
goto notenough;
@@ -2377,8 +2367,9 @@ typecheckas2(Node *n)
n->op = OAS2MAPR;
goto common;
case ORECV:
- yyerror("cannot use multiple-value assignment for non-blocking receive; use select");
- goto out;
+ n->op = OAS2RECV;
+ n->right = n->rlist->n;
+ goto common;
case ODOTTYPE:
n->op = OAS2DOTTYPE;
r->op = ODOTTYPE2;
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
index bd7b7771a..b2a341d39 100644
--- a/src/cmd/gc/unsafe.go
+++ b/src/cmd/gc/unsafe.go
@@ -8,7 +8,7 @@
package PACKAGE
-type Pointer *any
+type Pointer uintptr // not really; filled in by compiler
func Offsetof(any) int
func Sizeof(any) int
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b32b6fff5..b8c6842e0 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -403,12 +403,11 @@ walkstmt(Node **np)
case OAS:
case OAS2:
case OAS2DOTTYPE:
- case OAS2RECVCLOSED:
+ case OAS2RECV:
case OAS2FUNC:
case OAS2MAPW:
case OAS2MAPR:
case OCLOSE:
- case OCLOSED:
case OCOPY:
case OCALLMETH:
case OCALLINTER:
@@ -822,14 +821,13 @@ walkexpr(Node **np, NodeList **init)
n = liststmt(concat(concat(list1(r), ll), lpost));
goto ret;
- case OAS2RECVCLOSED:
- // a = <-c; b = closed(c) but atomic
+ case OAS2RECV:
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
- fn = chanfn("chanrecv3", 2, r->left->type);
+ fn = chanfn("chanrecv2", 2, r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, r->left);
n->rlist->n = r;
n->op = OAS2FUNC;
@@ -1309,13 +1307,6 @@ walkexpr(Node **np, NodeList **init)
n = mkcall1(fn, T, init, n->left);
goto ret;
- case OCLOSED:
- // cannot use chanfn - closechan takes any, not chan any
- fn = syslook("closedchan", 1);
- argtype(fn, n->left->type);
- n = mkcall1(fn, n->type, init, n->left);
- goto ret;
-
case OMAKECHAN:
n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
typename(n->type->type),