runtime: rethrow/panic; llgo/ssa: DeferData; Null => Nil
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
75
ssa/eh.go
75
ssa/eh.go
@@ -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()
|
||||
}
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
12
ssa/expr.go
12
ssa/expr.go
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user