llgo run: strlen

This commit is contained in:
xushiwei
2024-04-26 04:44:49 +08:00
parent 91d1d71f6d
commit 773ae2c8c6
4 changed files with 71 additions and 22 deletions

View File

@@ -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

27
cl/builtin_test.go Normal file
View File

@@ -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")
}
}

View File

@@ -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,15 +155,19 @@ 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)
if ssaMthd := prog.MethodValue(mthd); ssaMthd != nil {
p.compileFunc(pkg, mthd.Obj().Pkg(), ssaMthd)
}
}
}
// Global variable.
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

View File

@@ -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 {
name := funcName(pkg, fn)
if v, ok := p.link[name]; ok {
return v
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"))
}
return name
func (p *context) funcName(pkg *types.Package, fn *ssa.Function, ignore bool) (string, bool) {
name := funcName(pkg, fn)
if ignore && ignoreName(name) || checkCgo(fn.Name()) {
return name, false
}
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
}