transform: allow updating tests with -update flag
This should make it much easier to update existing tests.
Этот коммит содержится в:
		
							родитель
							
								
									5308e8903e
								
							
						
					
					
						коммит
						584e94ce2f
					
				
					 5 изменённых файлов: 73 добавлений и 44 удалений
				
			
		
							
								
								
									
										6
									
								
								transform/testdata/allocs.out.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										6
									
								
								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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										21
									
								
								transform/testdata/coroutines.out.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										21
									
								
								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 }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								transform/testdata/func-lowering.out.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										35
									
								
								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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								transform/testdata/interface.out.ll
									
										
									
									
										предоставленный
									
									
								
							
							
						
						
									
										20
									
								
								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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче