From 81b3add443a45c37f3d6cfb7b0176c1347bd4210 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 24 Apr 2024 14:27:14 +0800 Subject: [PATCH 1/3] build.Do: verbose --- cl/_testdata/importpkg/in.go | 1 + cl/_testdata/importpkg/out.ll | 3 +++ cl/internal/stdio/printf.go | 7 +++++++ internal/build/build_install.go | 19 +++++++++++++------ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/cl/_testdata/importpkg/in.go b/cl/_testdata/importpkg/in.go index f9c1c830..96afbd51 100644 --- a/cl/_testdata/importpkg/in.go +++ b/cl/_testdata/importpkg/in.go @@ -5,5 +5,6 @@ import "github.com/goplus/llgo/cl/internal/stdio" var hello = [...]int8{'H', 'e', 'l', 'l', 'o', '\n', 0} func main() { + _ = stdio.Max(2, 100) stdio.Printf(&hello[0]) } diff --git a/cl/_testdata/importpkg/out.ll b/cl/_testdata/importpkg/out.ll index c07ae22b..de2212b5 100644 --- a/cl/_testdata/importpkg/out.ll +++ b/cl/_testdata/importpkg/out.ll @@ -28,10 +28,13 @@ _llgo_2: ; preds = %_llgo_1, %_llgo_0 define void @main() { _llgo_0: call void @main.init() + %0 = call i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64 2, i64 100) call void (ptr, ...) @printf(ptr @main.hello) ret void } declare void @"github.com/goplus/llgo/cl/internal/stdio.init"() +declare i64 @"github.com/goplus/llgo/cl/internal/stdio.Max"(i64, i64) + declare void @printf(ptr, ...) diff --git a/cl/internal/stdio/printf.go b/cl/internal/stdio/printf.go index 38fffa6f..ac080937 100644 --- a/cl/internal/stdio/printf.go +++ b/cl/internal/stdio/printf.go @@ -8,3 +8,10 @@ const ( //go:linkname Printf printf func Printf(format *int8, __llgo_va_list ...any) + +func Max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/internal/build/build_install.go b/internal/build/build_install.go index 166fcaf8..84075441 100644 --- a/internal/build/build_install.go +++ b/internal/build/build_install.go @@ -48,7 +48,7 @@ const ( ) func Do(args []string, mode Mode) { - flags, patterns := parseArgs(args) + flags, patterns, verbose := parseArgs(args) cfg := &packages.Config{ Mode: loadSyntax | packages.NeedExportFile, BuildFlags: flags, @@ -67,8 +67,10 @@ func Do(args []string, mode Mode) { } llssa.Initialize(llssa.InitAll) - // llssa.SetDebug(llssa.DbgFlagAll) - // cl.SetDebug(cl.DbgFlagAll) + if verbose { + llssa.SetDebug(llssa.DbgFlagAll) + cl.SetDebug(cl.DbgFlagAll) + } prog := llssa.NewProgram(nil) llFiles := make([]string, 0, len(pkgs)) @@ -122,13 +124,18 @@ func allPkgs(initial []*packages.Package, mode ssa.BuilderMode) (prog *ssa.Progr return } -func parseArgs(args []string) (flags, patterns []string) { +func parseArgs(args []string) (flags, patterns []string, verbose bool) { for i, arg := range args { if !strings.HasPrefix(arg, "-") { - return args[:i], args[i:] + flags, patterns = args[:i], args[i:] + return + } + if arg == "-v" { + verbose = true } } - return args, nil + flags = args + return } func check(err error) { From cbaf9e21b21ce6d8c50894a0327a6837ad5bf39b Mon Sep 17 00:00:00 2001 From: xushiwei Date: Thu, 25 Apr 2024 00:14:02 +0800 Subject: [PATCH 2/3] llgo build/install: a.out generated --- cl/compile.go | 5 +++-- cl/import.go | 6 +++++- internal/build/build_install.go | 9 +++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cl/compile.go b/cl/compile.go index c9ebfb86..1b9501c8 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -305,7 +305,8 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll }) pkgTypes := pkg.Pkg - ret = prog.NewPackage(pkgTypes.Name(), pkgTypes.Path()) + pkgName, pkgPath := pkgTypes.Name(), pkgTypes.Path() + ret = prog.NewPackage(pkgName, pkgPath) ctx := &context{ prog: prog, @@ -316,7 +317,7 @@ func NewPackage(prog llssa.Program, pkg *ssa.Package, files []*ast.File) (ret ll link: make(map[string]string), loaded: make(map[*types.Package]none), } - ctx.initFiles(pkgTypes.Path(), files) + ctx.initFiles(pkgPath, files) for _, m := range members { member := m.val switch member := member.(type) { diff --git a/cl/import.go b/cl/import.go index 30a203a7..c3f175cb 100644 --- a/cl/import.go +++ b/cl/import.go @@ -106,7 +106,11 @@ func (p *context) initLinkname(pkgPath, line string) { } func fullName(pkg *types.Package, name string) string { - return pkg.Path() + "." + name + pkgPath := pkg.Name() + if pkgPath != "main" { + pkgPath = pkg.Path() + } + return pkgPath + "." + name } func funcName(pkg *types.Package, fn *ssa.Function) string { diff --git a/internal/build/build_install.go b/internal/build/build_install.go index 84075441..9b7f7617 100644 --- a/internal/build/build_install.go +++ b/internal/build/build_install.go @@ -50,7 +50,7 @@ const ( func Do(args []string, mode Mode) { flags, patterns, verbose := parseArgs(args) cfg := &packages.Config{ - Mode: loadSyntax | packages.NeedExportFile, + Mode: loadSyntax | packages.NeedDeps | packages.NeedExportFile, BuildFlags: flags, } @@ -61,7 +61,8 @@ func Do(args []string, mode Mode) { check(err) // Create SSA-form program representation. - _, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions) + ssaProg, pkgs, errPkgs := allPkgs(initial, ssa.SanityCheckFunctions) + ssaProg.Build() for _, errPkg := range errPkgs { log.Println("cannot build SSA for package", errPkg) } @@ -75,11 +76,11 @@ func Do(args []string, mode Mode) { prog := llssa.NewProgram(nil) llFiles := make([]string, 0, len(pkgs)) for _, pkg := range pkgs { - pkg.SSA.Build() llFiles = buildPkg(llFiles, prog, pkg, mode) } if mode == ModeInstall { - fmt.Fprintln(os.Stderr, "clang", llFiles) + // TODO(xsw): show work + // fmt.Fprintln(os.Stderr, "clang", llFiles) err = clang.New("").Exec(llFiles...) check(err) } From a2c6e5d7fc8646dcec2a8b7cb0c490a6173d2b64 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Thu, 25 Apr 2024 00:53:42 +0800 Subject: [PATCH 3/3] llgo install: /appName --- cmd/internal/build/build.go | 4 +- cmd/internal/install/install.go | 3 +- internal/build/{build_install.go => build.go} | 70 +++++++++++++++---- 3 files changed, 62 insertions(+), 15 deletions(-) rename internal/build/{build_install.go => build.go} (71%) diff --git a/cmd/internal/build/build.go b/cmd/internal/build/build.go index ebe5e4e2..627dcf86 100644 --- a/cmd/internal/build/build.go +++ b/cmd/internal/build/build.go @@ -33,5 +33,7 @@ func init() { } func runCmd(cmd *base.Command, args []string) { - build.Do(args, build.ModeBuild) + build.Do(args, &build.Config{ + Mode: build.ModeBuild, + }) } diff --git a/cmd/internal/install/install.go b/cmd/internal/install/install.go index 1ae49dbf..9f9e6dc2 100644 --- a/cmd/internal/install/install.go +++ b/cmd/internal/install/install.go @@ -33,5 +33,6 @@ func init() { } func runCmd(cmd *base.Command, args []string) { - build.Do(args, build.ModeInstall) + conf := build.NewDefaultConf(build.ModeInstall) + build.Do(args, conf) } diff --git a/internal/build/build_install.go b/internal/build/build.go similarity index 71% rename from internal/build/build_install.go rename to internal/build/build.go index 9b7f7617..49e595e1 100644 --- a/internal/build/build_install.go +++ b/internal/build/build.go @@ -21,14 +21,18 @@ import ( "go/token" "log" "os" + "path" + "path/filepath" + "runtime" "strings" "golang.org/x/tools/go/packages" "golang.org/x/tools/go/ssa" "github.com/goplus/llgo/cl" - llssa "github.com/goplus/llgo/ssa" "github.com/goplus/llgo/x/clang" + + llssa "github.com/goplus/llgo/ssa" ) type Mode int @@ -38,6 +42,27 @@ const ( ModeInstall ) +type Config struct { + BinPath string + AppSuffix string // ".exe" on Windows, empty on Unix + Mode Mode +} + +func NewDefaultConf(mode Mode) *Config { + bin := os.Getenv("GOBIN") + if bin == "" { + bin = filepath.Join(runtime.GOROOT(), "bin") + } + conf := &Config{ + BinPath: bin, + Mode: mode, + } + if runtime.GOOS == "windows" { + conf.AppSuffix = ".exe" + } + return conf +} + // ----------------------------------------------------------------------------- const ( @@ -47,7 +72,7 @@ const ( loadSyntax = loadTypes | packages.NeedSyntax | packages.NeedTypesInfo ) -func Do(args []string, mode Mode) { +func Do(args []string, conf *Config) { flags, patterns, verbose := parseArgs(args) cfg := &packages.Config{ Mode: loadSyntax | packages.NeedDeps | packages.NeedExportFile, @@ -74,32 +99,51 @@ func Do(args []string, mode Mode) { } prog := llssa.NewProgram(nil) - llFiles := make([]string, 0, len(pkgs)) + mode := conf.Mode for _, pkg := range pkgs { - llFiles = buildPkg(llFiles, prog, pkg, mode) + buildPkg(prog, pkg, mode) } + if mode == ModeInstall { - // TODO(xsw): show work - // fmt.Fprintln(os.Stderr, "clang", llFiles) - err = clang.New("").Exec(llFiles...) - check(err) + for _, pkg := range initial { + if pkg.Name == "main" { + linkMainPkg(pkg, conf) + } + } } } -func buildPkg(llFiles []string, prog llssa.Program, pkg aPackage, mode Mode) []string { +func linkMainPkg(pkg *packages.Package, conf *Config) { + name := path.Base(pkg.PkgPath) + args := make([]string, 2, len(pkg.Imports)+3) + args[0] = "-o" + args[1] = filepath.Join(conf.BinPath, name+conf.AppSuffix) + packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) { + if p.PkgPath != "unsafe" { // TODO(xsw): remove this special case + args = append(args, p.ExportFile+".ll") + } + }) + + // TODO(xsw): show work + // fmt.Fprintln(os.Stderr, "clang", args) + fmt.Fprintln(os.Stderr, args[1]) + err := clang.New("").Exec(args...) + check(err) +} + +func buildPkg(prog llssa.Program, aPkg aPackage, mode Mode) { + pkg := aPkg.Package pkgPath := pkg.PkgPath fmt.Fprintln(os.Stderr, pkgPath) if pkgPath == "unsafe" { // TODO(xsw): remove this special case - return llFiles + return } - ret, err := cl.NewPackage(prog, pkg.SSA, pkg.Syntax) + ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax) check(err) if mode == ModeInstall { file := pkg.ExportFile + ".ll" os.WriteFile(file, []byte(ret.String()), 0644) - llFiles = append(llFiles, file) } - return llFiles } type aPackage struct {