closureStub

This commit is contained in:
xushiwei
2024-05-05 18:48:09 +08:00
parent 87ca3a39dc
commit 4f1b6e95a1
4 changed files with 50 additions and 18 deletions

View File

@@ -22,11 +22,12 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0
br i1 %8, label %_llgo_2, label %_llgo_3 br i1 %8, label %_llgo_2, label %_llgo_3
_llgo_2: ; preds = %_llgo_1 _llgo_2: ; preds = %_llgo_1
%9 = extractvalue { ptr, ptr } %1, 0 %9 = extractvalue { ptr, ptr } %1, 1
%10 = call i32 %9() %10 = extractvalue { ptr, ptr } %1, 0
%11 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4) %11 = call i32 %10(ptr %9)
%12 = getelementptr inbounds i32, ptr %11, i64 %7 %12 = call ptr @"github.com/goplus/llgo/internal/runtime.SliceData"(%"github.com/goplus/llgo/internal/runtime.Slice" %4)
store i32 %10, ptr %12, align 4 %13 = getelementptr inbounds i32, ptr %12, i64 %7
store i32 %11, ptr %13, align 4
br label %_llgo_1 br label %_llgo_1
_llgo_3: ; preds = %_llgo_1 _llgo_3: ; preds = %_llgo_1
@@ -54,7 +55,7 @@ _llgo_0:
store i32 1, ptr %0, align 4 store i32 1, ptr %0, align 4
%1 = alloca { ptr, ptr }, align 8 %1 = alloca { ptr, ptr }, align 8
%2 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 0 %2 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 0
store ptr @rand, ptr %2, align 8 store ptr @__llgo_stub.rand, ptr %2, align 8
%3 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 1 %3 = getelementptr inbounds { ptr, ptr }, ptr %1, i32 0, i32 1
store ptr null, ptr %3, align 8 store ptr null, ptr %3, align 8
%4 = load { ptr, ptr }, ptr %1, align 8 %4 = load { ptr, ptr }, ptr %1, align 8
@@ -118,6 +119,12 @@ declare void @"github.com/goplus/llgo/internal/runtime.init"()
declare i32 @rand() declare i32 @rand()
define i32 @__llgo_stub.rand(ptr %0) {
_llgo_0:
%1 = call i32 @rand()
ret i32 %1
}
declare i32 @printf(ptr, ...) declare i32 @printf(ptr, ...)
define i32 @"main.main$1"({ ptr } %0) { define i32 @"main.main$1"({ ptr } %0) {

View File

@@ -27,6 +27,7 @@ import (
const ( const (
ClosureCtx = "__llgo_ctx" ClosureCtx = "__llgo_ctx"
ClosureStub = "__llgo_stub."
NameValist = "__llgo_va_list" NameValist = "__llgo_va_list"
) )

View File

@@ -358,10 +358,7 @@ func (b Builder) UnOp(op token.Token, x Expr) Expr {
func checkExpr(v Expr, t types.Type, b Builder) Expr { func checkExpr(v Expr, t types.Type, b Builder) Expr {
if t, ok := t.(*types.Struct); ok && isClosure(t) { if t, ok := t.(*types.Struct); ok && isClosure(t) {
if v.kind != vkClosure { if v.kind != vkClosure {
log.Panicln("checkExpr:", v.impl.Name()) return b.Func.Pkg.closureStub(b, t, v)
prog := b.Prog
nilVal := prog.Null(prog.VoidPtr()).impl
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
} }
} }
return v return v

View File

@@ -17,6 +17,7 @@
package ssa package ssa
import ( import (
"go/token"
"go/types" "go/types"
"log" "log"
@@ -223,10 +224,11 @@ func (p Program) NewPackage(name, pkgPath string) Package {
mod := p.ctx.NewModule(pkgPath) mod := p.ctx.NewModule(pkgPath)
// TODO(xsw): Finalize may cause panic, so comment it. // TODO(xsw): Finalize may cause panic, so comment it.
// mod.Finalize() // mod.Finalize()
fns := make(map[string]Function)
gbls := make(map[string]Global) gbls := make(map[string]Global)
fns := make(map[string]Function)
stubs := make(map[string]Function)
p.needRuntime = false p.needRuntime = false
return &aPackage{mod, fns, gbls, p} return &aPackage{mod, gbls, fns, stubs, p}
} }
// Void returns void type. // Void returns void type.
@@ -310,8 +312,9 @@ func (p Program) Float64() Type {
// and unspecified other things too. // and unspecified other things too.
type aPackage struct { type aPackage struct {
mod llvm.Module mod llvm.Module
fns map[string]Function
vars map[string]Global vars map[string]Global
fns map[string]Function
stubs map[string]Function
Prog Program Prog Program
} }
@@ -365,6 +368,30 @@ func (p Package) rtFunc(fnName string) Expr {
return p.NewFunc(name, sig, InGo).Expr return p.NewFunc(name, sig, InGo).Expr
} }
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
name := v.impl.Name()
prog := b.Prog
nilVal := prog.Null(prog.VoidPtr()).impl
if fn, ok := p.stubs[name]; ok {
v = fn.Expr
} else {
sig := v.raw.Type.(*types.Signature)
n := sig.Params().Len()
ctx := types.NewParam(token.NoPos, nil, ClosureCtx, types.Typ[types.UnsafePointer])
sig = FuncAddCtx(ctx, sig)
fn := p.NewFunc(ClosureStub+name, sig, InC)
args := make([]Expr, n)
for i := 0; i < n; i++ {
args[i] = fn.Param(i + 1)
}
b := fn.MakeBody(1)
b.Return(b.Call(v, args...))
p.stubs[name] = fn
v = fn.Expr
}
return b.aggregateValue(prog.rawType(t), v.impl, nilVal)
}
// FuncOf returns a function by name. // FuncOf returns a function by name.
func (p Package) FuncOf(name string) Function { func (p Package) FuncOf(name string) Function {
return p.fns[name] return p.fns[name]