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.c1654
1 files changed, 828 insertions, 826 deletions
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 4f6c0928b..36dd8767c 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -12,336 +12,340 @@
void
cgen(Node *n, Node *res)
{
-// fatal("cgen_unimplemented");
-// Node *nl, *nr, *r;
-// Node n1, n2;
-// int a, f;
-// Prog *p1, *p2, *p3;
-// Addr addr;
-
-// if(debug['g']) {
-// dump("\ncgen-n", n);
-// dump("cgen-res", res);
-// }
-// if(n == N || n->type == T)
-// return;
-
-// if(res == N || res->type == T)
-// fatal("cgen: res nil");
-
-// if(n->ullman >= UINF) {
-// if(n->op == OINDREG)
-// fatal("cgen: this is going to misscompile");
-// if(res->ullman >= UINF) {
-// tempname(&n1, n->type);
-// cgen(n, &n1);
-// cgen(&n1, res);
-// goto ret;
-// }
-// }
-
-// if(isfat(n->type)) {
-// sgen(n, res, n->type->width);
-// goto ret;
-// }
-
-// if(!res->addable) {
-// if(n->ullman > res->ullman) {
-// regalloc(&n1, n->type, res);
-// cgen(n, &n1);
-// if(n1.ullman > res->ullman) {
-// dump("n1", &n1);
-// dump("res", res);
-// fatal("loop in cgen");
-// }
-// cgen(&n1, res);
-// regfree(&n1);
-// goto ret;
-// }
-
-// if(res->ullman >= UINF)
-// goto gen;
-
-// f = 1; // gen thru register
-// switch(n->op) {
-// case OLITERAL:
-// if(smallintconst(n))
-// f = 0;
-// break;
-// case OREGISTER:
-// f = 0;
-// break;
-// }
-
-// if(sudoaddable(res, &addr)) {
-// a = optoas(OAS, res->type);
-// if(f) {
-// regalloc(&n2, res->type, N);
-// cgen(n, &n2);
-// p1 = gins(a, &n2, N);
-// regfree(&n2);
-// } else
-// p1 = gins(a, n, N);
-// p1->to = addr;
-// if(debug['g'])
-// print("%P [ignore previous line]\n", p1);
-// sudoclean();
-// goto ret;
-// }
-
-// gen:
-// igen(res, &n1, N);
-// cgen(n, &n1);
-// regfree(&n1);
-// goto ret;
-// }
-
-// if(n->addable) {
-// gmove(n, res);
-// goto ret;
-// }
-
-// nl = n->left;
-// nr = n->right;
-// if(nl != N && nl->ullman >= UINF)
-// if(nr != N && nr->ullman >= UINF) {
-// tempname(&n1, nl->type);
-// cgen(nl, &n1);
-// n2 = *n;
-// n2.left = &n1;
-// cgen(&n2, res);
-// goto ret;
-// }
-
-// if(sudoaddable(n, &addr)) {
-// a = optoas(OAS, n->type);
-// if(res->op == OREGISTER) {
-// p1 = gins(a, N, res);
-// p1->from = addr;
-// } else {
-// regalloc(&n2, n->type, N);
-// p1 = gins(a, N, &n2);
-// p1->from = addr;
-// gins(a, &n2, res);
-// regfree(&n2);
-// }
-// sudoclean();
-// goto ret;
-// }
-
-// switch(n->op) {
-// default:
-// dump("cgen", n);
-// fatal("cgen: unknown op %N", n);
-// break;
-
-// // these call bgen to get a bool value
-// case OOROR:
-// case OANDAND:
-// case OEQ:
-// case ONE:
-// case OLT:
-// case OLE:
-// case OGE:
-// case OGT:
-// case ONOT:
-// p1 = gbranch(AB, T);
-// p2 = pc;
-// gmove(nodbool(1), res);
-// p3 = gbranch(AB, T);
-// patch(p1, pc);
-// bgen(n, 1, p2);
-// gmove(nodbool(0), res);
-// patch(p3, pc);
-// goto ret;
-
-// case OPLUS:
-// cgen(nl, res);
-// goto ret;
-
-// // unary
-// case OCOM:
-// a = optoas(OXOR, nl->type);
-// regalloc(&n1, nl->type, N);
-// cgen(nl, &n1);
-// nodconst(&n2, nl->type, -1);
-// gins(a, &n2, &n1);
-// gmove(&n1, res);
-// regfree(&n1);
-// goto ret;
-
-// case OMINUS:
-// a = optoas(n->op, nl->type);
-// goto uop;
-
-// // symmetric binary
-// case OAND:
-// case OOR:
-// case OXOR:
-// case OADD:
-// case OMUL:
-// a = optoas(n->op, nl->type);
-// if(a != AIMULB)
-// goto sbop;
-// cgen_bmul(n->op, nl, nr, res);
-// break;
-
-// // asymmetric binary
-// case OSUB:
-// a = optoas(n->op, nl->type);
-// goto abop;
-
-// case OCONV:
-// if(eqtype(n->type, nl->type, 0)) {
-// cgen(nl, res);
-// break;
-// }
-// regalloc(&n1, nl->type, res);
-// cgen(nl, &n1);
-// gmove(&n1, res);
-// regfree(&n1);
-// break;
-
-// case ODOT:
-// case ODOTPTR:
-// case OINDEX:
-// case OIND:
-// case ONAME: // PHEAP or PPARAMREF var
-// igen(n, &n1, res);
-// gmove(&n1, res);
-// regfree(&n1);
-// break;
-
-// case OLEN:
-// if(istype(nl->type, TMAP)) {
-// // map hsd len in the first 32-bit word.
-// // a zero pointer means zero length
-// regalloc(&n1, types[tptr], res);
-// cgen(nl, &n1);
-
-// nodconst(&n2, types[tptr], 0);
-// gins(optoas(OCMP, types[tptr]), &n1, &n2);
-// p1 = gbranch(optoas(OEQ, types[tptr]), T);
-
-// n2 = n1;
-// n2.op = OINDREG;
-// n2.type = types[TINT32];
-// gmove(&n2, &n1);
-
-// patch(p1, pc);
-
-// gmove(&n1, res);
-// regfree(&n1);
-// break;
-// }
-// if(istype(nl->type, TSTRING) || isslice(nl->type)) {
-// // both slice and string have len in the first 32-bit word.
-// // a zero pointer means zero length
-// regalloc(&n1, types[tptr], res);
-// agen(nl, &n1);
-// n1.op = OINDREG;
-// n1.type = types[TUINT32];
-// n1.xoffset = Array_nel;
-// gmove(&n1, res);
-// regfree(&n1);
-// break;
-// }
-// fatal("cgen: OLEN: unknown type %lT", nl->type);
-// break;
-
-// case OCAP:
-// if(isslice(nl->type)) {
-// regalloc(&n1, types[tptr], res);
-// agen(nl, &n1);
-// n1.op = OINDREG;
-// n1.type = types[TUINT32];
-// n1.xoffset = Array_cap;
-// gmove(&n1, res);
-// regfree(&n1);
-// break;
-// }
-// fatal("cgen: OCAP: unknown type %lT", nl->type);
-// break;
-
-// case OADDR:
-// agen(nl, res);
-// break;
-
-// case OCALLMETH:
-// cgen_callmeth(n, 0);
-// cgen_callret(n, res);
-// break;
-
-// case OCALLINTER:
-// cgen_callinter(n, res, 0);
-// cgen_callret(n, res);
-// break;
-
-// case OCALL:
-// cgen_call(n, 0);
-// cgen_callret(n, res);
-// break;
-
-// case OMOD:
-// case ODIV:
-// if(isfloat[n->type->etype]) {
-// a = optoas(n->op, nl->type);
-// goto abop;
-// }
-// cgen_div(n->op, nl, nr, res);
-// break;
-
-// case OLSH:
-// case ORSH:
-// cgen_shift(n->op, nl, nr, res);
-// break;
-// }
-// goto ret;
-
-// sbop: // symmetric binary
-// if(nl->ullman < nr->ullman) {
-// r = nl;
-// nl = nr;
-// nr = r;
-// }
-
-// abop: // asymmetric binary
-// if(nl->ullman >= nr->ullman) {
-// regalloc(&n1, nl->type, res);
-// cgen(nl, &n1);
-
-// if(sudoaddable(nr, &addr)) {
-// p1 = gins(a, N, &n1);
-// p1->from = addr;
-// gmove(&n1, res);
-// sudoclean();
-// regfree(&n1);
-// goto ret;
-// }
-
-// regalloc(&n2, nr->type, N);
-// cgen(nr, &n2);
-// } else {
-// regalloc(&n2, nr->type, N);
-// cgen(nr, &n2);
-// regalloc(&n1, nl->type, res);
-// cgen(nl, &n1);
-// }
-// gins(a, &n2, &n1);
-// gmove(&n1, res);
-// regfree(&n1);
-// regfree(&n2);
-// goto ret;
-
-// uop: // unary
-// regalloc(&n1, nl->type, res);
-// cgen(nl, &n1);
-// gins(a, N, &n1);
-// gmove(&n1, res);
-// regfree(&n1);
-// goto ret;
+ Node *nl, *nr, *r;
+ Node n1, n2;
+ int a, f;
+ Prog *p1, *p2, *p3;
+ Addr addr;
+
+ if(debug['g']) {
+ dump("\ncgen-n", n);
+ dump("cgen-res", res);
+ }
+ if(n == N || n->type == T)
+ goto ret;
+
+ if(res == N || res->type == T)
+ fatal("cgen: res nil");
+
+ // static initializations
+ if(initflag && gen_as_init(n, res))
+ goto ret;
+
+ if(n->ullman >= UINF) {
+ if(n->op == OINDREG)
+ fatal("cgen: this is going to misscompile");
+ if(res->ullman >= UINF) {
+ tempname(&n1, n->type);
+ cgen(n, &n1);
+ cgen(&n1, res);
+ goto ret;
+ }
+ }
-// ret:
+ if(isfat(n->type)) {
+ sgen(n, res, n->type->width);
+ goto ret;
+ }
+
+ if(!res->addable) {
+ if(n->ullman > res->ullman) {
+ regalloc(&n1, n->type, res);
+ cgen(n, &n1);
+ if(n1.ullman > res->ullman) {
+ dump("n1", &n1);
+ dump("res", res);
+ fatal("loop in cgen");
+ }
+ cgen(&n1, res);
+ regfree(&n1);
+ goto ret;
+ }
+
+ if(res->ullman >= UINF)
+ goto gen;
+
+ f = 1; // gen thru register
+ switch(n->op) {
+ case OLITERAL:
+ if(smallintconst(n))
+ f = 0;
+ break;
+ case OREGISTER:
+ f = 0;
+ break;
+ }
+
+ a = optoas(OAS, res->type);
+ if(sudoaddable(a, res, &addr)) {
+ if(f) {
+ regalloc(&n2, res->type, N);
+ cgen(n, &n2);
+ p1 = gins(a, &n2, N);
+ regfree(&n2);
+ } else
+ p1 = gins(a, n, N);
+ p1->to = addr;
+ if(debug['g'])
+ print("%P [ignore previous line]\n", p1);
+ sudoclean();
+ goto ret;
+ }
+
+ gen:
+ igen(res, &n1, N);
+ cgen(n, &n1);
+ regfree(&n1);
+ goto ret;
+ }
+
+ if(n->addable) {
+ gmove(n, res);
+ goto ret;
+ }
+
+ nl = n->left;
+ nr = n->right;
+
+ if(nl != N && nl->ullman >= UINF)
+ if(nr != N && nr->ullman >= UINF) {
+ tempname(&n1, nl->type);
+ cgen(nl, &n1);
+ n2 = *n;
+ n2.left = &n1;
+ cgen(&n2, res);
+ goto ret;
+ }
+
+ a = optoas(OAS, n->type);
+ if(sudoaddable(a, n, &addr)) {
+ if(res->op == OREGISTER) {
+ p1 = gins(a, N, res);
+ p1->from = addr;
+ } else {
+ regalloc(&n2, n->type, N);
+ p1 = gins(a, N, &n2);
+ p1->from = addr;
+ gins(a, &n2, res);
+ regfree(&n2);
+ }
+ sudoclean();
+ goto ret;
+ }
+
+ switch(n->op) {
+ default:
+ dump("cgen", n);
+ fatal("cgen: unknown op %N", n);
+ break;
+
+ // these call bgen to get a bool value
+ case OOROR:
+ case OANDAND:
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OLE:
+ case OGE:
+ case OGT:
+ case ONOT:
+ p1 = gbranch(AB, T);
+ p2 = pc;
+ gmove(nodbool(1), res);
+ p3 = gbranch(AB, T);
+ patch(p1, pc);
+ bgen(n, 1, p2);
+ gmove(nodbool(0), res);
+ patch(p3, pc);
+ goto ret;
+
+ case OPLUS:
+ cgen(nl, res);
+ goto ret;
+
+ // unary
+ case OCOM:
+ a = optoas(OXOR, nl->type);
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
+ nodconst(&n2, nl->type, -1);
+ gins(a, &n2, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ goto ret;
+
+ case OMINUS:
+ a = optoas(n->op, nl->type);
+ goto uop;
+
+ // symmetric binary
+ case OAND:
+ case OOR:
+ case OXOR:
+ case OADD:
+ case OMUL:
+ fatal("cgen OMUL not implemented");
+// a = optoas(n->op, nl->type);
+// if(a != AIMULB)
+// goto sbop;
+// cgen_bmul(n->op, nl, nr, res);
+ break;
+
+ // asymmetric binary
+ case OSUB:
+ a = optoas(n->op, nl->type);
+ goto abop;
+
+ case OCONV:
+ if(eqtype(n->type, nl->type)) {
+ cgen(nl, res);
+ break;
+ }
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+
+ case ODOT:
+ case ODOTPTR:
+ case OINDEX:
+ case OIND:
+ case ONAME: // PHEAP or PPARAMREF var
+ igen(n, &n1, res);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+
+ case OLEN:
+ if(istype(nl->type, TMAP)) {
+ // map hsd len in the first 32-bit word.
+ // a zero pointer means zero length
+ regalloc(&n1, types[tptr], res);
+ cgen(nl, &n1);
+
+ nodconst(&n2, types[tptr], 0);
+ gins(optoas(OCMP, types[tptr]), &n1, &n2);
+ p1 = gbranch(optoas(OEQ, types[tptr]), T);
+
+ n2 = n1;
+ n2.op = OINDREG;
+ n2.type = types[TINT32];
+ gmove(&n2, &n1);
+
+ patch(p1, pc);
+
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ if(istype(nl->type, TSTRING) || isslice(nl->type)) {
+ // both slice and string have len in the first 32-bit word.
+ // a zero pointer means zero length
+ regalloc(&n1, types[tptr], res);
+ agen(nl, &n1);
+ n1.op = OINDREG;
+ n1.type = types[TUINT32];
+ n1.xoffset = Array_nel;
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ fatal("cgen: OLEN: unknown type %lT", nl->type);
+ break;
+
+ case OCAP:
+ if(isslice(nl->type)) {
+ regalloc(&n1, types[tptr], res);
+ agen(nl, &n1);
+ n1.op = OINDREG;
+ n1.type = types[TUINT32];
+ n1.xoffset = Array_cap;
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ fatal("cgen: OCAP: unknown type %lT", nl->type);
+ break;
+
+ case OADDR:
+ agen(nl, res);
+ break;
+
+ case OCALLMETH:
+ cgen_callmeth(n, 0);
+ cgen_callret(n, res);
+ break;
+
+ case OCALLINTER:
+ cgen_callinter(n, res, 0);
+ cgen_callret(n, res);
+ break;
+
+ case OCALL:
+ cgen_call(n, 0);
+ cgen_callret(n, res);
+ break;
+
+ case OMOD:
+ case ODIV:
+ if(isfloat[n->type->etype]) {
+ a = optoas(n->op, nl->type);
+ goto abop;
+ }
+ cgen_div(n->op, nl, nr, res);
+ break;
+
+ case OLSH:
+ case ORSH:
+ cgen_shift(n->op, nl, nr, res);
+ break;
+ }
+ goto ret;
+
+sbop: // symmetric binary
+ if(nl->ullman < nr->ullman) {
+ r = nl;
+ nl = nr;
+ nr = r;
+ }
+
+abop: // asymmetric binary
+ if(nl->ullman >= nr->ullman) {
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+
+ if(sudoaddable(a, nr, &addr)) {
+ p1 = gins(a, N, &n1);
+ p1->from = addr;
+ gmove(&n1, res);
+ sudoclean();
+ regfree(&n1);
+ goto ret;
+ }
+ regalloc(&n2, nr->type, N);
+ cgen(nr, &n2);
+ } else {
+ regalloc(&n2, nr->type, N);
+ cgen(nr, &n2);
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ }
+ gins(a, &n2, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ regfree(&n2);
+ goto ret;
+
+uop: // unary
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ gins(a, N, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ goto ret;
+
+ret:
;
}
@@ -352,230 +356,227 @@ cgen(Node *n, Node *res)
void
agen(Node *n, Node *res)
{
- fatal("agen_unimplemented");
-// Node *nl, *nr;
-// Node n1, n2, n3, tmp;
-// Prog *p1;
-// uint32 w;
-// uint64 v;
-// Type *t;
-
-// if(debug['g']) {
-// dump("\nagen-res", res);
-// dump("agen-r", n);
-// }
-// if(n == N || n->type == T)
-// return;
-
-// if(!isptr[res->type->etype])
-// fatal("agen: not tptr: %T", res->type);
-
-// if(n->addable) {
-// regalloc(&n1, types[tptr], res);
-// gins(ALEAQ, n, &n1);
-// gmove(&n1, res);
-// regfree(&n1);
-// goto ret;
-// }
-
-// nl = n->left;
-// nr = n->right;
-
-// switch(n->op) {
-// default:
-// fatal("agen: unknown op %N", n);
-// break;
-
-// case OCONV:
-// if(!eqtype(n->type, nl->type, 0))
-// fatal("agen: non-trivial OCONV");
-// agen(nl, res);
-// return;
-
-// case OCALLMETH:
-// cgen_callmeth(n, 0);
-// cgen_aret(n, res);
-// break;
-
-// case OCALLINTER:
-// cgen_callinter(n, res, 0);
-// cgen_aret(n, res);
-// break;
-
-// case OCALL:
-// cgen_call(n, 0);
-// cgen_aret(n, res);
-// break;
-
-// case OINDEX:
-// w = n->type->width;
-// if(nr->addable)
-// goto irad;
-// if(nl->addable) {
-// if(!isconst(nr, CTINT)) {
-// regalloc(&n1, nr->type, N);
-// cgen(nr, &n1);
-// }
-// regalloc(&n3, types[tptr], res);
-// agen(nl, &n3);
-// goto index;
-// }
-// cgen(nr, res);
-// tempname(&tmp, nr->type);
-// gmove(res, &tmp);
-
-// irad:
-// regalloc(&n3, types[tptr], res);
-// agen(nl, &n3);
-// if(!isconst(nr, CTINT)) {
-// regalloc(&n1, nr->type, N);
-// cgen(nr, &n1);
-// }
-// goto index;
-
-// index:
-// // &a is in &n3 (allocated in res)
-// // i is in &n1 (if not constant)
-// // w is width
-
-// if(w == 0)
-// fatal("index is zero width");
-
-// // constant index
-// if(isconst(nr, CTINT)) {
-// v = mpgetfix(nr->val.u.xval);
-// if(isslice(nl->type)) {
-
-// if(!debug['B']) {
-// n1 = n3;
-// n1.op = OINDREG;
-// n1.type = types[tptr];
-// n1.xoffset = Array_nel;
-// nodconst(&n2, types[TUINT64], v);
-// gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
-// p1 = gbranch(optoas(OGT, types[TUINT32]), T);
-// ginscall(throwindex, 0);
-// patch(p1, pc);
-// }
-
-// n1 = n3;
-// n1.op = OINDREG;
-// n1.type = types[tptr];
-// n1.xoffset = Array_array;
-// gmove(&n1, &n3);
-// } else
-// if(!debug['B']) {
-// 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);
-// gins(optoas(OADD, types[tptr]), &n2, &n3);
-
-// gmove(&n3, res);
-// regfree(&n3);
-// break;
-// }
-
-// // type of the index
-// t = types[TUINT64];
-// if(issigned[n1.type->etype])
-// t = types[TINT64];
-
-// regalloc(&n2, t, &n1); // i
-// gmove(&n1, &n2);
-// regfree(&n1);
-
-// if(!debug['B']) {
-// // check bounds
-// if(isslice(nl->type)) {
-// n1 = n3;
-// n1.op = OINDREG;
-// n1.type = types[tptr];
-// n1.xoffset = Array_nel;
-// } else
-// nodconst(&n1, types[TUINT64], nl->type->bound);
-// gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
-// p1 = gbranch(optoas(OLT, types[TUINT32]), T);
-// ginscall(throwindex, 0);
-// patch(p1, pc);
-// }
-
-// if(isslice(nl->type)) {
-// n1 = n3;
-// n1.op = OINDREG;
-// n1.type = types[tptr];
-// n1.xoffset = Array_array;
-// gmove(&n1, &n3);
-// }
-
-// if(w == 1 || w == 2 || w == 4 || w == 8) {
-// p1 = gins(ALEAQ, &n2, &n3);
-// p1->from.scale = w;
-// p1->from.index = p1->from.type;
-// p1->from.type = p1->to.type + D_INDIR;
-// } else {
-// nodconst(&n1, t, w);
-// gins(optoas(OMUL, t), &n1, &n2);
-// gins(optoas(OADD, types[tptr]), &n2, &n3);
-// gmove(&n3, res);
-// }
-
-// gmove(&n3, res);
-// regfree(&n2);
-// regfree(&n3);
-// break;
-
-// case ONAME:
-// // should only get here with names in this func.
-// if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
-// dump("bad agen", n);
-// fatal("agen: bad ONAME funcdepth %d != %d",
-// n->funcdepth, funcdepth);
-// }
-
-// // should only get here for heap vars or paramref
-// if(!(n->class & PHEAP) && n->class != PPARAMREF) {
-// dump("bad agen", n);
-// fatal("agen: bad ONAME class %#x", n->class);
-// }
-// cgen(n->heapaddr, res);
-// if(n->xoffset != 0) {
-// nodconst(&n1, types[TINT64], n->xoffset);
-// gins(optoas(OADD, types[tptr]), &n1, res);
-// }
-// break;
-
-// case OIND:
-// cgen(nl, res);
-// break;
-
-// case ODOT:
-// t = nl->type;
-// agen(nl, res);
-// if(n->xoffset != 0) {
-// nodconst(&n1, types[TINT64], n->xoffset);
-// gins(optoas(OADD, types[tptr]), &n1, res);
-// }
-// break;
-
-// case ODOTPTR:
-// t = nl->type;
-// if(!isptr[t->etype])
-// fatal("agen: not ptr %N", n);
-// cgen(nl, res);
-// if(n->xoffset != 0) {
-// nodconst(&n1, types[TINT64], n->xoffset);
-// gins(optoas(OADD, types[tptr]), &n1, res);
-// }
-// break;
-// }
+ fatal("agen not implemented");
+// Node *nl, *nr;
+// Node n1, n2, n3, tmp;
+// Prog *p1;
+// uint32 w;
+// uint64 v;
+// Type *t;
+
+// if(debug['g']) {
+// dump("\nagen-res", res);
+// dump("agen-r", n);
+// }
+// if(n == N || n->type == T)
+// return;
+
+// if(!isptr[res->type->etype])
+// fatal("agen: not tptr: %T", res->type);
+
+// if(n->addable) {
+// regalloc(&n1, types[tptr], res);
+// gins(ALEAQ, n, &n1);
+// gmove(&n1, res);
+// regfree(&n1);
+// goto ret;
+// }
+
+// nl = n->left;
+// nr = n->right;
+
+// switch(n->op) {
+// default:
+// fatal("agen: unknown op %N", n);
+// break;
+
+// case OCONV:
+// if(!cvttype(n->type, nl->type))
+// fatal("agen: non-trivial OCONV");
+// agen(nl, res);
+// return;
+
+// case OCALLMETH:
+// cgen_callmeth(n, 0);
+// cgen_aret(n, res);
+// break;
+
+// case OCALLINTER:
+// cgen_callinter(n, res, 0);
+// cgen_aret(n, res);
+// break;
+
+// case OCALL:
+// cgen_call(n, 0);
+// cgen_aret(n, res);
+// break;
+
+// TODO(kaib): Use the OINDEX case from 8g instead of this one.
+// case OINDEX:
+// w = n->type->width;
+// if(nr->addable)
+// goto irad;
+// if(nl->addable) {
+// if(!isconst(nr, CTINT)) {
+// regalloc(&n1, nr->type, N);
+// cgen(nr, &n1);
+// }
+// regalloc(&n3, types[tptr], res);
+// agen(nl, &n3);
+// goto index;
+// }
+// cgen(nr, res);
+// tempname(&tmp, nr->type);
+// gmove(res, &tmp);
+
+// irad:
+// regalloc(&n3, types[tptr], res);
+// agen(nl, &n3);
+// if(!isconst(nr, CTINT)) {
+// regalloc(&n1, nr->type, N);
+// cgen(nr, &n1);
+// }
+// goto index;
+
+// index:
+// // &a is in &n3 (allocated in res)
+// // i is in &n1 (if not constant)
+// // w is width
+
+// if(w == 0)
+// fatal("index is zero width");
+
+// // constant index
+// if(isconst(nr, CTINT)) {
+// v = mpgetfix(nr->val.u.xval);
+// if(isslice(nl->type)) {
+
+// if(!debug['B']) {
+// n1 = n3;
+// n1.op = OINDREG;
+// n1.type = types[tptr];
+// n1.xoffset = Array_nel;
+// nodconst(&n2, types[TUINT64], v);
+// gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
+// p1 = gbranch(optoas(OGT, types[TUINT32]), T);
+// ginscall(throwindex, 0);
+// patch(p1, pc);
+// }
+
+// n1 = n3;
+// n1.op = OINDREG;
+// n1.type = types[tptr];
+// n1.xoffset = Array_array;
+// gmove(&n1, &n3);
+// } else
+// if(!debug['B']) {
+// 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);
+// gins(optoas(OADD, types[tptr]), &n2, &n3);
+
+// gmove(&n3, res);
+// regfree(&n3);
+// break;
+// }
+
+// // type of the index
+// t = types[TUINT64];
+// if(issigned[n1.type->etype])
+// t = types[TINT64];
+
+// regalloc(&n2, t, &n1); // i
+// gmove(&n1, &n2);
+// regfree(&n1);
+
+// if(!debug['B']) {
+// // check bounds
+// if(isslice(nl->type)) {
+// n1 = n3;
+// n1.op = OINDREG;
+// n1.type = types[tptr];
+// n1.xoffset = Array_nel;
+// } else
+// nodconst(&n1, types[TUINT64], nl->type->bound);
+// gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
+// p1 = gbranch(optoas(OLT, types[TUINT32]), T);
+// ginscall(throwindex, 0);
+// patch(p1, pc);
+// }
+
+// if(isslice(nl->type)) {
+// n1 = n3;
+// n1.op = OINDREG;
+// n1.type = types[tptr];
+// n1.xoffset = Array_array;
+// gmove(&n1, &n3);
+// }
+
+// if(w == 1 || w == 2 || w == 4 || w == 8) {
+// p1 = gins(ALEAQ, &n2, &n3);
+// p1->from.scale = w;
+// p1->from.index = p1->from.type;
+// p1->from.type = p1->to.type + D_INDIR;
+// } else {
+// nodconst(&n1, t, w);
+// gins(optoas(OMUL, t), &n1, &n2);
+// gins(optoas(OADD, types[tptr]), &n2, &n3);
+// gmove(&n3, res);
+// }
+
+// gmove(&n3, res);
+// regfree(&n2);
+// regfree(&n3);
+// break;
+
+// case ONAME:
+// // should only get here with names in this func.
+// if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
+// dump("bad agen", n);
+// fatal("agen: bad ONAME funcdepth %d != %d",
+// n->funcdepth, funcdepth);
+// }
+
+// // should only get here for heap vars or paramref
+// if(!(n->class & PHEAP) && n->class != PPARAMREF) {
+// dump("bad agen", n);
+// fatal("agen: bad ONAME class %#x", n->class);
+// }
+// cgen(n->heapaddr, res);
+// if(n->xoffset != 0) {
+// nodconst(&n1, types[TINT64], n->xoffset);
+// gins(optoas(OADD, types[tptr]), &n1, res);
+// }
+// break;
+
+// case OIND:
+// cgen(nl, res);
+// break;
+
+// case ODOT:
+// agen(nl, res);
+// if(n->xoffset != 0) {
+// nodconst(&n1, types[TINT64], n->xoffset);
+// gins(optoas(OADD, types[tptr]), &n1, res);
+// }
+// break;
+
+// case ODOTPTR:
+// cgen(nl, res);
+// if(n->xoffset != 0) {
+// nodconst(&n1, types[TINT64], n->xoffset);
+// gins(optoas(OADD, types[tptr]), &n1, res);
+// }
+// break;
+// }
// ret:
-// ;
+// ;
}
/*
@@ -602,197 +603,198 @@ igen(Node *n, Node *a, Node *res)
void
bgen(Node *n, int true, Prog *to)
{
-// zzz
-// fatal("bgen_unimplemented");
-// int et, a;
-// Node *nl, *nr, *r;
-// Node n1, n2, tmp;
-// Prog *p1, *p2;
-
-// if(debug['g']) {
-// dump("\nbgen", n);
-// }
-
-// if(n == N)
-// n = nodbool(1);
-
-// nl = n->left;
-// nr = n->right;
-
-// if(n->type == T) {
-// convlit(n, types[TBOOL]);
-// if(n->type == T)
-// goto ret;
-// }
-
-// et = n->type->etype;
-// if(et != TBOOL) {
-// yyerror("cgen: bad type %T for %O", n->type, n->op);
-// patch(gins(AEND, N, N), to);
-// goto ret;
-// }
-// nl = N;
-// nr = N;
-
-// switch(n->op) {
-// default:
-// regalloc(&n1, n->type, N);
-// cgen(n, &n1);
-// nodconst(&n2, n->type, 0);
-// gins(optoas(OCMP, n->type), &n1, &n2);
-// a = AJNE;
-// if(!true)
-// a = AJEQ;
-// patch(gbranch(a, n->type), to);
-// regfree(&n1);
-// goto ret;
-
-// case OLITERAL:
-// // need to ask if it is bool?
-// if(!true == !n->val.u.bval)
-// patch(gbranch(AB, T), to);
-// goto ret;
-
-// case ONAME:
-// nodconst(&n1, n->type, 0);
-// gins(optoas(OCMP, n->type), n, &n1);
-// a = AJNE;
-// if(!true)
-// a = AJEQ;
-// patch(gbranch(a, n->type), to);
-// goto ret;
-
-// case OANDAND:
-// if(!true)
-// goto caseor;
-
-// caseand:
-// p1 = gbranch(AB, T);
-// p2 = gbranch(AB, T);
-// patch(p1, pc);
-// bgen(n->left, !true, p2);
-// bgen(n->right, !true, p2);
-// p1 = gbranch(AB, T);
-// patch(p1, to);
-// patch(p2, pc);
-// goto ret;
-
-// case OOROR:
-// if(!true)
-// goto caseand;
-
-// caseor:
-// bgen(n->left, true, to);
-// bgen(n->right, true, to);
-// goto ret;
-
-// case OEQ:
-// case ONE:
-// case OLT:
-// case OGT:
-// case OLE:
-// case OGE:
-// nr = n->right;
-// if(nr == N || nr->type == T)
-// goto ret;
-
-// case ONOT: // unary
-// nl = n->left;
-// if(nl == N || nl->type == T)
-// goto ret;
-// }
-
-// switch(n->op) {
-
-// case ONOT:
-// bgen(nl, !true, to);
-// goto ret;
-
-// case OEQ:
-// case ONE:
-// case OLT:
-// case OGT:
-// case OLE:
-// case OGE:
-// a = n->op;
-// if(!true)
-// a = brcom(a);
-
-// // make simplest on right
-// if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
-// a = brrev(a);
-// r = nl;
-// nl = nr;
-// nr = r;
-// }
-
-// if(isslice(nl->type)) {
-// // only valid to cmp darray to literal nil
-// if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
-// yyerror("illegal array comparison");
-// break;
-// }
-// a = optoas(a, types[tptr]);
-// regalloc(&n1, types[tptr], N);
-// agen(nl, &n1);
-// n2 = n1;
-// n2.op = OINDREG;
-// n2.xoffset = Array_array;
-// nodconst(&tmp, types[tptr], 0);
-// gins(optoas(OCMP, types[tptr]), &n2, &tmp);
-// patch(gbranch(a, types[tptr]), to);
-// regfree(&n1);
-// break;
-// }
-
-// a = optoas(a, nr->type);
-
-// if(nr->ullman >= UINF) {
-// regalloc(&n1, nr->type, N);
-// cgen(nr, &n1);
-
-// tempname(&tmp, nr->type);
-// gmove(&n1, &tmp);
-// regfree(&n1);
-
-// regalloc(&n1, nl->type, N);
-// cgen(nl, &n1);
-
-// regalloc(&n2, nr->type, &n2);
-// cgen(&tmp, &n2);
-
-// gins(optoas(OCMP, nr->type), &n1, &n2);
-// patch(gbranch(a, nr->type), to);
-
-// regfree(&n1);
-// regfree(&n2);
-// break;
-// }
-
-// regalloc(&n1, nl->type, N);
-// cgen(nl, &n1);
-
-// if(smallintconst(nr)) {
-// gins(optoas(OCMP, nr->type), &n1, nr);
-// patch(gbranch(a, nr->type), to);
-// regfree(&n1);
-// break;
-// }
-
-// regalloc(&n2, nr->type, N);
-// cgen(nr, &n2);
-
-// gins(optoas(OCMP, nr->type), &n1, &n2);
-// patch(gbranch(a, nr->type), to);
-
-// regfree(&n1);
-// regfree(&n2);
-// break;
-// }
-// goto ret;
+ int et, a;
+ Node *nl, *nr, *r;
+ Node n1, n2, tmp;
+ Prog *p1, *p2;
-// ret:
-// ;
+ if(debug['g']) {
+ dump("\nbgen", n);
+ }
+
+ if(n == N)
+ n = nodbool(1);
+
+ nl = n->left;
+ nr = n->right;
+
+ if(n->type == T) {
+ convlit(n, types[TBOOL]);
+ if(n->type == T)
+ goto ret;
+ }
+
+ et = n->type->etype;
+ if(et != TBOOL) {
+ yyerror("cgen: bad type %T for %O", n->type, n->op);
+ patch(gins(AEND, N, N), to);
+ goto ret;
+ }
+ nl = N;
+ nr = N;
+
+ switch(n->op) {
+ default:
+ def:
+ regalloc(&n1, n->type, N);
+ cgen(n, &n1);
+ nodconst(&n2, n->type, 0);
+ gins(optoas(OCMP, n->type), &n1, &n2);
+ a = ABNE;
+ if(!true)
+ a = ABEQ;
+ patch(gbranch(a, n->type), to);
+ regfree(&n1);
+ goto ret;
+
+ case OLITERAL:
+ // need to ask if it is bool?
+ if(!true == !n->val.u.bval)
+ patch(gbranch(AB, T), to);
+ goto ret;
+
+ case ONAME:
+ if(n->addable == 0)
+ goto def;
+ nodconst(&n1, n->type, 0);
+ gins(optoas(OCMP, n->type), n, &n1);
+ a = ABNE;
+ if(!true)
+ a = ABEQ;
+ patch(gbranch(a, n->type), to);
+ goto ret;
+
+ case OANDAND:
+ if(!true)
+ goto caseor;
+
+ caseand:
+ p1 = gbranch(AB, T);
+ p2 = gbranch(AB, T);
+ patch(p1, pc);
+ bgen(n->left, !true, p2);
+ bgen(n->right, !true, p2);
+ p1 = gbranch(AB, T);
+ patch(p1, to);
+ patch(p2, pc);
+ goto ret;
+
+ case OOROR:
+ if(!true)
+ goto caseand;
+
+ caseor:
+ bgen(n->left, true, to);
+ bgen(n->right, true, to);
+ goto ret;
+
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OGT:
+ case OLE:
+ case OGE:
+ nr = n->right;
+ if(nr == N || nr->type == T)
+ goto ret;
+
+ case ONOT: // unary
+ nl = n->left;
+ if(nl == N || nl->type == T)
+ goto ret;
+ }
+
+ switch(n->op) {
+
+ case ONOT:
+ bgen(nl, !true, to);
+ goto ret;
+
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OGT:
+ case OLE:
+ case OGE:
+ a = n->op;
+ if(!true)
+ a = brcom(a);
+
+ // make simplest on right
+ if(nl->op == OLITERAL || nl->ullman < nr->ullman) {
+ a = brrev(a);
+ r = nl;
+ nl = nr;
+ nr = r;
+ }
+
+ if(isslice(nl->type)) {
+ // only valid to cmp darray to literal nil
+ if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
+ yyerror("illegal array comparison");
+ break;
+ }
+ a = optoas(a, types[tptr]);
+ regalloc(&n1, types[tptr], N);
+ agen(nl, &n1);
+ n2 = n1;
+ n2.op = OINDREG;
+ n2.xoffset = Array_array;
+ nodconst(&tmp, types[tptr], 0);
+ gins(optoas(OCMP, types[tptr]), &n2, &tmp);
+ patch(gbranch(a, types[tptr]), to);
+ regfree(&n1);
+ break;
+ }
+
+ a = optoas(a, nr->type);
+
+ if(nr->ullman >= UINF) {
+ regalloc(&n1, nr->type, N);
+ cgen(nr, &n1);
+
+ tempname(&tmp, nr->type);
+ gmove(&n1, &tmp);
+ regfree(&n1);
+
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
+
+ regalloc(&n2, nr->type, &n2);
+ cgen(&tmp, &n2);
+
+ gins(optoas(OCMP, nr->type), &n1, &n2);
+ patch(gbranch(a, nr->type), to);
+
+ regfree(&n1);
+ regfree(&n2);
+ break;
+ }
+
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
+
+ if(smallintconst(nr)) {
+ gins(optoas(OCMP, nr->type), &n1, nr);
+ patch(gbranch(a, nr->type), to);
+ regfree(&n1);
+ break;
+ }
+
+ regalloc(&n2, nr->type, N);
+ cgen(nr, &n2);
+
+ gins(optoas(OCMP, nr->type), &n1, &n2);
+ patch(gbranch(a, nr->type), to);
+
+ regfree(&n1);
+ regfree(&n2);
+ break;
+ }
+ goto ret;
+
+ret:
+ ;
}
/*
@@ -835,89 +837,89 @@ stkof(Node *n)
void
sgen(Node *n, Node *ns, int32 w)
{
- fatal("sgen_unimplemented");
-// Node nodl, nodr;
-// int32 c, q, odst, osrc;
-
-// if(debug['g']) {
-// print("\nsgen w=%d\n", w);
-// dump("r", n);
-// dump("res", ns);
-// }
-// if(w == 0)
-// return;
-// if(n->ullman >= UINF && ns->ullman >= UINF) {
-// fatal("sgen UINF");
-// }
-
-// if(w < 0)
-// fatal("sgen copy %d", w);
-
-// // offset on the stack
-// osrc = stkof(n);
-// odst = stkof(ns);
-
-// nodreg(&nodl, types[tptr], D_DI);
-// nodreg(&nodr, types[tptr], D_SI);
-
-// if(n->ullman >= ns->ullman) {
-// agen(n, &nodr);
-// agen(ns, &nodl);
-// } else {
-// agen(ns, &nodl);
-// agen(n, &nodr);
-// }
-
-// c = w % 8; // bytes
-// q = w / 8; // quads
-
-// // if we are copying forward on the stack and
-// // the src and dst overlap, then reverse direction
-// if(osrc < odst && odst < osrc+w) {
-// // reverse direction
-// gins(ASTD, N, N); // set direction flag
-// if(c > 0) {
-// gconreg(AADDQ, w-1, D_SI);
-// gconreg(AADDQ, w-1, D_DI);
-
-// gconreg(AMOVQ, c, D_CX);
-// gins(AREP, N, N); // repeat
-// gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
-// }
-
-// if(q > 0) {
-// if(c > 0) {
-// gconreg(AADDQ, -7, D_SI);
-// gconreg(AADDQ, -7, D_DI);
-// } else {
-// gconreg(AADDQ, w-8, D_SI);
-// gconreg(AADDQ, w-8, D_DI);
-// }
-// gconreg(AMOVQ, q, D_CX);
-// gins(AREP, N, N); // repeat
-// gins(AMOVSQ, N, N); // MOVQ *(SI)-,*(DI)-
-// }
-// // we leave with the flag clear
-// gins(ACLD, N, N);
-// } else {
-// // normal direction
-// if(q >= 4) {
-// gconreg(AMOVQ, q, D_CX);
-// gins(AREP, N, N); // repeat
-// gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
-// } else
-// while(q > 0) {
-// gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
-// q--;
-// }
-
-// if(c >= 4) {
-// gins(AMOVSL, N, N); // MOVL *(SI)+,*(DI)+
-// c -= 4;
-// }
-// while(c > 0) {
-// gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
-// c--;
-// }
-// }
+ fatal("sgen not implemented");
+// Node nodl, nodr;
+// int32 c, q, odst, osrc;
+
+// if(debug['g']) {
+// print("\nsgen w=%d\n", w);
+// dump("r", n);
+// dump("res", ns);
+// }
+// if(w == 0)
+// return;
+// if(n->ullman >= UINF && ns->ullman >= UINF) {
+// fatal("sgen UINF");
+// }
+
+// if(w < 0)
+// fatal("sgen copy %d", w);
+
+// // offset on the stack
+// osrc = stkof(n);
+// odst = stkof(ns);
+
+// nodreg(&nodl, types[tptr], D_DI);
+// nodreg(&nodr, types[tptr], D_SI);
+
+// if(n->ullman >= ns->ullman) {
+// agen(n, &nodr);
+// agen(ns, &nodl);
+// } else {
+// agen(ns, &nodl);
+// agen(n, &nodr);
+// }
+
+// c = w % 8; // bytes
+// q = w / 8; // quads
+
+// // if we are copying forward on the stack and
+// // the src and dst overlap, then reverse direction
+// if(osrc < odst && odst < osrc+w) {
+// // reverse direction
+// gins(ASTD, N, N); // set direction flag
+// if(c > 0) {
+// gconreg(AADDQ, w-1, D_SI);
+// gconreg(AADDQ, w-1, D_DI);
+
+// gconreg(AMOVQ, c, D_CX);
+// gins(AREP, N, N); // repeat
+// gins(AMOVSB, N, N); // MOVB *(SI)-,*(DI)-
+// }
+
+// if(q > 0) {
+// if(c > 0) {
+// gconreg(AADDQ, -7, D_SI);
+// gconreg(AADDQ, -7, D_DI);
+// } else {
+// gconreg(AADDQ, w-8, D_SI);
+// gconreg(AADDQ, w-8, D_DI);
+// }
+// gconreg(AMOVQ, q, D_CX);
+// gins(AREP, N, N); // repeat
+// gins(AMOVSQ, N, N); // MOVQ *(SI)-,*(DI)-
+// }
+// // we leave with the flag clear
+// gins(ACLD, N, N);
+// } else {
+// // normal direction
+// if(q >= 4) {
+// gconreg(AMOVQ, q, D_CX);
+// gins(AREP, N, N); // repeat
+// gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
+// } else
+// while(q > 0) {
+// gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
+// q--;
+// }
+
+// if(c >= 4) {
+// gins(AMOVSL, N, N); // MOVL *(SI)+,*(DI)+
+// c -= 4;
+// }
+// while(c > 0) {
+// gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
+// c--;
+// }
+// }
}