diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index 186bc6d85b4..c413fb6e47f 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -12,10 +12,12 @@ abstract class KonanTest extends DefaultTask { def runtimeProject = project.project(":runtime") def llvmLlc = llvmTool("llc") def runtimeBc = new File("${runtimeProject.buildDir.canonicalPath}/runtime.bc") + def launcherBc = new File("${runtimeProject.buildDir.canonicalPath}/launcher.bc") def stdlibKtBc = new File("${runtimeProject.buildDir.canonicalPath}/stdlib.kt.bc") def mainC = 'main.c' String goldValue = null String testData = null + List arguments = null public KonanTest(){ dependsOn([project.project(":runtime").tasks['build'], @@ -59,6 +61,9 @@ abstract class KonanTest extends DefaultTask { def out = null project.exec { commandLine "${exe.absolutePath}" + if (arguments != null) { + args arguments + } if (testData != null) { standardInput = new ByteArrayInputStream(testData.bytes) } @@ -131,8 +136,8 @@ class UnitKonanTest extends KonanTest { 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 + commandLine "clang++", launcherBc.absolutePath, runtimeS.absolutePath, stdlibKtBc.absolutePath, sourceS.absolutePath, + "-o", exe.absolutePath, linkDl(), linkM(), rdynamic(), '-xc' } } } @@ -599,3 +604,10 @@ task range0(type: RunKonanTest) { goldValue = "123\nabcd\n" source = "runtime/collections/range0.kt" } + +task args0(type: RunKonanTest) { + arguments = ["AAA", "BB", "C"] + goldValue = "AAA\nBB\nC\n" + source = "runtime/basic/args0.kt" +} + diff --git a/backend.native/tests/main.c b/backend.native/tests/main.c index f12ebf38b83..ba6c5429eb1 100644 --- a/backend.native/tests/main.c +++ b/backend.native/tests/main.c @@ -4,10 +4,6 @@ #include #include #include -/** - * > llc-mp-3.8 b.out -o b.S - * > /opt/local/libexec/llvm-3.8/bin/clang main.c b.S -o sum-test - */ extern int run_test(); @@ -24,13 +20,6 @@ void * resolve_symbol(char *name) { } int -kotlinNativeMain() { -#ifdef RUN_TEST - void (*main)(void *) = resolve_symbol("kfun:main(Array)"); - main((void *)0); - return 0; -#else +main() { exit(run_test()); -#endif } - diff --git a/backend.native/tests/runtime/basic/args0.kt b/backend.native/tests/runtime/basic/args0.kt new file mode 100644 index 00000000000..29eb6a6baa1 --- /dev/null +++ b/backend.native/tests/runtime/basic/args0.kt @@ -0,0 +1,5 @@ +fun main(args : Array) { + for (s in args) { + println(s) + } +} diff --git a/runtime/build.gradle b/runtime/build.gradle index 2ff0e26d2d7..b0f42ba7b57 100644 --- a/runtime/build.gradle +++ b/runtime/build.gradle @@ -8,10 +8,18 @@ task build(type: CompileCppToBitcode) { srcRoot file('src/main') dependsOn ':common:compileHash' + dependsOn 'launcher' compilerArgs '-I' + project.file('../common/src/hash/headers') // TODO: copy-pasted from 'common' linkerArgs project.file('../common/build/hash.bc').path } +task launcher(type: CompileCppToBitcode) { + name 'launcher' + srcRoot file('src/launcher') + compilerArgs '-I' + project.file('../common/src/hash/headers') // TODO: copy-pasted from 'common' + compilerArgs '-I' + project.file('src/main/cpp') +} + task clean << { delete buildDir } diff --git a/runtime/src/launcher/cpp/launcher.cpp b/runtime/src/launcher/cpp/launcher.cpp new file mode 100644 index 00000000000..958a33ebe5a --- /dev/null +++ b/runtime/src/launcher/cpp/launcher.cpp @@ -0,0 +1,37 @@ +#include +#include "Memory.h" +#include "Natives.h" +#include "Types.h" + +extern "C" ArrayHeader* konanArrayInit(ArrayHeader*, int) + asm("_kfun:kotlin.Array.(Int)"); + +extern "C" const TypeInfo konanArrayType + asm("_ktype:kotlin.Array"); + +ArrayHeader* setupArgs(int argc, char** argv) { + + // The count is one less, because we skip argv[0] which is the binary name. + ArrayHeader* array = AllocArrayInstance(&konanArrayType, SCOPE_GLOBAL, argc-1); + ArrayHeader* args = konanArrayInit(array, argc-1); + + for (int i = 0; i < argc-1; i++) { + Kotlin_Array_set(args, i, (ArrayHeader*) makeString( argv[i+1] )); + } + + return args; +} + +extern "C" void konanMain(void*) asm("_kfun:main(Array)"); + +int main(int argc, char** argv) { + + InitMemory(); + + ArrayHeader* args = setupArgs(argc, argv); + konanMain(args); + + // Yes, we have to follow Java convention and return zero. + return 0; +} + diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index baae7e3ba37..7bd969785d3 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -180,4 +180,15 @@ KString Kotlin_String_subSequence(KString thiz, KInt startIndex, KInt endIndex) return result; } +KString makeString(const char* cstring) { + uint32_t length = strlen(cstring); + ArrayHeader* result = ArrayContainer( + theStringTypeInfo, length).GetPlace(); + memcpy( + ByteArrayAddressOfElementAt(result, 0), + cstring, + length); + return result; +} + } // extern "C" diff --git a/runtime/src/main/cpp/Natives.h b/runtime/src/main/cpp/Natives.h index a707eb7ef39..aa3b7e7f2eb 100644 --- a/runtime/src/main/cpp/Natives.h +++ b/runtime/src/main/cpp/Natives.h @@ -39,6 +39,8 @@ extern "C" { KString TheEmptyString(); +KString makeString(const char* cstring); + // Any.kt KBoolean Kotlin_Any_equals(KConstRef thiz, KConstRef other); KInt Kotlin_Any_hashCode(KConstRef thiz); diff --git a/runtime/src/main/cpp/ToString.cpp b/runtime/src/main/cpp/ToString.cpp index d73279e2878..806c89c7903 100644 --- a/runtime/src/main/cpp/ToString.cpp +++ b/runtime/src/main/cpp/ToString.cpp @@ -7,21 +7,6 @@ #include "Natives.h" #include "Types.h" -namespace { - -KString makeString(const char* cstring) { - uint32_t length = strlen(cstring); - ArrayHeader* result = ArrayContainer( - theStringTypeInfo, length).GetPlace(); - memcpy( - ByteArrayAddressOfElementAt(result, 0), - cstring, - length); - return result; -} - -} // namespace - extern "C" { KString Kotlin_Byte_toString(KByte value) { diff --git a/runtime/src/main/cpp/launcher.cpp b/runtime/src/main/cpp/launcher.cpp deleted file mode 100644 index e84c2ef645e..00000000000 --- a/runtime/src/main/cpp/launcher.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "Memory.h" - -extern "C" void kotlinNativeMain(); - -int main() { - InitMemory(); - kotlinNativeMain(); - return 0; -}