}
}
-/* deferred DATA output */
-static Prog *strdat;
-static Prog *estrdat;
-static int gflag;
-static Prog *savepc;
-
-void
-data(void)
-{
- gflag = debug['g'];
- debug['g'] = 0;
-
- if(estrdat == nil) {
- strdat = mal(sizeof(*pc));
- clearp(strdat);
- estrdat = strdat;
- }
- if(savepc)
- fatal("data phase error");
- savepc = pc;
- pc = estrdat;
-}
-
-void
-text(void)
-{
- if(!savepc)
- fatal("text phase error");
- debug['g'] = gflag;
- estrdat = pc;
- pc = savepc;
- savepc = nil;
-}
-
-void
-dumpdata(void)
-{
- Prog *p;
-
- if(estrdat == nil)
- return;
- *pc = *strdat;
- if(gflag)
- for(p=pc; p!=estrdat; p=p->link)
- print("%P\n", p);
- pc = estrdat;
-}
-
int
dsname(Sym *sym, int off, char *t, int n)
{
Prog *p;
vlong v;
+ if(nr->op == OLITERAL) {
+ switch(nr->val.ctype) {
+ case CTCPLX:
+ gdatacomplex(nam, nr->val.u.cval);
+ return;
+ case CTSTR:
+ gdatastring(nam, nr->val.u.sval);
+ return;
+ }
+ }
+
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
pcloc++;
}
+static int ddumped;
+static Prog *dfirst;
+static Prog *dpc;
+
/*
* generate and return proc with p->as = as,
* linked into program. pc is next instruction.
{
Prog *p;
- p = pc;
- pc = mal(sizeof(*pc));
-
- clearp(pc);
+ if(as == ADATA || as == AGLOBL) {
+ if(ddumped)
+ fatal("already dumped data");
+ if(dpc == nil) {
+ dpc = mal(sizeof(*dpc));
+ dfirst = dpc;
+ }
+ p = dpc;
+ dpc = mal(sizeof(*dpc));
+ p->link = dpc;
+ } else {
+ p = pc;
+ pc = mal(sizeof(*pc));
+ clearp(pc);
+ p->link = pc;
+ }
if(lineno == 0) {
if(debug['K'])
p->as = as;
p->lineno = lineno;
- p->link = pc;
return p;
}
+void
+dumpdata(void)
+{
+ ddumped = 1;
+ if(dfirst == nil)
+ return;
+ newplist();
+ *pc = *dfirst;
+ pc = dpc;
+ clearp(pc);
+}
+
/*
* generate a branch.
* t is ignored.
}
}
-/* deferred DATA output */
-static Prog *strdat;
-static Prog *estrdat;
-static int gflag;
-static Prog *savepc;
-
-void
-data(void)
-{
- gflag = debug['g'];
- debug['g'] = 0;
-
- if(estrdat == nil) {
- strdat = mal(sizeof(*pc));
- clearp(strdat);
- estrdat = strdat;
- }
- if(savepc)
- fatal("data phase error");
- savepc = pc;
- pc = estrdat;
-}
-
-void
-text(void)
-{
- if(!savepc)
- fatal("text phase error");
- debug['g'] = gflag;
- estrdat = pc;
- pc = savepc;
- savepc = nil;
-}
-
-void
-dumpdata(void)
-{
- Prog *p;
-
- if(estrdat == nil)
- return;
- *pc = *strdat;
- if(gflag)
- for(p=pc; p!=estrdat; p=p->link)
- print("%P\n", p);
- pc = estrdat;
-}
-
int
dsname(Sym *s, int off, char *t, int n)
{
{
Prog *p;
+ if(nr->op == OLITERAL) {
+ switch(nr->val.ctype) {
+ case CTCPLX:
+ gdatacomplex(nam, nr->val.u.cval);
+ return;
+ case CTSTR:
+ gdatastring(nam, nr->val.u.sval);
+ return;
+ }
+ }
p = gins(ADATA, nam, nr);
p->from.scale = wid;
}
pcloc++;
}
+static int ddumped;
+static Prog *dfirst;
+static Prog *dpc;
+
/*
* generate and return proc with p->as = as,
* linked into program. pc is next instruction.
{
Prog *p;
- p = pc;
- pc = mal(sizeof(*pc));
-
- clearp(pc);
+ if(as == ADATA || as == AGLOBL) {
+ if(ddumped)
+ fatal("already dumped data");
+ if(dpc == nil) {
+ dpc = mal(sizeof(*dpc));
+ dfirst = dpc;
+ }
+ p = dpc;
+ dpc = mal(sizeof(*dpc));
+ p->link = dpc;
+ } else {
+ p = pc;
+ pc = mal(sizeof(*pc));
+ clearp(pc);
+ p->link = pc;
+ }
if(lineno == 0) {
if(debug['K'])
p->as = as;
p->lineno = lineno;
- p->link = pc;
return p;
}
+void
+dumpdata(void)
+{
+ ddumped = 1;
+ if(dfirst == nil)
+ return;
+ newplist();
+ *pc = *dfirst;
+ pc = dpc;
+ clearp(pc);
+}
+
/*
* generate a branch.
* t is ignored.
void complexgen(Node*, Node*);
void complexbool(int, Node*, Node*, int, Prog*);
-/*
- * gobj.c
- */
-void data(void);
-void text(void);
-
/*
* list.c
*/
}
}
-/* deferred DATA output */
-static Prog *strdat;
-static Prog *estrdat;
-static int gflag;
-static Prog *savepc;
-
-void
-data(void)
-{
- gflag = debug['g'];
- debug['g'] = 0;
-
- if(estrdat == nil) {
- strdat = mal(sizeof(*pc));
- clearp(strdat);
- estrdat = strdat;
- }
- if(savepc)
- fatal("data phase error");
- savepc = pc;
- pc = estrdat;
-}
-
-void
-text(void)
-{
- if(!savepc)
- fatal("text phase error");
- debug['g'] = gflag;
- estrdat = pc;
- pc = savepc;
- savepc = nil;
-}
-
-void
-dumpdata(void)
-{
- Prog *p;
-
- if(estrdat == nil)
- return;
- *pc = *strdat;
- if(gflag)
- for(p=pc; p!=estrdat; p=p->link)
- print("%P\n", p);
- pc = estrdat;
-}
-
int
dsname(Sym *s, int off, char *t, int n)
{
Prog *p;
vlong v;
+ if(nr->op == OLITERAL) {
+ switch(nr->val.ctype) {
+ case CTCPLX:
+ gdatacomplex(nam, nr->val.u.cval);
+ return;
+ case CTSTR:
+ gdatastring(nam, nr->val.u.sval);
+ return;
+ }
+ }
+
if(wid == 8 && is64(nr->type)) {
v = mpgetfix(nr->val.u.xval);
p = gins(ADATA, nam, nodintconst(v));
pcloc++;
}
+static int ddumped;
+static Prog *dfirst;
+static Prog *dpc;
+
/*
* generate and return proc with p->as = as,
* linked into program. pc is next instruction.
{
Prog *p;
- p = pc;
- pc = mal(sizeof(*pc));
-
- clearp(pc);
+ if(as == ADATA || as == AGLOBL) {
+ if(ddumped)
+ fatal("already dumped data");
+ if(dpc == nil) {
+ dpc = mal(sizeof(*dpc));
+ dfirst = dpc;
+ }
+ p = dpc;
+ dpc = mal(sizeof(*dpc));
+ p->link = dpc;
+ } else {
+ p = pc;
+ pc = mal(sizeof(*pc));
+ clearp(pc);
+ p->link = pc;
+ }
if(lineno == 0) {
if(debug['K'])
p->as = as;
p->lineno = lineno;
- p->link = pc;
return p;
}
+void
+dumpdata(void)
+{
+ ddumped = 1;
+ if(dfirst == nil)
+ return;
+ newplist();
+ *pc = *dfirst;
+ pc = dpc;
+ clearp(pc);
+}
+
/*
* generate a branch.
* t is ignored.
int
smallintconst(Node *n)
{
- if(n->op == OLITERAL && n->type != T)
+ if(n->op == OLITERAL && n->val.ctype == CTINT && n->type != T)
switch(simtype[n->type->etype]) {
case TINT8:
case TUINT8:
case TBOOL:
case TPTR32:
return 1;
+ case TIDEAL:
case TINT64:
case TUINT64:
if(mpcmpfixfix(n->val.u.xval, minintval[TINT32]) < 0
};
#define T ((Type*)0)
+typedef struct InitEntry InitEntry;
+typedef struct InitPlan InitPlan;
+
+struct InitEntry
+{
+ vlong xoffset; // struct, array only
+ Node *key; // map only
+ Node *expr;
+};
+
+struct InitPlan
+{
+ vlong lit; // bytes of initialized non-zero literals
+ vlong zero; // bytes of zeros
+ vlong expr; // bytes of run-time computed expressions
+
+ InitEntry *e;
+ int len;
+ int cap;
+};
+
enum
{
EscUnknown,
uchar walkdef;
uchar typecheck;
uchar local;
+ uchar dodata;
uchar initorder;
- uchar dodata; // compile literal assignment as data statement
uchar used;
uchar isddd;
uchar pun; // don't registerize variable ONAME
// OPACK
Pkg* pkg;
+
+ // OARRAYLIT, OMAPLIT, OSTRUCTLIT.
+ InitPlan* initplan;
// Escape analysis.
NodeList* escflowsrc; // flow(this, src)
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);
#pragma varargck type "A" int
#pragma varargck type "B" Mpint*
outhist(bout);
- // add nil plist w AEND to catch
- // auto-generated trampolines, data
- newplist();
-
dumpglobls();
dumptypestructs();
dumpdata();
if(sym->flags & SymUniq)
return sym;
sym->flags |= SymUniq;
-
- data();
+
off = 0;
// string header
off = duint8(sym, off, 0); // terminating NUL for runtime
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
ggloblsym(sym, off, 1);
- text();
-
+
return sym;
}
Type *f, *mt, *it, *this;
Sig *a, *b;
Sym *method;
- Prog *oldlist;
// named method type
mt = methtype(t);
// make list of methods for t,
// generating code if necessary.
a = nil;
- oldlist = nil;
for(f=mt->xmethod; f; f=f->down) {
if(f->type->etype != TFUNC)
continue;
if(!(a->isym->flags & SymSiggen)) {
a->isym->flags |= SymSiggen;
if(!eqtype(this, it) || this->width < types[tptr]->width) {
- if(oldlist == nil)
- oldlist = pc;
// Is okay to call genwrapper here always,
// but we can generate more efficient code
// using genembedtramp if all that is necessary
if(!(a->tsym->flags & SymSiggen)) {
a->tsym->flags |= SymSiggen;
if(!eqtype(this, t)) {
- if(oldlist == nil)
- oldlist = pc;
if(isptr[t->etype] && isptr[this->etype]
&& f->embedded && !isifacemethod(f->type))
genembedtramp(t, f, a->tsym, 0);
}
}
- // restore data output
- if(oldlist) {
- // old list ended with AEND; change to ANOP
- // so that the trampolines that follow can be found.
- nopout(oldlist);
-
- // start new data list
- newplist();
- }
-
return lsort(a, sigcmp);
}
Sig *a, *all, *last;
Type *f;
Sym *method, *isym;
- Prog *oldlist;
all = nil;
last = nil;
- oldlist = nil;
for(f=t->type; f; f=f->down) {
if(f->etype != TFIELD)
fatal("imethods: not field");
isym = methodsym(method, t, 0);
if(!(isym->flags & SymSiggen)) {
isym->flags |= SymSiggen;
- if(oldlist == nil)
- oldlist = pc;
genwrapper(t, f, isym, 0);
}
}
-
- if(oldlist) {
- // old list ended with AEND; change to ANOP
- // so that the trampolines that follow can be found.
- nopout(oldlist);
-
- // start new data list
- newplist();
- }
-
return all;
}
#include <libc.h>
#include "go.h"
+enum
+{
+ InitNotStarted = 0,
+ InitDone = 1,
+ InitPending = 2,
+};
+
+static int iszero(Node*);
+static void initplan(Node*);
static NodeList *initlist;
static void init2(Node*, NodeList**);
static void init2list(NodeList*, NodeList**);
+static int staticinit(Node*, NodeList**);
+static Node *staticname(Type*, int);
static void
init1(Node *n, NodeList **out)
case PFUNC:
break;
default:
- if(isblank(n) && n->defn != N && !n->defn->initorder) {
- n->defn->initorder = 1;
+ if(isblank(n) && n->defn != N && n->defn->initorder == InitNotStarted) {
+ n->defn->initorder = InitDone;
*out = list(*out, n->defn);
}
return;
}
- if(n->initorder == 1)
+ if(n->initorder == InitDone)
return;
- if(n->initorder == 2) {
+ if(n->initorder == InitPending) {
if(n->class == PFUNC)
return;
print("\t%L %S\n", n->lineno, n->sym);
errorexit();
}
- n->initorder = 2;
+ n->initorder = InitPending;
l = malloc(sizeof *l);
l->next = initlist;
l->n = n;
case OAS:
if(n->defn->left != n)
goto bad;
+ /*
n->defn->dodata = 1;
init1(n->defn->right, out);
if(debug['j'])
print("%S\n", n->sym);
*out = list(*out, n->defn);
break;
+ */
+ if(1) {
+ init1(n->defn->right, out);
+ if(debug['j'])
+ print("%S\n", n->sym);
+ if(!staticinit(n, out)) {
+if(debug['%']) dump("nonstatic", n->defn);
+ *out = list(*out, n->defn);
+ }
+ } else if(0) {
+ n->defn->dodata = 1;
+ init1(n->defn->right, out);
+ if(debug['j'])
+ print("%S\n", n->sym);
+ *out = list(*out, n->defn);
+ }
+ break;
case OAS2FUNC:
case OAS2MAPR:
case OAS2DOTTYPE:
case OAS2RECV:
- if(n->defn->initorder)
+ if(n->defn->initorder != InitNotStarted)
break;
- n->defn->initorder = 1;
+ n->defn->initorder = InitDone;
for(l=n->defn->rlist; l; l=l->next)
init1(l->n, out);
*out = list(*out, n->defn);
if(l->n != n)
fatal("bad initlist");
free(l);
- n->initorder = 1;
+ n->initorder = InitDone;
return;
bad:
static void
init2(Node *n, NodeList **out)
{
- if(n == N || n->initorder == 1)
+ if(n == N || n->initorder == InitDone)
return;
init1(n, out);
init2(n->left, out);
init2(l->n, out);
}
-
static void
initreorder(NodeList *l, NodeList **out)
{
initfix(NodeList *l)
{
NodeList *lout;
+ int lno;
lout = nil;
+ lno = lineno;
initreorder(l, &lout);
+ lineno = lno;
return lout;
}
+/*
+ * compilation of top-level (static) assignments
+ * into DATA statements if at all possible.
+ */
+
+static int staticassign(Node*, Node*, NodeList**);
+
+static int
+staticinit(Node *n, NodeList **out)
+{
+ Node *l, *r;
+
+ if(n->op != ONAME || n->class != PEXTERN || n->defn == N || n->defn->op != OAS)
+ fatal("staticinit");
+
+ lineno = n->lineno;
+ l = n->defn->left;
+ r = n->defn->right;
+ return staticassign(l, r, out);
+}
+
+// like staticassign but we are copying an already
+// initialized value r.
+static int
+staticcopy(Node *l, Node *r, NodeList **out)
+{
+ int i;
+ InitEntry *e;
+ InitPlan *p;
+ Node *a, *ll, *rr, *orig, n1;
+
+ if(r->op != ONAME || r->class != PEXTERN || r->sym->pkg != localpkg)
+ return 0;
+ if(r->defn == N) // zeroed
+ return 1;
+ if(r->defn->op != OAS)
+ return 0;
+ orig = r;
+ r = r->defn->right;
+
+ switch(r->op) {
+ case ONAME:
+ if(staticcopy(l, r, out))
+ return 1;
+ *out = list(*out, nod(OAS, l, r));
+ return 1;
+
+ case OLITERAL:
+ if(iszero(r))
+ return 1;
+ gdata(l, r, l->type->width);
+ return 1;
+
+ case OADDR:
+ switch(r->left->op) {
+ case ONAME:
+ gdata(l, r, l->type->width);
+ return 1;
+ case OARRAYLIT:
+ case OSTRUCTLIT:
+ case OMAPLIT:
+ // copy pointer
+ gdata(l, nod(OADDR, r->nname, N), l->type->width);
+ return 1;
+ }
+ break;
+
+ case OARRAYLIT:
+ if(isslice(r->type)) {
+ // copy slice
+ a = r->nname;
+ n1 = *l;
+ n1.xoffset = l->xoffset + Array_array;
+ gdata(&n1, nod(OADDR, a, N), widthptr);
+ n1.xoffset = l->xoffset + Array_nel;
+ gdata(&n1, r->right, 4);
+ n1.xoffset = l->xoffset + Array_cap;
+ gdata(&n1, r->right, 4);
+ return 1;
+ }
+ // fall through
+ case OSTRUCTLIT:
+ p = r->initplan;
+ n1 = *l;
+ for(i=0; i<p->len; i++) {
+ e = &p->e[i];
+ n1.xoffset = l->xoffset + e->xoffset;
+ n1.type = e->expr->type;
+ if(e->expr->op == OLITERAL)
+ gdata(&n1, e->expr, n1.type->width);
+ else if(staticassign(&n1, e->expr, out)) {
+ // Done
+ } else {
+ // Requires computation, but we're
+ // copying someone else's computation.
+ ll = nod(OXXX, N, N);
+ *ll = n1;
+ rr = nod(OXXX, N, N);
+ *rr = *orig;
+ rr->type = ll->type;
+ rr->xoffset += e->xoffset;
+ *out = list(*out, nod(OAS, ll, rr));
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static int
+staticassign(Node *l, Node *r, NodeList **out)
+{
+ Node *a, n1;
+ Type *ta;
+ InitPlan *p;
+ InitEntry *e;
+ int i;
+
+ switch(r->op) {
+ default:
+ //dump("not static", r);
+ break;
+
+ case ONAME:
+ if(r->class == PEXTERN && r->sym->pkg == localpkg)
+ return staticcopy(l, r, out);
+ break;
+
+ case OLITERAL:
+ if(iszero(r))
+ return 1;
+ gdata(l, r, l->type->width);
+ return 1;
+
+ case OADDR:
+ switch(r->left->op) {
+ default:
+ //dump("not static addr", r);
+ break;
+
+ case ONAME:
+ gdata(l, r, l->type->width);
+ return 1;
+
+ case OARRAYLIT:
+ case OMAPLIT:
+ case OSTRUCTLIT:
+ // Init pointer.
+ a = staticname(r->left->type, 1);
+ r->nname = a;
+ gdata(l, nod(OADDR, a, N), l->type->width);
+ // Init underlying literal.
+ if(!staticassign(a, r->left, out))
+ *out = list(*out, nod(OAS, a, r->left));
+ return 1;
+ }
+ break;
+
+ case OARRAYLIT:
+ initplan(r);
+ if(isslice(r->type)) {
+ // Init slice.
+ ta = typ(TARRAY);
+ ta->type = r->type->type;
+ ta->bound = mpgetfix(r->right->val.u.xval);
+ a = staticname(ta, 1);
+ r->nname = a;
+ n1 = *l;
+ n1.xoffset = l->xoffset + Array_array;
+ gdata(&n1, nod(OADDR, a, N), widthptr);
+ n1.xoffset = l->xoffset + Array_nel;
+ gdata(&n1, r->right, 4);
+ n1.xoffset = l->xoffset + Array_cap;
+ gdata(&n1, r->right, 4);
+ // Fall through to init underlying array.
+ l = a;
+ }
+ // fall through
+ case OSTRUCTLIT:
+ initplan(r);
+ p = r->initplan;
+ n1 = *l;
+ for(i=0; i<p->len; i++) {
+ e = &p->e[i];
+ n1.xoffset = l->xoffset + e->xoffset;
+ n1.type = e->expr->type;
+ if(e->expr->op == OLITERAL)
+ gdata(&n1, e->expr, n1.type->width);
+ else if(staticassign(&n1, e->expr, out)) {
+ // done
+ } else {
+ a = nod(OXXX, N, N);
+ *a = n1;
+ *out = list(*out, nod(OAS, a, e->expr));
+ }
+ }
+ return 1;
+
+ case OMAPLIT:
+ // TODO: Table-driven map insert.
+ break;
+ }
+ return 0;
+}
+
/*
* from here down is the walk analysis
* of composite literals.
case TPTR64:
case TFLOAT32:
case TFLOAT64:
- gused(N); // in case the data is the dest of a goto
gdata(&nam, nr, nr->type->width);
break;
case TCOMPLEX64:
case TCOMPLEX128:
- gused(N); // in case the data is the dest of a goto
gdatacomplex(&nam, nr->val.u.cval);
break;
case TSTRING:
- gused(N); // in case the data is the dest of a goto
gdatastring(&nam, nr->val.u.sval);
break;
}
return 0;
}
+static int iszero(Node*);
+static int isvaluelit(Node*);
+static InitEntry* entry(InitPlan*);
+static void addvalue(InitPlan*, vlong, Node*, Node*);
+
+static void
+initplan(Node *n)
+{
+ InitPlan *p;
+ Node *a;
+ NodeList *l;
+
+ if(n->initplan != nil)
+ return;
+ p = mal(sizeof *p);
+ n->initplan = p;
+ switch(n->op) {
+ default:
+ fatal("initplan");
+ case OARRAYLIT:
+ for(l=n->list; l; l=l->next) {
+ a = l->n;
+ if(a->op != OKEY || !smallintconst(a->left))
+ fatal("initplan arraylit");
+ addvalue(p, n->type->type->width*mpgetfix(a->left->val.u.xval), N, a->right);
+ }
+ break;
+ case OSTRUCTLIT:
+ for(l=n->list; l; l=l->next) {
+ a = l->n;
+ if(a->op != OKEY || a->left->type == T)
+ fatal("initplan structlit");
+ addvalue(p, a->left->type->width, N, a->right);
+ }
+ break;
+ case OMAPLIT:
+ for(l=n->list; l; l=l->next) {
+ a = l->n;
+ if(a->op != OKEY)
+ fatal("initplan maplit");
+ addvalue(p, -1, a->left, a->right);
+ }
+ break;
+ }
+}
+
+static void
+addvalue(InitPlan *p, vlong xoffset, Node *key, Node *n)
+{
+ int i;
+ InitPlan *q;
+ InitEntry *e;
+
+ // special case: zero can be dropped entirely
+ if(iszero(n)) {
+ p->zero += n->type->width;
+ return;
+ }
+
+ // special case: inline struct and array (not slice) literals
+ if(isvaluelit(n)) {
+ initplan(n);
+ q = n->initplan;
+ for(i=0; i<q->len; i++) {
+ e = entry(p);
+ *e = q->e[i];
+ e->xoffset += xoffset;
+ }
+ return;
+ }
+
+ // add to plan
+ if(n->op == OLITERAL)
+ p->lit += n->type->width;
+ else
+ p->expr += n->type->width;
+
+ e = entry(p);
+ e->xoffset = xoffset;
+ e->expr = n;
+}
+
+static int
+iszero(Node *n)
+{
+ NodeList *l;
+
+ switch(n->op) {
+ case OLITERAL:
+ switch(n->val.ctype) {
+ default:
+ dump("unexpected literal", n);
+ fatal("iszero");
+
+ case CTNIL:
+ return 1;
+
+ case CTSTR:
+ return n->val.u.sval == nil || n->val.u.sval->len == 0;
+
+ case CTBOOL:
+ return n->val.u.bval == 0;
+
+ case CTINT:
+ return mpcmpfixc(n->val.u.xval, 0) == 0;
+
+ case CTFLT:
+ return mpcmpfltc(n->val.u.fval, 0) == 0;
+
+ case CTCPLX:
+ return mpcmpfltc(&n->val.u.cval->real, 0) == 0 && mpcmpfltc(&n->val.u.cval->imag, 0) == 0;
+ }
+ break;
+ case OARRAYLIT:
+ if(isslice(n->type))
+ break;
+ // fall through
+ case OSTRUCTLIT:
+ for(l=n->list; l; l=l->next)
+ if(!iszero(l->n->right))
+ return 0;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+isvaluelit(Node *n)
+{
+ return (n->op == OARRAYLIT && isfixedarray(n->type)) || n->op == OSTRUCTLIT;
+}
+
+static InitEntry*
+entry(InitPlan *p)
+{
+ if(p->len >= p->cap) {
+ if(p->cap == 0)
+ p->cap = 4;
+ else
+ p->cap *= 2;
+ p->e = realloc(p->e, p->cap*sizeof p->e[0]);
+ if(p->e == nil)
+ fatal("out of memory");
+ }
+ return &p->e[p->len++];
+}
}
if(n->typecheck == 2) {
- yyerror("typechecking loop");
+ yyerror("typechecking loop involving %#N", n);
lineno = lno;
return n;
}
yyerror("implicit assignment of unexported field '%s' in %T literal", s->name, t);
ll->n = assignconv(ll->n, f->type, "field value");
ll->n = nod(OKEY, newname(f->sym), ll->n);
+ ll->n->left->type = f;
ll->n->left->typecheck = 1;
f = f->down;
}
// before we do the lookup.
if(s->pkg != localpkg)
s = lookup(s->name);
- l->left = newname(s);
- l->left->typecheck = 1;
f = lookdot1(s, t, t->type, 0);
typecheck(&l->right, Erv);
if(f == nil) {
yyerror("unknown %T field '%s' in struct literal", t, s->name);
continue;
}
+ l->left = newname(s);
+ l->left->typecheck = 1;
+ l->left->type = f;
s = f->sym;
fielddup(newname(s), hash, nhash);
l->right = assignconv(l->right, f->type, "field value");
=========== ./sigchld.go
survived SIGCHLD
-=========== ./sinit.go
-FAIL
-
=========== ./turing.go
Hello World!
-// $G -S $D/$F.go | egrep initdone >/dev/null && echo FAIL || true
+// $G -S $D/$F.go | egrep initdone >/dev/null && echo BUG sinit || true
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// Should be no init func in the assembly.
// All these initializations should be done at link time.
-type S struct{ a,b,c int }
-type SS struct{ aa,bb,cc S }
-type SA struct{ a,b,c [3]int }
-type SC struct{ a,b,c []int }
+type S struct{ a, b, c int }
+type SS struct{ aa, bb, cc S }
+type SA struct{ a, b, c [3]int }
+type SC struct{ a, b, c []int }
var (
- zero = 2
- one = 1
- pi = 3.14
- slice = []byte{1,2,3}
- sliceInt = []int{1,2,3}
- hello = "hello, world"
- bytes = []byte("hello, world")
- four, five = 4, 5
- x, y = 0.1, "hello"
- nilslice []byte = nil
- nilmap map[string]int = nil
- nilfunc func() = nil
- nilchan chan int = nil
- nilptr *byte = nil
+ zero = 2
+ one = 1
+ pi = 3.14
+ slice = []byte{1, 2, 3}
+ sliceInt = []int{1, 2, 3}
+ hello = "hello, world"
+ bytes = []byte("hello, world")
+ four, five = 4, 5
+ x, y = 0.1, "hello"
+ nilslice []byte = nil
+ nilmap map[string]int = nil
+ nilfunc func() = nil
+ nilchan chan int = nil
+ nilptr *byte = nil
)
-var a = [3]int{1001, 1002, 1003}
-var s = S{1101, 1102, 1103}
-var c = []int{1201, 1202, 1203}
+var a = [3]int{1001, 1002, 1003}
+var s = S{1101, 1102, 1103}
+var c = []int{1201, 1202, 1203}
-var aa = [3][3]int{[3]int{2001,2002,2003}, [3]int{2004,2005,2006}, [3]int{2007,2008,2009}}
-var as = [3]S{S{2101,2102,2103},S{2104,2105,2106},S{2107,2108,2109}}
-var ac = [3][]int{[]int{2201,2202,2203}, []int{2204,2205,2206}, []int{2207,2208,2209}}
+var aa = [3][3]int{[3]int{2001, 2002, 2003}, [3]int{2004, 2005, 2006}, [3]int{2007, 2008, 2009}}
+var as = [3]S{S{2101, 2102, 2103}, S{2104, 2105, 2106}, S{2107, 2108, 2109}}
+var ac = [3][]int{[]int{2201, 2202, 2203}, []int{2204, 2205, 2206}, []int{2207, 2208, 2209}}
-var sa = SA{[3]int{3001,3002,3003},[3]int{3004,3005,3006},[3]int{3007,3008,3009}}
-var ss = SS{S{3101,3102,3103},S{3104,3105,3106},S{3107,3108,3109}}
-var sc = SC{[]int{3201,3202,3203},[]int{3204,3205,3206},[]int{3207,3208,3209}}
+var sa = SA{[3]int{3001, 3002, 3003}, [3]int{3004, 3005, 3006}, [3]int{3007, 3008, 3009}}
+var ss = SS{S{3101, 3102, 3103}, S{3104, 3105, 3106}, S{3107, 3108, 3109}}
+var sc = SC{[]int{3201, 3202, 3203}, []int{3204, 3205, 3206}, []int{3207, 3208, 3209}}
-var ca = [][3]int{[3]int{4001,4002,4003}, [3]int{4004,4005,4006}, [3]int{4007,4008,4009}}
-var cs = []S{S{4101,4102,4103},S{4104,4105,4106},S{4107,4108,4109}}
-var cc = [][]int{[]int{4201,4202,4203}, []int{4204,4205,4206}, []int{4207,4208,4209}}
+var ca = [][3]int{[3]int{4001, 4002, 4003}, [3]int{4004, 4005, 4006}, [3]int{4007, 4008, 4009}}
+var cs = []S{S{4101, 4102, 4103}, S{4104, 4105, 4106}, S{4107, 4108, 4109}}
+var cc = [][]int{[]int{4201, 4202, 4203}, []int{4204, 4205, 4206}, []int{4207, 4208, 4209}}
-var answers = [...]int {
+var answers = [...]int{
// s
1101, 1102, 1103,
2008, 2208, 2308, 4008, 4208, 4308, 5008, 5208, 5308,
2009, 2209, 2309, 4009, 4209, 4309, 5009, 5209, 5309,
}
+
+var (
+ copy_zero = zero
+ copy_one = one
+ copy_pi = pi
+ copy_slice = slice
+ copy_sliceInt = sliceInt
+ copy_hello = hello
+ copy_bytes = bytes
+ copy_four, copy_five = four, five
+ copy_x, copy_y = x, y
+ copy_nilslice = nilslice
+ copy_nilmap = nilmap
+ copy_nilfunc = nilfunc
+ copy_nilchan = nilchan
+ copy_nilptr = nilptr
+)
+
+var copy_a = a
+var copy_s = s
+var copy_c = c
+
+var copy_aa = aa
+var copy_as = as
+var copy_ac = ac
+
+var copy_sa = sa
+var copy_ss = ss
+var copy_sc = sc
+
+var copy_ca = ca
+var copy_cs = cs
+var copy_cc = cc
+
+var copy_answers = answers
+
+var bx bool
+var b0 = false
+var b1 = true
+
+var fx float32
+var f0 = float32(0)
+var f1 = float32(1)
+
+var gx float64
+var g0 = float64(0)
+var g1 = float64(1)
+
+var ix int
+var i0 = 0
+var i1 = 1
+
+var jx uint
+var j0 = uint(0)
+var j1 = uint(1)
+
+var cx complex64
+var c0 = complex64(0)
+var c1 = complex64(1)
+
+var dx complex128
+var d0 = complex128(0)
+var d1 = complex128(1)
+
+var sx []int
+var s0 = []int{0, 0, 0}
+var s1 = []int{1, 2, 3}
+
+func fi() int
+
+var ax [10]int
+var a0 = [10]int{0, 0, 0}
+var a1 = [10]int{1, 2, 3, 4}
+
+type T struct{ X, Y int }
+
+var tx T
+var t0 = T{}
+var t0a = T{0, 0}
+var t0b = T{X: 0}
+var t1 = T{X: 1, Y: 2}
+var t1a = T{3, 4}
+
+var psx *[]int
+var ps0 = &[]int{0, 0, 0}
+var ps1 = &[]int{1, 2, 3}
+
+var pax *[10]int
+var pa0 = &[10]int{0, 0, 0}
+var pa1 = &[10]int{1, 2, 3}
+
+var ptx *T
+var pt0 = &T{}
+var pt0a = &T{0, 0}
+var pt0b = &T{X: 0}
+var pt1 = &T{X: 1, Y: 2}
+var pt1a = &T{3, 4}
+
+var copy_bx = bx
+var copy_b0 = b0
+var copy_b1 = b1
+
+var copy_fx = fx
+var copy_f0 = f0
+var copy_f1 = f1
+
+var copy_gx = gx
+var copy_g0 = g0
+var copy_g1 = g1
+
+var copy_ix = ix
+var copy_i0 = i0
+var copy_i1 = i1
+
+var copy_jx = jx
+var copy_j0 = j0
+var copy_j1 = j1
+
+var copy_cx = cx
+var copy_c0 = c0
+var copy_c1 = c1
+
+var copy_dx = dx
+var copy_d0 = d0
+var copy_d1 = d1
+
+var copy_sx = sx
+var copy_s0 = s0
+var copy_s1 = s1
+
+var copy_ax = ax
+var copy_a0 = a0
+var copy_a1 = a1
+
+var copy_tx = tx
+var copy_t0 = t0
+var copy_t0a = t0a
+var copy_t0b = t0b
+var copy_t1 = t1
+var copy_t1a = t1a
+
+var copy_psx = psx
+var copy_ps0 = ps0
+var copy_ps1 = ps1
+
+var copy_pax = pax
+var copy_pa0 = pa0
+var copy_pa1 = pa1
+
+var copy_ptx = ptx
+var copy_pt0 = pt0
+var copy_pt0a = pt0a
+var copy_pt0b = pt0b
+var copy_pt1 = pt1
+var copy_pt1a = pt1a