diff --git a/cl/_testcgo/strlen/out.ll b/cl/_testcgo/strlen/out.ll index e69de29b..aa7b8522 100644 --- a/cl/_testcgo/strlen/out.ll +++ b/cl/_testcgo/strlen/out.ll @@ -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 +} diff --git a/cl/compile.go b/cl/compile.go index 6f435e8c..a499dbe8 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -25,6 +25,7 @@ import ( "log" "os" "sort" + "strings" llssa "github.com/goplus/llgo/ssa" "golang.org/x/tools/go/ssa" @@ -57,7 +58,7 @@ func SetDebug(dbgFlags dbgFlags) { const ( fnNormal = iota fnHasVArg - fnUnsafeInit + fnIgnore ) func funcKind(vfn ssa.Value) int { @@ -65,8 +66,8 @@ func funcKind(vfn ssa.Value) int { params := fn.Signature.Params() n := params.Len() if n == 0 { - if fn.Name() == "init" && fn.Pkg.Pkg.Path() == "unsafe" { - return fnUnsafeInit + if fn.Name() == "init" && ignorePkgInit(fn.Pkg.Pkg.Path()) { + return fnIgnore } } else { last := params.At(n - 1) @@ -78,6 +79,32 @@ func funcKind(vfn ssa.Value) int { 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{} @@ -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) { sig := f.Signature name := p.funcName(pkgTypes, f) - /* TODO(xsw): confirm this is not needed more - if name == "unsafe.init" { - return - } - */ if debugInstr { log.Println("==> NewFunc", name, "type:", sig.Recv(), sig) } + if ignoreFunc(name, f) { + return + } fn := pkg.NewFunc(name, sig) p.inits = append(p.inits, func() { p.fn = fn @@ -229,7 +254,7 @@ func (p *context) compileInstrAndValue(b llssa.Builder, iv instrAndValue) (ret l call := v.Call cv := call.Value kind := funcKind(cv) - if kind == fnUnsafeInit { + if kind == fnIgnore { return } if debugGoSSA { diff --git a/cl/compile_test.go b/cl/compile_test.go index 49759d2f..9e832a3c 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -27,8 +27,12 @@ func testCompile(t *testing.T, src, expected string) { cltest.TestCompileEx(t, src, "foo.go", expected) } +func TestFromTestcgo(t *testing.T) { + cltest.FromDir(t, "strlen", "./_testcgo", true) +} + func TestFromTestdata(t *testing.T) { - cltest.FromDir(t, "apkg", "./_testdata", false) + cltest.FromDir(t, "", "./_testdata", false) } func TestVar(t *testing.T) { diff --git a/cl/import.go b/cl/import.go index 5f2faf45..4abc9337 100644 --- a/cl/import.go +++ b/cl/import.go @@ -120,10 +120,11 @@ func fullName(pkg *types.Package, name string) string { // method: (pkg.T).name func funcName(pkg *types.Package, fn *ssa.Function) string { sig := fn.Signature + name := fn.Name() 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" { ret = "main" } diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index e447723a..9eca9f8d 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -22,6 +22,7 @@ import ( "github.com/goplus/llgo/cl" "golang.org/x/tools/go/packages" "golang.org/x/tools/go/ssa" + "golang.org/x/tools/go/ssa/ssautil" llssa "github.com/goplus/llgo/ssa" ) @@ -40,10 +41,11 @@ func GenFromFile(inFile string) string { initial, err := packages.Load(cfg, inFile) check(err) + _, pkgs := ssautil.AllPackages(initial, ssa.SanityCheckFunctions) + pkg := initial[0] - fset := pkg.Fset - ssaProg := ssa.NewProgram(fset, ssa.SanityCheckFunctions) - ssaPkg := ssaProg.CreatePackage(pkg.Types, pkg.Syntax, pkg.TypesInfo, true) + ssaPkg := pkgs[0] + ssaPkg.Build() prog := llssa.NewProgram(nil) ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax)