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 //go:linkname Printf C.printf
func Printf(format *Char, __llgo_va_list ...any) Int 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 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 return
} }
fail() 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 { 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) b.SetBlockEx(ret, llssa.AtEnd, false)
if ninstr := len(block.Instrs); ninstr > 0 { if ninstr := len(block.Instrs); ninstr > 0 {
if isPhi(block.Instrs[0]) { if isPhi(block.Instrs[0]) {

View File

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

View File

@@ -179,6 +179,7 @@ type aFunction struct {
blks []BasicBlock blks []BasicBlock
defer_ *aDefer defer_ *aDefer
recov BasicBlock
params []Type params []Type
freeVars Expr freeVars Expr
@@ -329,4 +330,9 @@ func (p Function) Block(idx int) BasicBlock {
return p.blks[idx] 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 ( import (
"go/token" "go/token"
"go/types" "go/types"
"log"
"unsafe" "unsafe"
"github.com/goplus/llvm" "github.com/goplus/llvm"
@@ -174,7 +175,7 @@ func (b Builder) getDefer(kind DoAction) *aDefer {
b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow b.SetBlockEx(rethrowBlk, AtEnd, false) // rethrow
b.Call(b.Pkg.rtFunc("Rethrow"), link) b.Call(b.Pkg.rtFunc("Rethrow"), link)
b.Unreachable() // TODO: func supports noreturn attribute b.Jump(self.recov)
if kind == DeferAlways { if kind == DeferAlways {
b.SetBlockEx(next, AtEnd, false) b.SetBlockEx(next, AtEnd, false)
@@ -266,16 +267,14 @@ func (b Builder) Unreachable() {
b.impl.CreateUnreachable() b.impl.CreateUnreachable()
} }
/*
// Recover emits a recover instruction. // Recover emits a recover instruction.
func (b Builder) Recover() (v Expr) { func (b Builder) Recover() Expr {
if debugInstr { if debugInstr {
log.Println("Recover") log.Println("Recover")
} }
prog := b.Prog // TODO(xsw): recover can't be a function call in Go
return prog.Zero(prog.Any()) return b.Call(b.Pkg.rtFunc("Recover"))
} }
*/
// Panic emits a panic instruction. // Panic emits a panic instruction.
func (b Builder) Panic(v Expr) { func (b Builder) Panic(v Expr) {

View File

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