llgo/ssa: MakeInterface
This commit is contained in:
@@ -120,62 +120,33 @@ func (b Builder) MakeInterface(tinter Type, x Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
typ := x.Type
|
typ := x.Type
|
||||||
switch tx := typ.raw.Type.Underlying().(type) {
|
tabi := b.abiType(typ.raw.Type)
|
||||||
case *types.Basic:
|
kind, _, lvl := abi.KindOf(typ.raw.Type, 0, prog.is32Bits)
|
||||||
kind := tx.Kind()
|
switch kind {
|
||||||
switch {
|
case abi.Indirect:
|
||||||
case kind >= types.Bool && kind <= types.Uintptr:
|
vptr := b.AllocU(typ)
|
||||||
if prog.is32Bits && (kind == types.Int64 || kind == types.Uint64) {
|
b.Store(vptr, x)
|
||||||
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
|
|
||||||
}
|
|
||||||
return b.makeIntfByIntptr(tinter, rawIntf, typ, x.impl)
|
|
||||||
case kind == types.Float32:
|
|
||||||
i32 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt32())
|
|
||||||
return b.makeIntfByIntptr(tinter, rawIntf, typ, i32)
|
|
||||||
case kind == types.Float64:
|
|
||||||
if prog.is32Bits {
|
|
||||||
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
|
|
||||||
}
|
|
||||||
i64 := llvm.CreateBitCast(b.impl, x.impl, prog.tyInt64())
|
|
||||||
return b.makeIntfByIntptr(tinter, rawIntf, typ, i64)
|
|
||||||
case kind == types.String:
|
|
||||||
return Expr{b.InlineCall(b.Pkg.rtFunc("MakeAnyString"), x).impl, tinter}
|
|
||||||
}
|
|
||||||
case *types.Struct:
|
|
||||||
size := int(prog.SizeOf(typ))
|
|
||||||
if size > prog.PointerSize() {
|
|
||||||
return b.makeIntfAlloc(tinter, rawIntf, typ, x)
|
|
||||||
}
|
|
||||||
tv := prog.ctx.IntType(size * 8)
|
|
||||||
iv := llvm.CreateBitCast(b.impl, x.impl, tv)
|
|
||||||
return b.makeIntfByIntptr(tinter, rawIntf, typ, iv)
|
|
||||||
}
|
|
||||||
panic("todo")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b Builder) makeIntfAlloc(tinter Type, rawIntf *types.Interface, typ Type, x Expr) (ret Expr) {
|
|
||||||
vptr := b.AllocU(typ)
|
|
||||||
b.Store(vptr, x)
|
|
||||||
return b.makeIntfByPtr(tinter, rawIntf, typ, vptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b Builder) makeIntfByPtr(tinter Type, rawIntf *types.Interface, typ Type, vptr Expr) (ret Expr) {
|
|
||||||
if rawIntf.Empty() {
|
|
||||||
tabi := b.abiType(typ.raw.Type)
|
|
||||||
return Expr{b.unsafeEface(tabi.impl, vptr.impl), tinter}
|
return Expr{b.unsafeEface(tabi.impl, vptr.impl), tinter}
|
||||||
}
|
}
|
||||||
panic("todo")
|
ximpl := x.impl
|
||||||
}
|
if lvl > 0 {
|
||||||
|
ximpl = extractVal(b.impl, ximpl, lvl)
|
||||||
// TODO(xsw): remove MakeAnyIntptr, MakeAnyString
|
|
||||||
func (b Builder) makeIntfByIntptr(tinter Type, rawIntf *types.Interface, typ Type, x llvm.Value) (ret Expr) {
|
|
||||||
if rawIntf.Empty() {
|
|
||||||
tptr := b.Prog.Uintptr()
|
|
||||||
x = llvm.CreateIntCast(b.impl, x, tptr.ll)
|
|
||||||
impl := b.InlineCall(b.Pkg.rtFunc("MakeAnyIntptr"), b.abiType(typ.raw.Type), Expr{x, tptr}).impl
|
|
||||||
return Expr{impl, tinter}
|
|
||||||
}
|
}
|
||||||
panic("todo")
|
var u llvm.Value
|
||||||
|
switch kind {
|
||||||
|
case abi.Pointer:
|
||||||
|
return Expr{b.unsafeEface(tabi.impl, ximpl), tinter}
|
||||||
|
case abi.Integer:
|
||||||
|
tu := prog.Uintptr()
|
||||||
|
u = llvm.CreateIntCast(b.impl, ximpl, tu.ll)
|
||||||
|
case abi.BitCast:
|
||||||
|
tu := prog.Uintptr()
|
||||||
|
u = llvm.CreateBitCast(b.impl, ximpl, tu.ll)
|
||||||
|
default:
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
data := llvm.CreateIntToPtr(b.impl, u, prog.tyVoidPtr())
|
||||||
|
return Expr{b.unsafeEface(tabi.impl, data), tinter}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
|
func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
|
||||||
@@ -188,14 +159,14 @@ func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
|
|||||||
tptr := llvm.PointerType(tll, 0)
|
tptr := llvm.PointerType(tll, 0)
|
||||||
ptr := llvm.CreatePointerCast(impl, data, tptr)
|
ptr := llvm.CreatePointerCast(impl, data, tptr)
|
||||||
return Expr{llvm.CreateLoad(impl, tll, ptr), typ}
|
return Expr{llvm.CreateLoad(impl, tll, ptr), typ}
|
||||||
case abi.Pointer:
|
|
||||||
return Expr{data, typ}
|
|
||||||
}
|
}
|
||||||
t := typ
|
t := typ
|
||||||
if lvl > 0 {
|
if lvl > 0 {
|
||||||
t = prog.rawType(real)
|
t = prog.rawType(real)
|
||||||
}
|
}
|
||||||
switch kind {
|
switch kind {
|
||||||
|
case abi.Pointer:
|
||||||
|
return b.buildVal(typ, data, lvl)
|
||||||
case abi.Integer:
|
case abi.Integer:
|
||||||
x := castUintptr(b, data, prog.Uintptr())
|
x := castUintptr(b, data, prog.Uintptr())
|
||||||
return b.buildVal(typ, castInt(b, x, t), lvl)
|
return b.buildVal(typ, castInt(b, x, t), lvl)
|
||||||
@@ -206,6 +177,15 @@ func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func extractVal(b llvm.Builder, val llvm.Value, lvl int) llvm.Value {
|
||||||
|
for lvl > 0 {
|
||||||
|
// TODO(xsw): check array support
|
||||||
|
val = llvm.CreateExtractValue(b, val, 0)
|
||||||
|
lvl--
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
func (b Builder) buildVal(typ Type, val llvm.Value, lvl int) Expr {
|
func (b Builder) buildVal(typ Type, val llvm.Value, lvl int) Expr {
|
||||||
if lvl == 0 {
|
if lvl == 0 {
|
||||||
return Expr{val, typ}
|
return Expr{val, typ}
|
||||||
|
|||||||
Reference in New Issue
Block a user