From d879d0d924e01aba7cce50ce06f2a6e51d6e8021 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Tue, 26 Nov 2024 11:20:15 +0800 Subject: [PATCH] build: make llgen, cltest, gentests call build.Do --- chore/gentests/gentests.go | 13 ++-- chore/llgen/llgen.go | 10 +-- cl/cltest/cltest.go | 15 ++--- cl/compile_test.go | 17 +++-- cmd/internal/build/build.go | 9 ++- cmd/internal/install/install.go | 9 ++- cmd/internal/run/run.go | 8 ++- internal/build/build.go | 21 ++++-- internal/llgen/llgen.go | 33 ---------- internal/llgen/llgenf.go | 112 +++++--------------------------- ssa/cl_test.go | 12 ++-- 11 files changed, 87 insertions(+), 172 deletions(-) diff --git a/chore/gentests/gentests.go b/chore/gentests/gentests.go index ea465748..480a3854 100644 --- a/chore/gentests/gentests.go +++ b/chore/gentests/gentests.go @@ -23,7 +23,6 @@ import ( "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/llgen" - "github.com/goplus/llgo/ssa" "github.com/goplus/mod" ) @@ -31,15 +30,12 @@ func main() { dir, _, err := mod.FindGoMod(".") check(err) - ssa.Initialize(ssa.InitAll | ssa.InitNative) - llgen.Verbose = false - llgenDir(dir + "/cl/_testlibc") llgenDir(dir + "/cl/_testlibgo") llgenDir(dir + "/cl/_testrt") llgenDir(dir + "/cl/_testgo") - llgenDir(dir+"/cl/_testpy", "") - llgenDir(dir+"/cl/_testdata", "") + llgenDir(dir + "/cl/_testpy") + llgenDir(dir + "/cl/_testdata") } func isDbgSymEnabled(flagsFile string) bool { @@ -56,7 +52,7 @@ func isDbgSymEnabled(flagsFile string) bool { return false } -func llgenDir(dir string, pkgPath ...string) { +func llgenDir(dir string) { fis, err := os.ReadDir(dir) check(err) for _, fi := range fis { @@ -69,8 +65,7 @@ func llgenDir(dir string, pkgPath ...string) { check(os.Chdir(testDir)) dbg := isDbgSymEnabled("flags.txt") cl.EnableDebugSymbols(dbg) - - llgen.SmartDoFile("in.go", pkgPath...) + llgen.SmartDoFile(testDir) } } diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go index 4f14892b..50e9a89e 100644 --- a/chore/llgen/llgen.go +++ b/chore/llgen/llgen.go @@ -17,6 +17,7 @@ package main import ( + "flag" "fmt" "os" @@ -24,11 +25,10 @@ import ( ) func main() { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: llgen [flags] [pkgPath]") + flag.Parse() + if len(flag.Args()) != 1 { + fmt.Fprintln(os.Stderr, "Usage: llgen [flags] ") return } - llgen.Init() - args := os.Args[1:] - llgen.SmartDoFile(args[0], args[1:]...) + llgen.SmartDoFile(flag.Args()[0]) } diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index 821f51a8..15c05185 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -50,7 +50,7 @@ func InitDebug() { llssa.SetDebug(llssa.DbgFlagAll) } -func FromDir(t *testing.T, sel, relDir string, byLLGen bool) { +func FromDir(t *testing.T, sel, relDir string) { dir, err := os.Getwd() if err != nil { t.Fatal("Getwd failed:", err) @@ -66,7 +66,7 @@ func FromDir(t *testing.T, sel, relDir string, byLLGen bool) { continue } t.Run(name, func(t *testing.T) { - testFrom(t, dir+"/"+name, sel, byLLGen) + testFrom(t, dir+"/"+name, sel) }) } } @@ -121,12 +121,11 @@ func isDbgSymEnabled(flagsFile string) bool { return false } -func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) { +func testFrom(t *testing.T, pkgDir, sel string) { if sel != "" && !strings.Contains(pkgDir, sel) { return } log.Println("Parsing", pkgDir) - in := pkgDir + "/in.go" out := pkgDir + "/out.ll" dbg := isDbgSymEnabled(pkgDir + "/flags.txt") if dbg { @@ -139,12 +138,8 @@ func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) { t.Fatal("ReadFile failed:", err) } expected := string(b) - if byLLGen { - if v := llgen.GenFrom(in); v != expected && expected != ";" { // expected == ";" means skipping out.ll - t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) - } - } else { - TestCompileEx(t, nil, in, expected, dbg) + if v := llgen.GenFrom(pkgDir); v != expected && expected != ";" { // expected == ";" means skipping out.ll + t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) } } diff --git a/cl/compile_test.go b/cl/compile_test.go index 47f1773c..4618ffef 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -30,34 +30,37 @@ func testCompile(t *testing.T, src, expected string) { } func TestFromTestgo(t *testing.T) { - cltest.FromDir(t, "", "./_testgo", false) + cltest.FromDir(t, "", "./_testgo") } func TestFromTestpy(t *testing.T) { - cltest.FromDir(t, "", "./_testpy", false) + cltest.FromDir(t, "", "./_testpy") } func TestFromTestlibgo(t *testing.T) { - cltest.FromDir(t, "", "./_testlibgo", true) + cltest.FromDir(t, "", "./_testlibgo") } func TestFromTestlibc(t *testing.T) { - cltest.FromDir(t, "", "./_testlibc", true) + cltest.FromDir(t, "", "./_testlibc") } func TestFromTestrt(t *testing.T) { cl.SetDebug(cl.DbgFlagAll) - cltest.FromDir(t, "", "./_testrt", true) + cltest.FromDir(t, "", "./_testrt") cl.SetDebug(0) } func TestFromTestdata(t *testing.T) { - cltest.FromDir(t, "", "./_testdata", false) + cltest.FromDir(t, "", "./_testdata") } func TestGoPkgMath(t *testing.T) { conf := build.NewDefaultConf(build.ModeInstall) - build.Do([]string{"math"}, conf) + _, err := build.Do([]string{"math"}, conf) + if err != nil { + t.Fatal(err) + } } func TestVar(t *testing.T) { diff --git a/cmd/internal/build/build.go b/cmd/internal/build/build.go index 67915c4a..c578a8ee 100644 --- a/cmd/internal/build/build.go +++ b/cmd/internal/build/build.go @@ -18,6 +18,9 @@ package build import ( + "fmt" + "os" + "github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/internal/build" ) @@ -41,5 +44,9 @@ func runCmd(cmd *base.Command, args []string) { conf.OutFile = args[1] args = args[2:] } - build.Do(args, conf) + _, err := build.Do(args, conf) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/internal/install/install.go b/cmd/internal/install/install.go index c486abb3..5c0f5621 100644 --- a/cmd/internal/install/install.go +++ b/cmd/internal/install/install.go @@ -18,6 +18,9 @@ package install import ( + "fmt" + "os" + "github.com/goplus/llgo/cmd/internal/base" "github.com/goplus/llgo/internal/build" ) @@ -34,5 +37,9 @@ func init() { func runCmd(cmd *base.Command, args []string) { conf := build.NewDefaultConf(build.ModeInstall) - build.Do(args, conf) + _, err := build.Do(args, conf) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/internal/run/run.go b/cmd/internal/run/run.go index 3317cfad..2b5ff2ad 100644 --- a/cmd/internal/run/run.go +++ b/cmd/internal/run/run.go @@ -19,6 +19,8 @@ package run import ( "errors" + "fmt" + "os" "path/filepath" "github.com/goplus/llgo/cmd/internal/base" @@ -63,7 +65,11 @@ func runCmdEx(_ *base.Command, args []string, mode build.Mode) { args, runArgs, err := parseRunArgs(args) check(err) conf.RunArgs = runArgs - build.Do(args, conf) + _, err = build.Do(args, conf) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } func parseRunArgs(args []string) ([]string, []string, error) { diff --git a/internal/build/build.go b/internal/build/build.go index 4eec5338..1f015109 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -53,6 +53,7 @@ const ( ModeInstall ModeRun ModeCmpTest + ModeGen ) const ( @@ -119,7 +120,7 @@ const ( loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo ) -func Do(args []string, conf *Config) { +func Do(args []string, conf *Config) ([]Package, error) { flags, patterns, verbose := ParseArgs(args, buildFlags) cl.EnableDebugSymbols(IsDebugEnabled()) flags = append(flags, "-tags", "llgo") @@ -159,7 +160,6 @@ func Do(args []string, conf *Config) { } initial, err := packages.LoadEx(dedup, sizes, cfg, patterns...) check(err) - mode := conf.Mode if len(initial) == 1 && len(initial[0].CompiledGoFiles) > 0 { if mode == ModeBuild { @@ -167,11 +167,10 @@ func Do(args []string, conf *Config) { } } else if mode == ModeRun { if len(initial) > 1 { - fmt.Fprintln(os.Stderr, "cannot run multiple packages") + return nil, fmt.Errorf("cannot run multiple packages") } else { - fmt.Fprintln(os.Stderr, "no Go files in matched packages") + return nil, fmt.Errorf("no Go files in matched packages") } - return } altPkgPaths := altPkgs(initial, llssa.PkgRuntime) @@ -203,12 +202,21 @@ func Do(args []string, conf *Config) { ctx := &context{env, cfg, progSSA, prog, dedup, patches, make(map[string]none), initial, mode, 0} pkgs := buildAllPkgs(ctx, initial, verbose) + if mode == ModeGen { + for _, pkg := range pkgs { + if pkg.Package == initial[0] { + return []*aPackage{pkg}, nil + } + } + return nil, fmt.Errorf("initial package not found") + } dpkg := buildAllPkgs(ctx, altPkgs[noRt:], verbose) var linkArgs []string for _, pkg := range dpkg { linkArgs = append(linkArgs, pkg.LinkArgs...) } + if mode != ModeBuild { nErr := 0 for _, pkg := range initial { @@ -220,6 +228,7 @@ func Do(args []string, conf *Config) { os.Exit(nErr) } } + return dpkg, nil } func setNeedRuntimeOrPyInit(pkg *packages.Package, needRuntime, needPyInit bool) { @@ -571,6 +580,8 @@ type aPackage struct { LinkArgs []string } +type Package = *aPackage + func allPkgs(ctx *context, initial []*packages.Package, verbose bool) (all []*aPackage, errs []*packages.Package) { prog := ctx.progSSA built := ctx.built diff --git a/internal/llgen/llgen.go b/internal/llgen/llgen.go index 14440c42..7401ebe5 100644 --- a/internal/llgen/llgen.go +++ b/internal/llgen/llgen.go @@ -16,41 +16,8 @@ package llgen -import ( - "os" - - "github.com/goplus/llgo/cl" - "github.com/goplus/llgo/internal/build" - "github.com/goplus/llgo/internal/mod" - - llssa "github.com/goplus/llgo/ssa" -) - -func Init() { - llssa.Initialize(llssa.InitAll) - llssa.SetDebug(llssa.DbgFlagAll) - cl.SetDebug(cl.DbgFlagAll) - cl.EnableDebugSymbols(build.IsDebugEnabled()) -} - -func PkgPath(dir string) string { - _, pkgPath, err := mod.Load(dir) - check(err) - return pkgPath -} - -func Do(pkgPath, inFile, outFile string) { - ret := genFrom(inFile, pkgPath) - err := os.WriteFile(outFile, []byte(ret), 0644) - check(err) -} - func check(err error) { if err != nil { panic(err) } } - -var ( - Verbose = true -) diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go index cf55c856..283f4d51 100644 --- a/internal/llgen/llgenf.go +++ b/internal/llgen/llgenf.go @@ -17,107 +17,30 @@ package llgen import ( - "go/ast" - "go/types" "os" "os/exec" "path/filepath" "strings" - "github.com/goplus/llgo/cl" "github.com/goplus/llgo/internal/build" - "github.com/goplus/llgo/internal/packages" - "golang.org/x/tools/go/ssa" - "golang.org/x/tools/go/ssa/ssautil" - - llssa "github.com/goplus/llgo/ssa" ) -const ( - loadFiles = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles - loadImports = loadFiles | packages.NeedImports - loadTypes = loadImports | packages.NeedTypes | packages.NeedTypesSizes - loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo -) - -func initRtAndPy(prog llssa.Program, cfg *packages.Config) { - var pkgRtAndPy []*packages.Package - load := func() []*packages.Package { - if pkgRtAndPy == nil { - var err error - pkgRtAndPy, err = packages.LoadEx(nil, prog.TypeSizes, cfg, llssa.PkgRuntime, llssa.PkgPython) - check(err) - } - return pkgRtAndPy - } - - prog.SetRuntime(func() *types.Package { - rt := load() - return rt[0].Types - }) - prog.SetPython(func() *types.Package { - rt := load() - return rt[1].Types - }) -} - func GenFrom(fileOrPkg string) string { - return genFrom(fileOrPkg, "") + pkg, err := genFrom(fileOrPkg) + check(err) + return pkg.LPkg.String() } -func genFrom(fileOrPkg string, pkgPath string) string { - prog := llssa.NewProgram(nil) - - cfg := &packages.Config{ - Mode: loadSyntax | packages.NeedDeps, - BuildFlags: []string{"-tags", "llgo"}, +func genFrom(pkgPath string) (build.Package, error) { + conf := &build.Config{ + Mode: build.ModeGen, + AppExt: build.DefaultAppExt(), } - - dedup := packages.NewDeduper() - dedup.SetPkgPath(func(path, name string) string { - if path == "command-line-arguments" { - if pkgPath != "" { - path = pkgPath - } else { - path = name - } - } - return path - }) - dedup.SetPreload(func(pkg *types.Package, files []*ast.File) { - cl.ParsePkgSyntax(prog, pkg, files) - }) - - initial, err := packages.LoadEx(dedup, prog.TypeSizes, cfg, fileOrPkg) - check(err) - - buildMode := ssa.SanityCheckFunctions | ssa.InstantiateGenerics - if build.IsDebugEnabled() { - buildMode |= ssa.GlobalDebug + pkgs, err := build.Do([]string{pkgPath}, conf) + if err != nil { + return nil, err } - if !build.IsOptimizeEnabled() { - buildMode |= ssa.NaiveForm - } - _, pkgs := ssautil.AllPackages(initial, buildMode) - - pkg := initial[0] - ssaPkg := pkgs[0] - ssaPkg.Build() - - initRtAndPy(prog, cfg) - - if Verbose { - ssaPkg.WriteTo(os.Stderr) - } - - ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax) - check(err) - - if prog.NeedPyInit { // call PyInit if needed - ret.PyInit() - } - - return ret.String() + return pkgs[0], nil } func DoFile(fileOrPkg, outFile string) { @@ -126,9 +49,12 @@ func DoFile(fileOrPkg, outFile string) { check(err) } -func SmartDoFile(inFile string, pkgPath ...string) { +func SmartDoFile(pkgPath ...string) { + pkg, err := genFrom(pkgPath[0]) + check(err) + const autgenFile = "llgo_autogen.ll" - dir, _ := filepath.Split(inFile) + dir, _ := filepath.Split(pkg.GoFiles[0]) absDir, _ := filepath.Abs(dir) absDir = filepath.ToSlash(absDir) fname := autgenFile @@ -142,10 +68,8 @@ func SmartDoFile(inFile string, pkgPath ...string) { return // skip to gen } - if len(pkgPath) > 0 { - Do(pkgPath[0], inFile, outFile) - } else { - DoFile(inFile, outFile) + if err = os.WriteFile(outFile, []byte(pkg.LPkg.String()), 0644); err != nil { + panic(err) } if false && fname == autgenFile { genZip(absDir, "llgo_autogen.lla", autgenFile) diff --git a/ssa/cl_test.go b/ssa/cl_test.go index 837a990a..86928f5f 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -30,27 +30,27 @@ func init() { } func TestFromTestlibgo(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testlibgo", false) + cltest.FromDir(t, "", "../cl/_testlibgo") } func TestFromTestgo(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testgo", false) + cltest.FromDir(t, "", "../cl/_testgo") } func TestFromTestpy(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testpy", false) + cltest.FromDir(t, "", "../cl/_testpy") } func TestFromTestlibc(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testlibc", true) + cltest.FromDir(t, "", "../cl/_testlibc") } func TestFromTestrt(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testrt", true) + cltest.FromDir(t, "", "../cl/_testrt") } func TestFromTestdata(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testdata", false) + cltest.FromDir(t, "", "../cl/_testdata") } func TestMakeInterface(t *testing.T) {