[K/N] FileCheck-based tests

Introduce a simple infrastructure for testing produced bitcode with
FileCheck LLVM utility.

^KT-48925
This commit is contained in:
Sergey Bogolepov
2021-09-24 17:24:19 +07:00
committed by Space
parent b692705092
commit b9bb56d9c6
6 changed files with 223 additions and 0 deletions
@@ -144,6 +144,8 @@ allprojects {
// backent.native/tests/coverage
ext.testOutputCoverage = rootProject.file("$testOutputRoot/coverage")
ext.testOutputFileCheck = rootProject.file("$testOutputRoot/filecheck")
}
testOutputExternal.mkdirs()
testOutputStdlib.mkdirs()
@@ -211,6 +213,7 @@ task sanity {
// Add regular gradle test tasks
dependsOn(tasksOf(Test))
dependsOn(tasksOf(CoverageTest))
dependsOn(tasksOf(FileCheckTest))
dependsOn(":kotlin-native:Interop:Indexer:check")
}
@@ -5811,6 +5814,53 @@ pluginTest("runtime_basic_init", "nopPlugin") {
flags = ["-tr"]
}
Task fileCheckTest(String name, Closure<FileCheckTest> configureClosure) {
return project.tasks.create(name, FileCheckTest) { task ->
task.configure(configureClosure)
task.llvmIr = project.file("$testOutputFileCheck/$name/out.ll")
if (task.enabled) {
konanArtifacts {
// We could use `bitcode` here to make things faster. But:
// 1. `bitcode` has no other usages.
// 2. Unification should help porting to the new test infra.
// 3. Compiler might behave differently when outputting bitcode instead of object files.
program(name, targets: [ target ]) {
srcFiles task.annotatedSource
baseDir "$testOutputFileCheck/$name"
extraOpts project.globalTestArgs
extraOpts "-Xtemporary-files-dir=$testOutputFileCheck/$name", "-Xsave-llvm-ir"
}
UtilsKt.dependsOnKonanBuildingTask(task, name, target)
}
}
}
}
fileCheckTest("filecheck_smoke0") {
annotatedSource = project.file('filecheck/smoke0.kt')
}
fileCheckTest("filecheck_replace_invoke_with_call") {
annotatedSource = project.file('filecheck/replace_invoke_with_call.kt')
}
fileCheckTest("filecheck_intrinsics") {
annotatedSource = project.file('filecheck/intrinsics.kt')
}
fileCheckTest("filecheck_escape_analysis_enabled") {
annotatedSource = project.file('filecheck/escape_analysis.kt')
enabled = project.globalTestArgs.contains('-opt')
checkPrefix = "CHECK-OPT"
}
fileCheckTest("filecheck_escape_analysis_disabled") {
annotatedSource = project.file('filecheck/escape_analysis.kt')
enabled = project.globalTestArgs.contains('-g')
checkPrefix = "CHECK-DEBUG"
}
dependencies {
nopPluginApi project(kotlinCompilerModule)
nopPluginApi project(":native:kotlin-native-utils")
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
class A(val x: Int)
// CHECK-LABEL: "kfun:#main(){}"
fun main() {
// CHECK-DEBUG: call %struct.ObjHeader* @AllocInstance
// CHECK-OPT: alloca %"kclassbody:A#internal"
val a = A(5)
println(a.x)
// CHECK-LABEL: epilogue
}
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// CHECK-LABEL: "kfun:#and(kotlin.Int;kotlin.Int){}kotlin.Int"
fun and(a: Int, b: Int): Int {
// CHECK: and {{.*}}, {{.*}}
return a and b
// CHECK-LABEL: epilogue
}
// CHECK-LABEL: "kfun:#ieee754(kotlin.Float;kotlin.Float){}kotlin.Boolean"
fun ieee754(a: Float, b: Float): Boolean {
// CHECK: fcmp oeq float {{.*}}, {{.*}}
return a == b
// CHECK-LABEL: epilogue
}
// CHECK-LABEL: "kfun:#main(){}"
fun main() {
val x = and(1, 2)
val y = ieee754(0.0f, 1.0f)
// CHECK-LABEL: epilogue
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun flameThrower() {
throw Throwable("🔥")
}
// CHECK-LABEL: "kfun:#f1(){}"
fun f1() {
// CHECK: call void @"kfun:#flameThrower(){}"()
flameThrower()
// CHECK-LABEL: epilogue
}
// CHECK-LABEL: "kfun:#f2(){}"
fun f2() {
try {
// CHECK: invoke void @"kfun:#flameThrower(){}"()
flameThrower()
} catch (t: Throwable) {}
// CHECK-LABEL: epilogue
}
// CHECK-LABEL: "kfun:#main(){}"
fun main() {
f1()
f2()
// CHECK-LABEL: epilogue
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// CHECK-LABEL: "kfun:#id(kotlin.Any?){}kotlin.Any?"
fun id(a: Any?): Any? {
return a
// CHECK-LABEL: epilogue
}
// CHECK-LABEL: "kfun:#main(){}"
fun main() {
// CHECK: invoke %struct.ObjHeader* @"kfun:#id(kotlin.Any?){}kotlin.Any?"
val x = id("Hello")
// CHECK: invoke void @"kfun:kotlin.io#println(kotlin.Any?){}"(%struct.ObjHeader* {{.*}})
println(x)
// CHECK-LABEL: epilogue
}