diff --git a/cl/_testcgo/strlen/out.ll b/cl/_testcgo/strlen/out.ll index 706fadc8..130d120f 100644 --- a/cl/_testcgo/strlen/out.ll +++ b/cl/_testcgo/strlen/out.ll @@ -1,7 +1,6 @@ ; ModuleID = 'main' source_filename = "main" -@main._Cgo_always_false = global ptr null @main.format = global ptr null @"main.init$guard" = global ptr null diff --git a/cl/builtin_test.go b/cl/builtin_test.go new file mode 100644 index 00000000..8daa7207 --- /dev/null +++ b/cl/builtin_test.go @@ -0,0 +1,27 @@ +/* + * 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 cl + +import ( + "testing" +) + +func TestIgnoreName(t *testing.T) { + if !ignoreName("runtime.foo") || !ignoreName("runtime/foo") || !ignoreName("internal/abi") { + t.Fatal("ignoreName failed") + } +} diff --git a/cl/compile.go b/cl/compile.go index 60530630..631246c8 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -87,20 +87,26 @@ func ignorePkgInit(pkgPath string) bool { return false } -func ignoreFunc(name string, fn *ssa.Function) bool { +func ignoreName(name string) bool { /* TODO(xsw): confirm this is not needed more if name == "unsafe.init" { return true } */ - fnName := fn.Name() - if strings.HasPrefix(fnName, "_Cgo_") { - return true + if strings.HasPrefix(name, "internal/") || strings.HasPrefix(name, "crypto/") || + 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.") { + return true // TODO(xsw) } - const runtime = "runtime" - if strings.HasPrefix(name, runtime) { - left := name[len(runtime):] - return strings.HasPrefix(left, ".cgo") || strings.HasPrefix(left, "/cgo") + return inPkg(name, "runtime") || inPkg(name, "sync") +} + +func inPkg(name, pkg string) bool { + if len(name) > len(pkg) && strings.HasPrefix(name, pkg) { + c := name[len(pkg)] + return c == '.' || c == '/' } return false } @@ -131,8 +137,12 @@ type context struct { func (p *context) compileType(pkg llssa.Package, t *ssa.Type) { tn := t.Object().(*types.TypeName) + tnName := tn.Name() typ := tn.Type() - name := fullName(tn.Pkg(), tn.Name()) + name := fullName(tn.Pkg(), tnName) + if ignoreName(name) { + return + } if debugInstr { log.Println("==> NewType", name, typ) } @@ -145,8 +155,9 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) { mthds := prog.MethodSets.MethodSet(typ) for i, n := 0, mthds.Len(); i < n; i++ { mthd := mthds.At(i) - ssaMthd := prog.MethodValue(mthd) - p.compileFunc(pkg, mthd.Obj().Pkg(), ssaMthd) + if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil { + p.compileFunc(pkg, mthd.Obj().Pkg(), ssaMthd) + } } } @@ -154,6 +165,9 @@ func (p *context) compileMethods(pkg llssa.Package, typ types.Type) { func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) { typ := gbl.Type() name := fullName(gbl.Pkg.Pkg, gbl.Name()) + if ignoreName(name) || checkCgo(gbl.Name()) { + return + } if debugInstr { log.Println("==> NewVar", name, typ) } @@ -163,13 +177,13 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) { func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function) { sig := f.Signature - name := p.funcName(pkgTypes, f) - if debugInstr { - log.Println("==> NewFunc", name, "type:", sig.Recv(), sig) - } - if ignoreFunc(name, f) { + name, ok := p.funcName(pkgTypes, f, true) + if !ok { // ignored return } + if debugInstr { + log.Println("==> NewFunc", f.Name(), name, "type:", sig.Recv(), sig) + } fn := pkg.NewFunc(name, sig) p.inits = append(p.inits, func() { p.fn = fn diff --git a/cl/import.go b/cl/import.go index d73b236e..9a02ec0b 100644 --- a/cl/import.go +++ b/cl/import.go @@ -137,18 +137,27 @@ func funcName(pkg *types.Package, fn *ssa.Function) string { return ret } -func (p *context) funcName(pkg *types.Package, fn *ssa.Function) string { +func checkCgo(fnName string) bool { + return len(fnName) > 4 && fnName[0] == '_' && fnName[2] == 'g' && fnName[3] == 'o' && + (fnName[1] == 'C' || fnName[1] == 'c') && + (fnName[4] == '_' || strings.HasPrefix(fnName[4:], "Check")) +} + +func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, bool) { name := funcName(pkg, fn) - if v, ok := p.link[name]; ok { - return v + if ignore && ignoreName(name) || checkCgo(fn.Name()) { + return name, false } - return name + if v, ok := p.link[name]; ok { + return v, true + } + return name, true } func (p *context) funcOf(fn *ssa.Function) llssa.Function { pkgTypes := p.ensureLoaded(fn.Pkg.Pkg) pkg := p.pkg - name := p.funcName(pkgTypes, fn) + name, _ := p.funcName(pkgTypes, fn, false) if ret := pkg.FuncOf(name); ret != nil { return ret }