llgo/ssa: EndBuild

This commit is contained in:
xushiwei
2024-06-02 21:54:51 +08:00
parent ba45217756
commit 410f9dd759
6 changed files with 95 additions and 91 deletions

View File

@@ -52,20 +52,11 @@ _llgo_0:
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
%1 = load i32, ptr @__llgo_defer, align 4
%2 = icmp eq i32 %1, ptr null
br i1 %2, label %_llgo_3, label %_llgo_4
call void @"main.init$after"()
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
_llgo_3: ; preds = %_llgo_1
%3 = call i32 @pthread_key_create(ptr @__llgo_defer, ptr null)
br label %_llgo_4
_llgo_4: ; preds = %_llgo_3, %_llgo_1
call void @"main.init$abi"()
}
define i32 @main(i32 %0, ptr %1) {
@@ -74,16 +65,16 @@ _llgo_0:
store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init()
%2 = load i32, ptr @__llgo_defer, align 4
%3 = call ptr @pthread_getspecific(i32 %2)
%2 = load ptr, ptr @__llgo_defer, align 8
%3 = call ptr @pthread_getspecific(ptr %2)
%4 = alloca i8, i64 32, align 1
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0
store ptr @main._llgo_defer, ptr %5, align 8
store ptr @"main$_llgo_defer", ptr %5, align 8
%6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
store i64 0, ptr %6, align 4
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2
store ptr %3, ptr %7, align 8
%8 = call i32 @pthread_setspecific(i32 %2, ptr %4)
%8 = call i32 @pthread_setspecific(ptr %2, ptr %4)
%9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%10 = load i64, ptr %9, align 4
%11 = or i64 %10, 1
@@ -107,7 +98,7 @@ _llgo_2: ; preds = %_llgo_0
%19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 1
store i64 5, ptr %19, align 4
%20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %17, align 8
%21 = load i32, ptr @__llgo_defer, align 4
%21 = load ptr, ptr @__llgo_defer, align 8
%22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%23 = load i64, ptr %22, align 4
%24 = or i64 %23, 2
@@ -121,14 +112,14 @@ _llgo_3: ; preds = %_llgo_4, %_llgo_2
%27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1
store i64 3, ptr %27, align 4
%28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8
%29 = load i32, ptr @__llgo_defer, align 4
%29 = load ptr, ptr @__llgo_defer, align 8
%30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%31 = load i64, ptr %30, align 4
%32 = or i64 %31, 4
store i64 %32, ptr %30, align 4
%33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%34 = load i64, ptr %33, align 4
call void @main._llgo_defer(i64 %34)
call void @"main$_llgo_defer"(i64 %34)
ret i32 0
_llgo_4: ; preds = %_llgo_0
@@ -138,7 +129,7 @@ _llgo_4: ; preds = %_llgo_0
%37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1
store i64 5, ptr %37, align 4
%38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8
%39 = load i32, ptr @__llgo_defer, align 4
%39 = load ptr, ptr @__llgo_defer, align 8
%40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%41 = load i64, ptr %40, align 4
%42 = or i64 %41, 8
@@ -147,7 +138,7 @@ _llgo_4: ; preds = %_llgo_0
br label %_llgo_3
}
define void @"main.init$abi"() {
define void @"main.init$after"() {
_llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null
@@ -159,6 +150,15 @@ _llgo_1: ; preds = %_llgo_0
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
%3 = load ptr, ptr @__llgo_defer, align 8
%4 = icmp eq ptr %3, null
br i1 %4, label %_llgo_3, label %_llgo_4
_llgo_3: ; preds = %_llgo_2
%5 = call i32 @pthread_key_create(ptr @__llgo_defer, ptr null)
br label %_llgo_4
_llgo_4: ; preds = %_llgo_3, %_llgo_2
ret void
}
@@ -183,7 +183,7 @@ _llgo_0:
ret void
}
define void @main._llgo_defer(i64 %0) {
define void @"main$_llgo_defer"(i64 %0) {
_llgo_0:
%1 = and i64 %0, 1
%2 = icmp ne i64 %1, 0

View File

@@ -285,6 +285,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
for _, phi := range p.phis {
phi()
}
b.EndBuild()
})
}
return fn, nil, goFunc

View File

@@ -19,7 +19,6 @@ package ssa
import (
"go/token"
"go/types"
"unsafe"
"github.com/goplus/llgo/ssa/abi"
"github.com/goplus/llvm"
@@ -285,32 +284,8 @@ func lastParamType(prog Program, fn Expr) Type {
// -----------------------------------------------------------------------------
type abiTypes struct {
iniabi unsafe.Pointer
}
func (p Package) hasAbiInit() bool {
return p.iniabi != nil
}
func (p Package) abiInit(b Builder) {
inib := Builder(p.iniabi)
inib.Return()
b.Call(inib.Func.Expr)
}
func (p Package) abiBuilder() Builder {
if p.iniabi == nil {
sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := p.NewFunc(p.Path()+".init$abi", sigAbiInit, InC)
fnb := fn.MakeBody(1)
p.iniabi = unsafe.Pointer(fnb)
}
return Builder(p.iniabi)
}
func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
b := p.abiBuilder()
b := p.afterBuilder()
tabi := b.abiTypeOf(t)
expr := g.Expr
var eq Expr

View File

@@ -22,6 +22,7 @@ import (
"sort"
"strconv"
"strings"
"unsafe"
"github.com/goplus/llvm"
)
@@ -186,6 +187,8 @@ type aFunction struct {
deferNextBit int // next defer bit
deferData Expr
deferParam Expr
deferb unsafe.Pointer
hasVArg bool
}

View File

@@ -20,6 +20,7 @@ import (
"go/token"
"go/types"
"strconv"
"unsafe"
"github.com/goplus/llgo/ssa/abi"
"github.com/goplus/llvm"
@@ -157,6 +158,7 @@ type aProgram struct {
abiTyPPtr Type
deferTy Type
deferPtr Type
deferPPtr Type
pyImpTy *types.Signature
pyNewList *types.Signature
@@ -333,14 +335,6 @@ func (p Program) Struct(typs ...Type) Type {
return p.rawType(types.NewStruct(els, nil))
}
// DeferPtr returns *runtime.Defer.
func (p Program) DeferPtr() Type {
if p.deferPtr == nil {
p.deferPtr = p.Pointer(p.Defer())
}
return p.deferPtr
}
// Defer returns runtime.Defer type.
func (p Program) Defer() Type {
if p.deferTy == nil {
@@ -349,7 +343,23 @@ func (p Program) Defer() Type {
return p.deferTy
}
// AbiTypePtr returns *abi.Type.
// DeferPtr returns *runtime.Defer type.
func (p Program) DeferPtr() Type {
if p.deferPtr == nil {
p.deferPtr = p.Pointer(p.Defer())
}
return p.deferPtr
}
// DeferPtrPtr returns **runtime.Defer type.
func (p Program) DeferPtrPtr() Type {
if p.deferPPtr == nil {
p.deferPPtr = p.Pointer(p.DeferPtr())
}
return p.deferPPtr
}
// AbiTypePtr returns *abi.Type type.
func (p Program) AbiTypePtr() Type {
if p.abiTyPtr == nil {
p.abiTyPtr = p.rawType(types.NewPointer(p.rtNamed("Type")))
@@ -357,7 +367,7 @@ func (p Program) AbiTypePtr() Type {
return p.abiTyPtr
}
// AbiTypePtrPtr returns **abi.Type.
// AbiTypePtrPtr returns **abi.Type type.
func (p Program) AbiTypePtrPtr() Type {
if p.abiTyPPtr == nil {
p.abiTyPPtr = p.Pointer(p.AbiTypePtr())
@@ -549,18 +559,17 @@ func (p Program) Uint64() Type {
type aPackage struct {
mod llvm.Module
abi abi.Builder
abiTypes
Prog Program
vars map[string]Global
fns map[string]Function
stubs map[string]Function
pyobjs map[string]PyObjRef
pymods map[string]Global
Prog Program
afterb unsafe.Pointer
iRoutine int
deferMgr
}
type Package = *aPackage
@@ -626,18 +635,29 @@ func (p Package) String() string {
return p.mod.String()
}
// -----------------------------------------------------------------------------
func (p Package) afterBuilder() Builder {
if p.afterb == nil {
sigAfterInit := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := p.NewFunc(p.Path()+".init$after", sigAfterInit, InC)
fnb := fn.MakeBody(1)
p.afterb = unsafe.Pointer(fnb)
}
return Builder(p.afterb)
}
// AfterInit is called after the package is initialized (init all packages that depends on).
func (p Package) AfterInit(b Builder, ret BasicBlock) {
doDeferInit := p.hasDefer()
doAbiInit := p.hasAbiInit()
doAfterb := p.afterb != nil
doPyLoadModSyms := p.pyHasModSyms()
if doDeferInit || doAbiInit || doPyLoadModSyms {
if doAfterb || doPyLoadModSyms {
b.SetBlockEx(ret, afterInit, false)
if doDeferInit {
p.deferInit(b)
}
if doAbiInit {
p.abiInit(b)
if doAfterb {
afterb := Builder(p.afterb)
p.deferInit(afterb)
afterb.Return()
b.Call(afterb.Func.Expr)
}
if doPyLoadModSyms {
p.pyLoadModSyms(b)
@@ -645,6 +665,8 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) {
}
}
// -----------------------------------------------------------------------------
/*
type CodeGenFileType = llvm.CodeGenFileType

View File

@@ -63,6 +63,11 @@ type aBuilder struct {
// Builder represents a builder for creating instructions in a function.
type Builder = *aBuilder
// EndBuild ends the build process of a function.
func (b Builder) EndBuild() {
b.endDeferFunc()
}
// Dispose disposes of the builder.
func (b Builder) Dispose() {
b.impl.Dispose()
@@ -136,11 +141,6 @@ const (
deferKey = "__llgo_defer"
)
type deferMgr struct {
deferb unsafe.Pointer
deferparam Expr
}
// func(uintptr)
func (p Program) tyDeferFunc() *types.Signature {
if p.deferFnTy == nil {
@@ -151,14 +151,13 @@ func (p Program) tyDeferFunc() *types.Signature {
return p.deferFnTy
}
func (p Package) hasDefer() bool {
return p.deferb != nil
}
func (p Package) deferInit(b Builder) {
keyVar := p.VarOf(deferKey)
if keyVar == nil {
return
}
prog := p.Prog
keyVar := p.newDeferKey()
keyNil := prog.Null(prog.CIntPtr())
keyNil := prog.Null(prog.DeferPtrPtr())
keyVar.Init(keyNil)
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
@@ -166,18 +165,19 @@ func (p Package) deferInit(b Builder) {
b.IfThen(eq, func() {
b.pthreadKeyCreate(keyVar.Expr, prog.Null(prog.VoidPtr()))
})
b = Builder(p.deferb)
b.Return()
}
func (p Package) newDeferKey() Global {
return p.NewVarEx(deferKey, p.Prog.CIntPtr())
return p.NewVarEx(deferKey, p.Prog.DeferPtrPtr())
}
func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newDeferKey().Expr)
}
// DeferFuncName returns the name of the defer procedure.
func (p Function) DeferFuncName() string {
return p.Name() + "._llgo_defer"
return p.Name() + "$_llgo_defer"
}
// DeferFunc returns the defer procedure of this function.
@@ -186,8 +186,12 @@ func (p Function) DeferFunc() Function {
return p.Pkg.NewFunc(name, p.Prog.tyDeferFunc(), InC)
}
func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newDeferKey().Expr)
func (b Builder) endDeferFunc() {
self := b.Func
if self.deferb != nil {
b = Builder(self.deferb)
b.Return()
}
}
// Defer emits a defer instruction.
@@ -196,7 +200,6 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
logCall("Defer", fn, args)
}
prog := b.Prog
pkg := b.Pkg
self := b.Func
next := self.deferNextBit
self.deferNextBit++
@@ -205,8 +208,8 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
if next == 0 {
deferfn := self.DeferFunc()
deferb := deferfn.MakeBody(1)
pkg.deferb = unsafe.Pointer(deferb)
pkg.deferparam = deferfn.Param(0)
self.deferb = unsafe.Pointer(deferb)
self.deferParam = deferfn.Param(0)
// TODO(xsw): move to funtion start
// proc func(uintptr)
@@ -221,8 +224,8 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
nextbit := prog.Val(uintptr(1 << next))
b.Store(bitsPtr, b.BinOp(token.OR, b.Load(bitsPtr), nextbit))
b = Builder(pkg.deferb)
has := b.BinOp(token.NEQ, b.BinOp(token.AND, pkg.deferparam, nextbit), zero)
b = Builder(self.deferb)
has := b.BinOp(token.NEQ, b.BinOp(token.AND, self.deferParam, nextbit), zero)
b.IfThen(has, func() {
b.Call(fn, args...)
})