Этот коммит содержится в:
Ayke van Laethem 2018-04-25 19:50:46 +02:00
родитель 69140c240b
коммит e80f06bc5e

45
tgo.go
Просмотреть файл

@ -663,10 +663,12 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
return c.parseBinOp(frame, expr) return c.parseBinOp(frame, expr)
case *ssa.Call: case *ssa.Call:
return c.parseCall(frame, expr) return c.parseCall(frame, expr)
case *ssa.ChangeType:
return c.parseConvert(frame, expr.Type(), expr.X)
case *ssa.Const: case *ssa.Const:
return c.parseConst(expr) return c.parseConst(expr)
case *ssa.Convert: case *ssa.Convert:
return c.parseConvert(frame, expr) return c.parseConvert(frame, expr.Type(), expr.X)
case *ssa.Extract: case *ssa.Extract:
value, err := c.parseExpr(frame, expr.Tuple) value, err := c.parseExpr(frame, expr.Tuple)
if err != nil { if err != nil {
@ -961,41 +963,42 @@ func (c *Compiler) parseConstInt(expr *ssa.Const, typ types.Type) (llvm.Value, e
} }
} }
func (c *Compiler) parseConvert(frame *Frame, expr *ssa.Convert) (llvm.Value, error) { func (c *Compiler) parseConvert(frame *Frame, typeTo types.Type, x ssa.Value) (llvm.Value, error) {
value, err := c.parseExpr(frame, expr.X) switch typeTo := typeTo.(type) {
case *types.Basic:
value, err := c.parseExpr(frame, x)
if err != nil { if err != nil {
return value, nil return value, nil
} }
typeFrom, err := c.getLLVMType(expr.X.Type()) llvmTypeFrom, err := c.getLLVMType(x.Type())
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
sizeFrom := c.targetData.TypeAllocSize(typeFrom) sizeFrom := c.targetData.TypeAllocSize(llvmTypeFrom)
typeTo, err := c.getLLVMType(expr.Type()) llvmTypeTo, err := c.getLLVMType(typeTo)
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
sizeTo := c.targetData.TypeAllocSize(typeTo) sizeTo := c.targetData.TypeAllocSize(llvmTypeTo)
if sizeFrom > sizeTo { if typeTo.Info() & types.IsInteger == 0 { // if not integer
return c.builder.CreateTrunc(value, typeTo, ""), nil
} else if sizeFrom == sizeTo {
return c.builder.CreateBitCast(value, typeTo, ""), nil
} else { // sizeFrom < sizeTo: extend
switch typ := expr.X.Type().(type) { // typeFrom
case *types.Basic:
if typ.Info() & types.IsInteger == 0 { // if not integer
return llvm.Value{}, errors.New("todo: convert: extend non-integer type") return llvm.Value{}, errors.New("todo: convert: extend non-integer type")
} }
if typ.Info() & types.IsUnsigned != 0 { // if unsigned
return c.builder.CreateZExt(value, typeTo, ""), nil if sizeFrom > sizeTo {
} else { return c.builder.CreateTrunc(value, llvmTypeTo, ""), nil
return c.builder.CreateSExt(value, typeTo, ""), nil } else if sizeFrom == sizeTo {
return c.builder.CreateBitCast(value, llvmTypeTo, ""), nil
} else if typeTo.Info() & types.IsUnsigned != 0 { // if unsigned
return c.builder.CreateZExt(value, llvmTypeTo, ""), nil
} else { // if signed
return c.builder.CreateSExt(value, llvmTypeTo, ""), nil
} }
case *types.Named:
return c.parseConvert(frame, typeTo.Underlying(), x)
default: default:
return llvm.Value{}, errors.New("todo: convert: extend non-basic type") return llvm.Value{}, errors.New("todo: convert: extend non-basic type: " + fmt.Sprintf("%#v", typeTo))
}
} }
} }