mirror of
https://github.com/golang/go
synced 2024-11-14 22:30:26 -07:00
924 lines
18 KiB
C
924 lines
18 KiB
C
|
// 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"
|
||
|
|
||
|
/*
|
||
|
* generate:
|
||
|
* res = n;
|
||
|
* simplifies and calls gmove.
|
||
|
*/
|
||
|
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;
|
||
|
|
||
|
// ret:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* generate:
|
||
|
* res = &n;
|
||
|
*/
|
||
|
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;
|
||
|
// }
|
||
|
|
||
|
// ret:
|
||
|
// ;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* generate:
|
||
|
* newreg = &n;
|
||
|
* res = newreg
|
||
|
*
|
||
|
* on exit, a has been changed to be *newreg.
|
||
|
* caller must regfree(a).
|
||
|
*/
|
||
|
void
|
||
|
igen(Node *n, Node *a, Node *res)
|
||
|
{
|
||
|
regalloc(a, types[tptr], res);
|
||
|
agen(n, a);
|
||
|
a->op = OINDREG;
|
||
|
a->type = n->type;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* generate:
|
||
|
* if(n == true) goto to;
|
||
|
*/
|
||
|
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;
|
||
|
|
||
|
// ret:
|
||
|
// ;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* n is on stack, either local variable
|
||
|
* or return value from function call.
|
||
|
* return n's offset from SP.
|
||
|
*/
|
||
|
int32
|
||
|
stkof(Node *n)
|
||
|
{
|
||
|
Type *t;
|
||
|
Iter flist;
|
||
|
|
||
|
switch(n->op) {
|
||
|
case OINDREG:
|
||
|
return n->xoffset;
|
||
|
|
||
|
case OCALLMETH:
|
||
|
case OCALLINTER:
|
||
|
case OCALL:
|
||
|
t = n->left->type;
|
||
|
if(isptr[t->etype])
|
||
|
t = t->type;
|
||
|
|
||
|
t = structfirst(&flist, getoutarg(t));
|
||
|
if(t != T)
|
||
|
return t->width;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// botch - probably failing to recognize address
|
||
|
// arithmetic on the above. eg INDEX and DOT
|
||
|
return -1000;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* block copy:
|
||
|
* memmove(&n, &ns, w);
|
||
|
*/
|
||
|
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--;
|
||
|
// }
|
||
|
// }
|
||
|
}
|