From 7a15cf1157f5c26287f4b4b5acf414c834411525 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 18 Jun 2024 13:50:55 +0800 Subject: [PATCH 1/4] patch: errors (todo) --- cl/_testlibgo/_errors/in.go | 8 ++++++++ cl/import.go | 3 +-- internal/build/build.go | 3 ++- internal/lib/errors/errors.go | 17 +++++++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 cl/_testlibgo/_errors/in.go create mode 100644 internal/lib/errors/errors.go diff --git a/cl/_testlibgo/_errors/in.go b/cl/_testlibgo/_errors/in.go new file mode 100644 index 00000000..e833b256 --- /dev/null +++ b/cl/_testlibgo/_errors/in.go @@ -0,0 +1,8 @@ +package main + +import "errors" + +func main() { + err := errors.New("error") + panic(err) +} diff --git a/cl/import.go b/cl/import.go index cf71b379..63d80bb4 100644 --- a/cl/import.go +++ b/cl/import.go @@ -507,8 +507,7 @@ func ignoreName(name string) bool { strings.HasPrefix(name, "arena.") || strings.HasPrefix(name, "maps.") || strings.HasPrefix(name, "time.") || strings.HasPrefix(name, "syscall.") || strings.HasPrefix(name, "os.") || strings.HasPrefix(name, "plugin.") || - strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "errors.") || - strings.HasPrefix(name, "runtime/") + strings.HasPrefix(name, "reflect.") || strings.HasPrefix(name, "runtime/") } // ----------------------------------------------------------------------------- diff --git a/internal/build/build.go b/internal/build/build.go index b25ef650..e3e1da8e 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -706,7 +706,7 @@ func decodeFile(outFile string, zipf *zip.File) (err error) { func canSkipToBuild(pkgPath string) bool { switch pkgPath { - case "unsafe", "errors": // TODO(xsw): remove it + case "unsafe": return true default: return strings.HasPrefix(pkgPath, "internal/") || @@ -717,6 +717,7 @@ func canSkipToBuild(pkgPath string) bool { type none struct{} var hasAltPkg = map[string]none{ + "errors": {}, "math": {}, "sync": {}, "sync/atomic": {}, diff --git a/internal/lib/errors/errors.go b/internal/lib/errors/errors.go new file mode 100644 index 00000000..465fac10 --- /dev/null +++ b/internal/lib/errors/errors.go @@ -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 From 778a4373ae7c08a7778d701b89ea2f92396ac393 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 18 Jun 2024 17:33:37 +0800 Subject: [PATCH 2/4] cl: fn.SetRecover; inPatch/hasPatch --- cl/compile.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 3136a2a5..4ac5ee69 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -100,8 +100,9 @@ type context struct { inits []func() phis []func() - inCFunc bool - skipall bool + inCFunc bool + skipall bool + hasPatch bool } func (p *context) inMain(instr ssa.Instruction) bool { @@ -184,6 +185,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun return fn, nil, goFunc } + var isInit bool var sig = f.Signature var hasCtx = len(f.FreeVars) > 0 if hasCtx { @@ -196,6 +198,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun if debugInstr { log.Println("==> NewFunc", name, "type:", sig.Recv(), sig, "ftype:", ftype) } + isInit = (f.Name() == "init" && sig.Recv() == nil) } if fn == nil { if name == "main" { @@ -210,7 +213,10 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun } 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.fn = fn defer func() { @@ -234,7 +240,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun for { block := f.Blocks[i] 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) if i = p.blkInfos[i].Next; i < 0 { break @@ -377,9 +383,6 @@ func isPhi(i ssa.Instruction) bool { func (p *context) compilePhis(b llssa.Builder, block *ssa.BasicBlock) int { 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]) { @@ -756,6 +759,7 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ ctx.skips = skips } if !ctx.skipall { + ctx.hasPatch = hasPatch processPkg(ctx, ret, pkg) } for len(ctx.inits) > 0 { @@ -768,6 +772,12 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ return } +/* TODO(xsw): +func inPatch(ctx *context) bool { + return ctx.skips == nil +} +*/ + func processPkg(ctx *context, ret llssa.Package, pkg *ssa.Package) { type namedMember struct { name string From 8c876c302af8d7cec3dde947dff89628f1b527b9 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 18 Jun 2024 18:23:16 +0800 Subject: [PATCH 3/4] patch library: call init --- cl/compile.go | 42 +++++++++++++++++++++++++++++------------- ssa/decl.go | 2 -- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index 4ac5ee69..2a501794 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -100,13 +100,21 @@ type context struct { inits []func() phis []func() - inCFunc bool - skipall bool - hasPatch bool + state pkgState + inCFunc bool + skipall bool } +type pkgState byte + +const ( + pkgNormal pkgState = iota + pkgHasPatch + pkgInPatch +) + 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) { @@ -186,6 +194,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun } var isInit bool + var state = p.state var sig = f.Signature var hasCtx = len(f.FreeVars) > 0 if hasCtx { @@ -208,6 +217,8 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun ret := types.NewParam(token.NoPos, pkgTypes, "", p.prog.CInt().RawType()) results := types.NewTuple(ret) 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) } @@ -219,6 +230,7 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun } p.inits = append(p.inits, func() { p.fn = fn + p.state = state // restore pkgState when compiling funcBody defer func() { p.fn = nil }() @@ -263,8 +275,9 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do var pyModInit bool var prog = p.prog var pkg = p.pkg + var fn = p.fn var instrs = block.Instrs[n:] - var ret = p.fn.Block(block.Index) + var ret = fn.Block(block.Index) b.SetBlock(ret) if doModInit { if pyModInit = p.pyMod != ""; pyModInit { @@ -277,7 +290,6 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do }) } } else if doMainInit { - fn := p.fn argc := pkg.NewVar("__llgo_argc", types.NewPointer(types.Typ[types.Int32]), llssa.InC) argv := pkg.NewVar("__llgo_argv", types.NewPointer(argvTy), llssa.InC) argc.InitNil() @@ -287,7 +299,12 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do callRuntimeInit(b, pkg) 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) } if pyModInit { @@ -298,7 +315,7 @@ func (p *context) compileBlock(b llssa.Builder, block *ssa.BasicBlock, n int, do modPtr := pkg.PyNewModVar(modName, true).Expr mod := b.Load(modPtr) cond := b.BinOp(token.NEQ, mod, prog.Nil(mod.Type)) - newBlk := p.fn.MakeBlock() + newBlk := fn.MakeBlock() b.If(cond, jumpTo, newBlk) b.SetBlockEx(newBlk, llssa.AtEnd, false) b.Store(modPtr, b.PyImportMod(modPath)) @@ -755,11 +772,12 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ if hasPatch { skips := ctx.skips ctx.skips = nil + ctx.state = pkgInPatch processPkg(ctx, ret, alt) + ctx.state = pkgHasPatch ctx.skips = skips } if !ctx.skipall { - ctx.hasPatch = hasPatch processPkg(ctx, ret, pkg) } for len(ctx.inits) > 0 { @@ -772,11 +790,9 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ return } -/* TODO(xsw): -func inPatch(ctx *context) bool { - return ctx.skips == nil +func initFnNameOfHasPatch(name string) string { + return name + "$hasPatch" } -*/ func processPkg(ctx *context, ret llssa.Package, pkg *ssa.Package) { type namedMember struct { diff --git a/ssa/decl.go b/ssa/decl.go index 9e4a6ca6..89128409 100644 --- a/ssa/decl.go +++ b/ssa/decl.go @@ -234,12 +234,10 @@ func newParams(fn Type, prog Program) (params []Type, hasVArg bool) { return } -/* // Name returns the function's name. func (p Function) Name() string { return p.impl.Name() } -*/ // Params returns the function's ith parameter. func (p Function) Param(i int) Expr { From 24c7928c4b0823c1c212ab268bc133eb600390db Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 18 Jun 2024 18:32:29 +0800 Subject: [PATCH 4/4] cl: pkgFNoOldInit flag if no initFnNameOld --- cl/compile.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cl/compile.go b/cl/compile.go index 2a501794..4b72f945 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -111,6 +111,8 @@ const ( pkgNormal pkgState = iota pkgHasPatch pkgInPatch + + pkgFNoOldInit = 0x80 // flag if no initFnNameOld ) func (p *context) inMain(instr ssa.Instruction) bool { @@ -773,6 +775,9 @@ func NewPackageEx(prog llssa.Program, patches Patches, pkg *ssa.Package, files [ skips := ctx.skips ctx.skips = nil ctx.state = pkgInPatch + if _, ok := skips["init"]; ok || ctx.skipall { + ctx.state |= pkgFNoOldInit + } processPkg(ctx, ret, alt) ctx.state = pkgHasPatch ctx.skips = skips