summaryrefslogtreecommitdiff
path: root/src/cmd/5g/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g/cgen.c')
-rw-r--r--src/cmd/5g/cgen.c232
1 files changed, 140 insertions, 92 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 8072c3ceb..1328f4be6 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -4,33 +4,6 @@
#include "gg.h"
-void
-mgen(Node *n, Node *n1, Node *rg)
-{
- n1->ostk = 0;
- n1->op = OEMPTY;
-
- if(n->addable) {
- *n1 = *n;
- n1->ostk = 0;
- if(n1->op == OREGISTER || n1->op == OINDREG)
- reg[n->val.u.reg]++;
- return;
- }
- if(n->type->width > widthptr)
- tempname(n1, n->type);
- else
- regalloc(n1, n->type, rg);
- cgen(n, n1);
-}
-
-void
-mfree(Node *n)
-{
- if(n->op == OREGISTER)
- regfree(n);
-}
-
/*
* generate:
* res = n;
@@ -55,12 +28,6 @@ cgen(Node *n, Node *res)
if(res == N || res->type == T)
fatal("cgen: res nil");
- // TODO compile complex
- if(n != N && n->type != T && iscomplex[n->type->etype])
- return;
- if(res != N && res->type != T && iscomplex[res->type->etype])
- return;
-
while(n->op == OCONVNOP)
n = n->left;
@@ -80,6 +47,7 @@ cgen(Node *n, Node *res)
goto ret;
}
+
// update addressability for string, slice
// can't do in walk because n->left->addable
// changes if n->left is an escaping local variable.
@@ -96,7 +64,9 @@ cgen(Node *n, Node *res)
// if both are addressable, move
if(n->addable && res->addable) {
- if (is64(n->type) || is64(res->type) || n->op == OREGISTER || res->op == OREGISTER) {
+ if(is64(n->type) || is64(res->type) ||
+ n->op == OREGISTER || res->op == OREGISTER ||
+ iscomplex[n->type->etype] || iscomplex[res->type->etype]) {
gmove(n, res);
} else {
regalloc(&n1, n->type, N);
@@ -126,8 +96,13 @@ cgen(Node *n, Node *res)
return;
}
+ if(complexop(n, res)) {
+ complexgen(n, res);
+ return;
+ }
+
// if n is sudoaddable generate addr and move
- if (!is64(n->type) && !is64(res->type)) {
+ if (!is64(n->type) && !is64(res->type) && !iscomplex[n->type->etype] && !iscomplex[res->type->etype]) {
a = optoas(OAS, n->type);
if(sudoaddable(a, n, &addr, &w)) {
if (res->op != OREGISTER) {
@@ -195,8 +170,8 @@ cgen(Node *n, Node *res)
case OREAL:
case OIMAG:
case OCMPLX:
- // TODO compile complex
- return;
+ fatal("unexpected complex");
+ break;
// these call bgen to get a bool value
case OOROR:
@@ -269,10 +244,26 @@ cgen(Node *n, Node *res)
cgen(nl, res);
break;
}
-
- mgen(nl, &n1, res);
- gmove(&n1, res);
- mfree(&n1);
+ if(nl->addable && !is64(nl->type)) {
+ regalloc(&n1, nl->type, res);
+ gmove(nl, &n1);
+ } else {
+ if(n->type->width > widthptr || is64(nl->type) || isfloat[nl->type->etype])
+ tempname(&n1, nl->type);
+ else
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ }
+ if(n->type->width > widthptr || is64(n->type) || isfloat[n->type->etype])
+ tempname(&n2, n->type);
+ else
+ regalloc(&n2, n->type, N);
+ gmove(&n1, &n2);
+ gmove(&n2, res);
+ if(n1.op == OREGISTER)
+ regfree(&n1);
+ if(n2.op == OREGISTER)
+ regfree(&n2);
break;
case ODOT:
@@ -461,6 +452,41 @@ ret:
}
/*
+ * generate array index into res.
+ * n might be any size; res is 32-bit.
+ * returns Prog* to patch to panic call.
+ */
+Prog*
+cgenindex(Node *n, Node *res)
+{
+ Node tmp, lo, hi, zero, n1, n2;
+
+ if(!is64(n->type)) {
+ cgen(n, res);
+ return nil;
+ }
+
+ tempname(&tmp, types[TINT64]);
+ cgen(n, &tmp);
+ split64(&tmp, &lo, &hi);
+ gmove(&lo, res);
+ if(debug['B']) {
+ splitclean();
+ return nil;
+ }
+ regalloc(&n1, types[TINT32], N);
+ regalloc(&n2, types[TINT32], N);
+ nodconst(&zero, types[TINT32], 0);
+ gmove(&hi, &n1);
+ gmove(&zero, &n2);
+ gcmp(ACMP, &n1, &n2);
+ regfree(&n2);
+ regfree(&n1);
+ splitclean();
+ return gbranch(ABNE, T);
+}
+
+/*
* generate:
* res = &n;
*/
@@ -469,10 +495,10 @@ agen(Node *n, Node *res)
{
Node *nl, *nr;
Node n1, n2, n3, n4, n5, tmp;
- Prog *p1;
+ Prog *p1, *p2;
uint32 w;
uint64 v;
- Type *t;
+ int r;
if(debug['g']) {
dump("\nagen-res", res);
@@ -504,7 +530,22 @@ agen(Node *n, Node *res)
break;
case OCALLMETH:
- cgen_callmeth(n, 0);
+ case OCALLFUNC:
+ // Release res so that it is available for cgen_call.
+ // Pick it up again after the call.
+ r = -1;
+ if(n->ullman >= UINF) {
+ if(res->op == OREGISTER || res->op == OINDREG) {
+ r = res->val.u.reg;
+ reg[r]--;
+ }
+ }
+ if(n->op == OCALLMETH)
+ cgen_callmeth(n, 0);
+ else
+ cgen_call(n, 0);
+ if(r >= 0)
+ reg[r]++;
cgen_aret(n, res);
break;
@@ -513,36 +554,36 @@ agen(Node *n, Node *res)
cgen_aret(n, res);
break;
- case OCALLFUNC:
- cgen_call(n, 0);
- cgen_aret(n, res);
- break;
-
case OINDEX:
- // TODO(rsc): uint64 indices
+ p2 = nil; // to be patched to panicindex.
w = n->type->width;
if(nr->addable) {
- agenr(nl, &n3, res);
- if(!isconst(nr, CTINT)) {
+ if(!isconst(nr, CTINT))
tempname(&tmp, types[TINT32]);
- cgen(nr, &tmp);
+ if(!isconst(nl, CTSTR))
+ agenr(nl, &n3, res);
+ if(!isconst(nr, CTINT)) {
+ p2 = cgenindex(nr, &tmp);
regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1);
}
} else if(nl->addable) {
if(!isconst(nr, CTINT)) {
tempname(&tmp, types[TINT32]);
- cgen(nr, &tmp);
+ p2 = cgenindex(nr, &tmp);
regalloc(&n1, tmp.type, N);
gmove(&tmp, &n1);
}
- regalloc(&n3, types[tptr], res);
- agen(nl, &n3);
+ if(!isconst(nl, CTSTR)) {
+ regalloc(&n3, types[tptr], res);
+ agen(nl, &n3);
+ }
} else {
tempname(&tmp, types[TINT32]);
- cgen(nr, &tmp);
+ p2 = cgenindex(nr, &tmp);
nr = &tmp;
- agenr(nl, &n3, res);
+ if(!isconst(nl, CTSTR))
+ agenr(nl, &n3, res);
regalloc(&n1, tmp.type, N);
gins(optoas(OAS, tmp.type), &tmp, &n1);
}
@@ -556,9 +597,10 @@ agen(Node *n, Node *res)
// constant index
if(isconst(nr, CTINT)) {
+ if(isconst(nl, CTSTR))
+ fatal("constant string constant index");
v = mpgetfix(nr->val.u.xval);
- if(isslice(nl->type)) {
-
+ if(isslice(nl->type) || nl->type->etype == TSTRING) {
if(!debug['B'] && !n->etype) {
n1 = n3;
n1.op = OINDREG;
@@ -582,13 +624,6 @@ agen(Node *n, Node *res)
n1.type = types[tptr];
n1.xoffset = Array_array;
gmove(&n1, &n3);
- } else
- if(!debug['B'] && !n->etype) {
- if(v < 0)
- yyerror("out of bounds on array");
- else
- if(v >= nl->type->bound)
- yyerror("out of bounds on array");
}
nodconst(&n2, types[tptr], v*w);
@@ -602,19 +637,17 @@ agen(Node *n, Node *res)
break;
}
- // type of the index
- t = types[TUINT32];
- if(issigned[n1.type->etype])
- t = types[TINT32];
-
- regalloc(&n2, t, &n1); // i
+ regalloc(&n2, types[TINT32], &n1); // i
gmove(&n1, &n2);
regfree(&n1);
if(!debug['B'] && !n->etype) {
// check bounds
regalloc(&n4, types[TUINT32], N);
- if(isslice(nl->type)) {
+ if(isconst(nl, CTSTR)) {
+ nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
+ gmove(&n1, &n4);
+ } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3;
n1.op = OINDREG;
n1.type = types[tptr];
@@ -627,11 +660,18 @@ agen(Node *n, Node *res)
gcmp(optoas(OCMP, types[TUINT32]), &n2, &n4);
regfree(&n4);
p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+ if(p2)
+ patch(p2, pc);
ginscall(panicindex, 0);
patch(p1, pc);
}
-
- if(isslice(nl->type)) {
+
+ if(isconst(nl, CTSTR)) {
+ regalloc(&n3, types[tptr], res);
+ p1 = gins(AMOVW, N, &n3);
+ datastring(nl->val.u.sval->s, nl->val.u.sval->len, &p1->from);
+ p1->from.type = D_CONST;
+ } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
n1 = n3;
n1.op = OINDREG;
n1.type = types[tptr];
@@ -653,10 +693,10 @@ agen(Node *n, Node *res)
else if(w == 8)
gshift(AADD, &n2, SHIFT_LL, 3, &n3);
} else {
- regalloc(&n4, t, N);
- nodconst(&n1, t, w);
+ regalloc(&n4, types[TUINT32], N);
+ nodconst(&n1, types[TUINT32], w);
gmove(&n1, &n4);
- gins(optoas(OMUL, t), &n4, &n2);
+ gins(optoas(OMUL, types[TUINT32]), &n4, &n2);
gins(optoas(OADD, types[tptr]), &n2, &n3);
regfree(&n4);
gmove(&n3, res);
@@ -769,12 +809,8 @@ igen(Node *n, Node *a, Node *res)
void
agenr(Node *n, Node *a, Node *res)
{
- Node n1;
-
- tempname(&n1, types[tptr]);
- agen(n, &n1);
regalloc(a, types[tptr], res);
- gmove(&n1, a);
+ agen(n, a);
}
/*
@@ -796,15 +832,12 @@ bgen(Node *n, int true, Prog *to)
if(n == N)
n = nodbool(1);
+ if(n->ninit != nil)
+ genlist(n->ninit);
+
nl = n->left;
nr = n->right;
- // TODO compile complex
- if(nl != N && nl->type != T && iscomplex[nl->type->etype])
- return;
- if(nr != N && nr->type != T && iscomplex[nr->type->etype])
- return;
-
if(n->type == T) {
convlit(&n, types[TBOOL]);
if(n->type == T)
@@ -925,6 +958,7 @@ bgen(Node *n, int true, Prog *to)
goto ret;
}
a = brcom(a);
+ true = !true;
}
// make simplest on right
@@ -985,6 +1019,11 @@ bgen(Node *n, int true, Prog *to)
break;
}
+ if(iscomplex[nl->type->etype]) {
+ complexbool(a, nl, nr, true, to);
+ break;
+ }
+
if(is64(nr->type)) {
if(!nl->addable) {
tempname(&n1, nl->type);
@@ -1031,7 +1070,16 @@ bgen(Node *n, int true, Prog *to)
cgen(nr, &n2);
gcmp(optoas(OCMP, nr->type), &n1, &n2);
- patch(gbranch(a, nr->type), to);
+ if(isfloat[nl->type->etype]) {
+ p1 = gbranch(ABVS, nr->type);
+ patch(gbranch(a, nr->type), to);
+ if(n->op == ONE)
+ patch(p1, to);
+ else
+ patch(p1, pc);
+ } else {
+ patch(gbranch(a, nr->type), to);
+ }
regfree(&n1);
regfree(&n2);
@@ -1088,7 +1136,7 @@ stkof(Node *n)
t = structfirst(&flist, getoutarg(t));
if(t != T)
- return t->width;
+ return t->width + 4; // correct for LR
break;
}