Add compiler source to new directory structure
SVN=121164
diff --git a/src/cmd/6g/cgen.c b/src/cmd/6g/cgen.c
new file mode 100644
index 0000000..7a00688
--- /dev/null
+++ b/src/cmd/6g/cgen.c
@@ -0,0 +1,638 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "gg.h"
+
+void
+cgen(Node *n, Node *res)
+{
+ long lno;
+ Node *nl, *nr, *r;
+ Node n1, tmp;
+ int a;
+ Prog *p1, *p2, *p3;
+
+ if(debug['g']) {
+ dump("\ncgen-l", res);
+ dump("cgen-r", n);
+ }
+ if(n == N || n->type == T)
+ return;
+ if(res == N || res->type == T)
+ fatal("cgen: res nil");
+
+ lno = dynlineno;
+ if(n->op != ONAME)
+ dynlineno = n->lineno; // for diagnostics
+
+ if(isfat(n->type)) {
+ sgen(n, res, n->type->width);
+ goto ret;
+ }
+
+ if(!res->addable) {
+ 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) {
+ fatal("cgen: both sides functions");
+ 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(AJMP, T);
+ p2 = pc;
+ gmove(booltrue, res);
+ p3 = gbranch(AJMP, T);
+ patch(p1, pc);
+ bgen(n, 1, p2);
+ gmove(boolfalse, res);
+ patch(p3, pc);
+ goto ret;
+
+ case OPLUS:
+ cgen(nl, res);
+ goto ret;
+
+ // unary
+ case OMINUS:
+ case OCOM:
+ 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);
+ goto sbop;
+
+ // asymmetric binary
+ case OMOD:
+ case OSUB:
+ case ODIV:
+ case OLSH:
+ case ORSH:
+ 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 OINDEXPTRSTR:
+// nl = n->left;
+// nr = n->right;
+// if(nl->addable) {
+// cgen(nr);
+// cgen(nl);
+// gopcode(P_LOADI, T_ADDR, N);
+// gopcodet(P_INDEXZ, nr->type, N);
+// break;
+// }
+// break;
+
+// case OINDEXSTR:
+// nl = n->left;
+// nr = n->right;
+// if(nl->addable) {
+// cgen(nr);
+// gopcodet(P_INDEXZ, nr->type, nl);
+// break;
+// }
+// cgen(nl);
+// r = tempname(nl->type);
+// gopcodet(P_STORE, nl->type, r);
+// cgen(nr);
+// gopcodet(P_INDEXZ, nr->type, r);
+// break;
+
+// case OSLICESTR:
+// case OSLICEPTRSTR:
+// nl = n->left; // name
+// nr = n->right;
+//
+// r = nr->right; // index2
+// if(!r->addable) {
+// cgen(r);
+// r = tempname(r->type);
+// gopcodet(P_STORE, r->type, r);
+// }
+//
+// // string into T_ADDR
+// if(!nl->addable) {
+// cgen(nl);
+// gconv(T_ADDR, nl->type->etype);
+// } else
+// gopcode(P_LOAD, T_ADDR, nl);
+//
+// if(n->op == OSLICEPTRSTR)
+// gopcode(P_LOADI, T_ADDR, N);
+//
+// // offset in int reg
+// cgen(nr->left);
+//
+// // index 2 addressed
+// gopcodet(P_SLICE, r->type, r);
+// break;
+
+ case OS2I:
+ case OI2I:
+ case OI2S:
+
+ case OINDEXPTR:
+ case OINDEX:
+ case ODOT:
+ case ODOTPTR:
+ case OIND:
+ igen(n, &n1, res);
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+
+ case OLEN:
+ if(isptrto(nl->type, TSTRING)) {
+ regalloc(&n1, types[tptr], res);
+ cgen(nl, res);
+ n1.op = OINDREG;
+ n1.type = types[TINT32];
+ gmove(&n1, res);
+ regfree(&n1);
+ break;
+ }
+ fatal("cgen: OLEN: unknown type %lT", nl->type);
+ break;
+
+// case ODOTMETH:
+// case ODOTINTER:
+// cgen(n->left);
+// break;
+
+ case OADDR:
+ agen(nl, res);
+ break;
+
+ case OCALLMETH:
+ cgen_callmeth(n);
+ cgen_callret(n, res);
+ break;
+
+ case OCALLINTER:
+ cgen_callinter(n, res);
+ cgen_callret(n, res);
+ break;
+
+ case OCALL:
+ cgen_call(n);
+ cgen_callret(n, res);
+ break;
+ }
+ goto ret;
+
+sbop: // symmetric binary
+ if(nl->ullman < nr->ullman) {
+ r = nl;
+ nl = nr;
+ nr = r;
+ }
+
+abop: // asymmetric binary
+ if(nr->addable) {
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ gins(a, nr, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ goto ret;
+ }
+
+ tempname(&tmp, nr->type);
+ regalloc(&n1, nr->type, res);
+ cgen(nr, &n1);
+ gmove(&n1, &tmp);
+ regfree(&n1);
+
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ gins(a, &tmp, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ goto ret;
+
+uop: // unary
+ regalloc(&n1, nl->type, res);
+ cgen(nl, &n1);
+ gins(a, N, &n1);
+ gmove(&n1, res);
+ regfree(&n1);
+ goto ret;
+
+ret:
+ dynlineno = lno;
+}
+
+void
+agen(Node *n, Node *res)
+{
+ Node *nl, *nr;
+ Node n1, n2, n3, tmp;
+ ulong w;
+ Type *t;
+
+ 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);
+ return;
+ }
+
+ switch(n->op) {
+ default:
+ fatal("agen: unknown op %N", n);
+ break;
+
+// case ONAME:
+// regalloc(&n1, types[tptr], res);
+// gins(optoas(OADDR, types[tptr]), n, &n1);
+// gmove(&n1, res);
+// regfree(&n1);
+// break;
+
+ case OINDEXPTR:
+ nl = n->left;
+ nr = n->right;
+ w = n->type->width;
+ if(nr->addable)
+ goto iprad;
+ if(nl->addable) {
+ regalloc(&n1, nr->type, N);
+ cgen(nr, &n1);
+ cgen(nl, res);
+ goto index;
+ }
+ cgen(nr, res);
+ tempname(&tmp, nr->type);
+ gmove(res, &tmp);
+
+ iprad:
+ cgen(nl, res);
+ regalloc(&n1, nr->type, N);
+ cgen(nr, &n1);
+ goto index;
+
+ case OS2I:
+ case OI2I:
+ case OI2S:
+ agen_inter(n, res);
+ break;
+
+// case OINDREG:
+
+ case OINDEX:
+ nl = n->left;
+ nr = n->right;
+ w = n->type->width;
+ if(nr->addable)
+ goto irad;
+ if(nl->addable) {
+ regalloc(&n1, nr->type, N);
+ cgen(nr, &n1);
+ agen(nl, res);
+ goto index;
+ }
+ cgen(nr, res);
+ tempname(&tmp, nr->type);
+ gmove(res, &tmp);
+
+ irad:
+ agen(nl, res);
+ regalloc(&n1, nr->type, N);
+ cgen(nr, &n1);
+ goto index;
+
+ index:
+ // &a is in res
+ // i is in &n1
+ // w is width
+ if(issigned[n1.type->etype]) {
+ nodconst(&n3, types[TINT64], w); // w/tint64
+ regalloc(&n2, types[TINT64], &n1); // i/int64
+ gmove(&n1, &n2);
+ gins(optoas(OMUL, types[TINT64]), &n3, &n2);
+ gins(optoas(OADD, types[tptr]), &n2, res);
+ regfree(&n1);
+ regfree(&n2);
+ break;
+ }
+ // unsigned multiply is a pain in the ass
+ fatal("agen: unsigned index");
+ break;
+
+// case OIND:
+// nl = n->left;
+// if(nl->addable) {
+// gopcode(P_LOAD, T_ADDR, nl);
+// break;
+// }
+// cgen(nl);
+// gconv(T_ADDR, nl->type->etype);
+// break;
+
+ case ODOT:
+ nl = n->left;
+ 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:
+ nl = n->left;
+ 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;
+ }
+}
+
+vlong
+fieldoffset(Type *t, Node *n)
+{
+ if(t->etype != TSTRUCT)
+ fatal("fieldoffset: not struct %lT", t);
+ if(n->op != ONAME)
+ fatal("fieldoffset: not field name %N", n);
+ return 0;
+}
+
+void
+igen(Node *n, Node *a, Node *res)
+{
+ regalloc(a, types[tptr], res);
+ agen(n, a);
+ a->op = OINDREG;
+ a->type = n->type;
+}
+
+void
+bgen(Node *n, int true, Prog *to)
+{
+ long lno;
+ int et, a, b;
+ Node *nl, *nr, *r;
+ Node n1, n2, tmp;
+ Prog *p1, *p2;
+
+ if(n == N)
+ n = booltrue;
+
+ lno = dynlineno;
+ if(n->op != ONAME)
+ dynlineno = n->lineno; // for diagnostics
+
+ 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:
+ if(!true == !n->val.vval)
+ patch(gbranch(AJMP, 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(AJMP, T);
+ p2 = gbranch(AJMP, T);
+ patch(p1, pc);
+ bgen(n->left, !true, p2);
+ bgen(n->right, !true, p2);
+ p1 = gbranch(AJMP, 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->ullman < nr->ullman) {
+ a = brrev(a);
+ r = nl;
+ nl = nr;
+ nr = r;
+ }
+ a = optoas(a, nr->type);
+
+ if(nr->addable) {
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
+ b = optoas(OCMP, nr->type);
+
+ switch(b) {
+ case ACMPQ:
+ if(nr->op == OLITERAL)
+ if(nr->val.vval >= (1LL<<32))
+ goto dolit;
+
+ case AUCOMISS:
+ if(nr->op == OLITERAL)
+ goto dolit;
+ if(nr->op == ONAME)
+ goto dolit;
+ }
+
+ gins(b, &n1, nr);
+ patch(gbranch(a, nr->type), to);
+ regfree(&n1);
+ break;
+
+ dolit:
+ regalloc(&n2, nr->type, N);
+ cgen(nr, &n2);
+ gins(b, &n1, &n2);
+ patch(gbranch(a, nr->type), to);
+ regfree(&n2);
+ regfree(&n1);
+ break;
+ }
+
+ tempname(&tmp, nr->type);
+ cgen(nr, &tmp);
+
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
+
+ gins(optoas(OCMP, nr->type), &n1, &tmp);
+ patch(gbranch(a, nr->type), to);
+ regfree(&n1);
+ break;
+ }
+ goto ret;
+
+ret:
+ dynlineno = lno;
+}
+
+void
+sgen(Node *n, Node *ns, ulong w)
+{
+ Node nodl, nodr;
+ long c;
+
+ if(w == 0)
+ return;
+ if(n->ullman >= UINF && ns->ullman >= UINF) {
+ fatal("sgen UINF");
+ }
+
+ 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);
+ }
+
+ gins(ACLD, N, N); // clear direction flag
+
+ c = w / 8;
+ if(c > 0) {
+ gconreg(AMOVQ, c, D_CX);
+ gins(AREP, N, N); // repeat
+ gins(AMOVSQ, N, N); // MOVQ *(SI)+,*(DI)+
+ }
+
+ c = w % 8;
+ if(c > 0) {
+ gconreg(AMOVQ, c, D_CX);
+ gins(AREP, N, N); // repeat
+ gins(AMOVSB, N, N); // MOVB *(SI)+,*(DI)+
+ }
+}