075562f46b
Implement throw and try-catch-finally in backend add corresponding tests
555 lines
14 KiB
Groovy
555 lines
14 KiB
Groovy
configurations {
|
|
cli_bc
|
|
}
|
|
|
|
dependencies {
|
|
cli_bc project(path: ':backend.native', configuration: 'cli_bc')
|
|
}
|
|
|
|
abstract class KonanTest extends DefaultTask {
|
|
protected String source
|
|
def backendNative = project.project(":backend.native")
|
|
def runtimeProject = project.project(":runtime")
|
|
def llvmLlc = llvmTool("llc")
|
|
def runtimeBc = new File("${runtimeProject.buildDir.canonicalPath}/runtime.bc")
|
|
def stdlibKtBc = new File("${runtimeProject.buildDir.canonicalPath}/stdlib.kt.bc")
|
|
def mainC = 'main.c'
|
|
String goldValue = null
|
|
String testData = null
|
|
|
|
public KonanTest(){
|
|
dependsOn([project.project(":runtime").tasks['build'],
|
|
project.parent.tasks['build'],
|
|
project.project(":backend.native").tasks['stdlib']])
|
|
}
|
|
|
|
|
|
|
|
abstract void compileTest(File sourceS, File runtimeS, File libraryPath, File out)
|
|
|
|
private File kt2bc(String ktSource) {
|
|
def sourceKt = project.file(ktSource)
|
|
def sourceBc = new File("${sourceKt.absolutePath}.bc")
|
|
println "${runtimeBc}"
|
|
|
|
project.javaexec {
|
|
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
|
|
classpath = project.configurations.cli_bc
|
|
jvmArgs "-ea"
|
|
args "-output", "${sourceBc.absolutePath}",
|
|
"-runtime", "${runtimeBc.absolutePath}",
|
|
"-library", "${stdlibKtBc.absolutePath}",
|
|
"${sourceKt.absolutePath}"
|
|
|
|
String libraryPath = "${project.llvmDir}/lib:${backendNative.buildDir.canonicalPath}/nativelibs"
|
|
environment 'LD_LIBRARY_PATH' : libraryPath
|
|
environment 'DYLD_LIBRARY_PATH' : libraryPath
|
|
}
|
|
return sourceBc
|
|
}
|
|
|
|
@TaskAction
|
|
void executeTest() {
|
|
def sourceS = bc2s(kt2bc(source))
|
|
def exe = new File(sourceS.absolutePath.replace(".kt.S", ".kt.exe"))
|
|
def libraryPath = new File("${runtimeProject.file('src/main/bc').absolutePath}")
|
|
compileTest(sourceS, bc2s(runtimeBc), stdlibKtBc, exe)
|
|
println "execution :${exe.absolutePath}"
|
|
|
|
def out = null
|
|
project.exec {
|
|
commandLine "${exe.absolutePath}"
|
|
if (testData != null) {
|
|
standardInput = new ByteArrayInputStream(testData.bytes)
|
|
}
|
|
if (goldValue != null) {
|
|
out = new ByteArrayOutputStream()
|
|
standardOutput = out
|
|
}
|
|
}
|
|
if (goldValue != null && goldValue != out.toString())
|
|
throw new RuntimeException("test failed")
|
|
}
|
|
|
|
private File bc2s(File bcFile) {
|
|
def outputFile = new File("${bcFile.absolutePath.replace(".bc",".S")}")
|
|
println "${bcFile.absolutePath} -> ${outputFile.absolutePath}"
|
|
println "tool: ${llvmLlc}"
|
|
project.exec {
|
|
commandLine "${llvmLlc}", "-o", "${outputFile.absolutePath}" , "${bcFile}"
|
|
}
|
|
return outputFile
|
|
}
|
|
|
|
private String llvmTool(String tool) {
|
|
return "${project.llvmDir}/bin/${tool}"
|
|
}
|
|
|
|
private linux() {
|
|
return project.isLinux()
|
|
}
|
|
|
|
// TODO: stop copy-pasting
|
|
protected String linkDl() {
|
|
if (linux()) {
|
|
return "-ldl"
|
|
}
|
|
else {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
protected String linkM() {
|
|
if (linux()) {
|
|
return "-lm"
|
|
}
|
|
else {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
protected String rdynamic() {
|
|
if (linux()) {
|
|
return "-rdynamic"
|
|
}
|
|
else {
|
|
return ""
|
|
}
|
|
}
|
|
}
|
|
|
|
class UnitKonanTest extends KonanTest {
|
|
void compileTest(File sourceS, File runtimeS, File stdlibKtBc, File exe) {
|
|
def testC = sourceS.absolutePath.replace(".kt.S", "-test.c")
|
|
project.execClang {
|
|
commandLine "clang++", runtimeS.absolutePath, stdlibKtBc.absolutePath, sourceS.absolutePath,
|
|
"-o", exe.absolutePath, linkDl(), linkM(), rdynamic(), '-xc', testC, mainC
|
|
}
|
|
}
|
|
}
|
|
|
|
class RunKonanTest extends KonanTest {
|
|
void compileTest(File sourceS, File runtimeS, File libraryPath, File exe) {
|
|
project.execClang {
|
|
commandLine "clang++", "-DRUN_TEST", runtimeS.absolutePath, stdlibKtBc.absolutePath, sourceS.absolutePath,
|
|
"-o", exe.absolutePath, linkDl(), linkM(), rdynamic(), '-xc', mainC
|
|
}
|
|
}
|
|
}
|
|
|
|
class LinkKonanTest extends KonanTest {
|
|
protected String lib
|
|
|
|
private File dir2bc(String ktSources) {
|
|
def sourcesKt = project.file(ktSources)
|
|
def libBc = new File("${sourcesKt.absolutePath}/libout.kt.bc")
|
|
def libPath = "${libBc.absolutePath}"
|
|
|
|
project.javaexec {
|
|
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
|
|
classpath = project.configurations.cli_bc
|
|
jvmArgs "-ea"
|
|
args "-output", "${libPath}",
|
|
"-runtime", "${runtimeBc.absolutePath}",
|
|
sourcesKt
|
|
|
|
String libraryPath = "${project.llvmDir}/lib:${backendNative.buildDir.canonicalPath}/nativelibs"
|
|
environment 'LD_LIBRARY_PATH' : libraryPath
|
|
environment 'DYLD_LIBRARY_PATH' : libraryPath
|
|
|
|
}
|
|
return libBc
|
|
}
|
|
|
|
private File link(String ktSource, File libBc) {
|
|
def sourceKt = project.file(ktSource)
|
|
def outPath = "${sourceKt.absolutePath.replace('.kt', '.kt.bc')}"
|
|
def outBc = new File(outPath)
|
|
|
|
project.javaexec {
|
|
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
|
|
classpath = project.configurations.cli_bc
|
|
jvmArgs "-ea"
|
|
args "-output", outPath,
|
|
"-runtime", "${runtimeBc.absolutePath}",
|
|
"-library", "${libBc.absolutePath}",
|
|
"${sourceKt.absolutePath}"
|
|
|
|
String libraryPath = "${project.llvmDir}/lib:${backendNative.buildDir.canonicalPath}/nativelibs"
|
|
environment 'LD_LIBRARY_PATH' : libraryPath
|
|
environment 'DYLD_LIBRARY_PATH' : libraryPath
|
|
|
|
}
|
|
return outBc
|
|
}
|
|
|
|
void compileTest(File sourceS, File runtimeS, File stdlibKtBc, File exe) {
|
|
def testC = sourceS.absolutePath.replace(".kt.S", "-test.c")
|
|
project.execClang {
|
|
commandLine "clang++", runtimeS.absolutePath, stdlibKtBc.absolutePath, sourceS.absolutePath,
|
|
"-o", exe.absolutePath, linkDl(), rdynamic(), '-xc', testC, mainC
|
|
}
|
|
}
|
|
|
|
|
|
@TaskAction
|
|
void executeTest() {
|
|
def libBc = dir2bc(lib)
|
|
def outBc = link(source, libBc)
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
task run() {
|
|
dependsOn(tasks.withType(KonanTest))
|
|
}
|
|
|
|
task sum (type:UnitKonanTest) {
|
|
source = "codegen/function/sum.kt"
|
|
}
|
|
|
|
task method_call(type: UnitKonanTest) {
|
|
source = "codegen/object/method_call.kt"
|
|
}
|
|
|
|
task fields(type: UnitKonanTest) {
|
|
source = "codegen/object/fields.kt"
|
|
}
|
|
|
|
|
|
task fields1(type: UnitKonanTest) {
|
|
source = "codegen/object/fields1.kt"
|
|
}
|
|
|
|
task constructor(type: UnitKonanTest) {
|
|
source = "codegen/object/constructor.kt"
|
|
}
|
|
|
|
task objectInitialization(type: UnitKonanTest) {
|
|
source = "codegen/object/initialization.kt"
|
|
}
|
|
|
|
/* field initialization test
|
|
task objectBasic(type: UnitKonanTest) {
|
|
source = "$codegen/klass/basic.kt"
|
|
}
|
|
*/
|
|
|
|
task check_type(type: UnitKonanTest) {
|
|
source = "codegen/basics/check_type.kt"
|
|
}
|
|
|
|
task safe_cast(type: RunKonanTest) {
|
|
goldValue = "safe_cast_positive: true\n" +
|
|
"safe_cast_negative: true\n"
|
|
source = "codegen/basics/safe_cast.kt"
|
|
}
|
|
|
|
task aritmetic(type: UnitKonanTest) {
|
|
source = "codegen/function/arithmetic.kt"
|
|
}
|
|
|
|
task sum1(type: UnitKonanTest) {
|
|
source = "codegen/function/sum_foo_bar.kt"
|
|
|
|
}
|
|
|
|
task sum2(type: UnitKonanTest) {
|
|
source = "codegen/function/sum_imm.kt"
|
|
}
|
|
|
|
task sum_3const(type: UnitKonanTest) {
|
|
source = "codegen/function/sum_3const.kt"
|
|
}
|
|
|
|
task local_variable(type: UnitKonanTest) {
|
|
source = "codegen/basics/local_variable.kt"
|
|
}
|
|
|
|
|
|
task cast_simple(type: UnitKonanTest) {
|
|
source = "codegen/basics/cast_simple.kt"
|
|
}
|
|
|
|
task null_check(type: UnitKonanTest) {
|
|
source = "codegen/basics/null_check.kt"
|
|
}
|
|
|
|
task hello0(type: RunKonanTest) {
|
|
goldValue = "Hello, world!\n"
|
|
source = "runtime/basic/hello0.kt"
|
|
}
|
|
|
|
task hello1(type: RunKonanTest) {
|
|
goldValue = "Hello World"
|
|
testData = "Hello World"
|
|
source = "runtime/basic/hello1.kt"
|
|
}
|
|
|
|
task hello2(type: RunKonanTest) {
|
|
goldValue = "you entered 'Hello World'"
|
|
testData = "Hello World"
|
|
source = "runtime/basic/hello2.kt"
|
|
}
|
|
|
|
task hello3(type: RunKonanTest) {
|
|
goldValue = "239\ntrue\n3.14159\nA\n"
|
|
source = "runtime/basic/hello3.kt"
|
|
}
|
|
|
|
task hello4(type: RunKonanTest) {
|
|
goldValue = "Hello\nПока\n"
|
|
source = "runtime/basic/hello4.kt"
|
|
}
|
|
|
|
task tostring0(type: RunKonanTest) {
|
|
goldValue = "127\n-1\n239\nA\n1122334455\n112233445566778899\n3.14159\n1E+27\n1E-300\ntrue\nfalse\n"
|
|
source = "runtime/basic/tostring0.kt"
|
|
}
|
|
|
|
task tostring1(type: RunKonanTest) {
|
|
goldValue = "ello\n"
|
|
source = "runtime/basic/tostring1.kt"
|
|
}
|
|
|
|
task array0(type: RunKonanTest) {
|
|
goldValue = "5\n6\n7\n8\n9\n10\n11\n12\n13\n"
|
|
source = "runtime/basic/array0.kt"
|
|
}
|
|
|
|
task array1(type: RunKonanTest) {
|
|
goldValue = "4 2\n1-1\n69\n38\n"
|
|
source = "runtime/basic/array1.kt"
|
|
}
|
|
|
|
task if_else(type: UnitKonanTest) {
|
|
source = "codegen/branching/if_else.kt"
|
|
}
|
|
|
|
task when2(type: UnitKonanTest) {
|
|
source = "codegen/branching/when2.kt"
|
|
}
|
|
|
|
task when5(type: UnitKonanTest) {
|
|
source = "codegen/branching/when5.kt"
|
|
}
|
|
|
|
task when_through(type: UnitKonanTest) {
|
|
source = "codegen/branching/when_through.kt"
|
|
}
|
|
|
|
task advanced_when2(type: UnitKonanTest) {
|
|
source = "codegen/branching/advanced_when2.kt"
|
|
}
|
|
|
|
task advanced_when5(type: UnitKonanTest) {
|
|
source = "codegen/branching/advanced_when5.kt"
|
|
}
|
|
|
|
task bool_yes(type: UnitKonanTest) {
|
|
source = "codegen/function/boolean.kt"
|
|
}
|
|
|
|
task plus_eq(type: UnitKonanTest) {
|
|
source = "codegen/function/plus_eq.kt"
|
|
}
|
|
|
|
task minus_eq(type: UnitKonanTest) {
|
|
source = "codegen/function/minus_eq.kt"
|
|
}
|
|
|
|
task eqeq(type: UnitKonanTest) {
|
|
source = "codegen/function/eqeq.kt"
|
|
}
|
|
|
|
task cycle(type: UnitKonanTest) {
|
|
source = "codegen/cycles/cycle.kt"
|
|
}
|
|
|
|
task cycle_do(type: UnitKonanTest) {
|
|
source = "codegen/cycles/cycle_do.kt"
|
|
}
|
|
|
|
task abstract_super(type: UnitKonanTest) {
|
|
source = "datagen/rtti/abstract_super.kt"
|
|
}
|
|
|
|
task vtable1(type: UnitKonanTest) {
|
|
source = "datagen/rtti/vtable1.kt"
|
|
}
|
|
|
|
task strdedup1(type: RunKonanTest) {
|
|
goldValue = "true\ntrue\n"
|
|
source = "datagen/literals/strdedup1.kt"
|
|
}
|
|
|
|
task intrinsic(type: UnitKonanTest) {
|
|
source = "codegen/function/intrinsic.kt"
|
|
}
|
|
|
|
task link(type: LinkKonanTest) {
|
|
source = "link/src/bar.kt"
|
|
lib = "link/lib"
|
|
}
|
|
|
|
task for0(type: RunKonanTest) {
|
|
goldValue = "2\n3\n4\n"
|
|
source = "runtime/basic/for0.kt"
|
|
}
|
|
|
|
task throw0(type: RunKonanTest) {
|
|
goldValue = "Done\n"
|
|
source = "runtime/basic/throw0.kt"
|
|
}
|
|
|
|
task statements0(type: RunKonanTest) {
|
|
goldValue = "239\n238\n30\n29\n"
|
|
source = "runtime/basic/statements0.kt"
|
|
}
|
|
|
|
/*
|
|
task boxing0(type: RunKonanTest) {
|
|
goldValue = "17\n"
|
|
source = "runtime/basic/boxing0.kt"
|
|
}
|
|
*/
|
|
|
|
task interface0(type: RunKonanTest) {
|
|
goldValue = "PASSED\n"
|
|
source = "runtime/basic/interface0.kt"
|
|
}
|
|
|
|
task array_list1(type: RunKonanTest) {
|
|
goldValue = "OK\n"
|
|
source = "runtime/collections/array_list1.kt"
|
|
}
|
|
/*
|
|
task moderately_large_array(type: RunKonanTest) {
|
|
goldValue = "OK\n"
|
|
source = "runtime/collections/moderately_large_array.kt"
|
|
}
|
|
*/
|
|
|
|
task catch1(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Throwable\nDone\n"
|
|
source = "runtime/exceptions/catch1.kt"
|
|
}
|
|
|
|
task catch2(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Error\nDone\n"
|
|
source = "runtime/exceptions/catch2.kt"
|
|
}
|
|
|
|
task catch7(type: RunKonanTest) {
|
|
goldValue = "Error happens\n"
|
|
source = "runtime/exceptions/catch7.kt"
|
|
}
|
|
|
|
task catch3(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Throwable\nDone\n"
|
|
source = "codegen/try/catch3.kt"
|
|
}
|
|
|
|
task catch4(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Error\nDone\n"
|
|
source = "codegen/try/catch4.kt"
|
|
}
|
|
|
|
task catch5(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Error\nDone\n"
|
|
source = "codegen/try/catch5.kt"
|
|
}
|
|
|
|
task catch6(type: RunKonanTest) {
|
|
goldValue = "Before\nCaught Error\nDone\n"
|
|
source = "codegen/try/catch6.kt"
|
|
}
|
|
|
|
task catch8(type: RunKonanTest) {
|
|
goldValue = "Error happens\n"
|
|
source = "codegen/try/catch8.kt"
|
|
}
|
|
|
|
task finally1(type: RunKonanTest) {
|
|
goldValue = "Try\nFinally\nDone\n"
|
|
source = "codegen/try/finally1.kt"
|
|
}
|
|
|
|
task finally2(type: RunKonanTest) {
|
|
goldValue = "Try\nCaught Error\nFinally\nDone\n"
|
|
source = "codegen/try/finally2.kt"
|
|
}
|
|
|
|
task finally3(type: RunKonanTest) {
|
|
goldValue = "Try\nFinally\nCaught Error\nDone\n"
|
|
source = "codegen/try/finally3.kt"
|
|
}
|
|
|
|
task finally4(type: RunKonanTest) {
|
|
goldValue = "Try\nCatch\nFinally\nCaught Exception\nDone\n"
|
|
source = "codegen/try/finally4.kt"
|
|
}
|
|
|
|
task finally5(type: RunKonanTest) {
|
|
goldValue = "Done\nFinally\n0\n"
|
|
source = "codegen/try/finally5.kt"
|
|
}
|
|
|
|
task finally6(type: RunKonanTest) {
|
|
goldValue = "Done\nFinally\n1\n"
|
|
source = "codegen/try/finally6.kt"
|
|
}
|
|
|
|
task finally7(type: RunKonanTest) {
|
|
goldValue = "Done\nFinally\n1\n"
|
|
source = "codegen/try/finally7.kt"
|
|
}
|
|
|
|
task finally8(type: RunKonanTest) {
|
|
goldValue = "Finally 1\nFinally 2\n42\n"
|
|
source = "codegen/try/finally8.kt"
|
|
}
|
|
|
|
/*
|
|
TODO: enable after implementing break and continue
|
|
task finally9(type: RunKonanTest) {
|
|
goldValue = "Finally 1\nFinally 2\nAfter\n"
|
|
source = "codegen/try/finally9.kt"
|
|
}
|
|
*/
|
|
|
|
/*
|
|
TODO: enable after improving LLVM variable naming
|
|
task scope1(type: RunKonanTest) {
|
|
goldValue = "1\n"
|
|
source = "codegen/dataflow/scope1.kt"
|
|
}
|
|
*/
|
|
|
|
task try1(type: RunKonanTest) {
|
|
goldValue = "5\n"
|
|
source = "codegen/try/try1.kt"
|
|
}
|
|
|
|
task try2(type: RunKonanTest) {
|
|
goldValue = "6\n"
|
|
source = "codegen/try/try2.kt"
|
|
}
|
|
|
|
task try3(type: RunKonanTest) {
|
|
goldValue = "6\n"
|
|
source = "codegen/try/try3.kt"
|
|
}
|
|
|
|
task try4(type: RunKonanTest) {
|
|
goldValue = "Try\n5\n"
|
|
source = "codegen/try/try4.kt"
|
|
}
|
|
|
|
task unreachable1(type: RunKonanTest) {
|
|
goldValue = "1\n"
|
|
source = "codegen/controlflow/unreachable1.kt"
|
|
}
|