llgo/ssa: valFromData, buildVal
This commit is contained in:
@@ -0,0 +1,150 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.eface" = type { ptr, ptr }
|
||||||
|
%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 }
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@__llgo_argc = global ptr null
|
||||||
|
@__llgo_argv = global ptr null
|
||||||
|
@"_llgo_struct$K-dZ9QotZfVPz2a0YdRa9vmZUuDXPTqZOlMShKEDJtk" = global ptr null
|
||||||
|
@"main.struct$MYpsoM99ZwFY087IpUOkIw1zjBA_sgFXVodmn1m-G88" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [12 x i8] c"Bar: not ok\00", align 1
|
||||||
|
@1 = private unnamed_addr constant [10 x i8] c"F: not ok\00", align 1
|
||||||
|
|
||||||
|
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
|
||||||
|
call void @"github.com/goplus/llgo/_demo/interf/foo.init"()
|
||||||
|
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 { i64 }, align 8
|
||||||
|
%3 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %2, i64 8)
|
||||||
|
%4 = call %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/_demo/interf/foo.Bar"()
|
||||||
|
%5 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %4, 0
|
||||||
|
%6 = load ptr, ptr @"_llgo_struct$K-dZ9QotZfVPz2a0YdRa9vmZUuDXPTqZOlMShKEDJtk", align 8
|
||||||
|
%7 = icmp eq ptr %5, %6
|
||||||
|
%8 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %4, 1
|
||||||
|
%9 = ptrtoint ptr %8 to i64
|
||||||
|
%10 = alloca { i64 }, align 8
|
||||||
|
%11 = getelementptr inbounds { i64 }, ptr %10, i32 0, i32 0
|
||||||
|
store i64 %9, ptr %11, align 4
|
||||||
|
%12 = load { i64 }, ptr %10, align 4
|
||||||
|
%13 = alloca { { i64 }, i1 }, align 8
|
||||||
|
%14 = getelementptr inbounds { { i64 }, i1 }, ptr %13, i32 0, i32 0
|
||||||
|
store { i64 } %12, ptr %14, align 4
|
||||||
|
%15 = getelementptr inbounds { { i64 }, i1 }, ptr %13, i32 0, i32 1
|
||||||
|
store i1 true, ptr %15, align 1
|
||||||
|
%16 = load { { i64 }, i1 }, ptr %13, align 4
|
||||||
|
%17 = alloca { { i64 }, i1 }, align 8
|
||||||
|
%18 = getelementptr inbounds { { i64 }, i1 }, ptr %17, i32 0, i32 0
|
||||||
|
store { i64 } zeroinitializer, ptr %18, align 4
|
||||||
|
%19 = getelementptr inbounds { { i64 }, i1 }, ptr %17, i32 0, i32 1
|
||||||
|
store i1 false, ptr %19, align 1
|
||||||
|
%20 = load { { i64 }, i1 }, ptr %17, align 4
|
||||||
|
%21 = select i1 %7, { { i64 }, i1 } %16, { { i64 }, i1 } %20
|
||||||
|
%22 = extractvalue { { i64 }, i1 } %21, 0
|
||||||
|
store { i64 } %22, ptr %3, align 4
|
||||||
|
%23 = extractvalue { { i64 }, i1 } %21, 1
|
||||||
|
br i1 %23, label %_llgo_1, label %_llgo_3
|
||||||
|
|
||||||
|
_llgo_1: ; preds = %_llgo_0
|
||||||
|
%24 = getelementptr inbounds { i64 }, ptr %3, i32 0, i32 0
|
||||||
|
%25 = load i64, ptr %24, align 4
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %25)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_3, %_llgo_1
|
||||||
|
%26 = alloca { i64 }, align 8
|
||||||
|
%27 = call ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr %26, i64 8)
|
||||||
|
%28 = call %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/_demo/interf/foo.F"()
|
||||||
|
%29 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %28, 0
|
||||||
|
%30 = load ptr, ptr @"main.struct$MYpsoM99ZwFY087IpUOkIw1zjBA_sgFXVodmn1m-G88", align 8
|
||||||
|
%31 = icmp eq ptr %29, %30
|
||||||
|
%32 = extractvalue %"github.com/goplus/llgo/internal/runtime.eface" %28, 1
|
||||||
|
%33 = ptrtoint ptr %32 to i64
|
||||||
|
%34 = alloca { i64 }, align 8
|
||||||
|
%35 = getelementptr inbounds { i64 }, ptr %34, i32 0, i32 0
|
||||||
|
store i64 %33, ptr %35, align 4
|
||||||
|
%36 = load { i64 }, ptr %34, align 4
|
||||||
|
%37 = alloca { { i64 }, i1 }, align 8
|
||||||
|
%38 = getelementptr inbounds { { i64 }, i1 }, ptr %37, i32 0, i32 0
|
||||||
|
store { i64 } %36, ptr %38, align 4
|
||||||
|
%39 = getelementptr inbounds { { i64 }, i1 }, ptr %37, i32 0, i32 1
|
||||||
|
store i1 true, ptr %39, align 1
|
||||||
|
%40 = load { { i64 }, i1 }, ptr %37, align 4
|
||||||
|
%41 = alloca { { i64 }, i1 }, align 8
|
||||||
|
%42 = getelementptr inbounds { { i64 }, i1 }, ptr %41, i32 0, i32 0
|
||||||
|
store { i64 } zeroinitializer, ptr %42, align 4
|
||||||
|
%43 = getelementptr inbounds { { i64 }, i1 }, ptr %41, i32 0, i32 1
|
||||||
|
store i1 false, ptr %43, align 1
|
||||||
|
%44 = load { { i64 }, i1 }, ptr %41, align 4
|
||||||
|
%45 = select i1 %31, { { i64 }, i1 } %40, { { i64 }, i1 } %44
|
||||||
|
%46 = extractvalue { { i64 }, i1 } %45, 0
|
||||||
|
store { i64 } %46, ptr %27, align 4
|
||||||
|
%47 = extractvalue { { i64 }, i1 } %45, 1
|
||||||
|
br i1 %47, label %_llgo_4, label %_llgo_6
|
||||||
|
|
||||||
|
_llgo_3: ; preds = %_llgo_0
|
||||||
|
%48 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%49 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %48, i32 0, i32 0
|
||||||
|
store ptr @0, ptr %49, align 8
|
||||||
|
%50 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %48, i32 0, i32 1
|
||||||
|
store i64 11, ptr %50, align 4
|
||||||
|
%51 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %48, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %51)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_4: ; preds = %_llgo_2
|
||||||
|
%52 = getelementptr inbounds { i64 }, ptr %27, i32 0, i32 0
|
||||||
|
%53 = load i64, ptr %52, align 4
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %53)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
br label %_llgo_5
|
||||||
|
|
||||||
|
_llgo_5: ; preds = %_llgo_6, %_llgo_4
|
||||||
|
ret i32 0
|
||||||
|
|
||||||
|
_llgo_6: ; preds = %_llgo_2
|
||||||
|
%54 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8
|
||||||
|
%55 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %54, i32 0, i32 0
|
||||||
|
store ptr @1, ptr %55, align 8
|
||||||
|
%56 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %54, i32 0, i32 1
|
||||||
|
store i64 9, ptr %56, align 4
|
||||||
|
%57 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %54, align 8
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %57)
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10)
|
||||||
|
br label %_llgo_5
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/_demo/interf/foo.init"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
declare ptr @"github.com/goplus/llgo/internal/runtime.Zeroinit"(ptr, i64)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/_demo/interf/foo.Bar"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64)
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8)
|
||||||
|
|
||||||
|
declare %"github.com/goplus/llgo/internal/runtime.eface" @"github.com/goplus/llgo/_demo/interf/foo.F"()
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String")
|
||||||
|
|||||||
@@ -36,41 +36,41 @@ const (
|
|||||||
BitCast // store other value (need bitcast) directly in the interface value
|
BitCast // store other value (need bitcast) directly in the interface value
|
||||||
)
|
)
|
||||||
|
|
||||||
func KindOf(raw types.Type, is32Bits bool) (ret Kind) {
|
func KindOf(raw types.Type, lvl int, is32Bits bool) (Kind, types.Type, int) {
|
||||||
switch t := raw.Underlying().(type) {
|
switch t := raw.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := t.Kind()
|
kind := t.Kind()
|
||||||
switch {
|
switch {
|
||||||
case types.Bool <= kind && kind <= types.Uintptr:
|
case types.Bool <= kind && kind <= types.Uintptr:
|
||||||
if is32Bits && (kind == types.Int64 || kind == types.Uint64) {
|
if is32Bits && (kind == types.Int64 || kind == types.Uint64) {
|
||||||
return Indirect
|
return Indirect, raw, lvl
|
||||||
}
|
}
|
||||||
return Integer
|
return Integer, raw, lvl
|
||||||
case kind == types.Float32:
|
case kind == types.Float32:
|
||||||
return BitCast
|
return BitCast, raw, lvl
|
||||||
case kind == types.Float64 || kind == types.Complex64:
|
case kind == types.Float64 || kind == types.Complex64:
|
||||||
if is32Bits {
|
if is32Bits {
|
||||||
return Indirect
|
return Indirect, raw, lvl
|
||||||
}
|
}
|
||||||
return BitCast
|
return BitCast, raw, lvl
|
||||||
case kind == types.UnsafePointer:
|
case kind == types.UnsafePointer:
|
||||||
return Pointer
|
return Pointer, raw, lvl
|
||||||
}
|
}
|
||||||
case *types.Pointer, *types.Signature, *types.Map, *types.Chan:
|
case *types.Pointer, *types.Signature, *types.Map, *types.Chan:
|
||||||
return Pointer
|
return Pointer, raw, lvl
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
if t.NumFields() == 1 {
|
if t.NumFields() == 1 {
|
||||||
return KindOf(t.Field(0).Type(), is32Bits)
|
return KindOf(t.Field(0).Type(), lvl+1, is32Bits)
|
||||||
}
|
}
|
||||||
case *types.Interface, *types.Slice:
|
case *types.Interface, *types.Slice:
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
if t.Len() == 1 {
|
if t.Len() == 1 {
|
||||||
return KindOf(t.Elem(), is32Bits)
|
return KindOf(t.Elem(), lvl+1, is32Bits)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
panic("unkown type")
|
panic("unkown type")
|
||||||
}
|
}
|
||||||
return Indirect
|
return Indirect, raw, lvl
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -178,23 +178,43 @@ func (b Builder) makeIntfByIntptr(tinter Type, rawIntf *types.Interface, typ Typ
|
|||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) valFromData(t Type, data Expr) Expr {
|
func (b Builder) valFromData(typ Type, data llvm.Value) Expr {
|
||||||
kind := abi.KindOf(t.raw.Type, b.Prog.is32Bits)
|
prog := b.Prog
|
||||||
|
kind, real, lvl := abi.KindOf(typ.raw.Type, 0, prog.is32Bits)
|
||||||
switch kind {
|
switch kind {
|
||||||
case abi.Indirect:
|
case abi.Indirect:
|
||||||
impl := b.impl
|
impl := b.impl
|
||||||
tll := t.ll
|
tll := typ.ll
|
||||||
tptr := llvm.PointerType(tll, 0)
|
tptr := llvm.PointerType(tll, 0)
|
||||||
ptr := llvm.CreatePointerCast(impl, data.impl, tptr)
|
ptr := llvm.CreatePointerCast(impl, data, tptr)
|
||||||
return Expr{llvm.CreateLoad(impl, tll, ptr), t}
|
return Expr{llvm.CreateLoad(impl, tll, ptr), typ}
|
||||||
case abi.Pointer:
|
case abi.Pointer:
|
||||||
return Expr{data.impl, t}
|
return Expr{data, typ}
|
||||||
|
}
|
||||||
|
t := typ
|
||||||
|
if lvl > 0 {
|
||||||
|
t = prog.rawType(real)
|
||||||
|
}
|
||||||
|
switch kind {
|
||||||
case abi.Integer:
|
case abi.Integer:
|
||||||
x := castUintptr(b, data.impl, b.Prog.Uintptr())
|
x := castUintptr(b, data, prog.Uintptr())
|
||||||
return Expr{castInt(b, x, t), t}
|
return b.buildVal(typ, castInt(b, x, t), lvl)
|
||||||
case abi.BitCast:
|
case abi.BitCast:
|
||||||
x := castUintptr(b, data.impl, b.Prog.Uintptr())
|
x := castUintptr(b, data, prog.Uintptr())
|
||||||
return Expr{llvm.CreateBitCast(b.impl, x, t.ll), t}
|
return b.buildVal(typ, llvm.CreateBitCast(b.impl, x, t.ll), lvl)
|
||||||
|
}
|
||||||
|
panic("todo")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Builder) buildVal(typ Type, val llvm.Value, lvl int) Expr {
|
||||||
|
if lvl == 0 {
|
||||||
|
return Expr{val, typ}
|
||||||
|
}
|
||||||
|
switch t := typ.raw.Type.Underlying().(type) {
|
||||||
|
case *types.Struct:
|
||||||
|
telem := b.Prog.rawType(t.Field(0).Type())
|
||||||
|
elem := b.buildVal(telem, val, lvl-1)
|
||||||
|
return Expr{aggregateValue(b.impl, typ.ll, elem.impl), typ}
|
||||||
}
|
}
|
||||||
panic("todo")
|
panic("todo")
|
||||||
}
|
}
|
||||||
@@ -248,7 +268,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
|
|||||||
if commaOk {
|
if commaOk {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
t := prog.Tuple(assertedTyp, prog.Bool())
|
t := prog.Tuple(assertedTyp, prog.Bool())
|
||||||
val := b.valFromData(assertedTyp, b.InterfaceData(x))
|
val := b.valFromData(assertedTyp, b.faceData(x.impl))
|
||||||
zero := prog.Zero(assertedTyp)
|
zero := prog.Zero(assertedTyp)
|
||||||
valTrue := aggregateValue(b.impl, t.ll, val.impl, prog.BoolVal(true).impl)
|
valTrue := aggregateValue(b.impl, t.ll, val.impl, prog.BoolVal(true).impl)
|
||||||
valFalse := aggregateValue(b.impl, t.ll, zero.impl, prog.BoolVal(false).impl)
|
valFalse := aggregateValue(b.impl, t.ll, zero.impl, prog.BoolVal(false).impl)
|
||||||
@@ -259,7 +279,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
|
|||||||
b.SetBlock(blks[1])
|
b.SetBlock(blks[1])
|
||||||
b.Panic(b.Str("type assertion failed"))
|
b.Panic(b.Str("type assertion failed"))
|
||||||
b.SetBlock(blks[0])
|
b.SetBlock(blks[0])
|
||||||
return b.valFromData(assertedTyp, b.InterfaceData(x))
|
return b.valFromData(assertedTyp, b.faceData(x.impl))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -337,8 +357,11 @@ func (b Builder) InterfaceData(x Expr) Expr {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("InterfaceData %v\n", x.impl)
|
log.Printf("InterfaceData %v\n", x.impl)
|
||||||
}
|
}
|
||||||
ptr := llvm.CreateExtractValue(b.impl, x.impl, 1)
|
return Expr{b.faceData(x.impl), b.Prog.VoidPtr()}
|
||||||
return Expr{ptr, b.Prog.VoidPtr()}
|
}
|
||||||
|
|
||||||
|
func (b Builder) faceData(x llvm.Value) llvm.Value {
|
||||||
|
return llvm.CreateExtractValue(b.impl, x, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) faceAbiType(x Expr) Expr {
|
func (b Builder) faceAbiType(x Expr) Expr {
|
||||||
|
|||||||
Reference in New Issue
Block a user