diff --git a/cl/_testrt/complex/in.go b/cl/_testrt/complex/in.go new file mode 100644 index 00000000..fe775bd9 --- /dev/null +++ b/cl/_testrt/complex/in.go @@ -0,0 +1,10 @@ +package main + +type T complex64 + +func main() { + c := 1 + 2i + d := T(c) + println(c, real(c), imag(c)) + println(d, real(d), imag(d)) +} diff --git a/cl/_testrt/complex/out.ll b/cl/_testrt/complex/out.ll new file mode 100644 index 00000000..a123708d --- /dev/null +++ b/cl/_testrt/complex/out.ll @@ -0,0 +1,68 @@ +; ModuleID = 'main' +source_filename = "main" + +@"main.init$guard" = global i1 false, align 1 +@__llgo_argc = global i32 0, align 4 +@__llgo_argv = global ptr null, align 8 + +define void @main.init() { +_llgo_0: + %0 = load i1, ptr @"main.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"main.init$guard", align 1 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @main(i32 %0, ptr %1) { +_llgo_0: + store i32 %0, ptr @__llgo_argc, align 4 + store ptr %1, ptr @__llgo_argv, align 8 + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + %2 = alloca { float, float }, align 8 + %3 = getelementptr inbounds { float, float }, ptr %2, i32 0, i32 0 + store float 1.000000e+00, ptr %3, align 4 + %4 = getelementptr inbounds { float, float }, ptr %2, i32 0, i32 1 + store float 2.000000e+00, ptr %4, align 4 + %5 = load { float, float }, ptr %2, align 4 + call void @"github.com/goplus/llgo/internal/runtime.PrintComplex"({ double, double } { double 1.000000e+00, double 2.000000e+00 }) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double 1.000000e+00) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double 2.000000e+00) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %6 = extractvalue { float, float } %5, 0 + %7 = extractvalue { float, float } %5, 1 + %8 = extractvalue { float, float } %5, 0 + %9 = extractvalue { float, float } %5, 1 + %10 = fpext float %8 to double + %11 = fpext float %9 to double + %12 = alloca { double, double }, align 8 + %13 = getelementptr inbounds { double, double }, ptr %12, i32 0, i32 0 + store double %10, ptr %13, align 8 + %14 = getelementptr inbounds { double, double }, ptr %12, i32 0, i32 1 + store double %11, ptr %14, align 8 + %15 = load { double, double }, ptr %12, align 8 + call void @"github.com/goplus/llgo/internal/runtime.PrintComplex"({ double, double } %15) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + %16 = fpext float %6 to double + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %16) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + %17 = fpext float %7 to double + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %17) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + ret i32 0 +} + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.PrintComplex"({ double, double }) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double) diff --git a/internal/runtime/z_print.go b/internal/runtime/z_print.go index cbf9d83d..6c426edc 100644 --- a/internal/runtime/z_print.go +++ b/internal/runtime/z_print.go @@ -47,12 +47,12 @@ func PrintFloat(v float64) { } return } - c.Fprintf(c.Stderr, c.Str("%e"), v) + c.Fprintf(c.Stderr, c.Str("%+e"), v) } -// func PrintComplex(c complex128) { -// print("(", real(c), imag(c), "i)") -// } +func PrintComplex(v complex128) { + print("(", real(v), imag(v), "i)") +} func PrintUint(v uint64) { c.Fprintf(c.Stderr, c.Str("%llu"), v) diff --git a/internal/runtime/z_rt.go b/internal/runtime/z_rt.go index 6653ff3d..eb9bbac9 100644 --- a/internal/runtime/z_rt.go +++ b/internal/runtime/z_rt.go @@ -122,6 +122,10 @@ func TracePanic(v any) { } else { println(*(*float64)(e.data)) } + case abi.Complex64: + println(*(*complex64)(e.data)) + case abi.Complex128: + println(*(*complex128)(e.data)) case abi.String: println(*(*string)(e.data)) default: diff --git a/ssa/abi/abi.go b/ssa/abi/abi.go index 127e36cb..90186b57 100644 --- a/ssa/abi/abi.go +++ b/ssa/abi/abi.go @@ -89,7 +89,7 @@ func DataKindOf(raw types.Type, lvl int, is32Bits bool) (DataKind, types.Type, i return Integer, raw, lvl case kind == types.Float32: return BitCast, raw, lvl - case kind == types.Float64 || kind == types.Complex64: + case kind == types.Float64: if is32Bits { return Indirect, raw, lvl } diff --git a/ssa/expr.go b/ssa/expr.go index ab6ecbfd..d7d1ef20 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -685,6 +685,18 @@ func (b Builder) Convert(t Type, x Expr) (ret Expr) { ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringFromRune"), x).impl return } + case types.Complex128: + switch xtyp := x.RawType().Underlying().(type) { + case *types.Basic: + if xtyp.Kind() == types.Complex64 { + r := b.impl.CreateExtractValue(x.impl, 0, "") + i := b.impl.CreateExtractValue(x.impl, 1, "") + r = castFloat(b, r, b.Prog.Float64()) + i = castFloat(b, i, b.Prog.Float64()) + ret.impl = b.aggregateValue(t, r, i).impl + return + } + } } switch xtyp := x.RawType().Underlying().(type) { case *types.Basic: @@ -716,6 +728,16 @@ func (b Builder) Convert(t Type, x Expr) (ret Expr) { } } } + if x.kind == vkComplex && t.kind == vkComplex { + ft := b.Prog.Float64() + if t.raw.Type.Underlying().(*types.Basic).Kind() == types.Complex64 { + ft = b.Prog.Float32() + } + r := b.impl.CreateExtractValue(x.impl, 0, "") + i := b.impl.CreateExtractValue(x.impl, 1, "") + ret.impl = b.Complex(Expr{castFloat(b, r, ft), ft}, Expr{castFloat(b, i, ft), ft}).impl + return + } case *types.Pointer: ret.impl = castPtr(b.impl, x.impl, t.ll) return @@ -1015,8 +1037,9 @@ func (b Builder) PrintEx(ln bool, args ...Expr) (ret Expr) { fn = "PrintEface" case vkIface: fn = "PrintIface" - // case vkComplex: - // fn = "PrintComplex" + case vkComplex: + fn = "PrintComplex" + typ = prog.Complex128() default: panic(fmt.Errorf("illegal types for operand: print %v", arg.RawType())) } diff --git a/ssa/type.go b/ssa/type.go index cc192ad5..16a98dd6 100644 --- a/ssa/type.go +++ b/ssa/type.go @@ -211,7 +211,7 @@ func (p Program) Index(typ Type) Type { func (p Program) Field(typ Type, i int) Type { var fld *types.Var - switch t := typ.raw.Type.(type) { + switch t := typ.raw.Type.Underlying().(type) { case *types.Tuple: fld = t.At(i) case *types.Basic: @@ -223,7 +223,7 @@ func (p Program) Field(typ Type, i int) Type { } panic("Field: basic type doesn't have fields") default: - fld = t.Underlying().(*types.Struct).Field(i) + fld = t.(*types.Struct).Field(i) } return p.rawType(fld.Type()) }