runtime: rethrow/panic; llgo/ssa: DeferData; Null => Nil
This commit is contained in:
@@ -201,7 +201,7 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
|
|||||||
}
|
}
|
||||||
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
g := pkg.NewVar(name, typ, llssa.Background(vtype))
|
||||||
if vtype == goVar {
|
if vtype == goVar {
|
||||||
g.Init(p.prog.Null(g.Type))
|
g.Init(p.prog.Nil(g.Type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,6 +338,8 @@ func (p *context) funcOf(fn *ssa.Function) (aFn llssa.Function, pyFn llssa.PyObj
|
|||||||
ftype = llgoSigsetjmp
|
ftype = llgoSigsetjmp
|
||||||
case "siglongjmp":
|
case "siglongjmp":
|
||||||
ftype = llgoSiglongjmp
|
ftype = llgoSiglongjmp
|
||||||
|
case "deferData":
|
||||||
|
ftype = llgoDeferData
|
||||||
case "unreachable":
|
case "unreachable":
|
||||||
ftype = llgoUnreachable
|
ftype = llgoUnreachable
|
||||||
default:
|
default:
|
||||||
@@ -378,8 +380,8 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
fn := p.fn
|
fn := p.fn
|
||||||
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC)
|
||||||
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC)
|
||||||
argc.Init(prog.Null(argc.Type))
|
argc.Init(prog.Nil(argc.Type))
|
||||||
argv.Init(prog.Null(argv.Type))
|
argv.Init(prog.Nil(argv.Type))
|
||||||
b.Store(argc.Expr, fn.Param(0))
|
b.Store(argc.Expr, fn.Param(0))
|
||||||
b.Store(argv.Expr, fn.Param(1))
|
b.Store(argv.Expr, fn.Param(1))
|
||||||
callRuntimeInit(b, pkg)
|
callRuntimeInit(b, pkg)
|
||||||
@@ -395,7 +397,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
|
|||||||
modName := pysymPrefix + modPath
|
modName := pysymPrefix + modPath
|
||||||
modPtr := pkg.PyNewModVar(modName, true).Expr
|
modPtr := pkg.PyNewModVar(modName, true).Expr
|
||||||
mod := b.Load(modPtr)
|
mod := b.Load(modPtr)
|
||||||
cond := b.BinOp(token.NEQ, mod, prog.Null(mod.Type))
|
cond := b.BinOp(token.NEQ, mod, prog.Nil(mod.Type))
|
||||||
newBlk := p.fn.MakeBlock()
|
newBlk := p.fn.MakeBlock()
|
||||||
b.If(cond, jumpTo, newBlk)
|
b.If(cond, jumpTo, newBlk)
|
||||||
b.SetBlockEx(newBlk, llssa.AtEnd, false)
|
b.SetBlockEx(newBlk, llssa.AtEnd, false)
|
||||||
@@ -431,8 +433,11 @@ func intVal(v ssa.Value) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
func (p *context) isVArgs(vx ssa.Value) (ret []llssa.Expr, ok bool) {
|
||||||
if va, vok := vx.(*ssa.Alloc); vok {
|
switch vx := vx.(type) {
|
||||||
ret, ok = p.vargs[va] // varargs: this is a varargs index
|
case *ssa.Alloc:
|
||||||
|
ret, ok = p.vargs[vx] // varargs: this is a varargs index
|
||||||
|
case *ssa.Const:
|
||||||
|
ok = vx.Value == nil
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -642,6 +647,8 @@ func (p *context) call(b llssa.Builder, act llssa.DoAction, call *ssa.CallCommon
|
|||||||
p.siglongjmp(b, args)
|
p.siglongjmp(b, args)
|
||||||
case llgoSigjmpbuf: // func sigjmpbuf()
|
case llgoSigjmpbuf: // func sigjmpbuf()
|
||||||
ret = b.AllocaSigjmpBuf()
|
ret = b.AllocaSigjmpBuf()
|
||||||
|
case llgoDeferData: // func deferData() *Defer
|
||||||
|
ret = b.DeferData()
|
||||||
case llgoUnreachable: // func unreachable()
|
case llgoUnreachable: // func unreachable()
|
||||||
b.Unreachable()
|
b.Unreachable()
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ const (
|
|||||||
llgoSigjmpbuf = llgoInstrBase + 10
|
llgoSigjmpbuf = llgoInstrBase + 10
|
||||||
llgoSigsetjmp = llgoInstrBase + 11
|
llgoSigsetjmp = llgoInstrBase + 11
|
||||||
llgoSiglongjmp = llgoInstrBase + 12
|
llgoSiglongjmp = llgoInstrBase + 12
|
||||||
|
llgoDeferData = llgoInstrBase + 13
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
func (p *context) funcName(fn *ssa.Function, ignore bool) (*types.Package, string, int) {
|
||||||
|
|||||||
@@ -42,15 +42,30 @@ func Alloca(size uintptr) Pointer
|
|||||||
//go:linkname AllocaCStr llgo.allocaCStr
|
//go:linkname AllocaCStr llgo.allocaCStr
|
||||||
func AllocaCStr(s string) *Char
|
func AllocaCStr(s string) *Char
|
||||||
|
|
||||||
|
//go:linkname GoDeferData llgo.deferData
|
||||||
|
func GoDeferData() Pointer
|
||||||
|
|
||||||
//go:linkname Unreachable llgo.unreachable
|
//go:linkname Unreachable llgo.unreachable
|
||||||
func Unreachable()
|
func Unreachable()
|
||||||
|
|
||||||
|
//go:linkname AllocaSigjmpBuf llgo.sigjmpbuf
|
||||||
|
func AllocaSigjmpBuf() Pointer
|
||||||
|
|
||||||
|
//go:linkname Sigsetjmp llgo.sigsetjmp
|
||||||
|
func Sigsetjmp(jb Pointer, savemask Int) Int
|
||||||
|
|
||||||
|
//go:linkname Siglongjmp llgo.siglongjmp
|
||||||
|
func Siglongjmp(jb Pointer, retval Int)
|
||||||
|
|
||||||
//go:linkname Rand C.rand
|
//go:linkname Rand C.rand
|
||||||
func Rand() Int
|
func Rand() Int
|
||||||
|
|
||||||
//go:linkname Malloc C.malloc
|
//go:linkname Malloc C.malloc
|
||||||
func Malloc(size uintptr) Pointer
|
func Malloc(size uintptr) Pointer
|
||||||
|
|
||||||
|
//go:linkname Free C.free
|
||||||
|
func Free(ptr Pointer)
|
||||||
|
|
||||||
//go:linkname Memcpy C.memcpy
|
//go:linkname Memcpy C.memcpy
|
||||||
func Memcpy(dst, src Pointer, n uintptr) Pointer
|
func Memcpy(dst, src Pointer, n uintptr) Pointer
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package runtime
|
|||||||
import (
|
import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/goplus/llgo/c/pthread"
|
||||||
"github.com/goplus/llgo/internal/abi"
|
"github.com/goplus/llgo/internal/abi"
|
||||||
"github.com/goplus/llgo/internal/runtime/c"
|
"github.com/goplus/llgo/internal/runtime/c"
|
||||||
)
|
)
|
||||||
@@ -27,19 +28,43 @@ import (
|
|||||||
|
|
||||||
// Defer presents defer statements in a function.
|
// Defer presents defer statements in a function.
|
||||||
type Defer struct {
|
type Defer struct {
|
||||||
Addr unsafe.Pointer
|
Addr unsafe.Pointer // sigjmpbuf
|
||||||
Bits uintptr
|
Bits uintptr
|
||||||
Link *Defer
|
Link *Defer
|
||||||
Rund int // index of RunDefers
|
Rund int // index of RunDefers
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// Panic panics with a value.
|
||||||
|
func Panic(v Eface) {
|
||||||
|
ptr := c.Malloc(unsafe.Sizeof(v))
|
||||||
|
*(*Eface)(ptr) = v
|
||||||
|
excepKey.Set(ptr)
|
||||||
|
|
||||||
// Zeroinit initializes memory to zero.
|
Rethrow((*Defer)(c.GoDeferData()))
|
||||||
func Zeroinit(p unsafe.Pointer, size uintptr) unsafe.Pointer {
|
|
||||||
return c.Memset(p, 0, size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rethrow rethrows a panic.
|
||||||
|
func Rethrow(link *Defer) {
|
||||||
|
if link == nil {
|
||||||
|
ptr := excepKey.Get()
|
||||||
|
TracePanic(*(*Eface)(ptr))
|
||||||
|
c.Free(ptr)
|
||||||
|
c.Unreachable()
|
||||||
|
} else {
|
||||||
|
c.Siglongjmp(link.Addr, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
excepKey pthread.Key
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
excepKey.Create(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// TracePanic prints panic message.
|
// TracePanic prints panic message.
|
||||||
func TracePanic(v Eface) {
|
func TracePanic(v Eface) {
|
||||||
kind := v._type.Kind()
|
kind := v._type.Kind()
|
||||||
@@ -56,3 +81,10 @@ func stringTracef(fp c.FilePtr, format *c.Char, s String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Zeroinit initializes memory to zero.
|
||||||
|
func Zeroinit(p unsafe.Pointer, size uintptr) unsafe.Pointer {
|
||||||
|
return c.Memset(p, 0, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
|
|||||||
var eq Expr
|
var eq Expr
|
||||||
var blks []BasicBlock
|
var blks []BasicBlock
|
||||||
if pub {
|
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)
|
blks = b.Func.MakeBlocks(2)
|
||||||
b.If(eq, blks[0], blks[1])
|
b.If(eq, blks[0], blks[1])
|
||||||
b.SetBlockEx(blks[0], AtEnd, false)
|
b.SetBlockEx(blks[0], AtEnd, false)
|
||||||
@@ -343,7 +343,7 @@ func (b Builder) abiType(t types.Type) Expr {
|
|||||||
if g == nil {
|
if g == nil {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
g = pkg.doNewVar(name, prog.AbiTypePtrPtr())
|
g = pkg.doNewVar(name, prog.AbiTypePtrPtr())
|
||||||
g.Init(prog.Null(g.Type))
|
g.Init(prog.Nil(g.Type))
|
||||||
if pub {
|
if pub {
|
||||||
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
}
|
}
|
||||||
|
|||||||
75
ssa/eh.go
75
ssa/eh.go
@@ -22,7 +22,6 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goplus/llvm"
|
"github.com/goplus/llvm"
|
||||||
@@ -77,6 +76,7 @@ func (b Builder) Siglongjmp(jb, retval Expr) {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
deferKey = "__llgo_defer"
|
deferKey = "__llgo_defer"
|
||||||
|
excepKey = "__llgo_ex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p Function) deferInitBuilder() (b Builder, next BasicBlock) {
|
func (p Function) deferInitBuilder() (b Builder, next BasicBlock) {
|
||||||
@@ -96,29 +96,33 @@ type aDefer struct {
|
|||||||
stmts []func(bits Expr)
|
stmts []func(bits Expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) deferInit() {
|
func (p Package) keyInit(name string) {
|
||||||
keyVar := p.VarOf(deferKey)
|
keyVar := p.VarOf(name)
|
||||||
if keyVar == nil {
|
if keyVar == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
prog := p.Prog
|
prog := p.Prog
|
||||||
keyNil := prog.Null(prog.DeferPtrPtr())
|
keyNil := prog.Nil(prog.CIntPtr())
|
||||||
keyVar.Init(keyNil)
|
keyVar.Init(keyNil)
|
||||||
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
keyVar.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
|
|
||||||
b := p.afterBuilder()
|
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.IfThen(eq, func() {
|
||||||
b.pthreadKeyCreate(keyVar.Expr, prog.Null(prog.VoidPtr()))
|
b.pthreadKeyCreate(keyVar.Expr, prog.Nil(prog.VoidPtr()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Package) newDeferKey() Global {
|
func (p Package) newKey(name string) Global {
|
||||||
return p.NewVarEx(deferKey, p.Prog.DeferPtrPtr())
|
return p.NewVarEx(name, p.Prog.CIntPtr())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Builder) deferKey() Expr {
|
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 {
|
func (b Builder) getDefer(kind DoAction) *aDefer {
|
||||||
@@ -148,7 +152,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
|
|||||||
deferData := Expr{ptr, prog.DeferPtr()}
|
deferData := Expr{ptr, prog.DeferPtr()}
|
||||||
b.pthreadSetspecific(key, deferData)
|
b.pthreadSetspecific(key, deferData)
|
||||||
blks := self.MakeBlocks(2)
|
blks := self.MakeBlocks(2)
|
||||||
procBlk, throwBlk := blks[0], blks[1]
|
procBlk, rethrowBlk := blks[0], blks[1]
|
||||||
bitsPtr := b.FieldAddr(deferData, deferBits)
|
bitsPtr := b.FieldAddr(deferData, deferBits)
|
||||||
rundPtr := b.FieldAddr(deferData, deferRund)
|
rundPtr := b.FieldAddr(deferData, deferRund)
|
||||||
self.defer_ = &aDefer{
|
self.defer_ = &aDefer{
|
||||||
@@ -157,7 +161,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
|
|||||||
bitsPtr: bitsPtr,
|
bitsPtr: bitsPtr,
|
||||||
rundPtr: rundPtr,
|
rundPtr: rundPtr,
|
||||||
procBlk: procBlk,
|
procBlk: procBlk,
|
||||||
runsNext: []BasicBlock{throwBlk},
|
runsNext: []BasicBlock{rethrowBlk},
|
||||||
}
|
}
|
||||||
czero := prog.IntVal(0, prog.CInt())
|
czero := prog.IntVal(0, prog.CInt())
|
||||||
retval := b.Sigsetjmp(jb, czero)
|
retval := b.Sigsetjmp(jb, czero)
|
||||||
@@ -168,12 +172,14 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
|
|||||||
next, rundBlk = blks[0], blks[1]
|
next, rundBlk = blks[0], blks[1]
|
||||||
}
|
}
|
||||||
b.If(b.BinOp(token.EQL, retval, czero), next, rundBlk)
|
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.Store(rundPtr, prog.Val(0))
|
||||||
b.Jump(procBlk)
|
b.Jump(procBlk)
|
||||||
b.SetBlockEx(throwBlk, AtEnd, false) // throw
|
|
||||||
linkJBPtr := b.FieldAddr(link, deferSigjmpbuf)
|
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
|
||||||
b.Siglongjmp(b.Load(linkJBPtr), prog.IntVal(1, prog.CInt()))
|
b.Call(b.Pkg.rtFunc("Rethrow"), b.Load(link))
|
||||||
|
b.Unreachable() // TODO: func supports noreturn attribute
|
||||||
|
|
||||||
if kind == DeferAlways {
|
if kind == DeferAlways {
|
||||||
b.SetBlockEx(next, AtEnd, false)
|
b.SetBlockEx(next, AtEnd, false)
|
||||||
b.blk.last = next.last
|
b.blk.last = next.last
|
||||||
@@ -182,6 +188,12 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
|
|||||||
return self.defer_
|
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.
|
// Defer emits a defer instruction.
|
||||||
func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) {
|
func (b Builder) Defer(kind DoAction, fn Expr, args ...Expr) {
|
||||||
if debugInstr {
|
if debugInstr {
|
||||||
@@ -249,13 +261,16 @@ func (p Function) endDefer(b Builder) {
|
|||||||
|
|
||||||
link := b.getField(b.Load(self.data), 2)
|
link := b.getField(b.Load(self.data), 2)
|
||||||
b.pthreadSetspecific(self.key, link)
|
b.pthreadSetspecific(self.key, link)
|
||||||
|
|
||||||
// rund := b.Load(self.rundPtr)
|
|
||||||
b.IndirectJump(self.rundPtr, nexts)
|
b.IndirectJump(self.rundPtr, nexts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Unreachable emits an unreachable instruction.
|
||||||
|
func (b Builder) Unreachable() {
|
||||||
|
b.impl.CreateUnreachable()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Recover emits a recover instruction.
|
// Recover emits a recover instruction.
|
||||||
func (b Builder) Recover() (v Expr) {
|
func (b Builder) Recover() (v Expr) {
|
||||||
@@ -263,22 +278,34 @@ func (b Builder) Recover() (v Expr) {
|
|||||||
log.Println("Recover")
|
log.Println("Recover")
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
return prog.Zero(prog.Eface())
|
return prog.Zero(prog.Any())
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Panic emits a panic instruction.
|
// Panic emits a panic instruction.
|
||||||
func (b Builder) Panic(v Expr) {
|
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 {
|
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.Call(b.Pkg.rtFunc("TracePanic"), v)
|
||||||
b.impl.CreateUnreachable()
|
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 {
|
func (p Program) Zero(t Type) Expr {
|
||||||
var ret llvm.Value
|
var ret llvm.Value
|
||||||
switch u := t.raw.Type.Underlying().(type) {
|
switch u := t.raw.Type.Underlying().(type) {
|
||||||
@@ -127,16 +128,11 @@ func (p Program) Zero(t Type) Expr {
|
|||||||
return Expr{ret, t}
|
return Expr{ret, t}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Null returns a null constant expression.
|
// Nil returns a null constant expression. t should be a pointer type.
|
||||||
func (p Program) Null(t Type) Expr {
|
func (p Program) Nil(t Type) Expr {
|
||||||
return Expr{llvm.ConstNull(t.ll), t}
|
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.
|
// BoolVal returns a boolean constant expression.
|
||||||
func (p Program) BoolVal(v bool) Expr {
|
func (p Program) BoolVal(v bool) Expr {
|
||||||
t := p.Bool()
|
t := p.Bool()
|
||||||
@@ -180,7 +176,7 @@ func (p Program) Val(v interface{}) Expr {
|
|||||||
func (b Builder) Const(v constant.Value, typ Type) Expr {
|
func (b Builder) Const(v constant.Value, typ Type) Expr {
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return prog.Null(typ)
|
return prog.Nil(typ)
|
||||||
}
|
}
|
||||||
raw := typ.raw.Type
|
raw := typ.raw.Type
|
||||||
switch t := raw.Underlying().(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}
|
data := Expr{b.aggregateMalloc(t, flds...), voidPtr}
|
||||||
size := prog.SizeOf(voidPtr)
|
size := prog.SizeOf(voidPtr)
|
||||||
pthd := b.Alloca(prog.IntVal(uint64(size), prog.Uintptr()))
|
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 {
|
func (p Package) routineName() string {
|
||||||
@@ -107,7 +107,7 @@ func (p Package) routine(t Type, n int) Expr {
|
|||||||
}
|
}
|
||||||
b.Call(fn, args...)
|
b.Call(fn, args...)
|
||||||
b.free(param)
|
b.free(param)
|
||||||
b.Return(prog.Null(prog.VoidPtr()))
|
b.Return(prog.Nil(prog.VoidPtr()))
|
||||||
return routine.Expr
|
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,
|
// The Alloc instruction reserves space for a variable of the given type,
|
||||||
|
|||||||
@@ -131,14 +131,16 @@ type aProgram struct {
|
|||||||
rtSliceTy llvm.Type
|
rtSliceTy llvm.Type
|
||||||
rtMapTy llvm.Type
|
rtMapTy llvm.Type
|
||||||
|
|
||||||
anyTy Type
|
anyTy Type
|
||||||
voidTy Type
|
//anyPtr Type
|
||||||
voidPtr Type
|
//anyPPtr Type
|
||||||
voidPPtr Type
|
voidTy Type
|
||||||
boolTy Type
|
voidPtr Type
|
||||||
cstrTy Type
|
voidPPtr Type
|
||||||
cintTy Type
|
boolTy Type
|
||||||
//cintPtr Type
|
cstrTy Type
|
||||||
|
cintTy Type
|
||||||
|
cintPtr Type
|
||||||
stringTy Type
|
stringTy Type
|
||||||
uintptrTy Type
|
uintptrTy Type
|
||||||
intTy Type
|
intTy Type
|
||||||
@@ -158,7 +160,6 @@ 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
|
||||||
@@ -328,14 +329,6 @@ func (p Program) DeferPtr() Type {
|
|||||||
return p.deferPtr
|
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.
|
// AbiTypePtr returns *abi.Type type.
|
||||||
func (p Program) AbiTypePtr() Type {
|
func (p Program) AbiTypePtr() Type {
|
||||||
if p.abiTyPtr == nil {
|
if p.abiTyPtr == nil {
|
||||||
@@ -360,6 +353,7 @@ func (p Program) Void() Type {
|
|||||||
return p.voidTy
|
return p.voidTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VoidPtr returns *void type.
|
||||||
func (p Program) VoidPtr() Type {
|
func (p Program) VoidPtr() Type {
|
||||||
if p.voidPtr == nil {
|
if p.voidPtr == nil {
|
||||||
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
|
p.voidPtr = p.rawType(types.Typ[types.UnsafePointer])
|
||||||
@@ -367,6 +361,7 @@ func (p Program) VoidPtr() Type {
|
|||||||
return p.voidPtr
|
return p.voidPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VoidPtrPtr returns **void type.
|
||||||
func (p Program) VoidPtrPtr() Type {
|
func (p Program) VoidPtrPtr() Type {
|
||||||
if p.voidPPtr == nil {
|
if p.voidPPtr == nil {
|
||||||
p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer]))
|
p.voidPPtr = p.rawType(types.NewPointer(types.Typ[types.UnsafePointer]))
|
||||||
@@ -382,6 +377,7 @@ func (p Program) Bool() Type {
|
|||||||
return p.boolTy
|
return p.boolTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CStr returns *int8 type.
|
||||||
func (p Program) CStr() Type {
|
func (p Program) CStr() Type {
|
||||||
if p.cstrTy == nil { // *int8
|
if p.cstrTy == nil { // *int8
|
||||||
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
|
p.cstrTy = p.rawType(types.NewPointer(types.Typ[types.Int8]))
|
||||||
@@ -389,6 +385,7 @@ func (p Program) CStr() Type {
|
|||||||
return p.cstrTy
|
return p.cstrTy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns string type.
|
||||||
func (p Program) String() Type {
|
func (p Program) String() Type {
|
||||||
if p.stringTy == nil {
|
if p.stringTy == nil {
|
||||||
p.stringTy = p.rawType(types.Typ[types.String])
|
p.stringTy = p.rawType(types.Typ[types.String])
|
||||||
@@ -396,6 +393,24 @@ func (p Program) String() Type {
|
|||||||
return p.stringTy
|
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.
|
// Any returns the any (empty interface) type.
|
||||||
func (p Program) Any() Type {
|
func (p Program) Any() Type {
|
||||||
if p.anyTy == nil {
|
if p.anyTy == nil {
|
||||||
@@ -410,6 +425,7 @@ func (p Program) Any() Type {
|
|||||||
func (p Program) Eface() Type {
|
func (p Program) Eface() Type {
|
||||||
return p.Any()
|
return p.Any()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// CIntPtr returns *c.Int type.
|
// CIntPtr returns *c.Int type.
|
||||||
func (p Program) CIntPtr() Type {
|
func (p Program) CIntPtr() Type {
|
||||||
@@ -418,7 +434,6 @@ func (p Program) CIntPtr() Type {
|
|||||||
}
|
}
|
||||||
return p.cintPtr
|
return p.cintPtr
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
// CInt returns c.Int type.
|
// CInt returns c.Int type.
|
||||||
func (p Program) CInt() 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 {
|
func (p Package) closureStub(b Builder, t *types.Struct, v Expr) Expr {
|
||||||
name := v.impl.Name()
|
name := v.impl.Name()
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
nilVal := prog.Null(prog.VoidPtr()).impl
|
nilVal := prog.Nil(prog.VoidPtr()).impl
|
||||||
if fn, ok := p.stubs[name]; ok {
|
if fn, ok := p.stubs[name]; ok {
|
||||||
v = fn.Expr
|
v = fn.Expr
|
||||||
} else {
|
} else {
|
||||||
@@ -605,7 +620,8 @@ func (p Package) afterBuilder() Builder {
|
|||||||
|
|
||||||
// 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) {
|
||||||
p.deferInit()
|
p.keyInit(deferKey)
|
||||||
|
p.keyInit(excepKey)
|
||||||
doAfterb := p.afterb != nil
|
doAfterb := p.afterb != nil
|
||||||
doPyLoadModSyms := p.pyHasModSyms()
|
doPyLoadModSyms := p.pyHasModSyms()
|
||||||
if doAfterb || doPyLoadModSyms {
|
if doAfterb || doPyLoadModSyms {
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ func (p Package) PyNewModVar(name string, doInit bool) Global {
|
|||||||
objPtr := prog.PyObjectPtrPtr().raw.Type
|
objPtr := prog.PyObjectPtrPtr().raw.Type
|
||||||
g := p.NewVar(name, objPtr, InC)
|
g := p.NewVar(name, objPtr, InC)
|
||||||
if doInit {
|
if doInit {
|
||||||
g.Init(prog.Null(g.Type))
|
g.Init(prog.Nil(g.Type))
|
||||||
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
g.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
}
|
}
|
||||||
p.pymods[name] = g
|
p.pymods[name] = g
|
||||||
@@ -246,7 +246,7 @@ func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr {
|
|||||||
args = append(args, o.Expr)
|
args = append(args, o.Expr)
|
||||||
}
|
}
|
||||||
prog := b.Prog
|
prog := b.Prog
|
||||||
args = append(args, prog.Null(prog.CStr()))
|
args = append(args, prog.Nil(prog.CStr()))
|
||||||
return b.Call(fnLoad, args...)
|
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 := make([]Expr, n+2)
|
||||||
callargs[0] = fn
|
callargs[0] = fn
|
||||||
copy(callargs[1:], args)
|
copy(callargs[1:], args)
|
||||||
callargs[n+1] = prog.PyNull()
|
callargs[n+1] = prog.Nil(prog.PyObjectPtr())
|
||||||
ret = b.Call(call, callargs...)
|
ret = b.Call(call, callargs...)
|
||||||
}
|
}
|
||||||
return
|
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)
|
obj := p.NewVar(name, prog.PyObjectPtrPtr().RawType(), InC)
|
||||||
if doInit {
|
if doInit {
|
||||||
prog.NeedPyInit = true
|
prog.NeedPyInit = true
|
||||||
obj.Init(prog.Null(obj.Type))
|
obj.Init(prog.Nil(obj.Type))
|
||||||
obj.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
obj.impl.SetLinkage(llvm.LinkOnceAnyLinkage)
|
||||||
}
|
}
|
||||||
ty := &aType{obj.ll, rawType{types.NewPointer(sig)}, vkPyFuncRef}
|
ty := &aType{obj.ll, rawType{types.NewPointer(sig)}, vkPyFuncRef}
|
||||||
|
|||||||
Reference in New Issue
Block a user