From 43ae7a23b2c9ebd4d260accd698c75301d4813b7 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Fri, 26 Apr 2024 02:05:49 +0800 Subject: [PATCH] cl: _testcgo/strlen - todo --- chore/llgen/llgen.go | 11 ++------ cl/_testcgo/strlen/in.go | 17 +++++++++++ cl/_testcgo/strlen/out.ll | 0 cl/cltest/cltest.go | 18 ++++++++---- cl/compile_test.go | 2 +- internal/build/build.go | 4 +-- internal/llgen/llgenf.go | 59 +++++++++++++++++++++++++++++++++++++++ ssa/cl_test.go | 2 +- 8 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 cl/_testcgo/strlen/in.go create mode 100644 cl/_testcgo/strlen/out.ll create mode 100644 internal/llgen/llgenf.go diff --git a/chore/llgen/llgen.go b/chore/llgen/llgen.go index 594076da..c5bdaf3f 100644 --- a/chore/llgen/llgen.go +++ b/chore/llgen/llgen.go @@ -26,7 +26,7 @@ import ( func main() { if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go [pkgPath]") + fmt.Fprintln(os.Stderr, "Usage: llgen xxx.go") return } @@ -35,13 +35,6 @@ func main() { dir, _ := filepath.Split(inFile) outFile := dir + "out.ll" - pkgPath := "" - if len(os.Args) == 3 { - pkgPath = os.Args[2] - } else { - pkgPath = llgen.PkgPath(dir) - } - llgen.Init() - llgen.Do(pkgPath, inFile, outFile) + llgen.DoFile(inFile, outFile) } diff --git a/cl/_testcgo/strlen/in.go b/cl/_testcgo/strlen/in.go new file mode 100644 index 00000000..edaa5e9d --- /dev/null +++ b/cl/_testcgo/strlen/in.go @@ -0,0 +1,17 @@ +package main + +import "C" +import _ "unsafe" + +//go:linkname printf printf +func printf(format *int8, __llgo_va_list ...any) + +//go:linkname strlen strlen +func strlen(str *int8) C.int + +var format = [...]int8{'H', 'e', 'l', 'l', 'o', ' ', '%', 'd', '\n', 0} + +func main() { + sfmt := &format[0] + printf(sfmt, strlen(sfmt)) +} diff --git a/cl/_testcgo/strlen/out.ll b/cl/_testcgo/strlen/out.ll new file mode 100644 index 00000000..e69de29b diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go index e0f633f2..bc6900e8 100644 --- a/cl/cltest/cltest.go +++ b/cl/cltest/cltest.go @@ -29,6 +29,7 @@ import ( "github.com/goplus/gogen/packages" "github.com/goplus/llgo/cl" + "github.com/goplus/llgo/internal/llgen" "golang.org/x/tools/go/ssa" "golang.org/x/tools/go/ssa/ssautil" @@ -41,7 +42,7 @@ func init() { llssa.SetDebug(llssa.DbgFlagAll) } -func FromDir(t *testing.T, sel, relDir string) { +func FromDir(t *testing.T, sel, relDir string, byLLGen bool) { dir, err := os.Getwd() if err != nil { t.Fatal("Getwd failed:", err) @@ -57,23 +58,30 @@ func FromDir(t *testing.T, sel, relDir string) { continue } t.Run(name, func(t *testing.T) { - testFrom(t, dir+"/"+name, sel) + testFrom(t, dir+"/"+name, sel, byLLGen) }) } } -func testFrom(t *testing.T, pkgDir, sel string) { +func testFrom(t *testing.T, pkgDir, sel string, byLLGen bool) { if sel != "" && !strings.Contains(pkgDir, sel) { return } log.Println("Parsing", pkgDir) in := pkgDir + "/in.go" out := pkgDir + "/out.ll" - expected, err := os.ReadFile(out) + b, err := os.ReadFile(out) if err != nil { t.Fatal("ReadFile failed:", err) } - TestCompileEx(t, nil, in, string(expected)) + expected := string(b) + if byLLGen { + if v := llgen.GenFromFile(in); v != expected { + t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) + } + } else { + TestCompileEx(t, nil, in, expected) + } } func TestCompileEx(t *testing.T, src any, fname, expected string) { diff --git a/cl/compile_test.go b/cl/compile_test.go index 6e250588..49759d2f 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -28,7 +28,7 @@ func testCompile(t *testing.T, src, expected string) { } func TestFromTestdata(t *testing.T) { - cltest.FromDir(t, "", "./_testdata") + cltest.FromDir(t, "apkg", "./_testdata", false) } func TestVar(t *testing.T) { diff --git a/internal/build/build.go b/internal/build/build.go index 3eb310aa..0cd2cc27 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -133,7 +133,7 @@ func linkMainPkg(pkg *packages.Package, conf *Config, mode Mode) { args[0] = "-o" args[1] = app packages.Visit([]*packages.Package{pkg}, nil, func(p *packages.Package) { - if p.PkgPath != "unsafe" { // TODO(xsw): remove this special case + if p.PkgPath != "unsafe" { // TODO(xsw): maybe can remove this special case args = append(args, p.ExportFile+".ll") } }) @@ -159,7 +159,7 @@ func buildPkg(prog llssa.Program, aPkg aPackage, mode Mode) { if mode != ModeRun { fmt.Fprintln(os.Stderr, pkgPath) } - if pkgPath == "unsafe" { // TODO(xsw): remove this special case + if pkgPath == "unsafe" { // TODO(xsw): maybe can remove this special case return } ret, err := cl.NewPackage(prog, aPkg.SSA, pkg.Syntax) diff --git a/internal/llgen/llgenf.go b/internal/llgen/llgenf.go new file mode 100644 index 00000000..e447723a --- /dev/null +++ b/internal/llgen/llgenf.go @@ -0,0 +1,59 @@ +/* + * 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 llgen + +import ( + "os" + + "github.com/goplus/llgo/cl" + "golang.org/x/tools/go/packages" + "golang.org/x/tools/go/ssa" + + 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 GenFromFile(inFile string) string { + cfg := &packages.Config{ + Mode: loadSyntax, + } + initial, err := packages.Load(cfg, inFile) + check(err) + + pkg := initial[0] + fset := pkg.Fset + ssaProg := ssa.NewProgram(fset, ssa.SanityCheckFunctions) + ssaPkg := ssaProg.CreatePackage(pkg.Types, pkg.Syntax, pkg.TypesInfo, true) + + prog := llssa.NewProgram(nil) + ret, err := cl.NewPackage(prog, ssaPkg, pkg.Syntax) + check(err) + + return ret.String() +} + +func DoFile(inFile, outFile string) { + ret := GenFromFile(inFile) + err := os.WriteFile(outFile, []byte(ret), 0644) + check(err) +} diff --git a/ssa/cl_test.go b/ssa/cl_test.go index 2dda76c7..05bb8418 100644 --- a/ssa/cl_test.go +++ b/ssa/cl_test.go @@ -23,5 +23,5 @@ import ( ) func TestFromTestdata(t *testing.T) { - cltest.FromDir(t, "", "../cl/_testdata") + cltest.FromDir(t, "", "../cl/_testdata", false) }