vkFuncDecl, vkFuncPtr, vkClosure; callback example
This commit is contained in:
15
cl/_testrt/callback/in.go
Normal file
15
cl/_testrt/callback/in.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
|
)
|
||||||
|
|
||||||
|
func callback(f func()) {
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
callback(func() {
|
||||||
|
c.Printf(c.Str("Hello, callback\n"))
|
||||||
|
})
|
||||||
|
}
|
||||||
49
cl/_testrt/callback/out.ll
Normal file
49
cl/_testrt/callback/out.ll
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
; ModuleID = 'main'
|
||||||
|
source_filename = "main"
|
||||||
|
|
||||||
|
@"main.init$guard" = global ptr null
|
||||||
|
@0 = private unnamed_addr constant [17 x i8] c"Hello, callback\0A\00", align 1
|
||||||
|
|
||||||
|
define void @main.callback({ ptr, ptr } %0) {
|
||||||
|
_llgo_0:
|
||||||
|
%1 = extractvalue { ptr, ptr } %0, 0
|
||||||
|
call void %1()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
br label %_llgo_2
|
||||||
|
|
||||||
|
_llgo_2: ; preds = %_llgo_1, %_llgo_0
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() {
|
||||||
|
_llgo_0:
|
||||||
|
call void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
call void @main.init()
|
||||||
|
%0 = alloca { ptr, ptr }, align 8
|
||||||
|
%1 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 0
|
||||||
|
store ptr @"main.main$1", ptr %1, align 8
|
||||||
|
%2 = getelementptr inbounds { ptr, ptr }, ptr %0, i32 0, i32 1
|
||||||
|
store ptr null, ptr %2, align 8
|
||||||
|
%3 = load { ptr, ptr }, ptr %0, align 8
|
||||||
|
call void @main.callback({ ptr, ptr } %3)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @"github.com/goplus/llgo/internal/runtime.init"()
|
||||||
|
|
||||||
|
define void @"main.main$1"() {
|
||||||
|
_llgo_0:
|
||||||
|
%0 = call i32 (ptr, ...) @printf(ptr @0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @printf(ptr, ...)
|
||||||
@@ -22,10 +22,10 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
|
|||||||
|
|
||||||
_llgo_2: ; preds = %_llgo_1
|
_llgo_2: ; preds = %_llgo_1
|
||||||
%9 = extractvalue { ptr, ptr } %1, 0
|
%9 = extractvalue { ptr, ptr } %1, 0
|
||||||
%10 = call addrspace(37) { ptr, ptr } %1()
|
%10 = call i32 %9()
|
||||||
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
|
||||||
%12 = getelementptr inbounds i32, ptr %11, i64 %7
|
%12 = getelementptr inbounds i32, ptr %11, i64 %7
|
||||||
store ptr %10, ptr %12, align 8
|
store i32 %10, ptr %12, align 4
|
||||||
br label %_llgo_1
|
br label %_llgo_1
|
||||||
|
|
||||||
_llgo_3: ; preds = %_llgo_1
|
_llgo_3: ; preds = %_llgo_1
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func testCompile(t *testing.T, src, expected string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestrt(t *testing.T) {
|
func TestFromTestrt(t *testing.T) {
|
||||||
cltest.FromDir(t, "", "./_testrt", true)
|
cltest.FromDir(t, "callback", "./_testrt", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFromTestdata(t *testing.T) {
|
func TestFromTestdata(t *testing.T) {
|
||||||
|
|||||||
@@ -35,6 +35,33 @@ func TestRuntime(t *testing.T) {
|
|||||||
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
cltest.Pkg(t, "github.com/goplus/llgo/internal/abi", "../internal/abi/llgo_autogen.ll")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func TestCallback(t *testing.T) {
|
||||||
|
ctx := llvm.NewContext()
|
||||||
|
mod := ctx.NewModule("foo/bar")
|
||||||
|
|
||||||
|
tc := llvm.FunctionType(ctx.VoidType(), nil, false)
|
||||||
|
callback := llvm.PointerType(tc, 0)
|
||||||
|
params := []llvm.Type{callback}
|
||||||
|
|
||||||
|
tfn := llvm.FunctionType(ctx.VoidType(), params, false)
|
||||||
|
f := llvm.AddFunction(mod, "fn", tfn)
|
||||||
|
b := ctx.NewBuilder()
|
||||||
|
blk := llvm.AddBasicBlock(f, "")
|
||||||
|
b.SetInsertPointAtEnd(blk)
|
||||||
|
|
||||||
|
arg := f.Param(0)
|
||||||
|
// arg = b.CreateLoad(tc, arg, "")
|
||||||
|
b.CreateCall(tc, arg, nil, "")
|
||||||
|
b.CreateRetVoid()
|
||||||
|
|
||||||
|
expected := `; ModuleID = 'foo/bar'
|
||||||
|
`
|
||||||
|
if v := mod.String(); v != expected {
|
||||||
|
t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
var m typeutil.Map
|
var m typeutil.Map
|
||||||
|
|||||||
@@ -124,8 +124,9 @@ func (g Global) Init(v Expr) {
|
|||||||
// respectively, and is nil in the generic method.
|
// respectively, and is nil in the generic method.
|
||||||
type aFunction struct {
|
type aFunction struct {
|
||||||
Expr
|
Expr
|
||||||
pkg Package
|
Pkg Package
|
||||||
prog Program
|
Prog Program
|
||||||
|
|
||||||
blks []BasicBlock
|
blks []BasicBlock
|
||||||
|
|
||||||
params []Type
|
params []Type
|
||||||
@@ -162,7 +163,7 @@ func (p Function) Param(i int) Expr {
|
|||||||
|
|
||||||
// NewBuilder creates a new Builder for the function.
|
// NewBuilder creates a new Builder for the function.
|
||||||
func (p Function) NewBuilder() Builder {
|
func (p Function) NewBuilder() Builder {
|
||||||
prog := p.prog
|
prog := p.Prog
|
||||||
b := prog.ctx.NewBuilder()
|
b := prog.ctx.NewBuilder()
|
||||||
// TODO(xsw): Finalize may cause panic, so comment it.
|
// TODO(xsw): Finalize may cause panic, so comment it.
|
||||||
// b.Finalize()
|
// b.Finalize()
|
||||||
|
|||||||
41
ssa/expr.go
41
ssa/expr.go
@@ -183,7 +183,7 @@ func (b Builder) CStr(v string) Expr {
|
|||||||
func (b Builder) Str(v string) (ret Expr) {
|
func (b Builder) Str(v string) (ret Expr) {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
cstr := b.CStr(v)
|
cstr := b.CStr(v)
|
||||||
ret = b.InlineCall(b.fn.pkg.rtFunc("NewString"), cstr, prog.Val(len(v)))
|
ret = b.InlineCall(b.Func.Pkg.rtFunc("NewString"), cstr, prog.Val(len(v)))
|
||||||
ret.Type = prog.String()
|
ret.Type = prog.String()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -296,7 +296,7 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr {
|
|||||||
switch kind {
|
switch kind {
|
||||||
case vkString:
|
case vkString:
|
||||||
if op == token.ADD {
|
if op == token.ADD {
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
return b.InlineCall(pkg.rtFunc("StringCat"), x, y)
|
return b.InlineCall(pkg.rtFunc("StringCat"), x, y)
|
||||||
}
|
}
|
||||||
case vkComplex:
|
case vkComplex:
|
||||||
@@ -566,7 +566,7 @@ func (b Builder) IndexAddr(x, idx Expr) Expr {
|
|||||||
pt := prog.Pointer(telem)
|
pt := prog.Pointer(telem)
|
||||||
switch x.raw.Type.Underlying().(type) {
|
switch x.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
ptr := b.InlineCall(pkg.rtFunc("SliceData"), x)
|
||||||
indices := []llvm.Value{idx.impl}
|
indices := []llvm.Value{idx.impl}
|
||||||
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}
|
||||||
@@ -596,7 +596,7 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr {
|
|||||||
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
panic(fmt.Errorf("invalid operation: cannot index %v", t))
|
||||||
}
|
}
|
||||||
telem = prog.rawType(types.Typ[types.Byte])
|
telem = prog.rawType(types.Typ[types.Byte])
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
ptr = b.InlineCall(pkg.rtFunc("StringData"), x)
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
telem = prog.Index(x.Type)
|
telem = prog.Index(x.Type)
|
||||||
@@ -631,7 +631,7 @@ func (b Builder) Slice(x, low, high, max Expr) (ret Expr) {
|
|||||||
log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl)
|
log.Printf("Slice %v, %v, %v\n", x.impl, low.impl, high.impl)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
var nCap Expr
|
var nCap Expr
|
||||||
var nEltSize Expr
|
var nEltSize Expr
|
||||||
var base Expr
|
var base Expr
|
||||||
@@ -693,7 +693,7 @@ func (b Builder) MakeMap(t Type, nReserve Expr) (ret Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl)
|
log.Printf("MakeMap %v, %v\n", t.RawType(), nReserve.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
ret.Type = t
|
ret.Type = t
|
||||||
ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl
|
ret.impl = b.InlineCall(pkg.rtFunc("MakeSmallMap")).impl
|
||||||
// TODO(xsw): nReserve
|
// TODO(xsw): nReserve
|
||||||
@@ -718,7 +718,7 @@ func (b Builder) MakeSlice(t Type, len, cap Expr) (ret Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl)
|
log.Printf("MakeSlice %v, %v, %v\n", t.RawType(), len.impl, cap.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
if cap.IsNil() {
|
if cap.IsNil() {
|
||||||
cap = len
|
cap = len
|
||||||
}
|
}
|
||||||
@@ -756,7 +756,7 @@ func (b Builder) Alloc(elem Type, heap bool) (ret Expr) {
|
|||||||
log.Printf("Alloc %v, %v\n", elem.RawType(), heap)
|
log.Printf("Alloc %v, %v\n", elem.RawType(), heap)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
size := b.SizeOf(elem)
|
size := b.SizeOf(elem)
|
||||||
if heap {
|
if heap {
|
||||||
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
ret = b.InlineCall(pkg.rtFunc("AllocZ"), size)
|
||||||
@@ -797,7 +797,7 @@ func (b Builder) AllocaCStr(gostr Expr) (ret Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("AllocaCStr %v\n", gostr.impl)
|
log.Printf("AllocaCStr %v\n", gostr.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
n := b.InlineCall(pkg.rtFunc("StringLen"), gostr)
|
n := b.InlineCall(pkg.rtFunc("StringLen"), gostr)
|
||||||
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
n1 := b.BinOp(token.ADD, n, b.Prog.Val(1))
|
||||||
cstr := b.Alloca(n1)
|
cstr := b.Alloca(n1)
|
||||||
@@ -931,7 +931,7 @@ func (b Builder) MakeInterface(tinter Type, x Expr, mayDelay bool) (ret Expr) {
|
|||||||
isAny := tiund.Empty()
|
isAny := tiund.Empty()
|
||||||
fnDo := func() Expr {
|
fnDo := func() Expr {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
switch tx := x.raw.Type.Underlying().(type) {
|
switch tx := x.raw.Type.Underlying().(type) {
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
kind := tx.Kind()
|
kind := tx.Kind()
|
||||||
@@ -998,7 +998,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) (ret Expr) {
|
|||||||
}
|
}
|
||||||
switch assertedTyp.kind {
|
switch assertedTyp.kind {
|
||||||
case vkSigned, vkUnsigned, vkFloat:
|
case vkSigned, vkUnsigned, vkFloat:
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
fnName := "I2Int"
|
fnName := "I2Int"
|
||||||
if commaOk {
|
if commaOk {
|
||||||
fnName = "CheckI2Int"
|
fnName = "CheckI2Int"
|
||||||
@@ -1051,20 +1051,25 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) {
|
|||||||
}
|
}
|
||||||
log.Println(b.String())
|
log.Println(b.String())
|
||||||
}
|
}
|
||||||
|
var ll llvm.Type
|
||||||
var sig *types.Signature
|
var sig *types.Signature
|
||||||
var raw = fn.raw.Type
|
var raw = fn.raw.Type
|
||||||
switch fn.kind {
|
switch fn.kind {
|
||||||
case vkClosure:
|
case vkClosure:
|
||||||
fn := b.Field(fn, 0)
|
fn = b.Field(fn, 0)
|
||||||
raw = fn.raw.Type
|
raw = fn.raw.Type
|
||||||
fallthrough
|
fallthrough
|
||||||
case vkFunc:
|
case vkFuncPtr:
|
||||||
sig = raw.(*types.Signature)
|
sig = raw.(*types.Signature)
|
||||||
ret.Type = prog.retType(sig)
|
ll = prog.FuncDecl(sig, InC).ll
|
||||||
|
case vkFuncDecl:
|
||||||
|
sig = raw.(*types.Signature)
|
||||||
|
ll = fn.ll
|
||||||
default:
|
default:
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
ret.impl = llvm.CreateCall(b.impl, fn.ll, fn.impl, llvmValues(args, sig.Params(), b))
|
ret.Type = prog.retType(sig)
|
||||||
|
ret.impl = llvm.CreateCall(b.impl, ll, fn.impl, llvmValues(args, sig.Params(), b))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,10 +1086,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch t := arg.raw.Type.Underlying().(type) {
|
switch t := arg.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceLen"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("SliceLen"), arg)
|
||||||
case *types.Basic:
|
case *types.Basic:
|
||||||
if t.Kind() == types.String {
|
if t.Kind() == types.String {
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("StringLen"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("StringLen"), arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1093,7 +1098,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
|
|||||||
arg := args[0]
|
arg := args[0]
|
||||||
switch arg.raw.Type.Underlying().(type) {
|
switch arg.raw.Type.Underlying().(type) {
|
||||||
case *types.Slice:
|
case *types.Slice:
|
||||||
return b.InlineCall(b.fn.pkg.rtFunc("SliceCap"), arg)
|
return b.InlineCall(b.Func.Pkg.rtFunc("SliceCap"), arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ type aPackage struct {
|
|||||||
mod llvm.Module
|
mod llvm.Module
|
||||||
fns map[string]Function
|
fns map[string]Function
|
||||||
vars map[string]Global
|
vars map[string]Global
|
||||||
prog Program
|
Prog Program
|
||||||
}
|
}
|
||||||
|
|
||||||
type Package = *aPackage
|
type Package = *aPackage
|
||||||
@@ -326,7 +326,7 @@ func (p Package) NewConst(name string, val constant.Value) NamedConst {
|
|||||||
|
|
||||||
// NewVar creates a new global variable.
|
// NewVar creates a new global variable.
|
||||||
func (p Package) NewVar(name string, typ types.Type, bg Background) Global {
|
func (p Package) NewVar(name string, typ types.Type, bg Background) Global {
|
||||||
t := p.prog.Type(typ, bg)
|
t := p.Prog.Type(typ, bg)
|
||||||
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
gbl := llvm.AddGlobal(p.mod, t.ll, name)
|
||||||
ret := &aGlobal{Expr{gbl, t}}
|
ret := &aGlobal{Expr{gbl, t}}
|
||||||
p.vars[name] = ret
|
p.vars[name] = ret
|
||||||
@@ -343,18 +343,18 @@ func (p Package) NewFunc(name string, sig *types.Signature, bg Background) Funct
|
|||||||
if v, ok := p.fns[name]; ok {
|
if v, ok := p.fns[name]; ok {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
t := p.prog.FuncDecl(sig, bg)
|
t := p.Prog.FuncDecl(sig, bg)
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Println("NewFunc", name, t.raw.Type)
|
log.Println("NewFunc", name, t.raw.Type)
|
||||||
}
|
}
|
||||||
fn := llvm.AddFunction(p.mod, name, t.ll)
|
fn := llvm.AddFunction(p.mod, name, t.ll)
|
||||||
ret := newFunction(fn, t, p, p.prog)
|
ret := newFunction(fn, t, p, p.Prog)
|
||||||
p.fns[name] = ret
|
p.fns[name] = ret
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) rtFunc(fnName string) Expr {
|
func (p Package) rtFunc(fnName string) Expr {
|
||||||
fn := p.prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
fn := p.Prog.runtime().Scope().Lookup(fnName).(*types.Func)
|
||||||
name := FullName(fn.Pkg(), fnName)
|
name := FullName(fn.Pkg(), fnName)
|
||||||
sig := fn.Type().(*types.Signature)
|
sig := fn.Type().(*types.Signature)
|
||||||
return p.NewFunc(name, sig, InGo).Expr
|
return p.NewFunc(name, sig, InGo).Expr
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (p BasicBlock) Index() int {
|
|||||||
|
|
||||||
type aBuilder struct {
|
type aBuilder struct {
|
||||||
impl llvm.Builder
|
impl llvm.Builder
|
||||||
fn Function
|
Func Function
|
||||||
Prog Program
|
Prog Program
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ type Builder = *aBuilder
|
|||||||
|
|
||||||
// SetBlock sets the current block to the specified basic block.
|
// SetBlock sets the current block to the specified basic block.
|
||||||
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
func (b Builder) SetBlock(blk BasicBlock) Builder {
|
||||||
if b.fn != blk.fn {
|
if b.Func != blk.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -74,7 +74,7 @@ func (b Builder) Panic(v Expr) {
|
|||||||
if debugInstr {
|
if debugInstr {
|
||||||
log.Printf("Panic %v\n", v.impl)
|
log.Printf("Panic %v\n", v.impl)
|
||||||
}
|
}
|
||||||
pkg := b.fn.pkg
|
pkg := b.Func.Pkg
|
||||||
b.Call(pkg.rtFunc("TracePanic"), v)
|
b.Call(pkg.rtFunc("TracePanic"), v)
|
||||||
b.impl.CreateUnreachable()
|
b.impl.CreateUnreachable()
|
||||||
}
|
}
|
||||||
@@ -103,14 +103,14 @@ func (b Builder) Return(results ...Expr) {
|
|||||||
case 1:
|
case 1:
|
||||||
b.impl.CreateRet(results[0].impl)
|
b.impl.CreateRet(results[0].impl)
|
||||||
default:
|
default:
|
||||||
tret := b.fn.raw.Type.(*types.Signature).Results()
|
tret := b.Func.raw.Type.(*types.Signature).Results()
|
||||||
b.impl.CreateAggregateRet(llvmValues(results, tret, b))
|
b.impl.CreateAggregateRet(llvmValues(results, tret, b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump emits a jump instruction.
|
// Jump emits a jump instruction.
|
||||||
func (b Builder) Jump(jmpb BasicBlock) {
|
func (b Builder) Jump(jmpb BasicBlock) {
|
||||||
if b.fn != jmpb.fn {
|
if b.Func != jmpb.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -121,7 +121,7 @@ func (b Builder) Jump(jmpb BasicBlock) {
|
|||||||
|
|
||||||
// If emits an if instruction.
|
// If emits an if instruction.
|
||||||
func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
|
func (b Builder) If(cond Expr, thenb, elseb BasicBlock) {
|
||||||
if b.fn != thenb.fn || b.fn != elseb.fn {
|
if b.Func != thenb.fn || b.Func != elseb.fn {
|
||||||
panic("mismatched function")
|
panic("mismatched function")
|
||||||
}
|
}
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ const (
|
|||||||
vkString
|
vkString
|
||||||
vkBool
|
vkBool
|
||||||
vkPtr
|
vkPtr
|
||||||
vkFunc
|
vkFuncDecl
|
||||||
|
vkFuncPtr
|
||||||
vkClosure
|
vkClosure
|
||||||
vkTuple
|
vkTuple
|
||||||
vkDelayExpr = -1
|
vkDelayExpr = -1
|
||||||
@@ -241,7 +242,7 @@ func (p Program) toType(raw types.Type) Type {
|
|||||||
case *types.Named:
|
case *types.Named:
|
||||||
return p.toNamed(t)
|
return p.toNamed(t)
|
||||||
case *types.Signature: // represents a C function pointer in raw type
|
case *types.Signature: // represents a C function pointer in raw type
|
||||||
return &aType{p.toLLVMFuncPtr(t), typ, vkFunc}
|
return &aType{p.toLLVMFuncPtr(t), typ, vkFuncPtr}
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
elem := p.rawType(t.Elem())
|
elem := p.rawType(t.Elem())
|
||||||
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
return &aType{llvm.ArrayType(elem.ll, int(t.Len())), typ, vkInvalid}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (p Program) FuncDecl(sig *types.Signature, bg Background) Type {
|
|||||||
if bg == InGo {
|
if bg == InGo {
|
||||||
sig = p.gocvt.cvtFunc(sig, true)
|
sig = p.gocvt.cvtFunc(sig, true)
|
||||||
}
|
}
|
||||||
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFunc}
|
return &aType{p.toLLVMFunc(sig), rawType{sig}, vkFuncDecl}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) {
|
func (p goTypes) cvtType(typ types.Type) (raw types.Type, cvt bool) {
|
||||||
|
|||||||
Reference in New Issue
Block a user