diff options
Diffstat (limited to 'transform')
-rw-r--r-- | transform/testdata/allocs.out.ll | 6 | ||||
-rw-r--r-- | transform/testdata/coroutines.out.ll | 21 | ||||
-rw-r--r-- | transform/testdata/func-lowering.out.ll | 35 | ||||
-rw-r--r-- | transform/testdata/interface.out.ll | 20 | ||||
-rw-r--r-- | transform/transform_test.go | 35 |
5 files changed, 73 insertions, 44 deletions
diff --git a/transform/testdata/allocs.out.ll b/transform/testdata/allocs.out.ll index e788beeba..eacf62b24 100644 --- a/transform/testdata/allocs.out.ll +++ b/transform/testdata/allocs.out.ll @@ -54,13 +54,15 @@ define void @testNonEscapingLoop() { entry: %stackalloc.alloca = alloca [1 x i32] br label %loop -loop: + +loop: ; preds = %loop, %entry store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca %stackalloc = bitcast [1 x i32]* %stackalloc.alloca to i32* %0 = call i32* @noescapeIntPtr(i32* %stackalloc) %1 = icmp eq i32* null, %0 br i1 %1, label %loop, label %end -end: + +end: ; preds = %loop ret void } diff --git a/transform/testdata/coroutines.out.ll b/transform/testdata/coroutines.out.ll index ec03650bc..b46a414f0 100644 --- a/transform/testdata/coroutines.out.ll +++ b/transform/testdata/coroutines.out.ll @@ -5,11 +5,13 @@ target triple = "armv7m-none-eabi" %"internal/task.state" = type { i8* } declare void @"internal/task.start"(i32, i8*, i8*, i8*) + declare void @"internal/task.Pause"(i8*, i8*) declare void @runtime.scheduler(i8*, i8*) declare i8* @runtime.alloc(i32, i8*, i8*) + declare void @runtime.free(i8*, i8*, i8*) declare %"internal/task.Task"* @"internal/task.Current"(i8*, i8*) @@ -17,9 +19,11 @@ declare %"internal/task.Task"* @"internal/task.Current"(i8*, i8*) declare i8* @"(*internal/task.Task).setState"(%"internal/task.Task"*, i8*, i8*, i8*) declare void @"(*internal/task.Task).setReturnPtr"(%"internal/task.Task"*, i8*, i8*, i8*) + declare i8* @"(*internal/task.Task).getReturnPtr"(%"internal/task.Task"*, i8*, i8*) declare void @"(*internal/task.Task).returnTo"(%"internal/task.Task"*, i8*, i8*, i8*) + declare void @"(*internal/task.Task).returnCurrent"(%"internal/task.Task"*, i8*, i8*) declare %"internal/task.Task"* @"internal/task.createTask"(i8*, i8*) @@ -27,6 +31,7 @@ declare %"internal/task.Task"* @"internal/task.createTask"(i8*, i8*) declare void @callMain(i8*, i8*) declare void @enqueueTimer(%"internal/task.Task"*, i64, i8*, i8*) + define void @sleep(i64, i8*, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* @@ -159,15 +164,31 @@ entry: ret void } +; Function Attrs: argmemonly nounwind readonly declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #0 + +; Function Attrs: nounwind readnone declare i32 @llvm.coro.size.i32() #1 + +; Function Attrs: nounwind declare i8* @llvm.coro.begin(token, i8* writeonly) #2 + +; Function Attrs: nounwind declare i8 @llvm.coro.suspend(token, i1) #2 + +; Function Attrs: nounwind declare i1 @llvm.coro.end(i8*, i1) #2 + +; Function Attrs: argmemonly nounwind readonly declare i8* @llvm.coro.free(token, i8* nocapture readonly) #0 + +; Function Attrs: nounwind declare token @llvm.coro.save(i8*) #2 +; Function Attrs: argmemonly nounwind declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #3 + +; Function Attrs: argmemonly nounwind declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #3 attributes #0 = { argmemonly nounwind readonly } diff --git a/transform/testdata/func-lowering.out.ll b/transform/testdata/func-lowering.out.ll index 97621730b..747d6e6e7 100644 --- a/transform/testdata/func-lowering.out.ll +++ b/transform/testdata/func-lowering.out.ll @@ -29,9 +29,6 @@ declare void @func1Uint8(i8, i8*, i8*) declare void @func2Uint8(i8, i8*, i8*) -; Call a function of which only one function with this signature is used as a -; function value. This means that lowering it to IR is trivial: simply check -; whether the func value is nil, and if not, call that one function directly. define void @runFunc1(i8*, i32, i8, i8* %context, i8* %parentHandle) { entry: %3 = icmp eq i32 %1, 0 @@ -39,53 +36,49 @@ entry: %5 = icmp eq void (i8, i8*, i8*)* %4, null br i1 %5, label %fpcall.nil, label %fpcall.next -fpcall.nil: +fpcall.nil: ; preds = %entry call void @runtime.nilPanic(i8* undef, i8* null) unreachable -fpcall.next: +fpcall.next: ; preds = %entry call void %4(i8 %2, i8* %0, i8* undef) ret void } -; There are two functions with this signature used in a func value. That means -; that we'll have to check at runtime which of the two it is (or whether the -; func value is nil). This call will thus be lowered to a switch statement. define void @runFunc2(i8*, i32, i8, i8* %context, i8* %parentHandle) { entry: br i1 false, label %fpcall.nil, label %fpcall.next -fpcall.nil: +fpcall.nil: ; preds = %entry call void @runtime.nilPanic(i8* undef, i8* null) unreachable -fpcall.next: +fpcall.next: ; preds = %entry switch i32 %1, label %func.default [ i32 0, label %func.nil i32 1, label %func.call1 i32 2, label %func.call2 ] -func.nil: +func.nil: ; preds = %fpcall.next call void @runtime.nilPanic(i8* undef, i8* null) unreachable -func.call1: +func.call1: ; preds = %fpcall.next call void @func1Uint8(i8 %2, i8* %0, i8* undef) br label %func.next -func.call2: +func.call2: ; preds = %fpcall.next call void @func2Uint8(i8 %2, i8* %0, i8* undef) br label %func.next -func.next: +func.next: ; preds = %func.call2, %func.call1 ret void -func.default: +func.default: ; preds = %fpcall.next unreachable } -; Special case for runtime.makeGoroutine. define void @sleepFuncValue(i8*, i32, i8* nocapture readnone %context, i8* nocapture readnone %parentHandle) { entry: switch i32 %1, label %func.default [ @@ -94,21 +87,21 @@ entry: i32 2, label %func.call2 ] -func.nil: +func.nil: ; preds = %entry call void @runtime.nilPanic(i8* undef, i8* null) unreachable -func.call1: +func.call1: ; preds = %entry call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$1" to i32), i8* null, i8* undef, i8* null) br label %func.next -func.call2: +func.call2: ; preds = %entry call void @"internal/task.start"(i32 ptrtoint (void (i32, i8*, i8*)* @"main$2" to i32), i8* null, i8* undef, i8* null) br label %func.next -func.next: +func.next: ; preds = %func.call2, %func.call1 ret void -func.default: +func.default: ; preds = %entry unreachable } diff --git a/transform/testdata/interface.out.ll b/transform/testdata/interface.out.ll index 25f47d0c8..9ae8b4886 100644 --- a/transform/testdata/interface.out.ll +++ b/transform/testdata/interface.out.ll @@ -36,32 +36,32 @@ define void @printInterface(i32 %typecode, i8* %value) { %typeassert.ok1 = call i1 @"Unmatched$typeassert"(i32 %typecode) br i1 %typeassert.ok1, label %typeswitch.Unmatched, label %typeswitch.notUnmatched -typeswitch.Unmatched: +typeswitch.Unmatched: ; preds = %0 %unmatched = ptrtoint i8* %value to i32 call void @runtime.printptr(i32 %unmatched) call void @runtime.printnl() ret void -typeswitch.notUnmatched: +typeswitch.notUnmatched: ; preds = %0 %typeassert.ok = call i1 @"Doubler$typeassert"(i32 %typecode) br i1 %typeassert.ok, label %typeswitch.Doubler, label %typeswitch.notDoubler -typeswitch.Doubler: +typeswitch.Doubler: ; preds = %typeswitch.notUnmatched %doubler.result = call i32 @"(Number).Double$invoke"(i8* %value, i8* null) call void @runtime.printint32(i32 %doubler.result) ret void -typeswitch.notDoubler: +typeswitch.notDoubler: ; preds = %typeswitch.notUnmatched %typeassert.ok2 = icmp eq i32 16, %typecode br i1 %typeassert.ok2, label %typeswitch.byte, label %typeswitch.notByte -typeswitch.byte: +typeswitch.byte: ; preds = %typeswitch.notDoubler %byte = ptrtoint i8* %value to i8 call void @runtime.printuint8(i8 %byte) call void @runtime.printnl() ret void -typeswitch.notByte: +typeswitch.notByte: ; preds = %typeswitch.notDoubler ret void } @@ -82,10 +82,10 @@ entry: i32 68, label %then ] -then: +then: ; preds = %entry ret i1 true -else: +else: ; preds = %entry ret i1 false } @@ -94,9 +94,9 @@ entry: switch i32 %actualType, label %else [ ] -then: +then: ; No predecessors! ret i1 true -else: +else: ; preds = %entry ret i1 false } diff --git a/transform/transform_test.go b/transform/transform_test.go index d0f125692..3905293c0 100644 --- a/transform/transform_test.go +++ b/transform/transform_test.go @@ -3,6 +3,7 @@ package transform // This file defines some helper functions for testing transforms. import ( + "flag" "io/ioutil" "os" "strings" @@ -11,6 +12,8 @@ import ( "tinygo.org/x/go-llvm" ) +var update = flag.Bool("update", false, "update transform package tests") + // testTransform runs a transformation pass on an input file (pathPrefix+".ll") // and checks whether it matches the expected output (pathPrefix+".out.ll"). The // output is compared with a fuzzy match that ignores some irrelevant lines such @@ -31,18 +34,28 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu // Perform the transform. transform(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) + // Get the output from the test and filter some irrelevant lines. actual := mod.String() - if !fuzzyEqualIR(expected, actual) { - t.Logf("output does not match expected output:\n%s", actual) - t.Fail() + actual = actual[strings.Index(actual, "\ntarget datalayout = ")+1:] + + if *update { + err := ioutil.WriteFile(pathPrefix+".out.ll", []byte(actual), 0666) + if err != nil { + t.Error("failed to write out new output:", err) + } + } else { + // 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) + if !fuzzyEqualIR(expected, actual) { + t.Logf("output does not match expected output:\n%s", actual) + t.Fail() + } } } |