runtime: rethrow/panic; llgo/ssa: DeferData; Null => Nil

This commit is contained in:
xushiwei
2024-06-12 17:26:07 +08:00
parent 60dd33b48f
commit b787de0163
11 changed files with 176 additions and 71 deletions

View File

@@ -303,7 +303,7 @@ func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
var eq Expr
var blks []BasicBlock
if pub {
eq = b.BinOp(token.EQL, b.Load(expr), b.Prog.Null(expr.Type))
eq = b.BinOp(token.EQL, b.Load(expr), b.Prog.Nil(expr.Type))
blks = b.Func.MakeBlocks(2)
b.If(eq, blks[0], blks[1])
b.SetBlockEx(blks[0], AtEnd, false)
@@ -343,7 +343,7 @@ func (b Builder) abiType(t types.Type) Expr {
if g == nil {
prog := b.Prog
g = pkg.doNewVar(name, prog.AbiTypePtrPtr())
g.Init(prog.Null(g.Type))
g.Init(prog.Nil(g.Type))
if pub {
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
}

View File

@@ -22,7 +22,6 @@ import "C"
import (
"go/token"
"go/types"
"log"
"unsafe"
"github.com/goplus/llvm"
@@ -77,6 +76,7 @@ func (b Builder) Siglongjmp(jb, retval Expr) {
const (
deferKey = "__llgo_defer"
excepKey = "__llgo_ex"
)
func (p Function) deferInitBuilder() (b Builder, next BasicBlock) {
@@ -96,29 +96,33 @@ type aDefer struct {
stmts []func(bits Expr)
}
func (p Package) deferInit() {
keyVar := p.VarOf(deferKey)
func (p Package) keyInit(name string) {
keyVar := p.VarOf(name)
if keyVar == nil {
return
}
prog := p.Prog
keyNil := prog.Null(prog.DeferPtrPtr())
keyNil := prog.Nil(prog.CIntPtr())
keyVar.Init(keyNil)
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
b := p.afterBuilder()
eq := b.BinOp(token.EQL, b.Load(keyVar.Expr), keyNil)
eq := b.BinOp(token.EQL, b.Load(keyVar.Expr), prog.IntVal(0, prog.CInt()))
b.IfThen(eq, func() {
b.pthreadKeyCreate(keyVar.Expr, prog.Null(prog.VoidPtr()))
b.pthreadKeyCreate(keyVar.Expr, prog.Nil(prog.VoidPtr()))
})
}
func (p Package) newDeferKey() Global {
return p.NewVarEx(deferKey, p.Prog.DeferPtrPtr())
func (p Package) newKey(name string) Global {
return p.NewVarEx(name, p.Prog.CIntPtr())
}
func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newDeferKey().Expr)
return b.Load(b.Pkg.newKey(deferKey).Expr)
}
func (b Builder) excepKey() Expr {
return b.Load(b.Pkg.newKey(excepKey).Expr)
}
func (b Builder) getDefer(kind DoAction) *aDefer {
@@ -148,7 +152,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
deferData := Expr{ptr, prog.DeferPtr()}
b.pthreadSetspecific(key, deferData)
blks := self.MakeBlocks(2)
procBlk, throwBlk := blks[0], blks[1]
procBlk, rethrowBlk := blks[0], blks[1]
bitsPtr := b.FieldAddr(deferData, deferBits)
rundPtr := b.FieldAddr(deferData, deferRund)
self.defer_ = &aDefer{
@@ -157,7 +161,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
bitsPtr: bitsPtr,
rundPtr: rundPtr,
procBlk: procBlk,
runsNext: []BasicBlock{throwBlk},
runsNext: []BasicBlock{rethrowBlk},
}
czero := prog.IntVal(0, prog.CInt())
retval := b.Sigsetjmp(jb, czero)
@@ -168,12 +172,14 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
next, rundBlk = blks[0], blks[1]
}
b.If(b.BinOp(token.EQL, retval, czero), next, rundBlk)
b.SetBlockEx(rundBlk, AtEnd, false) // exec runDefers and throw
b.SetBlockEx(rundBlk, AtEnd, false) // exec runDefers and rethrow
b.Store(rundPtr, prog.Val(0))
b.Jump(procBlk)
b.SetBlockEx(throwBlk, AtEnd, false) // throw
linkJBPtr := b.FieldAddr(link, deferSigjmpbuf)
b.Siglongjmp(b.Load(linkJBPtr), prog.IntVal(1, prog.CInt()))
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
b.Call(b.Pkg.rtFunc("Rethrow"), b.Load(link))
b.Unreachable() // TODO: func supports noreturn attribute
if kind == DeferAlways {
b.SetBlockEx(next, AtEnd, false)
b.blk.last = next.last
@@ -182,6 +188,12 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
return self.defer_
}
// DeferData returns the defer data (*runtime.Defer).
func (b Builder) DeferData() Expr {
key := b.deferKey()
return Expr{b.pthreadGetspecific(key).impl, b.Prog.DeferPtr()}
}
// Defer emits a defer instruction.
func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) {
if debugInstr {
@@ -249,13 +261,16 @@ func (p Function) endDefer(b Builder) {
link := b.getField(b.Load(self.data), 2)
b.pthreadSetspecific(self.key, link)
// rund := b.Load(self.rundPtr)
b.IndirectJump(self.rundPtr, nexts)
}
// -----------------------------------------------------------------------------
// Unreachable emits an unreachable instruction.
func (b Builder) Unreachable() {
b.impl.CreateUnreachable()
}
/*
// Recover emits a recover instruction.
func (b Builder) Recover() (v Expr) {
@@ -263,22 +278,34 @@ func (b Builder) Recover() (v Expr) {
log.Println("Recover")
}
prog := b.Prog
return prog.Zero(prog.Eface())
return prog.Zero(prog.Any())
}
*/
// Panic emits a panic instruction.
func (b Builder) Panic(v Expr) {
b.Call(b.Pkg.rtFunc("Panic"), v)
b.Unreachable() // TODO: func supports noreturn attribute
}
/*
// Panic emits a panic instruction.
func (b Builder) Panic(v Expr) {
vimpl := v.impl
if debugInstr {
log.Printf("Panic %v\n", v.impl)
log.Printf("Panic %v\n", vimpl)
}
if v.kind != vkEface {
panic("Panic only accepts an any expression")
}
ptr := b.dupMalloc(v)
b.pthreadSetspecific(b.excepKey(), ptr)
}
func (b Builder) doPanic(v Expr) {
b.Call(b.Pkg.rtFunc("TracePanic"), v)
b.impl.CreateUnreachable()
}
// Unreachable emits an unreachable instruction.
func (b Builder) Unreachable() {
b.impl.CreateUnreachable()
}
*/
// -----------------------------------------------------------------------------

View File

@@ -83,6 +83,7 @@ func pyVarExpr(mod Expr, name string) Expr {
// -----------------------------------------------------------------------------
// Zero returns a zero constant expression.
func (p Program) Zero(t Type) Expr {
var ret llvm.Value
switch u := t.raw.Type.Underlying().(type) {
@@ -127,16 +128,11 @@ func (p Program) Zero(t Type) Expr {
return Expr{ret, t}
}
// Null returns a null constant expression.
func (p Program) Null(t Type) Expr {
// Nil returns a null constant expression. t should be a pointer type.
func (p Program) Nil(t Type) Expr {
return Expr{llvm.ConstNull(t.ll), t}
}
// PyNull returns a null *PyObject constant expression.
func (p Program) PyNull() Expr {
return p.Null(p.PyObjectPtr())
}
// BoolVal returns a boolean constant expression.
func (p Program) BoolVal(v bool) Expr {
t := p.Bool()
@@ -180,7 +176,7 @@ func (p Program) Val(v interface{}) Expr {
func (b Builder) Const(v constant.Value, typ Type) Expr {
prog := b.Prog
if v == nil {
return prog.Null(typ)
return prog.Nil(typ)
}
raw := typ.raw.Type
switch t := raw.Underlying().(type) {

View File

@@ -86,7 +86,7 @@ func (b Builder) Go(fn Expr, args ...Expr) {
data := Expr{b.aggregateMalloc(t, flds...), voidPtr}
size := prog.SizeOf(voidPtr)
pthd := b.Alloca(prog.IntVal(uint64(size), prog.Uintptr()))
b.pthreadCreate(pthd, prog.Null(voidPtr), pkg.routine(t, len(args)), data)
b.pthreadCreate(pthd, prog.Nil(voidPtr), pkg.routine(t, len(args)), data)
}
func (p Package) routineName() string {
@@ -107,7 +107,7 @@ func (p Package) routine(t Type, n int) Expr {
}
b.Call(fn, args...)
b.free(param)
b.Return(prog.Null(prog.VoidPtr()))
b.Return(prog.Nil(prog.VoidPtr()))
return routine.Expr
}

View File

@@ -107,6 +107,17 @@ func aggregateInit(b llvm.Builder, ptr llvm.Value, tll llvm.Type, flds ...llvm.V
}
}
/*
func (b Builder) dupMalloc(v Expr) Expr {
prog := b.Prog
n := prog.SizeOf(v.Type)
tptr := prog.Pointer(v.Type)
ptr := b.malloc(prog.Val(uintptr(n))).impl
b.Store(Expr{ptr, tptr}, v)
return Expr{ptr, tptr}
}
*/
// -----------------------------------------------------------------------------
// The Alloc instruction reserves space for a variable of the given type,

View File

@@ -131,14 +131,16 @@ type aProgram struct {
rtSliceTy llvm.Type
rtMapTy llvm.Type
anyTy Type
voidTy Type
voidPtr Type
voidPPtr Type
boolTy Type
cstrTy Type
cintTy Type
//cintPtr Type
anyTy Type
//anyPtr Type
//anyPPtr Type
voidTy Type
voidPtr Type
voidPPtr Type
boolTy Type
cstrTy Type
cintTy Type
cintPtr Type
stringTy Type
uintptrTy Type
intTy Type
@@ -158,7 +160,6 @@ type aProgram struct {
abiTyPPtr Type
deferTy Type
deferPtr Type
deferPPtr Type
pyImpTy *types.Signature
pyNewList *types.Signature
@@ -328,14 +329,6 @@ func (p Program) DeferPtr() Type {
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 {
@@ -360,6 +353,7 @@ func (p Program) Void() Type {
return p.voidTy
}
// VoidPtr returns *void type.
func (p Program) VoidPtr() Type {
if p.voidPtr == nil {
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
@@ -367,6 +361,7 @@ func (p Program) VoidPtr() Type {
return p.voidPtr
}
// VoidPtrPtr returns **void type.
func (p Program) VoidPtrPtr() Type {
if p.voidPPtr == nil {
p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer]))
@@ -382,6 +377,7 @@ func (p Program) Bool() Type {
return p.boolTy
}
// CStr returns *int8 type.
func (p Program) CStr() Type {
if p.cstrTy == nil { // *int8
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
@@ -389,6 +385,7 @@ func (p Program) CStr() Type {
return p.cstrTy
}
// String returns string type.
func (p Program) String() Type {
if p.stringTy == nil {
p.stringTy = p.rawType(types.Typ[types.String])
@@ -396,6 +393,24 @@ func (p Program) String() Type {
return p.stringTy
}
/*
// AnyPtrPtr returns **any type.
func (p Program) AnyPtrPtr() Type {
if p.anyPPtr == nil {
p.anyPPtr = p.Pointer(p.AnyPtr())
}
return p.anyPPtr
}
// AnyPtr returns *any type.
func (p Program) AnyPtr() Type {
if p.anyPtr == nil {
p.anyPtr = p.Pointer(p.Any())
}
return p.anyPtr
}
*/
// Any returns the any (empty interface) type.
func (p Program) Any() Type {
if p.anyTy == nil {
@@ -410,6 +425,7 @@ func (p Program) Any() Type {
func (p Program) Eface() Type {
return p.Any()
}
*/
// CIntPtr returns *c.Int type.
func (p Program) CIntPtr() Type {
@@ -418,7 +434,6 @@ func (p Program) CIntPtr() Type {
}
return p.cintPtr
}
*/
// CInt returns c.Int type.
func (p Program) CInt() Type {
@@ -550,7 +565,7 @@ func (p Package) cFunc(fullName string, sig *types.Signature) 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
nilVal := prog.Nil(prog.VoidPtr()).impl
if fn, ok := p.stubs[name]; ok {
v = fn.Expr
} else {
@@ -605,7 +620,8 @@ func (p Package) afterBuilder() Builder {
// AfterInit is called after the package is initialized (init all packages that depends on).
func (p Package) AfterInit(b Builder, ret BasicBlock) {
p.deferInit()
p.keyInit(deferKey)
p.keyInit(excepKey)
doAfterb := p.afterb != nil
doPyLoadModSyms := p.pyHasModSyms()
if doAfterb || doPyLoadModSyms {

View File

@@ -217,7 +217,7 @@ func (p Package) PyNewModVar(name string, doInit bool) Global {
objPtr := prog.PyObjectPtrPtr().raw.Type
g := p.NewVar(name, objPtr, InC)
if doInit {
g.Init(prog.Null(g.Type))
g.Init(prog.Nil(g.Type))
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
}
p.pymods[name] = g
@@ -246,7 +246,7 @@ func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr {
args = append(args, o.Expr)
}
prog := b.Prog
args = append(args, prog.Null(prog.CStr()))
args = append(args, prog.Nil(prog.CStr()))
return b.Call(fnLoad, args...)
}
@@ -273,7 +273,7 @@ func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) {
callargs := make([]Expr, n+2)
callargs[0] = fn
copy(callargs[1:], args)
callargs[n+1] = prog.PyNull()
callargs[n+1] = prog.Nil(prog.PyObjectPtr())
ret = b.Call(call, callargs...)
}
return
@@ -372,7 +372,7 @@ func (p Package) PyNewFunc(name string, sig *types.Signature, doInit bool) PyObj
obj := p.NewVar(name, prog.PyObjectPtrPtr().RawType(), InC)
if doInit {
prog.NeedPyInit = true
obj.Init(prog.Null(obj.Type))
obj.Init(prog.Nil(obj.Type))
obj.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
}
ty := &aType{obj.ll, rawType{types.NewPointer(sig)}, vkPyFuncRef}