interp: add basic test to interp package
More tests should be added in the future, but this is a start.
Этот коммит содержится в:
родитель
da7f7eef00
коммит
4ea1559d46
5 изменённых файлов: 162 добавлений и 2 удалений
|
@ -65,7 +65,7 @@ commands:
|
||||||
- go-cache-v2-{{ checksum "go.mod" }}
|
- go-cache-v2-{{ checksum "go.mod" }}
|
||||||
- llvm-source-linux
|
- llvm-source-linux
|
||||||
- run: go install .
|
- run: go install .
|
||||||
- run: go test -v ./transform .
|
- run: go test -v ./interp ./transform .
|
||||||
- run: make gen-device -j4
|
- run: make gen-device -j4
|
||||||
- run: make smoketest RISCV=0
|
- run: make smoketest RISCV=0
|
||||||
- save_cache:
|
- save_cache:
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -100,7 +100,7 @@ build/tinygo:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -o build/tinygo -tags byollvm .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) build -o build/tinygo -tags byollvm .
|
||||||
|
|
||||||
test:
|
test:
|
||||||
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./transform .
|
CGO_CPPFLAGS="$(CGO_CPPFLAGS)" CGO_CXXFLAGS="$(CGO_CXXFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" $(GO) test -v -tags byollvm ./interp ./transform .
|
||||||
|
|
||||||
tinygo-test:
|
tinygo-test:
|
||||||
cd tests/tinygotest && tinygo test
|
cd tests/tinygotest && tinygo test
|
||||||
|
|
98
interp/interp_test.go
Обычный файл
98
interp/interp_test.go
Обычный файл
|
@ -0,0 +1,98 @@
|
||||||
|
package interp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"tinygo.org/x/go-llvm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInterp(t *testing.T) {
|
||||||
|
for _, name := range []string{
|
||||||
|
"basic",
|
||||||
|
} {
|
||||||
|
name := name // make tc local to this closure
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
runTest(t, "testdata/"+name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runTest(t *testing.T, pathPrefix string) {
|
||||||
|
// Read the input IR.
|
||||||
|
ctx := llvm.NewContext()
|
||||||
|
buf, err := llvm.NewMemoryBufferFromFile(pathPrefix + ".ll")
|
||||||
|
os.Stat(pathPrefix + ".ll") // make sure this file is tracked by `go test` caching
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not read file %s: %v", pathPrefix+".ll", err)
|
||||||
|
}
|
||||||
|
mod, err := ctx.ParseIR(buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not load module:\n%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the transform.
|
||||||
|
err = Run(mod, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run some cleanup passes to get easy-to-read outputs.
|
||||||
|
pm := llvm.NewPassManager()
|
||||||
|
defer pm.Dispose()
|
||||||
|
pm.AddGlobalOptimizerPass()
|
||||||
|
pm.AddDeadStoreEliminationPass()
|
||||||
|
pm.Run(mod)
|
||||||
|
|
||||||
|
// Read the expected output IR.
|
||||||
|
out, err := ioutil.ReadFile(pathPrefix + ".out.ll")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not read output file %s: %v", pathPrefix+".out.ll", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See whether the transform output matches with the expected output IR.
|
||||||
|
expected := string(out)
|
||||||
|
actual := mod.String()
|
||||||
|
if !fuzzyEqualIR(expected, actual) {
|
||||||
|
t.Logf("output does not match expected output:\n%s", actual)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly
|
||||||
|
// equal. That means, only relevant lines are compared (excluding comments
|
||||||
|
// etc.).
|
||||||
|
func fuzzyEqualIR(s1, s2 string) bool {
|
||||||
|
lines1 := filterIrrelevantIRLines(strings.Split(s1, "\n"))
|
||||||
|
lines2 := filterIrrelevantIRLines(strings.Split(s2, "\n"))
|
||||||
|
if len(lines1) != len(lines2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, line := range lines1 {
|
||||||
|
if line != lines2[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// filterIrrelevantIRLines removes lines from the input slice of strings that
|
||||||
|
// are not relevant in comparing IR. For example, empty lines and comments are
|
||||||
|
// stripped out.
|
||||||
|
func filterIrrelevantIRLines(lines []string) []string {
|
||||||
|
var out []string
|
||||||
|
for _, line := range lines {
|
||||||
|
if line == "" || line[0] == ';' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(line, "source_filename = ") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, line)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
42
interp/testdata/basic.ll
предоставленный
Обычный файл
42
interp/testdata/basic.ll
предоставленный
Обычный файл
|
@ -0,0 +1,42 @@
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
@main.v1 = internal global i64 0
|
||||||
|
|
||||||
|
declare void @runtime.printint64(i64) unnamed_addr
|
||||||
|
|
||||||
|
declare void @runtime.printnl() unnamed_addr
|
||||||
|
|
||||||
|
define void @runtime.initAll() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @runtime.init()
|
||||||
|
call void @main.init()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
%0 = load i64, i64* @main.v1
|
||||||
|
call void @runtime.printint64(i64 %0)
|
||||||
|
call void @runtime.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @runtime.init() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @main.init() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
store i64 3, i64* @main.v1
|
||||||
|
call void @"main.init#1"()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal void @"main.init#1"() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @runtime.printint64(i64 5)
|
||||||
|
call void @runtime.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
20
interp/testdata/basic.out.ll
предоставленный
Обычный файл
20
interp/testdata/basic.out.ll
предоставленный
Обычный файл
|
@ -0,0 +1,20 @@
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64--linux"
|
||||||
|
|
||||||
|
declare void @runtime.printint64(i64) unnamed_addr
|
||||||
|
|
||||||
|
declare void @runtime.printnl() unnamed_addr
|
||||||
|
|
||||||
|
define void @runtime.initAll() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @runtime.printint64(i64 5)
|
||||||
|
call void @runtime.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @main() unnamed_addr {
|
||||||
|
entry:
|
||||||
|
call void @runtime.printint64(i64 3)
|
||||||
|
call void @runtime.printnl()
|
||||||
|
ret void
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче