mirror of
https://github.com/golang/go
synced 2024-10-04 03:21:22 -06:00
148 lines
2.3 KiB
C
148 lines
2.3 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"
|
||
|
|
||
|
#define CASE(a,b) (((a)<<16)|((b)<<0))
|
||
|
|
||
|
/*
|
||
|
* generate:
|
||
|
* res = n;
|
||
|
* simplifies and calls gmove.
|
||
|
*/
|
||
|
void
|
||
|
complexmove(Node *f, Node *t)
|
||
|
{
|
||
|
int ft, tt;
|
||
|
Node n1, n2;
|
||
|
|
||
|
if(debug['g']) {
|
||
|
dump("\ncomplex-f", f);
|
||
|
dump("complex-t", t);
|
||
|
}
|
||
|
|
||
|
if(!t->addable)
|
||
|
fatal("to no addable");
|
||
|
|
||
|
ft = cplxsubtype(simsimtype(f->type));
|
||
|
tt = cplxsubtype(simsimtype(t->type));
|
||
|
|
||
|
// copy halfs of complex literal
|
||
|
if(f->op == OLITERAL) {
|
||
|
// real part
|
||
|
nodfconst(&n1, types[ft], &f->val.u.cval->real);
|
||
|
n2 = *t;
|
||
|
n2.type = types[tt];
|
||
|
gmove(&n1, &n2);
|
||
|
|
||
|
// imag part
|
||
|
nodfconst(&n1, types[ft], &f->val.u.cval->imag);
|
||
|
n2.xoffset += n2.type->width;
|
||
|
gmove(&n1, &n2);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// make from addable
|
||
|
if(!f->addable) {
|
||
|
tempname(&n1, f->type);
|
||
|
complexgen(f, &n1);
|
||
|
f = &n1;
|
||
|
}
|
||
|
|
||
|
// real part
|
||
|
n1 = *f;
|
||
|
n1.type = types[ft];
|
||
|
|
||
|
n2 = *t;
|
||
|
n2.type = types[tt];
|
||
|
|
||
|
gmove(&n1, &n2);
|
||
|
|
||
|
// imag part
|
||
|
n1.xoffset += n1.type->width;
|
||
|
n2.xoffset += n2.type->width;
|
||
|
gmove(&n1, &n2);
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
complexgen(Node *n, Node *res)
|
||
|
{
|
||
|
Node *nl, *nr;
|
||
|
Node n1, n2;
|
||
|
int tl, tr;
|
||
|
|
||
|
if(debug['g']) {
|
||
|
dump("\ncomplex-n", n);
|
||
|
dump("complex-res", res);
|
||
|
}
|
||
|
|
||
|
// perform conversion from n to res
|
||
|
tl = simsimtype(res->type);
|
||
|
tl = cplxsubtype(tl);
|
||
|
tr = simsimtype(n->type);
|
||
|
tr = cplxsubtype(tr);
|
||
|
if(tl != tr) {
|
||
|
tempname(&n1, n->type);
|
||
|
complexgen(n, &n1);
|
||
|
complexmove(&n1, n);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
nl = n->left;
|
||
|
if(nl == N)
|
||
|
return;
|
||
|
|
||
|
nr = n->right;
|
||
|
if(nr != N) {
|
||
|
// make both sides addable in ullman order
|
||
|
if(nl->ullman > nr->ullman) {
|
||
|
if(!nl->addable) {
|
||
|
tempname(&n1, nl->type);
|
||
|
complexgen(nl, &n1);
|
||
|
nl = &n1;
|
||
|
}
|
||
|
if(!nr->addable) {
|
||
|
tempname(&n1, nr->type);
|
||
|
complexgen(nr, &n2);
|
||
|
nr = &n2;
|
||
|
}
|
||
|
} else {
|
||
|
if(!nr->addable) {
|
||
|
tempname(&n1, nr->type);
|
||
|
complexgen(nr, &n2);
|
||
|
nr = &n2;
|
||
|
}
|
||
|
if(!nl->addable) {
|
||
|
tempname(&n1, nl->type);
|
||
|
complexgen(nl, &n1);
|
||
|
nl = &n1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
switch(n->op) {
|
||
|
default:
|
||
|
fatal("opcode %O", n->op);
|
||
|
break;
|
||
|
|
||
|
case OADD:
|
||
|
case OSUB:
|
||
|
case OMUL:
|
||
|
case ODIV:
|
||
|
if(nr == N)
|
||
|
fatal("");
|
||
|
fatal("opcode %O", n->op);
|
||
|
break;
|
||
|
|
||
|
case OMINUS:
|
||
|
fatal("opcode %O", n->op);
|
||
|
break;
|
||
|
|
||
|
case OCONV:
|
||
|
complexmove(nl, res);
|
||
|
break;
|
||
|
}
|
||
|
}
|