s.Fatalf("bad float size %d", n.Type.Size())
return nil
}
+ case CTCPLX:
+ c := n.Val().U.(*Mpcplx)
+ r := &c.Real
+ i := &c.Imag
+ switch n.Type.Size() {
+ case 8:
+ {
+ pt := Types[TFLOAT32]
+ return s.newValue2(ssa.OpComplexMake, n.Type,
+ s.constFloat32(pt, mpgetflt32(r)),
+ s.constFloat32(pt, mpgetflt32(i)))
+ }
+ case 16:
+ {
+ pt := Types[TFLOAT64]
+ return s.newValue2(ssa.OpComplexMake, n.Type,
+ s.constFloat32(pt, mpgetflt(r)),
+ s.constFloat32(pt, mpgetflt(i)))
+ }
+ default:
+ s.Fatalf("bad float size %d", n.Type.Size())
+ return nil
+ }
default:
s.Unimplementedf("unhandled OLITERAL %v", n.Val().Ctype())
default:
s.Fatalf("bad sized float type %s", t)
}
+ case t.IsComplex():
+ switch t.Size() {
+ case 8:
+ z := s.constFloat32(Types[TFLOAT32], 0)
+ return s.newValue2(ssa.OpComplexMake, t, z, z)
+ case 16:
+ z := s.constFloat64(Types[TFLOAT64], 0)
+ return s.newValue2(ssa.OpComplexMake, t, z, z)
+ default:
+ s.Fatalf("bad sized complex type %s", t)
+ }
+
case t.IsString():
return s.entryNewValue0A(ssa.OpConstString, t, "")
case t.IsPtr():
func (s *ssaExport) TypeUInt16() ssa.Type { return Types[TUINT16] }
func (s *ssaExport) TypeUInt32() ssa.Type { return Types[TUINT32] }
func (s *ssaExport) TypeUInt64() ssa.Type { return Types[TUINT64] }
+func (s *ssaExport) TypeFloat32() ssa.Type { return Types[TFLOAT32] }
+func (s *ssaExport) TypeFloat64() ssa.Type { return Types[TFLOAT64] }
func (s *ssaExport) TypeInt() ssa.Type { return Types[TINT] }
func (s *ssaExport) TypeUintptr() ssa.Type { return Types[TUINTPTR] }
func (s *ssaExport) TypeString() ssa.Type { return Types[TSTRING] }
}
}
+func complex64_ssa(a, b complex64, x bool) complex64 {
+ switch {
+ }
+ var c complex64
+ if x {
+ c = a
+ } else {
+ c = b
+ }
+ return c
+}
+
+func complex128_ssa(a, b complex128, x bool) complex128 {
+ switch {
+ }
+ var c complex128
+ if x {
+ c = a
+ } else {
+ c = b
+ }
+ return c
+}
+
+func testComplex64() {
+ var a complex64 = 1 + 2i
+ var b complex64 = 3 + 4i
+
+ if want, got := a, complex64_ssa(a, b, true); got != want {
+ fmt.Printf("complex64_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
+ failed = true
+ }
+ if want, got := b, complex64_ssa(a, b, false); got != want {
+ fmt.Printf("complex64_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
+ failed = true
+ }
+}
+
+func testComplex128() {
+ var a complex128 = 1 + 2i
+ var b complex128 = 3 + 4i
+
+ if want, got := a, complex128_ssa(a, b, true); got != want {
+ fmt.Printf("complex128_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
+ failed = true
+ }
+ if want, got := b, complex128_ssa(a, b, false); got != want {
+ fmt.Printf("complex128_ssa(%v, %v, true) = %v, want %v\n", a, b, got, want)
+ failed = true
+ }
+}
+
func slice_ssa(a, b []byte, x bool) []byte {
var s []byte
if x {
testString()
testSlice()
testInterface()
+ testComplex64()
+ testComplex128()
if failed {
panic("failed")
}
return t.Etype == TFLOAT32 || t.Etype == TFLOAT64
}
+func (t *Type) IsComplex() bool {
+ return t.Etype == TCOMPLEX64 || t.Etype == TCOMPLEX128
+}
+
func (t *Type) IsPtr() bool {
return t.Etype == TPTR32 || t.Etype == TPTR64 || t.Etype == TUNSAFEPTR ||
t.Etype == TMAP || t.Etype == TCHAN || t.Etype == TFUNC
TypeUInt32() Type
TypeUInt64() Type
TypeInt() Type
+ TypeFloat32() Type
+ TypeFloat64() Type
TypeUintptr() Type
TypeString() Type
TypeBytePtr() Type // TODO: use unsafe.Pointer instead?
continue
}
switch {
+ case v.Type.IsComplex():
+ decomposeComplexPhi(v)
case v.Type.IsString():
decomposeStringPhi(v)
case v.Type.IsSlice():
v.AddArg(cap)
}
+func decomposeComplexPhi(v *Value) {
+ fe := v.Block.Func.Config.fe
+ var partType Type
+ if v.Type.Size() == 8 {
+ partType = fe.TypeFloat32()
+ } else if v.Type.Size() == 16 {
+ partType = fe.TypeFloat64()
+ } else {
+ panic("Whoops, are sizes in bytes or bits?")
+ }
+
+ real := v.Block.NewValue0(v.Line, OpPhi, partType)
+ imag := v.Block.NewValue0(v.Line, OpPhi, partType)
+ for _, a := range v.Args {
+ real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a))
+ imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a))
+ }
+ v.Op = OpComplexMake
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v.AddArg(real)
+ v.AddArg(imag)
+}
+
func decomposeInterfacePhi(v *Value) {
ptrType := v.Block.Func.Config.fe.TypeBytePtr()
func (d DummyFrontend) TypeUInt16() Type { return TypeUInt16 }
func (d DummyFrontend) TypeUInt32() Type { return TypeUInt32 }
func (d DummyFrontend) TypeUInt64() Type { return TypeUInt64 }
+func (d DummyFrontend) TypeFloat32() Type { return TypeFloat32 }
+func (d DummyFrontend) TypeFloat64() Type { return TypeFloat64 }
func (d DummyFrontend) TypeInt() Type { return TypeInt64 }
func (d DummyFrontend) TypeUintptr() Type { return TypeUInt64 }
func (d DummyFrontend) TypeString() Type { panic("unimplemented") }
(PtrIndex <t> ptr idx) -> (AddPtr ptr (MulPtr <config.fe.TypeUintptr()> idx (ConstPtr <config.fe.TypeUintptr()> [t.Elem().Size()])))
(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
+// complex ops
+(ComplexReal (ComplexMake real _ )) -> real
+(ComplexImag (ComplexMake _ imag )) -> imag
+
+(Load <t> ptr mem) && t.IsComplex() && t.Size() == 8 ->
+ (ComplexMake
+ (Load <config.fe.TypeFloat32()> ptr mem)
+ (Load <config.fe.TypeFloat32()>
+ (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] ptr)
+ mem)
+ )
+(Store [8] dst (ComplexMake real imag) mem) ->
+ (Store [4]
+ (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst)
+ imag
+ (Store <TypeMem> [4] dst real mem))
+
+(Load <t> ptr mem) && t.IsComplex() && t.Size() == 16 ->
+ (ComplexMake
+ (Load <config.fe.TypeFloat64()> ptr mem)
+ (Load <config.fe.TypeFloat64()>
+ (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] ptr)
+ mem)
+ )
+(Store [16] dst (ComplexMake real imag) mem) ->
+ (Store [8]
+ (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst)
+ imag
+ (Store <TypeMem> [8] dst real mem))
+
// string ops
(StringPtr (StringMake ptr _)) -> ptr
(StringLen (StringMake _ len)) -> len
{name: "SliceLen"}, // len(arg0)
{name: "SliceCap"}, // cap(arg0)
+ // Complex (part/whole)
+ {name: "ComplexMake"}, // arg0=real, arg1=imag
+ {name: "ComplexReal"}, // real_part(arg0)
+ {name: "ComplexImag"}, // imaginary_part(arg0)
+
// Strings
{name: "StringMake"}, // arg0=ptr, arg1=len
{name: "StringPtr"}, // ptr(arg0)
OpSlicePtr
OpSliceLen
OpSliceCap
+ OpComplexMake
+ OpComplexReal
+ OpComplexImag
OpStringMake
OpStringPtr
OpStringLen
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934593, // .AX .FLAGS
+ clobbers: 1, // .AX
outputs: []regMask{
65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934593, // .AX .FLAGS
+ clobbers: 1, // .AX
outputs: []regMask{
65518, // .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
inputs: []inputInfo{
{0, 8589934592}, // .FLAGS
},
- clobbers: 8589934592, // .FLAGS
outputs: []regMask{
65519, // .AX .CX .DX .BX .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15
},
name: "SliceCap",
generic: true,
},
+ {
+ name: "ComplexMake",
+ generic: true,
+ },
+ {
+ name: "ComplexReal",
+ generic: true,
+ },
+ {
+ name: "ComplexImag",
+ generic: true,
+ },
{
name: "StringMake",
generic: true,
goto end4d92ff3ba567d9afd38fc9ca113602ad
end4d92ff3ba567d9afd38fc9ca113602ad:
;
+ case OpComplexImag:
+ // match: (ComplexImag (ComplexMake _ imag ))
+ // cond:
+ // result: imag
+ {
+ if v.Args[0].Op != OpComplexMake {
+ goto endec3009fd8727d03002021997936e091f
+ }
+ imag := v.Args[0].Args[1]
+ v.Op = OpCopy
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v.Type = imag.Type
+ v.AddArg(imag)
+ return true
+ }
+ goto endec3009fd8727d03002021997936e091f
+ endec3009fd8727d03002021997936e091f:
+ ;
+ case OpComplexReal:
+ // match: (ComplexReal (ComplexMake real _ ))
+ // cond:
+ // result: real
+ {
+ if v.Args[0].Op != OpComplexMake {
+ goto end8db3e16bd59af1adaa4b734c8adcc71d
+ }
+ real := v.Args[0].Args[0]
+ v.Op = OpCopy
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v.Type = real.Type
+ v.AddArg(real)
+ return true
+ }
+ goto end8db3e16bd59af1adaa4b734c8adcc71d
+ end8db3e16bd59af1adaa4b734c8adcc71d:
+ ;
case OpConstInterface:
// match: (ConstInterface)
// cond:
end84d6ae817944985f572ecaac51999d6c:
;
case OpLoad:
+ // match: (Load <t> ptr mem)
+ // cond: t.IsComplex() && t.Size() == 8
+ // result: (ComplexMake (Load <config.fe.TypeFloat32()> ptr mem) (Load <config.fe.TypeFloat32()> (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] ptr) mem) )
+ {
+ t := v.Type
+ ptr := v.Args[0]
+ mem := v.Args[1]
+ if !(t.IsComplex() && t.Size() == 8) {
+ goto end665854b31b828893d90b36bb462ff381
+ }
+ v.Op = OpComplexMake
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+ v0.Type = config.fe.TypeFloat32()
+ v0.AddArg(ptr)
+ v0.AddArg(mem)
+ v.AddArg(v0)
+ v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+ v1.Type = config.fe.TypeFloat32()
+ v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+ v2.Type = config.fe.TypeFloat32().PtrTo()
+ v2.AuxInt = 4
+ v2.AddArg(ptr)
+ v1.AddArg(v2)
+ v1.AddArg(mem)
+ v.AddArg(v1)
+ return true
+ }
+ goto end665854b31b828893d90b36bb462ff381
+ end665854b31b828893d90b36bb462ff381:
+ ;
+ // match: (Load <t> ptr mem)
+ // cond: t.IsComplex() && t.Size() == 16
+ // result: (ComplexMake (Load <config.fe.TypeFloat64()> ptr mem) (Load <config.fe.TypeFloat64()> (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] ptr) mem) )
+ {
+ t := v.Type
+ ptr := v.Args[0]
+ mem := v.Args[1]
+ if !(t.IsComplex() && t.Size() == 16) {
+ goto end1b106f89e0e3e26c613b957a7c98d8ad
+ }
+ v.Op = OpComplexMake
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v0 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+ v0.Type = config.fe.TypeFloat64()
+ v0.AddArg(ptr)
+ v0.AddArg(mem)
+ v.AddArg(v0)
+ v1 := b.NewValue0(v.Line, OpLoad, TypeInvalid)
+ v1.Type = config.fe.TypeFloat64()
+ v2 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+ v2.Type = config.fe.TypeFloat64().PtrTo()
+ v2.AuxInt = 8
+ v2.AddArg(ptr)
+ v1.AddArg(v2)
+ v1.AddArg(mem)
+ v.AddArg(v1)
+ return true
+ }
+ goto end1b106f89e0e3e26c613b957a7c98d8ad
+ end1b106f89e0e3e26c613b957a7c98d8ad:
+ ;
// match: (Load <t> ptr mem)
// cond: t.IsString()
// result: (StringMake (Load <config.fe.TypeBytePtr()> ptr mem) (Load <config.fe.TypeUintptr()> (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] ptr) mem))
end526acc0a705137a5d25577499206720b:
;
case OpStore:
+ // match: (Store [8] dst (ComplexMake real imag) mem)
+ // cond:
+ // result: (Store [4] (OffPtr <config.fe.TypeFloat32().PtrTo()> [4] dst) imag (Store <TypeMem> [4] dst real mem))
+ {
+ if v.AuxInt != 8 {
+ goto endba187c049aa71488994c8a2eb3453045
+ }
+ dst := v.Args[0]
+ if v.Args[1].Op != OpComplexMake {
+ goto endba187c049aa71488994c8a2eb3453045
+ }
+ real := v.Args[1].Args[0]
+ imag := v.Args[1].Args[1]
+ mem := v.Args[2]
+ v.Op = OpStore
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v.AuxInt = 4
+ v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+ v0.Type = config.fe.TypeFloat32().PtrTo()
+ v0.AuxInt = 4
+ v0.AddArg(dst)
+ v.AddArg(v0)
+ v.AddArg(imag)
+ v1 := b.NewValue0(v.Line, OpStore, TypeInvalid)
+ v1.Type = TypeMem
+ v1.AuxInt = 4
+ v1.AddArg(dst)
+ v1.AddArg(real)
+ v1.AddArg(mem)
+ v.AddArg(v1)
+ return true
+ }
+ goto endba187c049aa71488994c8a2eb3453045
+ endba187c049aa71488994c8a2eb3453045:
+ ;
+ // match: (Store [16] dst (ComplexMake real imag) mem)
+ // cond:
+ // result: (Store [8] (OffPtr <config.fe.TypeFloat64().PtrTo()> [8] dst) imag (Store <TypeMem> [8] dst real mem))
+ {
+ if v.AuxInt != 16 {
+ goto end4df4c826201cf51af245d6b89de00589
+ }
+ dst := v.Args[0]
+ if v.Args[1].Op != OpComplexMake {
+ goto end4df4c826201cf51af245d6b89de00589
+ }
+ real := v.Args[1].Args[0]
+ imag := v.Args[1].Args[1]
+ mem := v.Args[2]
+ v.Op = OpStore
+ v.AuxInt = 0
+ v.Aux = nil
+ v.resetArgs()
+ v.AuxInt = 8
+ v0 := b.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+ v0.Type = config.fe.TypeFloat64().PtrTo()
+ v0.AuxInt = 8
+ v0.AddArg(dst)
+ v.AddArg(v0)
+ v.AddArg(imag)
+ v1 := b.NewValue0(v.Line, OpStore, TypeInvalid)
+ v1.Type = TypeMem
+ v1.AuxInt = 8
+ v1.AddArg(dst)
+ v1.AddArg(real)
+ v1.AddArg(mem)
+ v.AddArg(v1)
+ return true
+ }
+ goto end4df4c826201cf51af245d6b89de00589
+ end4df4c826201cf51af245d6b89de00589:
+ ;
// match: (Store [2*config.PtrSize] dst (StringMake ptr len) mem)
// cond:
// result: (Store [config.PtrSize] (OffPtr <config.fe.TypeUintptr().PtrTo()> [config.PtrSize] dst) len (Store <TypeMem> [config.PtrSize] dst ptr mem))
IsInteger() bool // ... ditto for the others
IsSigned() bool
IsFloat() bool
+ IsComplex() bool
IsPtr() bool
IsString() bool
IsSlice() bool
Flags bool
}
-func (t *CompilerType) Size() int64 { return 0 }
+func (t *CompilerType) Size() int64 { return 0 } // Size in bytes
func (t *CompilerType) Alignment() int64 { return 0 }
func (t *CompilerType) IsBoolean() bool { return false }
func (t *CompilerType) IsInteger() bool { return false }
func (t *CompilerType) IsSigned() bool { return false }
func (t *CompilerType) IsFloat() bool { return false }
+func (t *CompilerType) IsComplex() bool { return false }
func (t *CompilerType) IsPtr() bool { return false }
func (t *CompilerType) IsString() bool { return false }
func (t *CompilerType) IsSlice() bool { return false }
Integer bool
Signed bool
Float bool
+ Complex bool
Ptr bool
string bool
slice bool
func (t *TypeImpl) IsInteger() bool { return t.Integer }
func (t *TypeImpl) IsSigned() bool { return t.Signed }
func (t *TypeImpl) IsFloat() bool { return t.Float }
+func (t *TypeImpl) IsComplex() bool { return t.Complex }
func (t *TypeImpl) IsPtr() bool { return t.Ptr }
func (t *TypeImpl) IsString() bool { return t.string }
func (t *TypeImpl) IsSlice() bool { return t.slice }
var (
// shortcuts for commonly used basic types
- TypeInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Signed: true, Name: "int8"}
- TypeInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Signed: true, Name: "int16"}
- TypeInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Signed: true, Name: "int32"}
- TypeInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Signed: true, Name: "int64"}
- TypeUInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Name: "uint8"}
- TypeUInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Name: "uint16"}
- TypeUInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Name: "uint32"}
- TypeUInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Name: "uint64"}
- TypeBool = &TypeImpl{Size_: 1, Align: 1, Boolean: true, Name: "bool"}
- TypeBytePtr = &TypeImpl{Size_: 8, Align: 8, Ptr: true, Name: "*byte"}
+ TypeInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Signed: true, Name: "int8"}
+ TypeInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Signed: true, Name: "int16"}
+ TypeInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Signed: true, Name: "int32"}
+ TypeInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Signed: true, Name: "int64"}
+ TypeFloat32 = &TypeImpl{Size_: 4, Align: 4, Float: true, Name: "float32"}
+ TypeFloat64 = &TypeImpl{Size_: 8, Align: 8, Float: true, Name: "float64"}
+ TypeComplex64 = &TypeImpl{Size_: 8, Align: 4, Complex: true, Name: "complex64"}
+ TypeComplex128 = &TypeImpl{Size_: 16, Align: 8, Complex: true, Name: "complex128"}
+ TypeUInt8 = &TypeImpl{Size_: 1, Align: 1, Integer: true, Name: "uint8"}
+ TypeUInt16 = &TypeImpl{Size_: 2, Align: 2, Integer: true, Name: "uint16"}
+ TypeUInt32 = &TypeImpl{Size_: 4, Align: 4, Integer: true, Name: "uint32"}
+ TypeUInt64 = &TypeImpl{Size_: 8, Align: 8, Integer: true, Name: "uint64"}
+ TypeBool = &TypeImpl{Size_: 1, Align: 1, Boolean: true, Name: "bool"}
+ TypeBytePtr = &TypeImpl{Size_: 8, Align: 8, Ptr: true, Name: "*byte"}
)