Merge pull request #352 from xushiwei/q

cl: fn.SetRecover; patch library: call init
This commit is contained in:
xushiwei
2024-06-18 18:35:33 +08:00
committed by GitHub
6 changed files with 69 additions and 15 deletions

View File

@@ -0,0 +1,8 @@
package main
import "errors"
func main() {
err := errors.New("error")
panic(err)
}

View File

@@ -100,12 +100,23 @@ type context struct {
inits []func() inits []func()
phis []func() phis []func()
state pkgState
inCFunc bool inCFunc bool
skipall bool skipall bool
} }
type pkgState byte
const (
pkgNormal pkgState = iota
pkgHasPatch
pkgInPatch
pkgFNoOldInit = 0x80 // flag if no initFnNameOld
)
func (p *context) inMain(instr ssa.Instruction) bool { func (p *context) inMain(instr ssa.Instruction) bool {
return instr.Parent().Name() == "main" return p.fn.Name() == "main"
} }
func (p *context) compileType(pkg llssa.Package, t *ssa.Type) { func (p *context) compileType(pkg llssa.Package, t *ssa.Type) {
@@ -184,6 +195,8 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
return fn, nil, goFunc return fn, nil, goFunc
} }
var isInit bool
var state = p.state
var sig = f.Signature var sig = f.Signature
var hasCtx = len(f.FreeVars) > 0 var hasCtx = len(f.FreeVars) > 0
if hasCtx { if hasCtx {
@@ -196,6 +209,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
if debugInstr { if debugInstr {
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype) log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype)
} }
isInit = (f.Name() == "init" && sig.Recv() == nil)
} }
if fn == nil { if fn == nil {
if name == "main" { if name == "main" {
@@ -205,14 +219,20 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
ret := types.NewParam(token.NoPos, pkgTypes, "", p.prog.CInt().RawType()) ret := types.NewParam(token.NoPos, pkgTypes, "", p.prog.CInt().RawType())
results := types.NewTuple(ret) results := types.NewTuple(ret)
sig = types.NewSignatureType(nil, nil, nil, params, results, false) sig = types.NewSignatureType(nil, nil, nil, params, results, false)
} else if isInit && state == pkgHasPatch {
name = initFnNameOfHasPatch(name)
} }
fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx) fn = pkg.NewFuncEx(name, sig, llssa.Background(ftype), hasCtx)
} }
if nblk := len(f.Blocks); nblk > 0 { if nblk := len(f.Blocks); nblk > 0 {
fn.MakeBlocks(nblk) // to set fn.HasBody() = true fn.MakeBlocks(nblk) // to set fn.HasBody() = true
if f.Recover != nil { // set recover block
fn.SetRecover(fn.Block(f.Recover.Index))
}
p.inits = append(p.inits, func() { p.inits = append(p.inits, func() {
p.fn = fn p.fn = fn
p.state = state // restore pkgState when compiling funcBody
defer func() { defer func() {
p.fn = nil p.fn = nil
}() }()
@@ -234,7 +254,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun
for { for {
block := f.Blocks[i] block := f.Blocks[i]
doMainInit := (i == 0 && name == "main") doMainInit := (i == 0 && name == "main")
doModInit := (i == 1 && f.Name() == "init" && sig.Recv() == nil) doModInit := (i == 1 && isInit)
p.compileBlock(b, block, off[i], doMainInit, doModInit) p.compileBlock(b, block, off[i], doMainInit, doModInit)
if i = p.blkInfos[i].Next; i < 0 { if i = p.blkInfos[i].Next; i < 0 {
break break
@@ -257,8 +277,9 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
var pyModInit bool var pyModInit bool
var prog = p.prog var prog = p.prog
var pkg = p.pkg var pkg = p.pkg
var fn = p.fn
var instrs = block.Instrs[n:] var instrs = block.Instrs[n:]
var ret = p.fn.Block(block.Index) var ret = fn.Block(block.Index)
b.SetBlock(ret) b.SetBlock(ret)
if doModInit { if doModInit {
if pyModInit = p.pyMod != ""; pyModInit { if pyModInit = p.pyMod != ""; pyModInit {
@@ -271,7 +292,6 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
}) })
} }
} else if doMainInit { } else if doMainInit {
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.InitNil() argc.InitNil()
@@ -281,7 +301,12 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
callRuntimeInit(b, pkg) callRuntimeInit(b, pkg)
b.Call(pkg.FuncOf("main.init").Expr) b.Call(pkg.FuncOf("main.init").Expr)
} }
for _, instr := range instrs { for i, instr := range instrs {
if i == 1 && doModInit && p.state == pkgInPatch {
initFnNameOld := initFnNameOfHasPatch(p.fn.Name())
fnOld := pkg.NewFunc(initFnNameOld, llssa.NoArgsNoRet, llssa.InC)
b.Call(fnOld.Expr)
}
p.compileInstr(b, instr) p.compileInstr(b, instr)
} }
if pyModInit { if pyModInit {
@@ -292,7 +317,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do
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.Nil(mod.Type)) cond := b.BinOp(token.NEQ, mod, prog.Nil(mod.Type))
newBlk := p.fn.MakeBlock() newBlk := fn.MakeBlock()
b.If(cond, jumpTo, newBlk) b.If(cond, jumpTo, newBlk)
b.SetBlockEx(newBlk, llssa.AtEnd, false) b.SetBlockEx(newBlk, llssa.AtEnd, false)
b.Store(modPtr, b.PyImportMod(modPath)) b.Store(modPtr, b.PyImportMod(modPath))
@@ -377,9 +402,6 @@ 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 {
fn := p.fn fn := p.fn
ret := fn.Block(block.Index) 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]) {
@@ -752,7 +774,12 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
if hasPatch { if hasPatch {
skips := ctx.skips skips := ctx.skips
ctx.skips = nil ctx.skips = nil
ctx.state = pkgInPatch
if _, ok := skips["init"]; ok || ctx.skipall {
ctx.state |= pkgFNoOldInit
}
processPkg(ctx, ret, alt) processPkg(ctx, ret, alt)
ctx.state = pkgHasPatch
ctx.skips = skips ctx.skips = skips
} }
if !ctx.skipall { if !ctx.skipall {
@@ -768,6 +795,10 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [
return return
} }
func initFnNameOfHasPatch(name string) string {
return name + "$hasPatch"
}
func processPkg(ctx *context, ret llssa.Package, pkg *ssa.Package) { func processPkg(ctx *context, ret llssa.Package, pkg *ssa.Package) {
type namedMember struct { type namedMember struct {
name string name string

View File

@@ -507,8 +507,7 @@ func ignoreName(name string) bool {
strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") || strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") ||
strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") || strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") ||
strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") || strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") ||
strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "errors.") || strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "runtime/")
strings.HasPrefix(name, "runtime/")
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -706,7 +706,7 @@ func decodeFile(outFile string, zipf *zip.File) (err error) {
func canSkipToBuild(pkgPath string) bool { func canSkipToBuild(pkgPath string) bool {
switch pkgPath { switch pkgPath {
case "unsafe", "errors": // TODO(xsw): remove it case "unsafe":
return true return true
default: default:
return strings.HasPrefix(pkgPath, "internal/") || return strings.HasPrefix(pkgPath, "internal/") ||
@@ -717,6 +717,7 @@ func canSkipToBuild(pkgPath string) bool {
type none struct{} type none struct{}
var hasAltPkg = map[string]none{ var hasAltPkg = map[string]none{
"errors": {},
"math": {}, "math": {},
"sync": {}, "sync": {},
"sync/atomic": {}, "sync/atomic": {},

View File

@@ -0,0 +1,17 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package errors

View File

@@ -234,12 +234,10 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
return return
} }
/*
// Name returns the function's name. // Name returns the function's name.
func (p Function) Name() string { func (p Function) Name() string {
return p.impl.Name() return p.impl.Name()
} }
*/
// Params returns the function's ith parameter. // Params returns the function's ith parameter.
func (p Function) Param(i int) Expr { func (p Function) Param(i int) Expr {