2015-02-13 14:40:36 -05:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import "cmd/internal/obj"
|
|
|
|
|
|
|
|
|
|
func CASE(a int, b int) int {
|
|
|
|
|
return a<<16 | b
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func overlap_cplx(f *Node, t *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
// check whether f and t could be overlapping stack references.
|
|
|
|
|
// not exact, because it's hard to check for the stack register
|
|
|
|
|
// in portable code. close enough: worst case we will allocate
|
|
|
|
|
// an extra temporary and the registerizer will clean it up.
|
2015-02-17 22:13:49 -05:00
|
|
|
return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Complexbool(op int, nl *Node, nr *Node, true_ bool, likely int, to *obj.Prog) {
|
|
|
|
|
var tnl Node
|
|
|
|
|
|
|
|
|
|
// make both sides addable in ullman order
|
|
|
|
|
if nr != nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
if nl.Ullman > nr.Ullman && nl.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnl, nl.Type)
|
|
|
|
|
Thearch.Cgen(nl, &tnl)
|
|
|
|
|
nl = &tnl
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if nr.Addable == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var tnr Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnr, nr.Type)
|
|
|
|
|
Thearch.Cgen(nr, &tnr)
|
|
|
|
|
nr = &tnr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if nl.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnl, nl.Type)
|
|
|
|
|
Thearch.Cgen(nl, &tnl)
|
|
|
|
|
nl = &tnl
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build tree
|
|
|
|
|
// real(l) == real(r) && imag(l) == imag(r)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var n2 Node
|
|
|
|
|
var n1 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n1, &n2, nl)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var n3 Node
|
|
|
|
|
var n4 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n3, &n4, nr)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
na := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
na.Op = OANDAND
|
2015-02-23 16:07:24 -05:00
|
|
|
var nb Node
|
2015-02-13 14:40:36 -05:00
|
|
|
na.Left = &nb
|
2015-02-23 16:07:24 -05:00
|
|
|
var nc Node
|
2015-02-13 14:40:36 -05:00
|
|
|
na.Right = &nc
|
|
|
|
|
na.Type = Types[TBOOL]
|
|
|
|
|
|
|
|
|
|
nb = Node{}
|
|
|
|
|
nb.Op = OEQ
|
|
|
|
|
nb.Left = &n1
|
|
|
|
|
nb.Right = &n3
|
|
|
|
|
nb.Type = Types[TBOOL]
|
|
|
|
|
|
|
|
|
|
nc = Node{}
|
|
|
|
|
nc.Op = OEQ
|
|
|
|
|
nc.Left = &n2
|
|
|
|
|
nc.Right = &n4
|
|
|
|
|
nc.Type = Types[TBOOL]
|
|
|
|
|
|
|
|
|
|
if op == ONE {
|
|
|
|
|
true_ = !true_
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thearch.Bgen(&na, true_, likely, to)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// break addable nc-complex into nr-real and ni-imaginary
|
|
|
|
|
func subnode(nr *Node, ni *Node, nc *Node) {
|
2015-02-17 22:13:49 -05:00
|
|
|
if nc.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Fatal("subnode not addable")
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
tc := Simsimtype(nc.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
tc = cplxsubtype(tc)
|
2015-02-23 16:07:24 -05:00
|
|
|
t := Types[tc]
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
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
|
|
|
|
|
func minus(nl *Node, res *Node) {
|
2015-02-23 16:07:24 -05:00
|
|
|
ra := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
ra.Op = OMINUS
|
|
|
|
|
ra.Left = nl
|
|
|
|
|
ra.Type = nl.Type
|
|
|
|
|
Thearch.Cgen(&ra, res)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// build and execute tree
|
|
|
|
|
// real(res) = -real(nl)
|
|
|
|
|
// imag(res) = -imag(nl)
|
|
|
|
|
func complexminus(nl *Node, res *Node) {
|
|
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
|
|
|
|
var n5 Node
|
|
|
|
|
var n6 Node
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
func complexadd(op int, nl *Node, nr *Node, res *Node) {
|
|
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
|
|
|
|
var n3 Node
|
|
|
|
|
var n4 Node
|
|
|
|
|
var n5 Node
|
|
|
|
|
var n6 Node
|
|
|
|
|
|
|
|
|
|
subnode(&n1, &n2, nl)
|
|
|
|
|
subnode(&n3, &n4, nr)
|
|
|
|
|
subnode(&n5, &n6, res)
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
ra := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
ra.Op = uint8(op)
|
|
|
|
|
ra.Left = &n1
|
|
|
|
|
ra.Right = &n3
|
|
|
|
|
ra.Type = n1.Type
|
|
|
|
|
Thearch.Cgen(&ra, &n5)
|
|
|
|
|
|
|
|
|
|
ra = Node{}
|
|
|
|
|
ra.Op = uint8(op)
|
|
|
|
|
ra.Left = &n2
|
|
|
|
|
ra.Right = &n4
|
|
|
|
|
ra.Type = n2.Type
|
|
|
|
|
Thearch.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
|
|
|
|
|
func complexmul(nl *Node, nr *Node, res *Node) {
|
|
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
|
|
|
|
var n3 Node
|
|
|
|
|
var n4 Node
|
|
|
|
|
var n5 Node
|
|
|
|
|
var n6 Node
|
|
|
|
|
var tmp Node
|
|
|
|
|
|
|
|
|
|
subnode(&n1, &n2, nl)
|
|
|
|
|
subnode(&n3, &n4, nr)
|
|
|
|
|
subnode(&n5, &n6, res)
|
|
|
|
|
Tempname(&tmp, n5.Type)
|
|
|
|
|
|
|
|
|
|
// real part -> tmp
|
2015-02-23 16:07:24 -05:00
|
|
|
rm1 := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
rm1.Op = OMUL
|
|
|
|
|
rm1.Left = &n1
|
|
|
|
|
rm1.Right = &n3
|
|
|
|
|
rm1.Type = n1.Type
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
rm2 := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
rm2.Op = OMUL
|
|
|
|
|
rm2.Left = &n2
|
|
|
|
|
rm2.Right = &n4
|
|
|
|
|
rm2.Type = n2.Type
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
ra := Node{}
|
2015-02-13 14:40:36 -05:00
|
|
|
ra.Op = OSUB
|
|
|
|
|
ra.Left = &rm1
|
|
|
|
|
ra.Right = &rm2
|
|
|
|
|
ra.Type = rm1.Type
|
|
|
|
|
Thearch.Cgen(&ra, &tmp)
|
|
|
|
|
|
|
|
|
|
// imag part
|
|
|
|
|
rm1 = Node{}
|
|
|
|
|
|
|
|
|
|
rm1.Op = OMUL
|
|
|
|
|
rm1.Left = &n1
|
|
|
|
|
rm1.Right = &n4
|
|
|
|
|
rm1.Type = n1.Type
|
|
|
|
|
|
|
|
|
|
rm2 = Node{}
|
|
|
|
|
rm2.Op = OMUL
|
|
|
|
|
rm2.Left = &n2
|
|
|
|
|
rm2.Right = &n3
|
|
|
|
|
rm2.Type = n2.Type
|
|
|
|
|
|
|
|
|
|
ra = Node{}
|
|
|
|
|
ra.Op = OADD
|
|
|
|
|
ra.Left = &rm1
|
|
|
|
|
ra.Right = &rm2
|
|
|
|
|
ra.Type = rm1.Type
|
|
|
|
|
Thearch.Cgen(&ra, &n6)
|
|
|
|
|
|
|
|
|
|
// tmp ->real part
|
|
|
|
|
Thearch.Cgen(&tmp, &n5)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func nodfconst(n *Node, t *Type, fval *Mpflt) {
|
|
|
|
|
*n = Node{}
|
|
|
|
|
n.Op = OLITERAL
|
|
|
|
|
n.Addable = 1
|
|
|
|
|
ullmancalc(n)
|
|
|
|
|
n.Val.U.Fval = fval
|
|
|
|
|
n.Val.Ctype = CTFLT
|
|
|
|
|
n.Type = t
|
|
|
|
|
|
2015-03-01 07:54:01 +00:00
|
|
|
if !Isfloat[t.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
Fatal("nodfconst: bad type %v", Tconv(t, 0))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* cplx.c
|
|
|
|
|
*/
|
2015-02-17 22:13:49 -05:00
|
|
|
func Complexop(n *Node, res *Node) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if n != nil && n.Type != nil {
|
2015-03-01 07:54:01 +00:00
|
|
|
if Iscomplex[n.Type.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto maybe
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if res != nil && res.Type != nil {
|
2015-03-01 07:54:01 +00:00
|
|
|
if Iscomplex[res.Type.Etype] {
|
2015-02-13 14:40:36 -05:00
|
|
|
goto maybe
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op == OREAL || n.Op == OIMAG {
|
2015-03-02 12:35:15 -05:00
|
|
|
//dump("\ncomplex-yes", n);
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
//dump("\ncomplex-no", n);
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
maybe:
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case OCONV, // implemented ops
|
|
|
|
|
OADD,
|
|
|
|
|
OSUB,
|
|
|
|
|
OMUL,
|
|
|
|
|
OMINUS,
|
|
|
|
|
OCOMPLEX,
|
|
|
|
|
OREAL,
|
|
|
|
|
OIMAG:
|
2015-03-02 12:35:15 -05:00
|
|
|
//dump("\ncomplex-yes", n);
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case ODOT,
|
|
|
|
|
ODOTPTR,
|
|
|
|
|
OINDEX,
|
|
|
|
|
OIND,
|
|
|
|
|
ONAME:
|
2015-03-02 12:35:15 -05:00
|
|
|
//dump("\ncomplex-yes", n);
|
|
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//dump("\ncomplex-no", n);
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Complexmove(f *Node, t *Node) {
|
|
|
|
|
if Debug['g'] != 0 {
|
|
|
|
|
Dump("\ncomplexmove-f", f)
|
|
|
|
|
Dump("complexmove-t", t)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if t.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Fatal("complexmove: to not addable")
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
ft := Simsimtype(f.Type)
|
|
|
|
|
tt := Simsimtype(t.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
switch uint32(ft)<<16 | uint32(tt) {
|
|
|
|
|
default:
|
|
|
|
|
Fatal("complexmove: unknown conversion: %v -> %v\n", Tconv(f.Type, 0), Tconv(t.Type, 0))
|
|
|
|
|
|
|
|
|
|
// complex to complex move/convert.
|
|
|
|
|
// make f addable.
|
|
|
|
|
// also use temporary if possible stack overlap.
|
|
|
|
|
case TCOMPLEX64<<16 | TCOMPLEX64,
|
|
|
|
|
TCOMPLEX64<<16 | TCOMPLEX128,
|
|
|
|
|
TCOMPLEX128<<16 | TCOMPLEX64,
|
|
|
|
|
TCOMPLEX128<<16 | TCOMPLEX128:
|
2015-02-17 22:13:49 -05:00
|
|
|
if f.Addable == 0 || overlap_cplx(f, t) {
|
2015-02-23 16:07:24 -05:00
|
|
|
var tmp Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tmp, f.Type)
|
|
|
|
|
Complexmove(f, &tmp)
|
|
|
|
|
f = &tmp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n1, &n2, f)
|
2015-02-23 16:07:24 -05:00
|
|
|
var n4 Node
|
|
|
|
|
var n3 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n3, &n4, t)
|
|
|
|
|
|
|
|
|
|
Thearch.Cgen(&n1, &n3)
|
|
|
|
|
Thearch.Cgen(&n2, &n4)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Complexgen(n *Node, res *Node) {
|
|
|
|
|
if Debug['g'] != 0 {
|
|
|
|
|
Dump("\ncomplexgen-n", n)
|
|
|
|
|
Dump("complexgen-res", res)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for n.Op == OCONVNOP {
|
|
|
|
|
n = n.Left
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pick off float/complex opcodes
|
|
|
|
|
switch n.Op {
|
|
|
|
|
case OCOMPLEX:
|
|
|
|
|
if res.Addable != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n1, &n2, res)
|
2015-02-23 16:07:24 -05:00
|
|
|
var tmp Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tmp, n1.Type)
|
|
|
|
|
Thearch.Cgen(n.Left, &tmp)
|
|
|
|
|
Thearch.Cgen(n.Right, &n2)
|
|
|
|
|
Thearch.Cgen(&tmp, &n1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OREAL,
|
|
|
|
|
OIMAG:
|
2015-02-23 16:07:24 -05:00
|
|
|
nl := n.Left
|
2015-02-17 22:13:49 -05:00
|
|
|
if nl.Addable == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var tmp Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tmp, nl.Type)
|
|
|
|
|
Complexgen(nl, &tmp)
|
|
|
|
|
nl = &tmp
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
|
|
|
|
var n2 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
subnode(&n1, &n2, nl)
|
|
|
|
|
if n.Op == OREAL {
|
|
|
|
|
Thearch.Cgen(&n1, res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thearch.Cgen(&n2, res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// perform conversion from n to res
|
2015-02-23 16:07:24 -05:00
|
|
|
tl := Simsimtype(res.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
tl = cplxsubtype(tl)
|
2015-02-23 16:07:24 -05:00
|
|
|
tr := Simsimtype(n.Type)
|
2015-02-13 14:40:36 -05:00
|
|
|
tr = cplxsubtype(tr)
|
|
|
|
|
if tl != tr {
|
2015-02-17 22:13:49 -05:00
|
|
|
if n.Addable == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&n1, n.Type)
|
|
|
|
|
Complexmove(n, &n1)
|
|
|
|
|
n = &n1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Complexmove(n, res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if res.Addable == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Thearch.Igen(res, &n1, nil)
|
|
|
|
|
Thearch.Cgen(n, &n1)
|
|
|
|
|
Thearch.Regfree(&n1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Addable != 0 {
|
|
|
|
|
Complexmove(n, res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
|
|
|
|
Dump("complexgen: unknown op", n)
|
|
|
|
|
Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))
|
|
|
|
|
|
|
|
|
|
case ODOT,
|
|
|
|
|
ODOTPTR,
|
|
|
|
|
OINDEX,
|
|
|
|
|
OIND,
|
|
|
|
|
ONAME, // PHEAP or PPARAMREF var
|
|
|
|
|
OCALLFUNC,
|
|
|
|
|
OCALLMETH,
|
|
|
|
|
OCALLINTER:
|
2015-02-23 16:07:24 -05:00
|
|
|
var n1 Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Thearch.Igen(n, &n1, res)
|
|
|
|
|
|
|
|
|
|
Complexmove(&n1, res)
|
|
|
|
|
Thearch.Regfree(&n1)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
case OCONV,
|
|
|
|
|
OADD,
|
|
|
|
|
OSUB,
|
|
|
|
|
OMUL,
|
|
|
|
|
OMINUS,
|
|
|
|
|
OCOMPLEX,
|
|
|
|
|
OREAL,
|
|
|
|
|
OIMAG:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
nl := n.Left
|
2015-02-13 14:40:36 -05:00
|
|
|
if nl == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
nr := n.Right
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// make both sides addable in ullman order
|
2015-02-23 16:07:24 -05:00
|
|
|
var tnl Node
|
2015-02-13 14:40:36 -05:00
|
|
|
if nr != nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
if nl.Ullman > nr.Ullman && nl.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnl, nl.Type)
|
|
|
|
|
Thearch.Cgen(nl, &tnl)
|
|
|
|
|
nl = &tnl
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if nr.Addable == 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
var tnr Node
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnr, nr.Type)
|
|
|
|
|
Thearch.Cgen(nr, &tnr)
|
|
|
|
|
nr = &tnr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if nl.Addable == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Tempname(&tnl, nl.Type)
|
|
|
|
|
Thearch.Cgen(nl, &tnl)
|
|
|
|
|
nl = &tnl
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op {
|
|
|
|
|
default:
|
|
|
|
|
Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))
|
|
|
|
|
|
|
|
|
|
case OCONV:
|
|
|
|
|
Complexmove(nl, res)
|
|
|
|
|
|
|
|
|
|
case OMINUS:
|
|
|
|
|
complexminus(nl, res)
|
|
|
|
|
|
|
|
|
|
case OADD,
|
|
|
|
|
OSUB:
|
|
|
|
|
complexadd(int(n.Op), nl, nr, res)
|
|
|
|
|
|
|
|
|
|
case OMUL:
|
|
|
|
|
complexmul(nl, nr, res)
|
|
|
|
|
}
|
|
|
|
|
}
|