summaryrefslogtreecommitdiff
path: root/src/cmd/gc/gen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/gen.c')
-rw-r--r--src/cmd/gc/gen.c228
1 files changed, 159 insertions, 69 deletions
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index 96e7b526c..5f03d9476 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -266,6 +266,8 @@ gen(Node *n)
Label *lab;
int32 wasregalloc;
+//dump("gen", n);
+
lno = setlineno(n);
wasregalloc = anyregalloc();
@@ -279,7 +281,7 @@ gen(Node *n)
switch(n->op) {
default:
- fatal("gen: unknown op %N", n);
+ fatal("gen: unknown op %+hN", n);
break;
case OCASE:
@@ -394,7 +396,7 @@ gen(Node *n)
}
gen(n->nincr); // contin: incr
patch(p1, pc); // test:
- bgen(n->ntest, 0, breakpc); // if(!test) goto break
+ bgen(n->ntest, 0, -1, breakpc); // if(!test) goto break
genlist(n->nbody); // body
gjmp(continpc);
patch(breakpc, pc); // done:
@@ -410,7 +412,7 @@ gen(Node *n)
p1 = gjmp(P); // goto test
p2 = gjmp(P); // p2: goto else
patch(p1, pc); // test:
- bgen(n->ntest, 0, p2); // if(!test) goto p2
+ bgen(n->ntest, 0, -n->likely, p2); // if(!test) goto p2
genlist(n->nbody); // then
p3 = gjmp(P); // goto done
patch(p2, pc); // else:
@@ -509,22 +511,24 @@ ret:
void
cgen_callmeth(Node *n, int proc)
{
+ Node n2;
Node *l;
- // generate a rewrite for method call
+ // generate a rewrite in n2 for the method call
// (p.f)(...) goes to (f)(p,...)
l = n->left;
if(l->op != ODOTMETH)
fatal("cgen_callmeth: not dotmethod: %N");
- n->op = OCALLFUNC;
- n->left = n->left->right;
- n->left->type = l->type;
+ n2 = *n;
+ n2.op = OCALLFUNC;
+ n2.left = l->right;
+ n2.left->type = l->type;
- if(n->left->op == ONAME)
- n->left->class = PFUNC;
- cgen_call(n, proc);
+ if(n2.left->op == ONAME)
+ n2.left->class = PFUNC;
+ cgen_call(&n2, proc);
}
/*
@@ -631,6 +635,67 @@ cgen_discard(Node *nr)
}
/*
+ * clearslim generates code to zero a slim node.
+ */
+void
+clearslim(Node *n)
+{
+ Node z;
+ Mpflt zero;
+
+ memset(&z, 0, sizeof(z));
+ z.op = OLITERAL;
+ z.type = n->type;
+ z.addable = 1;
+
+ switch(simtype[n->type->etype]) {
+ case TCOMPLEX64:
+ case TCOMPLEX128:
+ z.val.u.cval = mal(sizeof(*z.val.u.cval));
+ mpmovecflt(&z.val.u.cval->real, 0.0);
+ mpmovecflt(&z.val.u.cval->imag, 0.0);
+ break;
+
+ case TFLOAT32:
+ case TFLOAT64:
+ mpmovecflt(&zero, 0.0);
+ z.val.ctype = CTFLT;
+ z.val.u.fval = &zero;
+ break;
+
+ case TPTR32:
+ case TPTR64:
+ case TCHAN:
+ case TMAP:
+ z.val.ctype = CTNIL;
+ break;
+
+ case TBOOL:
+ z.val.ctype = CTBOOL;
+ break;
+
+ case TINT8:
+ case TINT16:
+ case TINT32:
+ case TINT64:
+ case TUINT8:
+ case TUINT16:
+ case TUINT32:
+ case TUINT64:
+ z.val.ctype = CTINT;
+ z.val.u.xval = mal(sizeof(*z.val.u.xval));
+ mpmovecfix(z.val.u.xval, 0);
+ break;
+
+ default:
+ fatal("clearslim called on type %T", n->type);
+ }
+
+ ullmancalc(&z);
+ cgen(&z, n);
+}
+
+/*
* generate assignment:
* nl = nr
* nr == N means zero nl.
@@ -638,9 +703,7 @@ cgen_discard(Node *nr)
void
cgen_as(Node *nl, Node *nr)
{
- Node nc;
Type *tl;
- int iszer;
if(debug['g']) {
dump("cgen_as", nl);
@@ -655,7 +718,6 @@ cgen_as(Node *nl, Node *nr)
return;
}
- iszer = 0;
if(nr == N || isnil(nr)) {
// externals and heaps should already be clear
if(nr == N) {
@@ -670,59 +732,10 @@ cgen_as(Node *nl, Node *nr)
return;
if(isfat(tl)) {
clearfat(nl);
- goto ret;
- }
-
- /* invent a "zero" for the rhs */
- iszer = 1;
- nr = &nc;
- memset(nr, 0, sizeof(*nr));
- switch(simtype[tl->etype]) {
- default:
- fatal("cgen_as: tl %T", tl);
- break;
-
- case TINT8:
- case TUINT8:
- case TINT16:
- case TUINT16:
- case TINT32:
- case TUINT32:
- case TINT64:
- case TUINT64:
- nr->val.u.xval = mal(sizeof(*nr->val.u.xval));
- mpmovecfix(nr->val.u.xval, 0);
- nr->val.ctype = CTINT;
- break;
-
- case TFLOAT32:
- case TFLOAT64:
- nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
- mpmovecflt(nr->val.u.fval, 0.0);
- nr->val.ctype = CTFLT;
- break;
-
- case TBOOL:
- nr->val.u.bval = 0;
- nr->val.ctype = CTBOOL;
- break;
-
- case TPTR32:
- case TPTR64:
- nr->val.ctype = CTNIL;
- break;
-
- case TCOMPLEX64:
- case TCOMPLEX128:
- nr->val.u.cval = mal(sizeof(*nr->val.u.cval));
- mpmovecflt(&nr->val.u.cval->real, 0.0);
- mpmovecflt(&nr->val.u.cval->imag, 0.0);
- break;
+ return;
}
- nr->op = OLITERAL;
- nr->type = tl;
- nr->addable = 1;
- ullmancalc(nr);
+ clearslim(nl);
+ return;
}
tl = nl->type;
@@ -730,11 +743,88 @@ cgen_as(Node *nl, Node *nr)
return;
cgen(nr, nl);
- if(iszer && nl->addable)
- gused(nl);
+}
-ret:
- ;
+/*
+ * generate:
+ * res = iface{typ, data}
+ * n->left is typ
+ * n->right is data
+ */
+void
+cgen_eface(Node *n, Node *res)
+{
+ /*
+ * the right node of an eface may contain function calls that uses res as an argument,
+ * so it's important that it is done first
+ */
+ Node dst;
+ dst = *res;
+ dst.type = types[tptr];
+ dst.xoffset += widthptr;
+ cgen(n->right, &dst);
+ dst.xoffset -= widthptr;
+ cgen(n->left, &dst);
+}
+
+/*
+ * generate:
+ * res = s[lo, hi];
+ * n->left is s
+ * n->list is (cap(s)-lo(TUINT), hi-lo(TUINT)[, lo*width(TUINTPTR)])
+ * caller (cgen) guarantees res is an addable ONAME.
+ */
+void
+cgen_slice(Node *n, Node *res)
+{
+ Node src, dst, *cap, *len, *offs, *add;
+
+ cap = n->list->n;
+ len = n->list->next->n;
+ offs = N;
+ if(n->list->next->next)
+ offs = n->list->next->next->n;
+
+ // dst.len = hi [ - lo ]
+ dst = *res;
+ dst.xoffset += Array_nel;
+ dst.type = types[simtype[TUINT]];
+ cgen(len, &dst);
+
+ if(n->op != OSLICESTR) {
+ // dst.cap = cap [ - lo ]
+ dst = *res;
+ dst.xoffset += Array_cap;
+ dst.type = types[simtype[TUINT]];
+ cgen(cap, &dst);
+ }
+
+ // dst.array = src.array [ + lo *width ]
+ dst = *res;
+ dst.xoffset += Array_array;
+ dst.type = types[TUINTPTR];
+
+ if(n->op == OSLICEARR) {
+ if(!isptr[n->left->type->etype])
+ fatal("slicearr is supposed to work on pointer: %+N\n", n);
+ checkref(n->left);
+ }
+
+ if(isnil(n->left)) {
+ tempname(&src, n->left->type);
+ cgen(n->left, &src);
+ } else
+ src = *n->left;
+ src.xoffset += Array_array;
+ src.type = types[TUINTPTR];
+
+ if(offs == N) {
+ cgen(&src, &dst);
+ } else {
+ add = nod(OADD, &src, offs);
+ typecheck(&add, Erv);
+ cgen(add, &dst);
+ }
}
/*