diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 43c16d0a..d3789159 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -60,4 +60,7 @@ jobs: run: go build -v ./... - name: Test - run: go test -v ./... + run: go test -v -coverprofile="coverage.txt" -covermode=atomic ./... + + - name: Codecov + uses: codecov/codecov-action@v2 diff --git a/README.md b/README.md index 0ed89870..eb1e3c12 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ llgo - A Go compiler based on LLVM [![Build Status](https://github.com/goplus/llgo/actions/workflows/go.yml/badge.svg)](https://github.com/goplus/llgo/actions/workflows/go.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/goplus/llgo)](https://goreportcard.com/report/github.com/goplus/llgo) [![GitHub release](https://img.shields.io/github/v/tag/goplus/llgo.svg?label=release)](https://github.com/goplus/llgo/releases) -[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo) - +[![GoDoc](https://pkg.go.dev/badge/github.com/goplus/llgo.svg)](https://pkg.go.dev/github.com/goplus/llgo) +[![Language](https://img.shields.io/badge/language-Go+-blue.svg)](https://github.com/goplus/gop) + +This is a Go compiler based on LLVM in order to better integrate Go with the C ecosystem. It's a subproject of [the Go+ project](https://github.com/goplus/gop). diff --git a/cl/cltest/cltest.go b/cl/cltest/cltest.go new file mode 100644 index 00000000..e0f633f2 --- /dev/null +++ b/cl/cltest/cltest.go @@ -0,0 +1,104 @@ +/* + * 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 cltest + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" + "log" + "os" + "path" + "strings" + "testing" + + "github.com/goplus/gogen/packages" + "github.com/goplus/llgo/cl" + "golang.org/x/tools/go/ssa" + "golang.org/x/tools/go/ssa/ssautil" + + llssa "github.com/goplus/llgo/ssa" +) + +func init() { + cl.SetDebug(cl.DbgFlagAll) + llssa.Initialize(llssa.InitAll) + llssa.SetDebug(llssa.DbgFlagAll) +} + +func FromDir(t *testing.T, sel, relDir string) { + dir, err := os.Getwd() + if err != nil { + t.Fatal("Getwd failed:", err) + } + dir = path.Join(dir, relDir) + fis, err := os.ReadDir(dir) + if err != nil { + t.Fatal("ReadDir failed:", err) + } + for _, fi := range fis { + name := fi.Name() + if !fi.IsDir() || strings.HasPrefix(name, "_") { + continue + } + t.Run(name, func(t *testing.T) { + testFrom(t, dir+"/"+name, sel) + }) + } +} + +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" + expected, err := os.ReadFile(out) + if err != nil { + t.Fatal("ReadFile failed:", err) + } + TestCompileEx(t, nil, in, string(expected)) +} + +func TestCompileEx(t *testing.T, src any, fname, expected string) { + t.Helper() + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, fname, src, parser.ParseComments) + if err != nil { + t.Fatal("ParseFile failed:", err) + } + files := []*ast.File{f} + name := f.Name.Name + pkg := types.NewPackage(name, name) + imp := packages.NewImporter(fset) + foo, _, err := ssautil.BuildPackage( + &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) + if err != nil { + t.Fatal("BuildPackage failed:", err) + } + foo.WriteTo(os.Stderr) + prog := llssa.NewProgram(nil) + ret, err := cl.NewPackage(prog, foo, files) + if err != nil { + t.Fatal("cl.NewPackage failed:", err) + } + if v := ret.String(); v != expected { + 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 2deacb58..c18dfa2b 100644 --- a/cl/compile_test.go +++ b/cl/compile_test.go @@ -14,101 +14,21 @@ * limitations under the License. */ -package cl +package cl_test import ( - "go/ast" - "go/parser" - "go/token" - "go/types" - "log" - "os" - "path" - "strings" "testing" - "github.com/goplus/gogen/packages" - "golang.org/x/tools/go/ssa" - "golang.org/x/tools/go/ssa/ssautil" - - llssa "github.com/goplus/llgo/ssa" + "github.com/goplus/llgo/cl/cltest" ) func TestFromTestdata(t *testing.T) { - testFromDir(t, "", "./_testdata") -} - -func init() { - SetDebug(DbgFlagAll) - llssa.Initialize(llssa.InitAll) - llssa.SetDebug(llssa.DbgFlagAll) -} - -func testFromDir(t *testing.T, sel, relDir string) { - dir, err := os.Getwd() - if err != nil { - t.Fatal("Getwd failed:", err) - } - dir = path.Join(dir, relDir) - fis, err := os.ReadDir(dir) - if err != nil { - t.Fatal("ReadDir failed:", err) - } - for _, fi := range fis { - name := fi.Name() - if !fi.IsDir() || strings.HasPrefix(name, "_") { - continue - } - t.Run(name, func(t *testing.T) { - testFrom(t, dir+"/"+name, sel) - }) - } -} - -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" - expected, err := os.ReadFile(out) - if err != nil { - t.Fatal("ReadFile failed:", err) - } - testCompileEx(t, nil, in, string(expected)) -} - -func testCompileEx(t *testing.T, src any, fname, expected string) { - t.Helper() - fset := token.NewFileSet() - f, err := parser.ParseFile(fset, fname, src, parser.ParseComments) - if err != nil { - t.Fatal("ParseFile failed:", err) - } - files := []*ast.File{f} - name := f.Name.Name - pkg := types.NewPackage(name, name) - imp := packages.NewImporter(fset) - foo, _, err := ssautil.BuildPackage( - &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) - if err != nil { - t.Fatal("BuildPackage failed:", err) - } - foo.WriteTo(os.Stderr) - prog := llssa.NewProgram(nil) - ret, err := NewPackage(prog, foo, files) - if err != nil { - t.Fatal("cl.NewPackage failed:", err) - } - if v := ret.String(); v != expected { - t.Fatalf("\n==> got:\n%s\n==> expected:\n%s\n", v, expected) - } + cltest.FromDir(t, "", "./_testdata") } func testCompile(t *testing.T, src, expected string) { t.Helper() - testCompileEx(t, src, "foo.go", expected) + cltest.TestCompileEx(t, src, "foo.go", expected) } func TestVar(t *testing.T) { diff --git a/ssa/cl_test.go b/ssa/cl_test.go new file mode 100644 index 00000000..2dda76c7 --- /dev/null +++ b/ssa/cl_test.go @@ -0,0 +1,27 @@ +/* + * 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 ssa_test + +import ( + "testing" + + "github.com/goplus/llgo/cl/cltest" +) + +func TestFromTestdata(t *testing.T) { + cltest.FromDir(t, "", "../cl/_testdata") +} diff --git a/ssa/ssa_test.go b/ssa/ssa_test.go index 7978b223..1eb402cf 100644 --- a/ssa/ssa_test.go +++ b/ssa/ssa_test.go @@ -23,11 +23,6 @@ import ( "testing" ) -func init() { - Initialize(InitAll) - SetDebug(DbgFlagAll) -} - func assertPkg(t *testing.T, p Package, expected string) { t.Helper() if v := p.String(); v != expected {