aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2019-02-08 19:42:24 +0100
committerRon Evans <[email protected]>2019-02-18 17:17:56 +0100
commitfab38a07493bd4f4030cdef2356afc316d73f509 (patch)
tree8200f35aa3063ae0d355511d453d5e91658acd86
parent0a3dbbd1cb566e787b7530da1311de25d8eff25c (diff)
downloadtinygo-fab38a07493bd4f4030cdef2356afc316d73f509.tar.gz
tinygo-fab38a07493bd4f4030cdef2356afc316d73f509.zip
compiler: use Clang data layout for complex numbers
Match data layout of complex numbers to that of Clang, for better interoperability. This makes alignment of complex numbes the same as the individual elements (real and imaginary), as is required by the C spec and implemented in Clang, but unlike the gc compler. The Go language specification is silent on this matter. > Each complex type has the same object representation and alignment > requirements as an array of two elements of the corresponding real > type (float for float complex, double for double complex, long double > for long double complex). The first element of the array holds the > real part, and the second element of the array holds the imaginary > component. Source: https://en.cppreference.com/w/c/language/arithmetic_types
-rw-r--r--compiler/compiler.go70
-rw-r--r--compiler/interface.go2
2 files changed, 29 insertions, 43 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go
index e07d83f06..a934515c1 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -418,9 +418,9 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
case types.Float64:
return c.ctx.DoubleType(), nil
case types.Complex64:
- return llvm.VectorType(c.ctx.FloatType(), 2), nil
+ return c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false), nil
case types.Complex128:
- return llvm.VectorType(c.ctx.DoubleType(), 2), nil
+ return c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false), nil
case types.String, types.UntypedString:
return c.mod.GetTypeByName("runtime._string"), nil
case types.Uintptr:
@@ -567,16 +567,6 @@ func (c *Compiler) getZeroValue(typ llvm.Type) (llvm.Value, error) {
} else {
return c.ctx.ConstStruct(vals, false), nil
}
- case llvm.VectorTypeKind:
- zero, err := c.getZeroValue(typ.ElementType())
- if err != nil {
- return llvm.Value{}, err
- }
- vals := make([]llvm.Value, typ.VectorSize())
- for i := range vals {
- vals[i] = zero
- }
- return llvm.ConstVector(vals, false), nil
default:
return llvm.Value{}, errors.New("todo: LLVM zero initializer: " + typ.String())
}
@@ -1396,14 +1386,14 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
var cplx llvm.Value
switch t.Kind() {
case types.Float32:
- cplx = llvm.Undef(llvm.VectorType(c.ctx.FloatType(), 2))
+ cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
case types.Float64:
- cplx = llvm.Undef(llvm.VectorType(c.ctx.DoubleType(), 2))
+ cplx = llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
default:
return llvm.Value{}, c.makeError(pos, "unsupported type in complex builtin: "+t.String())
}
- cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
- cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
+ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
+ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
case "copy":
dst, err := c.parseExpr(frame, args[0])
@@ -1438,8 +1428,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
if err != nil {
return llvm.Value{}, err
}
- index := llvm.ConstInt(c.ctx.Int32Type(), 1, false)
- return c.builder.CreateExtractElement(cplx, index, "imag"), nil
+ return c.builder.CreateExtractValue(cplx, 1, "imag"), nil
case "len":
value, err := c.parseExpr(frame, args[0])
if err != nil {
@@ -1528,8 +1517,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
if err != nil {
return llvm.Value{}, err
}
- index := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
- return c.builder.CreateExtractElement(cplx, index, "real"), nil
+ return c.builder.CreateExtractValue(cplx, 0, "real"), nil
case "recover":
return c.createRuntimeCall("_recover", nil, ""), nil
case "ssa:wrapnilchk":
@@ -2440,12 +2428,10 @@ func (c *Compiler) parseBinOp(op token.Token, typ types.Type, x, y llvm.Value, p
panic("binop on float: " + op.String())
}
} else if typ.Info()&types.IsComplex != 0 {
- indexr := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
- indexi := llvm.ConstInt(c.ctx.Int32Type(), 1, false)
- r1 := c.builder.CreateExtractElement(x, indexr, "r1")
- r2 := c.builder.CreateExtractElement(y, indexr, "r2")
- i1 := c.builder.CreateExtractElement(x, indexi, "i1")
- i2 := c.builder.CreateExtractElement(y, indexi, "i2")
+ r1 := c.builder.CreateExtractValue(x, 0, "r1")
+ r2 := c.builder.CreateExtractValue(y, 0, "r2")
+ i1 := c.builder.CreateExtractValue(x, 1, "i1")
+ i2 := c.builder.CreateExtractValue(y, 1, "i2")
switch op {
case token.EQL: // ==
req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
@@ -2665,9 +2651,9 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
if err != nil {
return llvm.Value{}, err
}
- cplx := llvm.Undef(llvm.VectorType(c.ctx.FloatType(), 2))
- cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
- cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
+ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
+ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
} else if typ.Kind() == types.Complex128 {
r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]))
@@ -2678,9 +2664,9 @@ func (c *Compiler) parseConst(prefix string, expr *ssa.Const) (llvm.Value, error
if err != nil {
return llvm.Value{}, err
}
- cplx := llvm.Undef(llvm.VectorType(c.ctx.DoubleType(), 2))
- cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
- cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
+ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
+ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
} else {
return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
@@ -2848,25 +2834,25 @@ func (c *Compiler) parseConvert(typeFrom, typeTo types.Type, value llvm.Value, p
if typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 {
// Conversion from complex128 to complex64.
- r := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 0, false), "real.f64")
- i := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 1, false), "imag.f64")
+ r := c.builder.CreateExtractValue(value, 0, "real.f64")
+ i := c.builder.CreateExtractValue(value, 1, "imag.f64")
r = c.builder.CreateFPTrunc(r, c.ctx.FloatType(), "real.f32")
i = c.builder.CreateFPTrunc(i, c.ctx.FloatType(), "imag.f32")
- cplx := llvm.Undef(llvm.VectorType(c.ctx.FloatType(), 2))
- cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
- cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
+ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
+ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
}
if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {
// Conversion from complex64 to complex128.
- r := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 0, false), "real.f32")
- i := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 1, false), "imag.f32")
+ r := c.builder.CreateExtractValue(value, 0, "real.f32")
+ i := c.builder.CreateExtractValue(value, 1, "imag.f32")
r = c.builder.CreateFPExt(r, c.ctx.DoubleType(), "real.f64")
i = c.builder.CreateFPExt(i, c.ctx.DoubleType(), "imag.f64")
- cplx := llvm.Undef(llvm.VectorType(c.ctx.DoubleType(), 2))
- cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
- cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
+ cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
+ cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
+ cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
}
diff --git a/compiler/interface.go b/compiler/interface.go
index 6aec6298c..9e2e8b437 100644
--- a/compiler/interface.go
+++ b/compiler/interface.go
@@ -53,7 +53,7 @@ func (c *Compiler) parseMakeInterface(val llvm.Value, typ types.Type, global str
itfValue = c.builder.CreateIntToPtr(val, c.i8ptrType, "makeinterface.cast.int")
case llvm.PointerTypeKind:
itfValue = c.builder.CreateBitCast(val, c.i8ptrType, "makeinterface.cast.ptr")
- case llvm.StructTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind, llvm.VectorTypeKind:
+ case llvm.StructTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:
// A bitcast would be useful here, but bitcast doesn't allow
// aggregate types. So we'll bitcast it using an alloca.
// Hopefully this will get optimized away.