|
|
@ -70,52 +70,11 @@ func TestCompiler(t *testing.T) { |
|
|
|
options := &compileopts.Options{ |
|
|
|
Target: targetString, |
|
|
|
} |
|
|
|
target, err := compileopts.LoadTarget(options) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to load target:", err) |
|
|
|
} |
|
|
|
if tc.scheduler != "" { |
|
|
|
options.Scheduler = tc.scheduler |
|
|
|
} |
|
|
|
config := &compileopts.Config{ |
|
|
|
Options: options, |
|
|
|
Target: target, |
|
|
|
} |
|
|
|
compilerConfig := &Config{ |
|
|
|
Triple: config.Triple(), |
|
|
|
Features: config.Features(), |
|
|
|
ABI: config.ABI(), |
|
|
|
GOOS: config.GOOS(), |
|
|
|
GOARCH: config.GOARCH(), |
|
|
|
CodeModel: config.CodeModel(), |
|
|
|
RelocationModel: config.RelocationModel(), |
|
|
|
Scheduler: config.Scheduler(), |
|
|
|
AutomaticStackSize: config.AutomaticStackSize(), |
|
|
|
DefaultStackSize: config.StackSize(), |
|
|
|
NeedsStackObjects: config.NeedsStackObjects(), |
|
|
|
} |
|
|
|
machine, err := NewTargetMachine(compilerConfig) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to create target machine:", err) |
|
|
|
} |
|
|
|
defer machine.Dispose() |
|
|
|
|
|
|
|
// Load entire program AST into memory.
|
|
|
|
lprogram, err := loader.Load(config, "./testdata/"+tc.file, config.ClangHeaders, types.Config{ |
|
|
|
Sizes: Sizes(machine), |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to create target machine:", err) |
|
|
|
} |
|
|
|
err = lprogram.Parse() |
|
|
|
if err != nil { |
|
|
|
t.Fatalf("could not parse test case %s: %s", tc.file, err) |
|
|
|
} |
|
|
|
|
|
|
|
// Compile AST to IR.
|
|
|
|
program := lprogram.LoadSSA() |
|
|
|
pkg := lprogram.MainPkg() |
|
|
|
mod, errs := CompilePackage(tc.file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false) |
|
|
|
mod, errs := testCompilePackage(t, options, tc.file) |
|
|
|
if errs != nil { |
|
|
|
for _, err := range errs { |
|
|
|
t.Error(err) |
|
|
@ -123,7 +82,7 @@ func TestCompiler(t *testing.T) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
err = llvm.VerifyModule(mod, llvm.PrintMessageAction) |
|
|
|
err := llvm.VerifyModule(mod, llvm.PrintMessageAction) |
|
|
|
if err != nil { |
|
|
|
t.Error(err) |
|
|
|
} |
|
|
@ -216,3 +175,86 @@ func filterIrrelevantIRLines(lines []string) []string { |
|
|
|
} |
|
|
|
return out |
|
|
|
} |
|
|
|
|
|
|
|
func TestCompilerErrors(t *testing.T) { |
|
|
|
t.Parallel() |
|
|
|
|
|
|
|
// Read expected errors from the test file.
|
|
|
|
var expectedErrors []string |
|
|
|
errorsFile, err := os.ReadFile("testdata/errors.go") |
|
|
|
if err != nil { |
|
|
|
t.Error(err) |
|
|
|
} |
|
|
|
errorsFileString := strings.ReplaceAll(string(errorsFile), "\r\n", "\n") |
|
|
|
for _, line := range strings.Split(errorsFileString, "\n") { |
|
|
|
if strings.HasPrefix(line, "// ERROR: ") { |
|
|
|
expectedErrors = append(expectedErrors, strings.TrimPrefix(line, "// ERROR: ")) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Compile the Go file with errors.
|
|
|
|
options := &compileopts.Options{ |
|
|
|
Target: "wasm", |
|
|
|
} |
|
|
|
_, errs := testCompilePackage(t, options, "errors.go") |
|
|
|
|
|
|
|
// Check whether the actual errors match the expected errors.
|
|
|
|
expectedErrorsIdx := 0 |
|
|
|
for _, err := range errs { |
|
|
|
err := err.(types.Error) |
|
|
|
position := err.Fset.Position(err.Pos) |
|
|
|
position.Filename = "errors.go" // don't use a full path
|
|
|
|
if expectedErrorsIdx >= len(expectedErrors) || expectedErrors[expectedErrorsIdx] != err.Msg { |
|
|
|
t.Errorf("unexpected compiler error: %s: %s", position.String(), err.Msg) |
|
|
|
continue |
|
|
|
} |
|
|
|
expectedErrorsIdx++ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Build a package given a number of compiler options and a file.
|
|
|
|
func testCompilePackage(t *testing.T, options *compileopts.Options, file string) (llvm.Module, []error) { |
|
|
|
target, err := compileopts.LoadTarget(options) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to load target:", err) |
|
|
|
} |
|
|
|
config := &compileopts.Config{ |
|
|
|
Options: options, |
|
|
|
Target: target, |
|
|
|
} |
|
|
|
compilerConfig := &Config{ |
|
|
|
Triple: config.Triple(), |
|
|
|
Features: config.Features(), |
|
|
|
ABI: config.ABI(), |
|
|
|
GOOS: config.GOOS(), |
|
|
|
GOARCH: config.GOARCH(), |
|
|
|
CodeModel: config.CodeModel(), |
|
|
|
RelocationModel: config.RelocationModel(), |
|
|
|
Scheduler: config.Scheduler(), |
|
|
|
AutomaticStackSize: config.AutomaticStackSize(), |
|
|
|
DefaultStackSize: config.StackSize(), |
|
|
|
NeedsStackObjects: config.NeedsStackObjects(), |
|
|
|
} |
|
|
|
machine, err := NewTargetMachine(compilerConfig) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to create target machine:", err) |
|
|
|
} |
|
|
|
defer machine.Dispose() |
|
|
|
|
|
|
|
// Load entire program AST into memory.
|
|
|
|
lprogram, err := loader.Load(config, "./testdata/"+file, config.ClangHeaders, types.Config{ |
|
|
|
Sizes: Sizes(machine), |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
t.Fatal("failed to create target machine:", err) |
|
|
|
} |
|
|
|
err = lprogram.Parse() |
|
|
|
if err != nil { |
|
|
|
t.Fatalf("could not parse test case %s: %s", file, err) |
|
|
|
} |
|
|
|
|
|
|
|
// Compile AST to IR.
|
|
|
|
program := lprogram.LoadSSA() |
|
|
|
pkg := lprogram.MainPkg() |
|
|
|
return CompilePackage(file, pkg, program.Package(pkg.Pkg), machine, compilerConfig, false) |
|
|
|
} |
|
|
|