llgo/ssa: RunDefers

This commit is contained in:
xushiwei
2024-06-02 15:24:42 +08:00
parent 5a5929048d
commit ba45217756
7 changed files with 303 additions and 29 deletions

View File

@@ -254,11 +254,6 @@ func (p Function) Name() string {
return p.impl.Name()
}
// DeferFuncName returns the name of the defer procedure.
func (p Function) DeferFuncName() string {
return p.Name() + "._llgo_defer"
}
// Params returns the function's ith parameter.
func (p Function) Param(i int) Expr {
i += p.base // skip if hasFreeVars

View File

@@ -113,6 +113,16 @@ func (p Program) Zero(t Type) Expr {
ret = llvm.ConstStruct(flds, false)
case *types.Slice:
ret = p.Zero(p.rtType("Slice")).impl
/* TODO(xsw):
case *types.Interface:
var name string
if u.Empty() {
name = "Eface"
} else {
name = "Iface"
}
ret = p.Zero(p.rtType(name)).impl
*/
default:
log.Panicln("todo:", u)
}
@@ -818,6 +828,11 @@ func (b Builder) Do(da DoAction, fn Expr, args ...Expr) (ret Expr) {
// Go spec (excluding "make" and "new").
func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
switch fn {
case "String": // unsafe.String
return b.unsafeString(args[0].impl, args[1].impl)
case "Slice": // unsafe.Slice
size := args[1].impl
return b.unsafeSlice(args[0], size, size)
case "len":
if len(args) == 1 {
arg := args[0]
@@ -857,8 +872,6 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
}
}
}
case "print", "println":
return b.PrintEx(fn == "println", args...)
case "copy":
if len(args) == 2 {
dst := args[0]
@@ -874,11 +887,10 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
}
}
}
case "String": // unsafe.String
return b.unsafeString(args[0].impl, args[1].impl)
case "Slice": // unsafe.Slice
size := args[1].impl
return b.unsafeSlice(args[0], size, size)
//case "recover":
// return b.Recover()
case "print", "println":
return b.PrintEx(fn == "println", args...)
}
panic("todo: " + fn)
}

View File

@@ -333,16 +333,6 @@ func (p Program) Struct(typs ...Type) Type {
return p.rawType(types.NewStruct(els, nil))
}
/*
// Eface returns the empty interface type.
func (p Program) Eface() Type {
if p.efaceTy == nil {
p.efaceTy = p.rawType(tyAny)
}
return p.efaceTy
}
*/
// DeferPtr returns *runtime.Defer.
func (p Program) DeferPtr() Type {
if p.deferPtr == nil {
@@ -436,7 +426,7 @@ func (p Program) String() Type {
return p.stringTy
}
// Any returns any type.
// Any returns the any (empty interface) type.
func (p Program) Any() Type {
if p.anyTy == nil {
p.anyTy = p.rawType(tyAny)
@@ -444,6 +434,12 @@ func (p Program) Any() Type {
return p.anyTy
}
// Eface returns the empty interface type.
// It is equivalent to Any.
func (p Program) Eface() Type {
return p.Any()
}
// CIntPtr returns *c.Int type.
func (p Program) CIntPtr() Type {
if p.cintPtr == nil {

View File

@@ -175,6 +175,17 @@ func (p Package) newDeferKey() Global {
return p.NewVarEx(deferKey, p.Prog.CIntPtr())
}
// DeferFuncName returns the name of the defer procedure.
func (p Function) DeferFuncName() string {
return p.Name() + "._llgo_defer"
}
// DeferFunc returns the defer procedure of this function.
func (p Function) DeferFunc() Function {
name := p.DeferFuncName()
return p.Pkg.NewFunc(name, p.Prog.tyDeferFunc(), InC)
}
func (b Builder) deferKey() Expr {
return b.Load(b.Pkg.newDeferKey().Expr)
}
@@ -192,8 +203,7 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
zero := prog.Val(uintptr(0))
key := b.deferKey()
if next == 0 {
name := self.DeferFuncName()
deferfn := pkg.NewFunc(name, b.Prog.tyDeferFunc(), InC)
deferfn := self.DeferFunc()
deferb := deferfn.MakeBody(1)
pkg.deferb = unsafe.Pointer(deferb)
pkg.deferparam = deferfn.Param(0)
@@ -218,8 +228,27 @@ func (b Builder) Defer(fn Expr, args ...Expr) {
})
}
// RunDefers emits instructions to run deferred instructions.
func (b Builder) RunDefers() {
self := b.Func
deferfn := self.DeferFunc()
bitsPtr := b.FieldAddr(self.deferData, 1)
b.Call(deferfn.Expr, b.Load(bitsPtr))
}
// -----------------------------------------------------------------------------
/*
// Recover emits a recover instruction.
func (b Builder) Recover() (v Expr) {
if debugInstr {
log.Println("Recover")
}
prog := b.Prog
return prog.Zero(prog.Eface())
}
*/
// Panic emits a panic instruction.
func (b Builder) Panic(v Expr) {
if debugInstr {