This commit is contained in:
xushiwei
2024-06-13 13:51:36 +08:00
parent 64e96cc101
commit 4abcbb9b51
9 changed files with 75 additions and 21 deletions

8
c/c.go
View File

@@ -103,6 +103,11 @@ func Qsort(base Pointer, count, elem uintptr, compar func(a, b Pointer) Int)
// -----------------------------------------------------------------------------
//go:linkname Atoi C.atoi
func Atoi(s *Char) Int
// -----------------------------------------------------------------------------
//go:linkname Printf C.printf
func Printf(format *Char, __llgo_va_list ...any) Int
@@ -171,6 +176,3 @@ func GetoptLong(argc Int, argv **Char, optstring *Char, longopts *Option, longin
func GetoptLongOnly(argc Int, argv **Char, optstring *Char, longopts *Option, longindex *Int) Int
// -----------------------------------------------------------------------------
//go:linkname Atoi C.atoi
func Atoi(s *Char) Int

View File

@@ -20,4 +20,5 @@ func main() {
return
}
fail()
println("unreachable")
}

29
cl/_testgo/defer4/in.go Normal file
View File

@@ -0,0 +1,29 @@
package main
func f(s string) bool {
return len(s) > 2
}
func fail() {
defer println("bye")
defer func() {
if e := recover(); e != nil {
println("recover:", e.(string))
}
}()
panic("panic message")
}
func main() {
defer func() {
println("hi")
}()
if s := "hello"; f(s) {
defer println(s)
} else {
defer println("world")
return
}
fail()
println("reachable")
}

1
cl/_testgo/defer4/out.ll Normal file
View File

@@ -0,0 +1 @@
;

View File

@@ -555,7 +555,11 @@ func isPhi(i ssa.Instruction) bool {
}
func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int {
ret := p.fn.Block(block.Index)
fn := p.fn
ret := fn.Block(block.Index)
if block.Comment == "recover" { // set recover block
fn.SetRecover(ret)
}
b.SetBlockEx(ret, llssa.AtEnd, false)
if ninstr := len(block.Instrs); ninstr > 0 {
if isPhi(block.Instrs[0]) {

View File

@@ -34,10 +34,21 @@ type Defer struct {
Rund unsafe.Pointer // block address after RunDefers
}
// Recover recovers a panic.
func Recover() (ret any) {
ptr := excepKey.Get()
if ptr != nil {
excepKey.Set(nil)
ret = *(*any)(ptr)
c.Free(ptr)
}
return
}
// Panic panics with a value.
func Panic(v Eface) {
func Panic(v any) {
ptr := c.Malloc(unsafe.Sizeof(v))
*(*Eface)(ptr) = v
*(*any)(ptr) = v
excepKey.Set(ptr)
Rethrow((*Defer)(c.GoDeferData()))
@@ -45,13 +56,14 @@ func Panic(v Eface) {
// Rethrow rethrows a panic.
func Rethrow(link *Defer) {
if link == nil {
ptr := excepKey.Get()
TracePanic(*(*Eface)(ptr))
c.Free(ptr)
c.Exit(2)
} else {
c.Siglongjmp(link.Addr, 1)
if ptr := excepKey.Get(); ptr != nil {
if link == nil {
TracePanic(*(*Eface)(ptr))
c.Free(ptr)
c.Exit(2)
} else {
c.Siglongjmp(link.Addr, 1)
}
}
}

View File

@@ -179,6 +179,7 @@ type aFunction struct {
blks []BasicBlock
defer_ *aDefer
recov BasicBlock
params []Type
freeVars Expr
@@ -329,4 +330,9 @@ func (p Function) Block(idx int) BasicBlock {
return p.blks[idx]
}
// SetRecover sets the recover block for the function.
func (p Function) SetRecover(blk BasicBlock) {
p.recov = blk
}
// -----------------------------------------------------------------------------

View File

@@ -22,6 +22,7 @@ import "C"
import (
"go/token"
"go/types"
"log"
"unsafe"
"github.com/goplus/llvm"
@@ -174,7 +175,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
b.Call(b.Pkg.rtFunc("Rethrow"), link)
b.Unreachable() // TODO: func supports noreturn attribute
b.Jump(self.recov)
if kind == DeferAlways {
b.SetBlockEx(next, AtEnd, false)
@@ -266,16 +267,14 @@ func (b Builder) Unreachable() {
b.impl.CreateUnreachable()
}
/*
// Recover emits a recover instruction.
func (b Builder) Recover() (v Expr) {
func (b Builder) Recover() Expr {
if debugInstr {
log.Println("Recover")
}
prog := b.Prog
return prog.Zero(prog.Any())
// TODO(xsw): recover can't be a function call in Go
return b.Call(b.Pkg.rtFunc("Recover"))
}
*/
// Panic emits a panic instruction.
func (b Builder) Panic(v Expr) {

View File

@@ -898,8 +898,8 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) {
}
}
}
//case "recover":
// return b.Recover()
case "recover":
return b.Recover()
case "print", "println":
return b.PrintEx(fn == "println", args...)
}