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
Этот коммит содержится в:
родитель
0a3dbbd1cb
коммит
fab38a0749
2 изменённых файлов: 29 добавлений и 43 удалений
|
@ -418,9 +418,9 @@ func (c *Compiler) getLLVMType(goType types.Type) (llvm.Type, error) {
|
||||||
case types.Float64:
|
case types.Float64:
|
||||||
return c.ctx.DoubleType(), nil
|
return c.ctx.DoubleType(), nil
|
||||||
case types.Complex64:
|
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:
|
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:
|
case types.String, types.UntypedString:
|
||||||
return c.mod.GetTypeByName("runtime._string"), nil
|
return c.mod.GetTypeByName("runtime._string"), nil
|
||||||
case types.Uintptr:
|
case types.Uintptr:
|
||||||
|
@ -567,16 +567,6 @@ func (c *Compiler) getZeroValue(typ llvm.Type) (llvm.Value, error) {
|
||||||
} else {
|
} else {
|
||||||
return c.ctx.ConstStruct(vals, false), nil
|
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:
|
default:
|
||||||
return llvm.Value{}, errors.New("todo: LLVM zero initializer: " + typ.String())
|
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
|
var cplx llvm.Value
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case types.Float32:
|
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:
|
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:
|
default:
|
||||||
return llvm.Value{}, c.makeError(pos, "unsupported type in complex builtin: "+t.String())
|
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.CreateInsertValue(cplx, r, 0, "")
|
||||||
cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||||
return cplx, nil
|
return cplx, nil
|
||||||
case "copy":
|
case "copy":
|
||||||
dst, err := c.parseExpr(frame, args[0])
|
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 {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
index := llvm.ConstInt(c.ctx.Int32Type(), 1, false)
|
return c.builder.CreateExtractValue(cplx, 1, "imag"), nil
|
||||||
return c.builder.CreateExtractElement(cplx, index, "imag"), nil
|
|
||||||
case "len":
|
case "len":
|
||||||
value, err := c.parseExpr(frame, args[0])
|
value, err := c.parseExpr(frame, args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1528,8 +1517,7 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
index := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
return c.builder.CreateExtractValue(cplx, 0, "real"), nil
|
||||||
return c.builder.CreateExtractElement(cplx, index, "real"), nil
|
|
||||||
case "recover":
|
case "recover":
|
||||||
return c.createRuntimeCall("_recover", nil, ""), nil
|
return c.createRuntimeCall("_recover", nil, ""), nil
|
||||||
case "ssa:wrapnilchk":
|
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())
|
panic("binop on float: " + op.String())
|
||||||
}
|
}
|
||||||
} else if typ.Info()&types.IsComplex != 0 {
|
} else if typ.Info()&types.IsComplex != 0 {
|
||||||
indexr := llvm.ConstInt(c.ctx.Int32Type(), 0, false)
|
r1 := c.builder.CreateExtractValue(x, 0, "r1")
|
||||||
indexi := llvm.ConstInt(c.ctx.Int32Type(), 1, false)
|
r2 := c.builder.CreateExtractValue(y, 0, "r2")
|
||||||
r1 := c.builder.CreateExtractElement(x, indexr, "r1")
|
i1 := c.builder.CreateExtractValue(x, 1, "i1")
|
||||||
r2 := c.builder.CreateExtractElement(y, indexr, "r2")
|
i2 := c.builder.CreateExtractValue(y, 1, "i2")
|
||||||
i1 := c.builder.CreateExtractElement(x, indexi, "i1")
|
|
||||||
i2 := c.builder.CreateExtractElement(y, indexi, "i2")
|
|
||||||
switch op {
|
switch op {
|
||||||
case token.EQL: // ==
|
case token.EQL: // ==
|
||||||
req := c.builder.CreateFCmp(llvm.FloatOEQ, r1, r2, "")
|
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 {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
cplx := llvm.Undef(llvm.VectorType(c.ctx.FloatType(), 2))
|
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
|
||||||
cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||||
cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||||
return cplx, nil
|
return cplx, nil
|
||||||
} else if typ.Kind() == types.Complex128 {
|
} else if typ.Kind() == types.Complex128 {
|
||||||
r, err := c.parseConst(prefix, ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64]))
|
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 {
|
if err != nil {
|
||||||
return llvm.Value{}, err
|
return llvm.Value{}, err
|
||||||
}
|
}
|
||||||
cplx := llvm.Undef(llvm.VectorType(c.ctx.DoubleType(), 2))
|
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
|
||||||
cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||||
cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||||
return cplx, nil
|
return cplx, nil
|
||||||
} else {
|
} else {
|
||||||
return llvm.Value{}, errors.New("todo: unknown constant: " + expr.String())
|
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 {
|
if typeFrom.Kind() == types.Complex128 && typeTo.Kind() == types.Complex64 {
|
||||||
// Conversion from complex128 to complex64.
|
// Conversion from complex128 to complex64.
|
||||||
r := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 0, false), "real.f64")
|
r := c.builder.CreateExtractValue(value, 0, "real.f64")
|
||||||
i := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 1, false), "imag.f64")
|
i := c.builder.CreateExtractValue(value, 1, "imag.f64")
|
||||||
r = c.builder.CreateFPTrunc(r, c.ctx.FloatType(), "real.f32")
|
r = c.builder.CreateFPTrunc(r, c.ctx.FloatType(), "real.f32")
|
||||||
i = c.builder.CreateFPTrunc(i, c.ctx.FloatType(), "imag.f32")
|
i = c.builder.CreateFPTrunc(i, c.ctx.FloatType(), "imag.f32")
|
||||||
cplx := llvm.Undef(llvm.VectorType(c.ctx.FloatType(), 2))
|
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false))
|
||||||
cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||||
cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||||
return cplx, nil
|
return cplx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {
|
if typeFrom.Kind() == types.Complex64 && typeTo.Kind() == types.Complex128 {
|
||||||
// Conversion from complex64 to complex128.
|
// Conversion from complex64 to complex128.
|
||||||
r := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 0, false), "real.f32")
|
r := c.builder.CreateExtractValue(value, 0, "real.f32")
|
||||||
i := c.builder.CreateExtractElement(value, llvm.ConstInt(c.ctx.Int32Type(), 1, false), "imag.f32")
|
i := c.builder.CreateExtractValue(value, 1, "imag.f32")
|
||||||
r = c.builder.CreateFPExt(r, c.ctx.DoubleType(), "real.f64")
|
r = c.builder.CreateFPExt(r, c.ctx.DoubleType(), "real.f64")
|
||||||
i = c.builder.CreateFPExt(i, c.ctx.DoubleType(), "imag.f64")
|
i = c.builder.CreateFPExt(i, c.ctx.DoubleType(), "imag.f64")
|
||||||
cplx := llvm.Undef(llvm.VectorType(c.ctx.DoubleType(), 2))
|
cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false))
|
||||||
cplx = c.builder.CreateInsertElement(cplx, r, llvm.ConstInt(c.ctx.Int8Type(), 0, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, r, 0, "")
|
||||||
cplx = c.builder.CreateInsertElement(cplx, i, llvm.ConstInt(c.ctx.Int8Type(), 1, false), "")
|
cplx = c.builder.CreateInsertValue(cplx, i, 1, "")
|
||||||
return cplx, nil
|
return cplx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
itfValue = c.builder.CreateIntToPtr(val, c.i8ptrType, "makeinterface.cast.int")
|
||||||
case llvm.PointerTypeKind:
|
case llvm.PointerTypeKind:
|
||||||
itfValue = c.builder.CreateBitCast(val, c.i8ptrType, "makeinterface.cast.ptr")
|
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
|
// A bitcast would be useful here, but bitcast doesn't allow
|
||||||
// aggregate types. So we'll bitcast it using an alloca.
|
// aggregate types. So we'll bitcast it using an alloca.
|
||||||
// Hopefully this will get optimized away.
|
// Hopefully this will get optimized away.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче