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 _llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1 store i1 true, ptr @"main.init$guard", align 1
%1 = load i32, ptr @__llgo_defer, align 4 call void @"main.init$after"()
%2 = icmp eq i32 %1, ptr null
br i1 %2, label %_llgo_3, label %_llgo_4
br label %_llgo_2 br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0 _llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void 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) { define i32 @main(i32 %0, ptr %1) {
@@ -74,16 +65,16 @@ _llgo_0:
store ptr %1, ptr @__llgo_argv, align 8 store ptr %1, ptr @__llgo_argv, align 8
call void @"github.com/goplus/llgo/internal/runtime.init"() call void @"github.com/goplus/llgo/internal/runtime.init"()
call void @main.init() call void @main.init()
%2 = load i32, ptr @__llgo_defer, align 4 %2 = load ptr, ptr @__llgo_defer, align 8
%3 = call ptr @pthread_getspecific(i32 %2) %3 = call ptr @pthread_getspecific(ptr %2)
%4 = alloca i8, i64 32, align 1 %4 = alloca i8, i64 32, align 1
%5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 0 %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 %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
store i64 0, ptr %6, align 4 store i64 0, ptr %6, align 4
%7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2 %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 2
store ptr %3, ptr %7, align 8 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 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%10 = load i64, ptr %9, align 4 %10 = load i64, ptr %9, align 4
%11 = or i64 %10, 1 %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 %19 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %17, i32 0, i32 1
store i64 5, ptr %19, align 4 store i64 5, ptr %19, align 4
%20 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %17, align 8 %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 %22 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%23 = load i64, ptr %22, align 4 %23 = load i64, ptr %22, align 4
%24 = or i64 %23, 2 %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 %27 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %25, i32 0, i32 1
store i64 3, ptr %27, align 4 store i64 3, ptr %27, align 4
%28 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %25, align 8 %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 %30 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%31 = load i64, ptr %30, align 4 %31 = load i64, ptr %30, align 4
%32 = or i64 %31, 4 %32 = or i64 %31, 4
store i64 %32, ptr %30, align 4 store i64 %32, ptr %30, align 4
%33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1 %33 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%34 = load i64, ptr %33, align 4 %34 = load i64, ptr %33, align 4
call void @main._llgo_defer(i64 %34) call void @"main$_llgo_defer"(i64 %34)
ret i32 0 ret i32 0
_llgo_4: ; preds = %_llgo_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 %37 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %35, i32 0, i32 1
store i64 5, ptr %37, align 4 store i64 5, ptr %37, align 4
%38 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %35, align 8 %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 %40 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.Defer", ptr %4, i32 0, i32 1
%41 = load i64, ptr %40, align 4 %41 = load i64, ptr %40, align 4
%42 = or i64 %41, 8 %42 = or i64 %41, 8
@@ -147,7 +138,7 @@ _llgo_4: ; preds = %_llgo_0
br label %_llgo_3 br label %_llgo_3
} }
define void @"main.init$abi"() { define void @"main.init$after"() {
_llgo_0: _llgo_0:
%0 = load ptr, ptr @_llgo_string, align 8 %0 = load ptr, ptr @_llgo_string, align 8
%1 = icmp eq ptr %0, null %1 = icmp eq ptr %0, null
@@ -159,6 +150,15 @@ _llgo_1: ; preds = %_llgo_0
br label %_llgo_2 br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0 _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 ret void
} }
@@ -183,7 +183,7 @@ _llgo_0:
ret void ret void
} }
define void @main._llgo_defer(i64 %0) { define void @"main$_llgo_defer"(i64 %0) {
_llgo_0: _llgo_0:
%1 = and i64 %0, 1 %1 = and i64 %0, 1
%2 = icmp ne i64 %1, 0 %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 { for _, phi := range p.phis {
phi() phi()
} }
b.EndBuild()
}) })
} }
return fn, nil, goFunc return fn, nil, goFunc

View File

@@ -19,7 +19,6 @@ package ssa
import ( import (
"go/token" "go/token"
"go/types" "go/types"
"unsafe"
"github.com/goplus/llgo/ssa/abi" "github.com/goplus/llgo/ssa/abi"
"github.com/goplus/llvm" "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) { func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
b := p.abiBuilder() b := p.afterBuilder()
tabi := b.abiTypeOf(t) tabi := b.abiTypeOf(t)
expr := g.Expr expr := g.Expr
var eq Expr var eq Expr

View File

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

View File

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

View File

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