1
0
mirror of https://github.com/golang/go synced 2024-10-04 03:21:22 -06:00
go/src/cmd/6g/cplx.c

148 lines
2.3 KiB
C
Raw Normal View History

// 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;
}
}