// 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"

static	void	subnode(Node *nr, Node *ni, Node *nc);
static	void	minus(Node *nl, Node *res);
	void	complexminus(Node*, Node*);
	void	complexadd(int op, Node*, Node*, Node*);
	void	complexmul(Node*, Node*, Node*);

#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, n3, n4;

	if(debug['g']) {
		dump("\ncomplexmove-f", f);
		dump("complexmove-t", t);
	}

	if(!t->addable)
		fatal("complexmove: to not addable");

	ft = simsimtype(f->type);
	tt = simsimtype(t->type);
	switch(CASE(ft,tt)) {

	default:
		fatal("complexmove: unknown conversion: %T -> %T\n",
			f->type, t->type);

	case CASE(TCOMPLEX64,TCOMPLEX64):
	case CASE(TCOMPLEX64,TCOMPLEX128):
	case CASE(TCOMPLEX128,TCOMPLEX64):
	case CASE(TCOMPLEX128,TCOMPLEX128):
		// complex to complex move/convert
		// make from addable
		if(!f->addable) {
			tempname(&n1, f->type);
			complexmove(f, &n1);
			f = &n1;
		}

		subnode(&n1, &n2, f);
		subnode(&n3, &n4, t);

		cgen(&n1, &n3);
		cgen(&n2, &n4);
		break;
	}
}

int
complexop(Node *n, Node *res)
{
	if(n != N && n->type != T)
	if(iscomplex[n->type->etype]) {
		goto maybe;
	}
	if(res != N && res->type != T)
	if(iscomplex[res->type->etype]) {
		goto maybe;
	}

	if(n->op == OREAL || n->op == OIMAG)
		goto yes;

	goto no;

maybe:
	switch(n->op) {
	case OCONV:	// implemented ops
	case OADD:
	case OSUB:
	case OMUL:
	case OMINUS:
	case OCMPLX:
	case OREAL:
	case OIMAG:
		goto yes;

	case ODOT:
	case ODOTPTR:
	case OINDEX:
	case OIND:
	case ONAME:
		goto yes;
	}

no:
//dump("\ncomplex-no", n);
	return 0;
yes:
//dump("\ncomplex-yes", n);
	return 1;
}

void
complexgen(Node *n, Node *res)
{
	Node *nl, *nr;
	Node tnl, tnr;
	Node n1, n2, tmp;
	int tl, tr;

	if(debug['g']) {
		dump("\ncomplexgen-n", n);
		dump("complexgen-res", res);
	}

	// pick off float/complex opcodes
	switch(n->op) {
	case OCMPLX:
		if(res->addable) {
			subnode(&n1, &n2, res);
			tempname(&tmp, n1.type);
			cgen(n->left, &tmp);
			cgen(n->right, &n2);
			cgen(&tmp, &n1);
			return;
		}
		break;

	case OREAL:
	case OIMAG:
		nl = n->left;
		if(!nl->addable) {
			tempname(&tmp, nl->type);
			complexgen(nl, &tmp);
			nl = &tmp;
		}
		subnode(&n1, &n2, nl);
		if(n->op == OREAL) {
			cgen(&n1, res);
			return;
		}
		cgen(&n2, res);
		return;
	}

	// perform conversion from n to res
	tl = simsimtype(res->type);
	tl = cplxsubtype(tl);
	tr = simsimtype(n->type);
	tr = cplxsubtype(tr);
	if(tl != tr) {
		if(!n->addable) {
			tempname(&n1, n->type);
			complexmove(n, &n1);
			n = &n1;
		}
		complexmove(n, res);
		return;
	}

	if(!res->addable) {
		igen(res, &n1, N);
		cgen(n, &n1);
		regfree(&n1);
		return;
	}
	if(n->addable) {
		complexmove(n, res);
		return;
	}

	switch(n->op) {
	default:
		dump("complexgen: unknown op", n);
		fatal("complexgen: unknown op %O", n->op);

	case ODOT:
	case ODOTPTR:
	case OINDEX:
	case OIND:
	case ONAME:	// PHEAP or PPARAMREF var
		igen(n, &n1, res);
		complexmove(&n1, res);
		regfree(&n1);
		return;

	case OCONV:
	case OADD:
	case OSUB:
	case OMUL:
	case OMINUS:
	case OCMPLX:
	case OREAL:
	case OIMAG:
		break;
	}

	nl = n->left;
	if(nl == N)
		return;
	nr = n->right;

	// make both sides addable in ullman order
	if(nr != N) {
		if(nl->ullman > nr->ullman && !nl->addable) {
			tempname(&tnl, nl->type);
			cgen(nl, &tnl);
			nl = &tnl;
		}
		if(!nr->addable) {
			tempname(&tnr, nr->type);
			cgen(nr, &tnr);
			nr = &tnr;
		}
	}
	if(!nl->addable) {
		tempname(&tnl, nl->type);
		cgen(nl, &tnl);
		nl = &tnl;
	}

	switch(n->op) {
	default:
		fatal("complexgen: unknown op %O", n->op);
		break;

	case OCONV:
		complexmove(nl, res);
		break;

	case OMINUS:
		complexminus(nl, res);
		break;

	case OADD:
	case OSUB:
		complexadd(n->op, nl, nr, res);
		break;

	case OMUL:
		complexmul(nl, nr, res);
		break;
	// ODIV call a runtime function
	}
}

void
complexbool(int op, Node *nl, Node *nr, int true, Prog *to)
{
	Node tnl, tnr;
	Node n1, n2, n3, n4;
	Node na, nb, nc;

	// make both sides addable in ullman order
	if(nr != N) {
		if(nl->ullman > nr->ullman && !nl->addable) {
			tempname(&tnl, nl->type);
			cgen(nl, &tnl);
			nl = &tnl;
		}
		if(!nr->addable) {
			tempname(&tnr, nr->type);
			cgen(nr, &tnr);
			nr = &tnr;
		}
	}
	if(!nl->addable) {
		tempname(&tnl, nl->type);
		cgen(nl, &tnl);
		nl = &tnl;
	}

	// build tree
	// real(l) == real(r) && imag(l) == imag(r)

	subnode(&n1, &n2, nl);
	subnode(&n3, &n4, nr);

	memset(&na, 0, sizeof(na));
	na.op = OANDAND;
	na.left = &nb;
	na.right = &nc;
	na.type = types[TBOOL];

	memset(&nb, 0, sizeof(na));
	nb.op = OEQ;
	nb.left = &n1;
	nb.right = &n3;
	nb.type = types[TBOOL];

	memset(&nc, 0, sizeof(na));
	nc.op = OEQ;
	nc.left = &n2;
	nc.right = &n4;
	nc.type = types[TBOOL];

	if(op == ONE)
		true = !true;

	bgen(&na, true, to);
}

void
nodfconst(Node *n, Type *t, Mpflt* fval)
{
	memset(n, 0, sizeof(*n));
	n->op = OLITERAL;
	n->addable = 1;
	ullmancalc(n);
	n->val.u.fval = fval;
	n->val.ctype = CTFLT;
	n->type = t;

	if(!isfloat[t->etype])
		fatal("nodfconst: bad type %T", t);
}

// break addable nc-complex into nr-real and ni-imaginary
static void
subnode(Node *nr, Node *ni, Node *nc)
{
	int tc;
	Type *t;

	if(!nc->addable)
		fatal("subnode not addable");

	tc = simsimtype(nc->type);
	tc = cplxsubtype(tc);
	t = types[tc];

	if(nc->op == OLITERAL) {
		nodfconst(nr, t, &nc->val.u.cval->real);
		nodfconst(ni, t, &nc->val.u.cval->imag);
		return;
	}

	*nr = *nc;
	nr->type = t;

	*ni = *nc;
	ni->type = t;
	ni->xoffset += t->width;
}

// generate code res = -nl
static void
minus(Node *nl, Node *res)
{
	Node ra;

	memset(&ra, 0, sizeof(ra));
	ra.op = OMINUS;
	ra.left = nl;
	ra.type = nl->type;
	cgen(&ra, res);
}

// build and execute tree
//	real(res) = -real(nl)
//	imag(res) = -imag(nl)
void
complexminus(Node *nl, Node *res)
{
	Node n1, n2, n5, n6;

	subnode(&n1, &n2, nl);
	subnode(&n5, &n6, res);

	minus(&n1, &n5);
	minus(&n2, &n6);
}


// build and execute tree
//	real(res) = real(nl) op real(nr)
//	imag(res) = imag(nl) op imag(nr)
void
complexadd(int op, Node *nl, Node *nr, Node *res)
{
	Node n1, n2, n3, n4, n5, n6;
	Node ra;

	subnode(&n1, &n2, nl);
	subnode(&n3, &n4, nr);
	subnode(&n5, &n6, res);

	memset(&ra, 0, sizeof(ra));
	ra.op = op;
	ra.left = &n1;
	ra.right = &n3;
	ra.type = n1.type;
	cgen(&ra, &n5);

	memset(&ra, 0, sizeof(ra));
	ra.op = op;
	ra.left = &n2;
	ra.right = &n4;
	ra.type = n2.type;
	cgen(&ra, &n6);
}

// build and execute tree
//	tmp       = real(nl)*real(nr) - imag(nl)*imag(nr)
//	imag(res) = real(nl)*imag(nr) + imag(nl)*real(nr)
//	real(res) = tmp
void
complexmul(Node *nl, Node *nr, Node *res)
{
	Node n1, n2, n3, n4, n5, n6;
	Node rm1, rm2, ra, tmp;

	subnode(&n1, &n2, nl);
	subnode(&n3, &n4, nr);
	subnode(&n5, &n6, res);
	tempname(&tmp, n5.type);

	// real part -> tmp
	memset(&rm1, 0, sizeof(ra));
	rm1.op = OMUL;
	rm1.left = &n1;
	rm1.right = &n3;
	rm1.type = n1.type;

	memset(&rm2, 0, sizeof(ra));
	rm2.op = OMUL;
	rm2.left = &n2;
	rm2.right = &n4;
	rm2.type = n2.type;

	memset(&ra, 0, sizeof(ra));
	ra.op = OSUB;
	ra.left = &rm1;
	ra.right = &rm2;
	ra.type = rm1.type;
	cgen(&ra, &tmp);

	// imag part
	memset(&rm1, 0, sizeof(ra));
	rm1.op = OMUL;
	rm1.left = &n1;
	rm1.right = &n4;
	rm1.type = n1.type;

	memset(&rm2, 0, sizeof(ra));
	rm2.op = OMUL;
	rm2.left = &n2;
	rm2.right = &n3;
	rm2.type = n2.type;

	memset(&ra, 0, sizeof(ra));
	ra.op = OADD;
	ra.left = &rm1;
	ra.right = &rm2;
	ra.type = rm1.type;
	cgen(&ra, &n6);

	// tmp ->real part
	cgen(&tmp, &n5);
}
