cl: _testcgo/strlen

This commit is contained in:
xushiwei
2024-04-26 02:40:36 +08:00
parent 43ae7a23b2
commit a3d6a94600
5 changed files with 88 additions and 15 deletions

View File

@@ -0,0 +1,41 @@
; ModuleID = 'main'
source_filename = "main"
@"main.init$guard" = global ptr null
@main._Cgo_always_false = global ptr null
@main.format = global ptr null
define void @main.init() {
_llgo_0:
%0 = load i1, ptr @"main.init$guard", align 1
br i1 %0, label %_llgo_2, label %_llgo_1
_llgo_1: ; preds = %_llgo_0
store i1 true, ptr @"main.init$guard", align 1
store i8 72, ptr @main.format, align 1
store i8 101, ptr getelementptr inbounds (i8, ptr @main.format, i64 1), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 2), align 1
store i8 108, ptr getelementptr inbounds (i8, ptr @main.format, i64 3), align 1
store i8 111, ptr getelementptr inbounds (i8, ptr @main.format, i64 4), align 1
store i8 32, ptr getelementptr inbounds (i8, ptr @main.format, i64 5), align 1
store i8 37, ptr getelementptr inbounds (i8, ptr @main.format, i64 6), align 1
store i8 100, ptr getelementptr inbounds (i8, ptr @main.format, i64 7), align 1
store i8 10, ptr getelementptr inbounds (i8, ptr @main.format, i64 8), align 1
store i8 0, ptr getelementptr inbounds (i8, ptr @main.format, i64 9), align 1
br label %_llgo_2
_llgo_2: ; preds = %_llgo_1, %_llgo_0
ret void
}
declare void @printf(ptr, ...)
declare i32 @strlen(ptr)
define void @main() {
_llgo_0:
call void @main.init()
%0 = call i32 @strlen(ptr @main.format)
call void (ptr, ...) @printf(ptr @main.format, i32 %0)
ret void
}

View File

@@ -25,6 +25,7 @@ import (
"log" "log"
"os" "os"
"sort" "sort"
"strings"
llssa "github.com/goplus/llgo/ssa" llssa "github.com/goplus/llgo/ssa"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
@@ -57,7 +58,7 @@ func SetDebug(dbgFlags dbgFlags) {
const ( const (
fnNormal = iota fnNormal = iota
fnHasVArg fnHasVArg
fnUnsafeInit fnIgnore
) )
func funcKind(vfn ssa.Value) int { func funcKind(vfn ssa.Value) int {
@@ -65,8 +66,8 @@ func funcKind(vfn ssa.Value) int {
params := fn.Signature.Params() params := fn.Signature.Params()
n := params.Len() n := params.Len()
if n == 0 { if n == 0 {
if fn.Name() == "init" && fn.Pkg.Pkg.Path() == "unsafe" { if fn.Name() == "init" && ignorePkgInit(fn.Pkg.Pkg.Path()) {
return fnUnsafeInit return fnIgnore
} }
} else { } else {
last := params.At(n - 1) last := params.At(n - 1)
@@ -78,6 +79,32 @@ func funcKind(vfn ssa.Value) int {
return fnNormal return fnNormal
} }
func ignorePkgInit(pkgPath string) bool {
switch pkgPath {
case "unsafe", "syscall", "runtime/cgo":
return true
}
return false
}
func ignoreFunc(name string, fn *ssa.Function) 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
}
const runtime = "runtime"
if strings.HasPrefix(name, runtime) {
left := name[len(runtime):]
return strings.HasPrefix(left, ".cgo") || strings.HasPrefix(left, "/cgo")
}
return false
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
type none = struct{} type none = struct{}
@@ -137,14 +164,12 @@ func (p *context) compileGlobal(pkg llssa.Package, gbl *ssa.Global) {
func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function) { func (p *context) compileFunc(pkg llssa.Package, pkgTypes *types.Package, f *ssa.Function) {
sig := f.Signature sig := f.Signature
name := p.funcName(pkgTypes, f) name := p.funcName(pkgTypes, f)
/* TODO(xsw): confirm this is not needed more
if name == "unsafe.init" {
return
}
*/
if debugInstr { if debugInstr {
log.Println("==> NewFunc", name, "type:", sig.Recv(), sig) log.Println("==> NewFunc", name, "type:", sig.Recv(), sig)
} }
if ignoreFunc(name, f) {
return
}
fn := pkg.NewFunc(name, sig) fn := pkg.NewFunc(name, sig)
p.inits = append(p.inits, func() { p.inits = append(p.inits, func() {
p.fn = fn p.fn = fn
@@ -229,7 +254,7 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l
call := v.Call call := v.Call
cv := call.Value cv := call.Value
kind := funcKind(cv) kind := funcKind(cv)
if kind == fnUnsafeInit { if kind == fnIgnore {
return return
} }
if debugGoSSA { if debugGoSSA {

View File

@@ -27,8 +27,12 @@ func testCompile(t *testing.T, src, expected string) {
cltest.TestCompileEx(t, src, "foo.go", expected) cltest.TestCompileEx(t, src, "foo.go", expected)
} }
func TestFromTestcgo(t *testing.T) {
cltest.FromDir(t, "strlen", "./_testcgo", true)
}
func TestFromTestdata(t *testing.T) { func TestFromTestdata(t *testing.T) {
cltest.FromDir(t, "apkg", "./_testdata", false) cltest.FromDir(t, "", "./_testdata", false)
} }
func TestVar(t *testing.T) { func TestVar(t *testing.T) {

View File

@@ -120,10 +120,11 @@ func fullName(pkg *types.Package, name string) string {
// method: (pkg.T).name // method: (pkg.T).name
func funcName(pkg *types.Package, fn *ssa.Function) string { func funcName(pkg *types.Package, fn *ssa.Function) string {
sig := fn.Signature sig := fn.Signature
name := fn.Name()
if recv := sig.Recv(); recv != nil { if recv := sig.Recv(); recv != nil {
return "(" + recv.Type().String() + ")." + fn.Name() return "(" + recv.Type().String() + ")." + name
} }
ret := fullName(pkg, fn.Name()) ret := fullName(pkg, name)
if ret == "main.main" { if ret == "main.main" {
ret = "main" ret = "main"
} }

View File

@@ -22,6 +22,7 @@ import (
"github.com/goplus/llgo/cl" "github.com/goplus/llgo/cl"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
"golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
llssa "github.com/goplus/llgo/ssa" llssa "github.com/goplus/llgo/ssa"
) )
@@ -40,10 +41,11 @@ func GenFromFile(inFile string) string {
initial, err := packages.Load(cfg, inFile) initial, err := packages.Load(cfg, inFile)
check(err) check(err)
_, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions)
pkg := initial[0] pkg := initial[0]
fset := pkg.Fset ssaPkg := pkgs[0]
ssaProg := ssa.NewProgram(fset, ssa.SanityCheckFunctions) ssaPkg.Build()
ssaPkg := ssaProg.CreatePackage(pkg.Types, pkg.Syntax, pkg.TypesInfo, true)
prog := llssa.NewProgram(nil) prog := llssa.NewProgram(nil)
ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax) ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)