more on type complex.

getting close.

R=rsc
CC=golang-dev
https://golang.org/cl/224105
This commit is contained in:
Ken Thompson 2010-03-02 18:32:11 -08:00
parent 305f5433f3
commit 7d4b1e4c0d
11 changed files with 442 additions and 10 deletions

View file

@ -116,6 +116,11 @@ cgen(Node *n, Node *res)
break;
}
if(complexop(n, res)) {
complexgen(n, res);
goto ret;
}
if(n->addable) {
gmove(n, res);
goto ret;
@ -134,13 +139,6 @@ cgen(Node *n, Node *res)
goto ret;
}
// complex ops are special.
if(iscomplex[n->type->etype] || iscomplex[res->type->etype] ||
n->left != N && iscomplex[n->left->type->etype]) {
complexgen(n, res);
goto ret;
}
a = optoas(OAS, n->type);
if(sudoaddable(a, n, &addr)) {
if(res->op == OREGISTER) {
@ -802,6 +800,7 @@ bgen(Node *n, int true, Prog *to)
goto ret;
}
a = brcom(a);
true = !true;
}
// make simplest on right
@ -849,6 +848,10 @@ bgen(Node *n, int true, Prog *to)
regfree(&n1);
break;
}
if(iscomplex[nl->type->etype]) {
complexbool(a, nl, nr, true, to);
break;
}
if(nr->ullman >= UINF) {
regalloc(&n1, nr->type, N);

View file

@ -26,7 +26,7 @@ complexmove(Node *f, Node *t, int perm)
int ft, tt;
Node n1, n2, n3, n4, nc;
if(1||debug['g']) {
if(debug['g']) {
dump("\ncomplex-f", f);
dump("complex-t", t);
}
@ -113,6 +113,28 @@ complexmove(Node *f, Node *t, int perm)
}
}
int
complexop(Node *n, Node *res)
{
if(n != N && n->type != T)
if(iscomplex[n->type->etype]) {
switch(n->op) {
case OCONV:
case OADD:
case OSUB:
case OMUL:
case ODIV:
case OMINUS:
goto yes;
}
//dump("complexop no", n);
}
return 0;
yes:
return 1;
}
void
complexgen(Node *n, Node *res)
{
@ -121,7 +143,7 @@ complexgen(Node *n, Node *res)
Node ra, rb, rc, rd;
int tl, tr;
if(1||debug['g']) {
if(debug['g']) {
dump("\ncomplex-n", n);
dump("complex-res", res);
}
@ -257,10 +279,104 @@ complexgen(Node *n, Node *res)
complexmove(nl, res, 2);
break;
}
fatal("opcode %O", n->op);
subnode(&n1, &n2, nl);
subnode(&n3, &n4, nr);
subnode(&n5, &n6, res);
regalloc(&ra, n5.type, N);
regalloc(&rb, n5.type, N);
regalloc(&rc, n6.type, N);
regalloc(&rd, n6.type, N);
gmove(&n1, &ra);
gmove(&n3, &rc);
gins(optoas(OMUL, n5.type), &rc, &ra); // ra = a*c
gmove(&n2, &rb);
gmove(&n4, &rd);
gins(optoas(OMUL, n5.type), &rd, &rb); // rb = b*d
gins(optoas(OADD, n5.type), &rb, &ra); // ra = (a*c + b*d)
gins(optoas(OMUL, n5.type), &n2, &rc); // rc = b*c
gins(optoas(OMUL, n5.type), &n1, &rd); // rd = a*d
gins(optoas(OSUB, n5.type), &rd, &rc); // rc = (b*c - a*d)
gmove(&n3, &rb);
gins(optoas(OMUL, n5.type), &rb, &rb); // rb = c*c
gmove(&n4, &rd);
gins(optoas(OMUL, n5.type), &rd, &rd); // rd = d*d
gins(optoas(OADD, n5.type), &rd, &rb); // rb = (c*c + d*d)
gins(optoas(ODIV, n5.type), &rb, &ra); // ra = (a*c + b*d)/(c*c + d*d)
gins(optoas(ODIV, n5.type), &rb, &rc); // rc = (b*c - a*d)/(c*c + d*d)
gmove(&ra, &n5);
gmove(&rc, &n6);
regfree(&ra);
regfree(&rb);
regfree(&rc);
regfree(&rd);
break;
}
}
void
complexbool(int op, Node *nl, Node *nr, int true, Prog *to)
{
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(&n1, nl->type);
complexgen(nl, &n1);
nl = &n1;
}
if(!nr->addable) {
tempname(&n2, nr->type);
complexgen(nr, &n2);
nr = &n2;
}
}
if(!nl->addable) {
tempname(&n1, nl->type);
complexgen(nl, &n1);
nl = &n1;
}
// 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);
}
int
cplxsubtype(int et)
{

View file

@ -134,8 +134,10 @@ void nodfconst(Node*, Type*, Mpflt*);
/*
* cplx.c
*/
int complexop(Node*, Node*);
void complexmove(Node*, Node*, int);
void complexgen(Node*, Node*);
void complexbool(int, Node*, Node*, int, Prog*);
/*
* obj.c

View file

@ -288,6 +288,11 @@ regalloc(Node *n, Type *t, Node *o)
goto out;
yyerror("out of floating registers");
goto err;
case TCOMPLEX64:
case TCOMPLEX128:
tempname(n, t);
return;
}
yyerror("regalloc: unknown type %T", t);
@ -305,6 +310,8 @@ regfree(Node *n)
{
int i;
if(n->op == ONAME && iscomplex[n->type->etype])
return;
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
i = n->val.u.reg;

View file

@ -554,6 +554,12 @@ cgen_as(Node *nl, Node *nr)
nr->val.ctype = CTNIL;
break;
case TCOMPLEX64:
case TCOMPLEX128:
nr->val.u.cval = mal(sizeof(*nr->val.u.cval));
mpmovecflt(&nr->val.u.cval->real, 0.0);
mpmovecflt(&nr->val.u.cval->imag, 0.0);
break;
}
nr->op = OLITERAL;
nr->type = tl;

View file

@ -79,6 +79,21 @@ type FloatType struct {
commonType
}
// Complex64Type represents a complex64 type.
type Complex64Type struct {
commonType
}
// Complex128Type represents acomplex128 type.
type Complex128Type struct {
commonType
}
// ComplexType represents a complex type.
type ComplexType struct {
commonType
}
// Int16Type represents an int16 type.
type Int16Type struct {
commonType
@ -585,6 +600,12 @@ func toType(i interface{}) Type {
return (*Float32Type)(unsafe.Pointer(v))
case *runtime.Float64Type:
return (*Float64Type)(unsafe.Pointer(v))
case *runtime.ComplexType:
return (*ComplexType)(unsafe.Pointer(v))
case *runtime.Complex64Type:
return (*Complex64Type)(unsafe.Pointer(v))
case *runtime.Complex128Type:
return (*Complex128Type)(unsafe.Pointer(v))
case *runtime.IntType:
return (*IntType)(unsafe.Pointer(v))
case *runtime.Int8Type:

View file

@ -186,6 +186,63 @@ func (v *Float64Value) Set(x float64) {
// Set sets v to the value x.
func (v *Float64Value) SetValue(x Value) { v.Set(x.(*Float64Value).Get()) }
//// ComplexValue represents a complex value.
//type ComplexValue struct {
// value
//}
//
//// Get returns the underlying complex value.
//func (v *ComplexValue) Get() complex { return *(*complex)(v.addr) }
//
//// Set sets v to the value x.
//func (v *ComplexValue) Set(x complex) {
// if !v.canSet {
// panic(cannotSet)
// }
// *(*complex)(v.addr) = x
//}
//
//// Set sets v to the value x.
//func (v *ComplexValue) SetValue(x Value) { v.Set(x.(*ComplexValue).Get()) }
//
//// Complex64Value represents a complex64 value.
//type Complex64Value struct {
// value
//}
//
//// Get returns the underlying complex64 value.
//func (v *Complex64Value) Get() complex64 { return *(*complex64)(v.addr) }
//
//// Set sets v to the value x.
//func (v *Complex64Value) Set(x complex64) {
// if !v.canSet {
// panic(cannotSet)
// }
// *(*complex64)(v.addr) = x
//}
//
//// Set sets v to the value x.
//func (v *Complex64Value) SetValue(x Value) { v.Set(x.(*Complex64Value).Get()) }
//
//// Complex128Value represents a complex128 value.
//type Complex128Value struct {
// value
//}
//
//// Get returns the underlying complex128 value.
//func (v *Complex128Value) Get() complex128 { return *(*complex128)(v.addr) }
//
//// Set sets v to the value x.
//func (v *Complex128Value) Set(x complex128) {
// if !v.canSet {
// panic(cannotSet)
// }
// *(*complex128)(v.addr) = x
//}
//
//// Set sets v to the value x.
//func (v *Complex128Value) SetValue(x Value) { v.Set(x.(*Complex128Value).Get()) }
// IntValue represents an int value.
type IntValue struct {
value
@ -1246,6 +1303,12 @@ func newValue(typ Type, addr addr, canSet bool) Value {
return (*Float32Value)(v)
case *Float64Type:
return (*Float64Value)(v)
// case *ComplexType:
// return (*ComplexValue)(v)
// case *Complex64Type:
// return (*Complex64Value)(v)
// case *Complex128Type:
// return (*Complex128Value)(v)
case *IntType:
return (*IntValue)(v)
case *Int8Type:

View file

@ -56,6 +56,12 @@ Hello World!
== ken/
=========== ken/cplx0.go
(+5.000000e+000,+6.000000e+000i)
(+5.000000e+000,+6.000000e+000i)
(+5.000000e+000,+6.000000e+000i)
(+5.000000e+000,+6.000000e+000i)
=========== ken/intervar.go
print 1 bio 2 file 3 -- abc

28
test/ken/cplx0.go Normal file
View file

@ -0,0 +1,28 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// 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 main
const (
R = 5
I = 6i
C1 = R + I // ADD(5,6)
)
func doprint(c complex) { println(c) }
func main() {
// constants
println(C1)
doprint(C1)
// variables
c1 := C1
println(c1)
doprint(c1)
}

85
test/ken/cplx1.go Normal file
View file

@ -0,0 +1,85 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// 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 main
const (
R = 5
I = 6i
C1 = R + I // ADD(5,6)
)
func main() {
var b bool
// constants
b = (5 + 6i) == C1
if !b {
panicln("const bool 1", b)
}
b = (5 + 6i) != C1
if b {
panicln("const bool 2", b)
}
b = C1 == (5 + 6i)
if !b {
panicln("const bool 3", b)
}
b = C1 != (5 + 6i)
if b {
panicln("const bool 4", b)
}
// vars passed through parameters
booltest(5+6i, true)
booltest(5+7i, false)
booltest(6+6i, false)
booltest(6+9i, false)
}
func booltest(a complex, r bool) {
var b bool
b = a == C1
if b != r {
panicln("param bool 1", a, b, r)
}
b = a != C1
if b == r {
panicln("param bool 2", a, b, r)
}
b = C1 == a
if b != r {
panicln("param bool 3", a, b, r)
}
b = C1 != a
if b == r {
panicln("param bool 4", a, b, r)
}
if r {
if a != C1 {
panicln("param bool 5", a, b, r)
}
if C1 != a {
panicln("param bool 6", a, b, r)
}
} else {
if a == C1 {
panicln("param bool 6", a, b, r)
}
if C1 == a {
panicln("param bool 7", a, b, r)
}
}
}

95
test/ken/cplx2.go Normal file
View file

@ -0,0 +1,95 @@
// $G $D/$F.go && $L $F.$A && ./$A.out
// 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 main
const (
R = 5
I = 6i
C1 = R + I // ADD(5,6)
C2 = R - I // SUB(5,-6)
C3 = -(R + I) // ADD(5,6) NEG(-5,-6)
C4 = -(R - I) // SUB(5,-6) NEG(-5,6)
C5 = C1 + R // ADD(10,6)
C6 = C1 + I // ADD(5,12)
Ca = C5 + C6 // ADD(15,18)
Cb = C5 - C6 // SUB(5,-6)
Cc = C5 * C6 // MUL(-22,-150)
Cd = C5 / C6 // DIV(0.721893,-0.532544)
Ce = Cd * C6 // MUL(10,6) sb C5
)
func main() {
r := 5 + 0i
if r != R {
panicln("opcode 1", r, R)
}
i := 6i
if i != I {
panicln("opcode 2", i, I)
}
c1 := r + i
if c1 != C1 {
panicln("opcode x", c1, C1)
}
c2 := r - i
if c2 != C2 {
panicln("opcode x", c2, C2)
}
c3 := -(r + i)
if c3 != C3 {
panicln("opcode x", c3, C3)
}
c4 := -(r - i)
if c4 != C4 {
panicln("opcode x", c4, C4)
}
c5 := c1 + r
if c5 != C5 {
panicln("opcode x", c5, C5)
}
c6 := c1 + i
if c6 != C6 {
panicln("opcode x", c6, C6)
}
ca := c5 + c6
if ca != Ca {
panicln("opcode x", ca, Ca)
}
cb := c5 - c6
if cb != Cb {
panicln("opcode x", cb, Cb)
}
cc := c5 * c6
if cc != Cc {
panicln("opcode x", cc, Cc)
}
cd := c5 / c6
if cd != Cd {
panicln("opcode x", cd, Cd)
}
ce := cd * c6
if ce != Ce {
panicln("opcode x", ce, Ce)
}
}