Initial .wasm file generation for the wasm32 target.

Some basic launcher.js and runtime.
This commit is contained in:
Alexander Gorshenev
2017-07-14 17:08:55 +03:00
committed by alexander-gorshenev
parent 9ec5b24832
commit b4660d03a1
21 changed files with 576 additions and 68 deletions
@@ -37,17 +37,17 @@ internal abstract class PlatformFlags(val properties: KonanProperties) {
val linkerKonanFlags = properties.linkerKonanFlags
val linkerDebugFlags = properties.linkerDebugFlags
val llvmDebugOptFlags = properties.llvmDebugOptFlags
val s2wasmFlags = properties.s2wasmFlags
val targetToolchain = properties.absoluteTargetToolchain
val targetSysRoot = properties.absoluteTargetSysRoot
val targetLibffi = properties.libffiDir ?.let { listOf("${properties.absoluteLibffiDir}/lib/libffi.a") } ?: emptyList()
open val useCompilerDriverAsLinker: Boolean get() = false // TODO: refactor.
abstract fun linkCommand(objectFiles: List<ObjectFile>,
abstract fun linkCommand(objectFiles: List<ObjectFile>,
executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String>
val targetLibffiDir = properties.absoluteLibffiDir
val targetLibffi = "$targetLibffiDir/lib/libffi.a"
val targetToolchain = properties.absoluteTargetToolchain
val targetSysRoot = properties.absoluteTargetSysRoot
open fun linkCommandSuffix(): List<String> = emptyList()
protected fun propertyTargetString(name: String)
@@ -178,19 +178,19 @@ internal open class WasmPlatform(distribution: Distribution)
override fun linkCommand(objectFiles: List<ObjectFile>, executable: ExecutableFile, optimize: Boolean, debug: Boolean): List<String> {
return mutableListOf(clang).apply{
throw Error("Implement me!")
}
//No link stage for WASM yet, just give '.wasm' as output.
return mutableListOf("/bin/cp", objectFiles.single(), executable)
}
}
internal class LinkStage(val context: Context) {
val config = context.config.configuration
val target = context.config.targetManager.target
private val distribution = context.config.distribution
private val platform = when (context.config.targetManager.target) {
private val platform = when (target) {
KonanTarget.LINUX, KonanTarget.RASPBERRYPI ->
LinuxBasedPlatform(distribution)
KonanTarget.MACBOOK, KonanTarget.IPHONE, KonanTarget.IPHONE_SIM ->
@@ -202,7 +202,7 @@ internal class LinkStage(val context: Context) {
KonanTarget.WASM32 ->
WasmPlatform(distribution)
else ->
error("Unexpected target platform: ${context.config.targetManager.target}")
error("Unexpected target platform: ${target}")
}
private val optimize = config.get(KonanConfigKeys.OPTIMIZATION) ?: false
@@ -216,9 +216,7 @@ internal class LinkStage(val context: Context) {
}
private fun llvmLto(files: List<BitcodeFile>): ObjectFile {
val tmpCombined = createTempFile("combined", ".o")
tmpCombined.deleteOnExit()
val combined = tmpCombined.absolutePath
val combined = temporary("combined", ".o")
val tool = distribution.llvmLto
val command = mutableListOf(tool, "-o", combined)
@@ -234,6 +232,41 @@ internal class LinkStage(val context: Context) {
return combined
}
private fun temporary(name: String, suffix: String): String {
val temporaryFile = createTempFile(name, suffix)
temporaryFile.deleteOnExit()
return temporaryFile.absolutePath
}
private fun targetTool(tool: String, vararg arg: String) {
val absoluteToolName = "${platform.targetToolchain}/bin/$tool"
runTool(absoluteToolName, *arg)
}
private fun hostLlvmTool(tool: String, args: List<String>) {
val absoluteToolName = "${distribution.llvmBin}/$tool"
val command = listOf(absoluteToolName) + args
runTool(*command.toTypedArray())
}
private fun bitcodeToWasm(bitcodeFiles: List<BitcodeFile>): String {
val combinedBc = temporary("combined", ".bc")
hostLlvmTool("llvm-link", bitcodeFiles + listOf("-o", combinedBc))
val combinedS = temporary("combined", ".s")
targetTool("llc", combinedBc, "-o", combinedS)
val s2wasmFlags = platform.s2wasmFlags.toTypedArray()
val combinedWast = temporary( "combined", ".wast")
targetTool("s2wasm", combinedS, "-o", combinedWast, *s2wasmFlags)
val combinedWasm = temporary( "combined", ".wasm")
val combinedSmap = temporary( "combined", ".smap")
targetTool("wasm-as", combinedWast, "-o", combinedWasm, "-g", "-s", combinedSmap)
return combinedWasm
}
private fun asLinkerArgs(args: List<String>): List<String> {
if (platform.useCompilerDriverAsLinker) {
return args
@@ -261,8 +294,12 @@ internal class LinkStage(val context: Context) {
private val entryPointSelector: List<String>
get() = if (nomain) emptyList() else platform.entrySelector
private val libffi
get() = platform.targetLibffi ?.let { listOf(it) } ?: emptyList()
private fun link(objectFiles: List<ObjectFile>, libraryProvidedLinkerFlags: List<String>): ExecutableFile {
val executable = context.config.outputFile
val linkCommand = platform.linkCommand(objectFiles, executable, optimize, debug) +
platform.targetLibffi +
asLinkerArgs(config.getNotNull(KonanConfigKeys.LINKER_ARGS)) +
@@ -333,7 +370,12 @@ internal class LinkStage(val context: Context) {
val phaser = PhaseManager(context)
phaser.phase(KonanPhase.OBJECT_FILES) {
objectFiles = listOf( llvmLto(bitcodeFiles ) )
objectFiles = listOf(
if (target == KonanTarget.WASM32)
bitcodeToWasm(bitcodeFiles)
else
llvmLto(bitcodeFiles)
)
}
phaser.phase(KonanPhase.LINKER) {
link(objectFiles, libraryProvidedLinkerFlags)
+1 -9
View File
@@ -218,14 +218,6 @@ dependencies.osx-wasm32 = \
target-toolchain-1-osx-wasm
quadruple.wasm32 = wasm32
entrySelector.wasm32 = -Wl,--defsym -Wl,main=Konan_main
llvmLtoFlags.wasm32 =
targetSysRoot.wasm32 = target-sysroot-1-wasm
clangFlags.wasm32 = -O1 -fno-rtti -fno-exceptions \
-D_LIBCPP_ABI_VERSION=2 -DKONAN_NO_FFI=1 -DKONAN_NO_THREADS=1 -DKONAN_NO_EXCEPTIONS=1 \
-DKONAN_NO_DEBUG_API=1 \
-nostdinc -Xclang -nobuiltininc -Xclang -nostdsysteminc \
-Xclang -isystem<sysrootDir>/include/libcxx -Xclang -isystem<sysrootDir>/lib/libcxxabi/include \
-Xclang -isystem<sysrootDir>/include/compat -Xclang -isystem<sysrootDir>/include/libc
linkerKonanFlags.wasm32 = -lc
linkerDebugFlags.wasm32 = -Wl,-S
s2wasmFlags.wasm32 = --allocate-stack 1024 --import-memory
+71 -3
View File
@@ -328,6 +328,7 @@ task codegen_controlflow_for_loops_overflow(type: RunKonanTest) {
}
task codegen_controlflow_for_loops_errors(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // Uses exceptions.
source = "codegen/controlflow/for_loops_errors.kt"
goldValue = "OK\n"
}
@@ -349,6 +350,7 @@ task codegen_controlflow_for_loops_nested(type: RunKonanTest) {
}
task codegen_controlflow_for_loops_coroutines(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
source = "codegen/controlflow/for_loops_coroutines.kt"
goldValue = "before: 0 after: 0\n" +
"before: 2 after: 2\n" +
@@ -376,6 +378,7 @@ task cast_simple(type: RunKonanTest) {
}
task cast_null(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Ok\n"
source = "codegen/basics/cast_null.kt"
}
@@ -392,6 +395,7 @@ task unchecked_cast2(type: RunKonanTest) {
}
task unchecked_cast3(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "Ok\n"
source = "codegen/basics/unchecked_cast3.kt"
}
@@ -411,13 +415,13 @@ task hello0(type: RunKonanTest) {
task hello1(type: RunKonanTest) {
goldValue = "Hello World"
testData = "Hello World"
testData = "Hello World\n"
source = "runtime/basic/hello1.kt"
}
task hello2(type: RunKonanTest) {
goldValue = "you entered 'Hello World'"
testData = "Hello World"
testData = "Hello World\n"
source = "runtime/basic/hello2.kt"
}
@@ -481,16 +485,19 @@ task empty_substring(type: RunKonanTest) {
}
task worker0(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "Got Input processed\nOK\n"
source = "runtime/workers/worker0.kt"
}
task worker1(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "OK\n"
source = "runtime/workers/worker1.kt"
}
task worker2(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "OK\n"
source = "runtime/workers/worker2.kt"
}
@@ -813,77 +820,92 @@ task classDelegation_withBridge(type: RunKonanTest) {
}
task delegatedProperty_simpleVal(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails: not global_ctros support.
goldValue = "x\n42\n"
source = "codegen/delegatedProperty/simpleVal.kt"
}
task delegatedProperty_simpleVar(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "get x\n42\nset x\nget x\n117\n"
source = "codegen/delegatedProperty/simpleVar.kt"
}
task delegatedProperty_packageLevel(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "x\n42\n"
source = "codegen/delegatedProperty/packageLevel.kt"
}
task delegatedProperty_local(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "x\n42\n"
source = "codegen/delegatedProperty/local.kt"
}
task delegatedProperty_delegatedOverride(type: LinkKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "156\nx\n117\n42\n"
source = "codegen/delegatedProperty/delegatedOverride_main.kt"
lib = "codegen/delegatedProperty/delegatedOverride_lib.kt"
}
task delegatedProperty_lazy(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "computed!\nHello\nHello\n"
source = "codegen/delegatedProperty/lazy.kt"
}
task delegatedProperty_observable(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "<no name> -> first\nfirst -> second\n"
source = "codegen/delegatedProperty/observable.kt"
}
task delegatedProperty_map(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "John Doe\n25\n"
source = "codegen/delegatedProperty/map.kt"
}
task propertyCallableReference_valClass(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "42\n117\n"
source = "codegen/propertyCallableReference/valClass.kt"
}
task propertyCallableReference_valModule(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "42\n"
source = "codegen/propertyCallableReference/valModule.kt"
}
task propertyCallableReference_varClass(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // RuntimeError: memory access out of bounds
goldValue = "117\n117\n42\n42\n"
source = "codegen/propertyCallableReference/varClass.kt"
}
task propertyCallableReference_varModule(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "117\n117\n"
source = "codegen/propertyCallableReference/varModule.kt"
}
task propertyCallableReference_valExtension(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "42\n117\n"
source = "codegen/propertyCallableReference/valExtension.kt"
}
task propertyCallableReference_varExtension(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "117\n117\n42\n42\n"
source = "codegen/propertyCallableReference/varExtension.kt"
}
task propertyCallableReference_linkTest(type: LinkKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "42\n117\n"
source = "codegen/propertyCallableReference/linkTest_main.kt"
lib = "codegen/propertyCallableReference/linkTest_lib.kt"
@@ -900,6 +922,7 @@ task lateinit_initialized(type: RunKonanTest) {
}
task lateinit_notInitialized(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails.
goldValue = "OK\n"
source = "codegen/lateinit/notInitialized.kt"
}
@@ -910,116 +933,139 @@ task lateinit_inBaseClass(type: RunKonanTest) {
}
task coroutines_simple(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "42\n"
source = "codegen/coroutines/simple.kt"
}
task coroutines_withReceiver(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "42\n"
source = "codegen/coroutines/withReceiver.kt"
}
task coroutines_correctOrder1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\nf2\n160\n"
source = "codegen/coroutines/correctOrder1.kt"
}
task coroutines_controlFlow_if1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\nf3\n84\n"
source = "codegen/coroutines/controlFlow_if1.kt"
}
task coroutines_controlFlow_if2(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\nf2\n43\n"
source = "codegen/coroutines/controlFlow_if2.kt"
}
task coroutines_controlFlow_finally1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\n117\n"
source = "codegen/coroutines/controlFlow_finally1.kt"
}
task coroutines_controlFlow_finally2(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\n117\n"
source = "codegen/coroutines/controlFlow_finally2.kt"
}
task coroutines_controlFlow_finally3(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\n117\n"
source = "codegen/coroutines/controlFlow_finally3.kt"
}
task coroutines_controlFlow_finally4(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\nfinally\n42\n"
source = "codegen/coroutines/controlFlow_finally4.kt"
}
task coroutines_controlFlow_finally5(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\nf2\nfinally\n1\n"
source = "codegen/coroutines/controlFlow_finally5.kt"
}
task coroutines_controlFlow_finally6(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\nfinally\nerror\n0\n"
source = "codegen/coroutines/controlFlow_finally6.kt"
}
task coroutines_controlFlow_finally7(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\nf2\nfinally1\ns2\nfinally2\n42\n"
source = "codegen/coroutines/controlFlow_finally7.kt"
}
task coroutines_controlFlow_inline1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "42\n"
source = "codegen/coroutines/controlFlow_inline1.kt"
}
task coroutines_controlFlow_inline2(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\n42\n"
source = "codegen/coroutines/controlFlow_inline2.kt"
}
task coroutines_controlFlow_inline3(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "f1\ns1\n42\n"
source = "codegen/coroutines/controlFlow_inline3.kt"
}
task coroutines_controlFlow_tryCatch1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\n42\n"
source = "codegen/coroutines/controlFlow_tryCatch1.kt"
}
task coroutines_controlFlow_tryCatch2(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s1\n42\n"
source = "codegen/coroutines/controlFlow_tryCatch2.kt"
}
task coroutines_controlFlow_tryCatch3(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s2\nf2\n1\n"
source = "codegen/coroutines/controlFlow_tryCatch3.kt"
}
task coroutines_controlFlow_tryCatch4(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s2\nf2\n1\n"
source = "codegen/coroutines/controlFlow_tryCatch4.kt"
}
task coroutines_controlFlow_tryCatch5(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s2\ns1\nError\n42\n"
source = "codegen/coroutines/controlFlow_tryCatch5.kt"
}
task coroutines_controlFlow_while1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s3\ns3\ns3\ns3\n3\n"
source = "codegen/coroutines/controlFlow_while1.kt"
}
task coroutines_controlFlow_while2(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "s3\ns3\ns3\n3\n"
source = "codegen/coroutines/controlFlow_while2.kt"
}
task coroutines_returnsUnit1(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "117\ns1\n0\n"
source = "codegen/coroutines/returnsUnit1.kt"
}
@@ -1030,6 +1076,7 @@ task AbstractMutableCollection(type: RunKonanTest) {
}
task BitSet(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
expectedExitStatus = 0
source = "runtime/collections/BitSet.kt"
}
@@ -1223,6 +1270,7 @@ task boxing6(type: RunKonanTest) {
}
task boxing7(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "1\n0\n"
source = "codegen/boxing/boxing7.kt"
}
@@ -1283,6 +1331,7 @@ task array_list1(type: RunKonanTest) {
}
task hash_map0(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32 (remainder by zero)
goldValue = "OK\n"
source = "runtime/collections/hash_map0.kt"
}
@@ -1315,6 +1364,7 @@ task moderately_large_array1(type: RunKonanTest) {
}
task string_builder0(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32.
goldValue = "OK\n"
source = "runtime/text/string_builder0.kt"
}
@@ -1344,21 +1394,25 @@ task to_string0(type: RunKonanTest) {
}
task chars0(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
source = "runtime/text/chars0.kt"
expectedExitStatus = 0
}
task catch1(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Before\nCaught Throwable\nDone\n"
source = "runtime/exceptions/catch1.kt"
}
task catch2(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Before\nCaught Error\nDone\n"
source = "runtime/exceptions/catch2.kt"
}
task catch7(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Error happens\n"
source = "runtime/exceptions/catch7.kt"
}
@@ -1379,11 +1433,13 @@ task catch4(type: RunKonanTest) {
}
task catch5(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Before\nCaught Error\nDone\n"
source = "codegen/try/catch5.kt"
}
task catch6(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Before\nCaught Error\nDone\n"
source = "codegen/try/catch6.kt"
}
@@ -1646,6 +1702,7 @@ task objectExpression3(type: RunKonanTest) {
}
task initializers2(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32.
goldValue = "init globalValue2\n" +
"init globalValue3\n" +
"1\n" +
@@ -1656,11 +1713,13 @@ task initializers2(type: RunKonanTest) {
}
task initializers3(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32.
goldValue = "42\n"
source = "runtime/basic/initializers3.kt"
}
task initializers4(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32.
goldValue = "1073741824\ntrue\n"
source = "runtime/basic/initializers4.kt"
}
@@ -1671,6 +1730,7 @@ task initializers5(type: RunKonanTest) {
}
task expression_as_statement(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // The test fails on wasm32.
goldValue = "Ok\n"
source = "codegen/basics/expression_as_statement.kt"
}
@@ -1692,6 +1752,7 @@ task memory_var4(type: RunKonanTest) {
}
task memory_throw_cleanup(type: RunKonanTest) {
expectedFail = (project.testTarget == 'wasm32') // Uses exceptions.
goldValue = "Ok\n"
source = "runtime/memory/throw_cleanup.kt"
}
@@ -1947,18 +2008,21 @@ kotlinNativeInterop {
}
task interop0(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
goldValue = "0\n0\n"
source = "interop/basics/0.kt"
interop = 'sysstat'
}
task interop1(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
goldValue = "257\n-1\n-2\n"
source = "interop/basics/1.kt"
interop = 'cstdlib'
}
task interop2(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
goldValue = "Hello\n"
source = "interop/basics/2.kt"
interop = 'cstdio'
@@ -1970,19 +2034,22 @@ task interop3(type: RunInteropKonanTest) {
// should be different depending on the bitness of the target.
// There are plans to provide a solution and turn this
// test back on.
disabled = (project.testTarget == 'raspberrypi')
disabled = (project.testTarget == 'raspberrypi') ||
(project.testTarget == 'wasm32') // No interop for wasm yet.
goldValue = "8 9 12 13 14 \n"
source = "interop/basics/3.kt"
interop = 'cstdlib'
}
task interop4(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
goldValue = "a b -1 2 3 9223372036854775807 0.1 0.2\n1 42\n"
source = "interop/basics/4.kt"
interop = 'cstdio'
}
task interop_echo_server(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
if (!isMac()) {
// Not supported or not tested.
disabled = true
@@ -1994,6 +2061,7 @@ task interop_echo_server(type: RunInteropKonanTest) {
if (isMac()) {
task interop_opengl_teapot(type: RunInteropKonanTest) {
disabled = (project.testTarget == 'wasm32') // No interop for wasm yet.
run = false
source = "interop/basics/opengl_teapot.kt"
interop = 'opengl'
+5
View File
@@ -254,6 +254,11 @@ targetList.each { target ->
rename("${target}Start.bc", 'start.bc')
into("klib/stdlib/targets/$target/native")
}
if (target == 'wasm32') {
from(project(':runtime').file('src/launcher/js')) {
into('konan/nativelib')
}
}
}
}
@@ -23,17 +23,16 @@ import org.gradle.api.tasks.ParallelizableTask
import org.gradle.api.tasks.TaskAction
import org.gradle.process.ExecResult
import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.konan.properties.*
abstract class KonanTest extends JavaExec {
protected String source
def targetManager = new TargetManager(project.testTarget)
def target = targetManager.target
def backendNative = project.project(":backend.native")
def runtimeProject = project.project(":runtime")
def dist = project.rootProject.file("dist")
def dependenciesDir = project.findProject(":dependencies").file("all")
def runtimeBc = new File("${dist.canonicalPath}/lib/runtime.bc").absolutePath
def launcherBc = new File("${dist.canonicalPath}/lib/launcher.bc").absolutePath
def startKtBc = new File("${dist.canonicalPath}/lib/start.kt.bc").absolutePath
def stdlibKtBc = new File("${dist.canonicalPath}/lib/stdlib.kt.bc").absolutePath
def dependenciesDir = project.rootProject.dependenciesDir
def konancDriver = project.isWindows() ? "konanc.bat" : "konanc"
def konanc = new File("${dist.canonicalPath}/bin/$konancDriver").absolutePath
def mainC = 'main.c'
@@ -47,12 +46,17 @@ abstract class KonanTest extends JavaExec {
List<String> flags = null
boolean enabled = true
boolean expectedFail = false
boolean run = true
void setDisabled(boolean value) {
this.enabled = !value
}
void setExpectedFail(boolean value) {
this.expectedFail = value
}
// Uses directory defined in $outputSourceSetName source set.
// If such source set doesn't exist, uses temporary directory.
void createOutputDirectory() {
@@ -102,7 +106,7 @@ abstract class KonanTest extends JavaExec {
*moreArgs,
*project.globalTestArgs]
if (project.testTarget) {
args "-target", project.testTarget
args "-target", target.userName
}
if (enableKonanAssertions) {
args "-ea"
@@ -212,7 +216,6 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
void executeTest() {
createOutputDirectory()
def program = buildExePath()
def targetManager = new TargetManager(project.testTarget)
def suffix = targetManager.programSuffix
def exe = "$program$suffix"
@@ -227,7 +230,9 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
def out = new ByteArrayOutputStream()
//TODO Add test timeout
ExecResult execResult = project.execRemote {
commandLine exe
commandLine executionCommandLine(exe)
if (arguments != null) {
args arguments
}
@@ -239,15 +244,43 @@ fun handleExceptionContinuation(x: (Throwable) -> Unit): Continuation<Any?> = ob
ignoreExitValue = true
}
def result = out.toString("UTF-8")
println(result)
if (execResult.exitValue != expectedExitStatus) {
throw new TestFailedException(
"Test failed. Expected exit status: $expectedExitStatus, actual: ${execResult.exitValue}")
}
def exitCodeMismatch = execResult.exitValue != expectedExitStatus
if (exitCodeMismatch) {
def message = "Expected exit status: $expectedExitStatus, actual: ${execResult.exitValue}"
if (this.expectedFail) {
println("Expected failure. $message")
} else {
throw new TestFailedException("Test failed. $message")
}
}
def goldValueMismatch = goldValue != null && goldValue != result.replace(System.lineSeparator(), "\n")
if (goldValueMismatch) {
def message = "Expected output: $goldValue, actual output: $result"
if (this.expectedFail) {
println("Expected failure. $message")
} else {
throw new TestFailedException("Test failed. $message")
}
}
if (goldValue != null && goldValue != result.replace(System.lineSeparator(), "\n")) {
throw new TestFailedException("Test failed. Expected output: $goldValue, actual output: $result")
if (!exitCodeMismatch && !goldValueMismatch && this.expectedFail) println("Unexpected pass")
}
List<String> executionCommandLine(String exe) {
if (target == KonanTarget.WASM32) {
def properties = project.rootProject.konanProperties
def targetToolchain = TargetPropertiesKt.hostTargetString(properties, "targetToolchain", target)
def absoluteTargetToolchain = "$dependenciesDir/$targetToolchain"
def d8 = "$absoluteTargetToolchain/bin/d8"
def launcherJs = "${dist.absolutePath}/konan/nativelib/launcher.js"
return [d8, '--expose-wasm', launcherJs, '--', exe]
} else {
return [exe]
}
}
}
@@ -289,7 +322,7 @@ class RunDriverKonanTest extends KonanTest {
*moreArgs,
*project.globalTestArgs]
if (project.testTarget) {
args "-target", project.testTarget
args "-target", target.userName
}
if (enableKonanAssertions) {
args "-ea"
@@ -312,7 +345,7 @@ class RunInteropKonanTest extends KonanTest {
void setInterop(String value) {
this.interop = value
this.interopConf = project.kotlinNativeInterop[value]
this.interopConf.target = project.testTarget
this.interopConf.target = target.userName
this.dependsOn(this.interopConf.genTask)
}
-2
View File
@@ -25,7 +25,6 @@ targetList.each { targetName ->
dependsOn ":common:${targetName}Hash"
dependsOn "${targetName}Launcher"
target targetName
compilerArgs '-g'
compilerArgs '-I' + project.file('../common/src/hash/headers')
if (rootProject.hasProperty("${targetName}LibffiDir"))
compilerArgs '-I' + project.file(rootProject.ext.get("${targetName}LibffiDir") + "/include")
@@ -38,7 +37,6 @@ targetList.each { targetName ->
name "launcher"
srcRoot file('src/launcher')
target targetName
compilerArgs '-g'
compilerArgs '-I' + project.file('../common/src/hash/headers')
compilerArgs '-I' + project.file('src/main/cpp')
}
+16
View File
@@ -57,4 +57,20 @@ extern "C" RUNTIME_USED int Konan_main(int argc, const char** argv) {
return exitStatus;
}
#ifdef KONAN_WASM
// Before we pass control to Konan_main, we need to obtain argv elements
// from the javascript world.
extern "C" int Konan_js_arg_size(int index);
extern "C" int Konan_js_fetch_arg(int index, char* ptr);
extern "C" int Konan_js_main(int argc) {
char** argv = (char**)konan::calloc(1, argc);
for (int i = 0; i< argc; ++i) {
argv[i] = (char*)konan::calloc(1, Konan_js_arg_size(i));
Konan_js_fetch_arg(i, argv[i]);
}
return Konan_main(argc, (const char**)argv);
}
#endif
#endif
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var module;
var instance;
var heap;
var memory;
var global_arguments = arguments;
var exit_status = 0;
var globalBase = 0; // Is there any way to obtain global_base from JavaScript?
function print_usage() {
// TODO: any reliable way to obtain the current script name?
print('Usage: d8 --expose-wasm launcher.js -- <program.wasm> <program arg1> <program arg2> ...')
quit(1); // TODO: this is d8 specific
}
function utf8encode(s) {
return unescape(encodeURIComponent(s));
}
function utf8decode(s) {
return decodeURIComponent(escape(s));
}
function fromString(string, pointer) {
for (i = 0; i < string.length; i++) {
heap[pointer + i] = string.charCodeAt(i);
}
heap[pointer + string.length] = 0;
}
function toString(pointer) {
var string = '';
for (var i = pointer; heap[i] != 0; i++) {
string += String.fromCharCode(heap[i]);
}
return string;
}
function int32ToHeap(value, pointer) {
heap[pointer] = value & 0xff;
heap[pointer+1] = (value & 0xff00) >>> 8;
heap[pointer+2] = (value & 0xff0000) >>> 16;
heap[pointer+3] = (value & 0xff000000) >>> 24;
}
function stackTop() {
// Read the value module's `__stack_pointer` is initialized with.
// It is the very first static in .data section.
var addr = (globalBase == 0 ? 4 : globalBase);
var fourBytes = heap.buffer.slice(addr, addr+4);
return new Uint32Array(fourBytes)[0];
}
var konan_dependencies = {
env: {
abort: function() {
throw new Error("abort()");
},
// TODO: Account for file and size.
fgets: function(str, size, file) {
fromString(utf8encode(readline()), str);
return str;
},
Konan_heap_upper: function() {
return memory.buffer.byteLength;
},
Konan_heap_lower: function() {
return konanStackTop;
},
Konan_abort: function(pointer) {
throw new Error("Konan_abort(" + utf8decode(toString(pointer)) + ")");
},
Konan_js_arg_size: function(index) {
if (index >= global_arguments.length) return -1;
return global_arguments[index].length + 1; // + 1 for trailing zero.
},
Konan_js_fetch_arg: function(index, ptr) {
var arg = utf8encode(global_arguments[index]);
fromString(arg, ptr);
},
Konan_date_now: function(pointer) {
var now = Date.now();
var high = Math.floor(now / 0xffffffff);
var low = Math.floor(now % 0xffffffff);
int32ToHeap(low, pointer);
int32ToHeap(high, pointer+4);
},
stdin: 0, // This is for fgets(,,stdin) to resolve. It is ignored.
// TODO: Account for fd and size.
write: function(fd, str, size) {
if (fd != 1 && fd != 2) throw ("write(" + fd + ", ...)");
// TODO: There is no writeErr() in d8.
// Approximate it with write() to stdout for now.
write(utf8decode(toString(str))); // TODO: write() d8 specific.
},
memory: new WebAssembly.Memory({ initial: 256 })
}
};
if (arguments.length < 1) print_usage();
module = new WebAssembly.Module(new Uint8Array(readbuffer(arguments[0])));
module.env = {};
module.env.memoryBase = 0;
module.env.tablebase = 0;
instance = new WebAssembly.Instance(module, konan_dependencies);
memory = konan_dependencies.env.memory
heap = new Uint8Array(konan_dependencies.env.memory.buffer);
heap32 = new Uint32Array(konan_dependencies.env.memory.buffer);
konanStackTop = stackTop();
try {
exit_status = instance.exports.Konan_js_main(arguments.length);
} catch (e) {
print("Exception executing Konan_js_main: " + e);
print(e.stack);
exit_status = 1;
}
quit(exit_status); // TODO: d8 specific.
+3 -2
View File
@@ -50,7 +50,7 @@ class AutoFree {
AutoFree(void* mem): mem_(mem) {}
~AutoFree() {
free(mem_);
konan::free(mem_);
}
};
@@ -105,7 +105,7 @@ _Unwind_Reason_Code unwindCallback(
}
char line[512];
snprintf(line, sizeof(line) - 1, "%s (%p)",
konan::snprintf(line, sizeof(line) - 1, "%s (%p)",
symbol, (void*)(intptr_t)address);
backtrace->setNextElement(line);
return _URC_NO_REASON;
@@ -162,6 +162,7 @@ void ThrowException(KRef exception) {
RuntimeAssert(exception != nullptr && IsInstance(exception, theThrowableTypeInfo),
"Throwing something non-throwable");
#if KONAN_NO_EXCEPTIONS
PrintThrowable(exception);
RuntimeAssert(false, "Exceptions unsupported");
#else
#if (__MINGW32__ || __MINGW64__)
+2
View File
@@ -44,6 +44,8 @@ void ThrowArithmeticException();
void ThrowNumberFormatException();
// Throws out of memory error.
void ThrowOutOfMemoryError();
// Prints out mesage of Throwable.
void PrintThrowable(KRef);
#ifdef __cplusplus
} // extern "C"
+2 -2
View File
@@ -53,7 +53,7 @@ void* Kotlin_interop_malloc(KLong size, KInt align) {
return nullptr;
}
void* result = malloc(size);
void* result = konan::calloc(1, size);
if ((reinterpret_cast<uintptr_t>(result) & (align - 1)) != 0) {
// Unaligned!
RuntimeAssert(false, "unsupported alignment");
@@ -63,7 +63,7 @@ void* Kotlin_interop_malloc(KLong size, KInt align) {
}
void Kotlin_interop_free(void* ptr) {
free(ptr);
konan::free(ptr);
}
} // extern "C"
+181 -2
View File
@@ -76,7 +76,7 @@ void abort() {
// memcpy/memmove are not here intentionally, as frequently implemented/optimized
// by C compiler.
void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLen) {
#if KONAN_WINDOWS
#if KONAN_WINDOWS || KONAN_WASM
for (size_t i = 0; i + littleLen <= bigLen; ++i) {
void* pos = ((char*)big) + i;
if (::memcmp(little, pos, littleLen) == 0) return pos;
@@ -88,10 +88,19 @@ void* memmem(const void *big, size_t bigLen, const void *little, size_t littleLe
}
// The sprintf family.
#if KONAN_INTERNAL_SNPRINTF
extern "C" int rpl_vsnprintf(char *, size_t, const char *, va_list);
#endif
int snprintf(char* buffer, size_t size, const char* format, ...) {
va_list args;
va_start(args, format);
#if KONAN_INTERNAL_SNPRINTF
int rv = rpl_vsnprintf(buffer, size, format, args);
#else
int rv = ::vsnprintf(buffer, size, format, args);
#endif
va_end(args);
return rv;
}
@@ -122,6 +131,22 @@ void free(void* pointer) {
#endif
}
#if KONAN_INTERNAL_NOW
extern "C" void Konan_date_now(uint64_t*);
uint64_t getTimeMillis() {
uint64_t now;
Konan_date_now(&now);
return now;
}
uint64_t getTimeMicros() {
return getTimeMillis() * 1000ULL;
}
uint64_t getTimeNanos() {
return getTimeMillis() * 1000000ULL;
}
#else
// Time operations.
using namespace std::chrono;
@@ -136,12 +161,166 @@ uint64_t getTimeNanos() {
uint64_t getTimeMicros() {
return duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
}
#endif
#if KONAN_INTERNAL_DLMALLOC
// This function is being called when memory allocator needs more RAM.
#ifdef KONAN_WASM
// This one is an interface to query module.env.memory.buffer.byteLength
extern "C" unsigned long Konan_heap_upper();
extern "C" unsigned long Konan_heap_lower();
#define MFAIL ((void*) ~(size_t)0)
#define WASM_PAGESIZE 65536U
#define WASM_PAGEMASK ((WASM_PAGESIZE-(size_t)1))
#define PAGE_ALIGN(value) ((value + WASM_PAGEMASK) & ~(WASM_PAGEMASK))
void* moreCore(int size) {
return sbrk(size);
static int initialized = 0;
static void* sbrk_top = MFAIL;
static void* upperHeapLimit = MFAIL;
if (!initialized) {
sbrk_top = (void*)PAGE_ALIGN(Konan_heap_lower());
upperHeapLimit = (void*)Konan_heap_upper();
initialized = 1;
}
if (size == 0) {
return sbrk_top;
} else if (size < 0) {
return MFAIL;
}
size = PAGE_ALIGN(size);
void* old_sbrk_top = sbrk_top;
sbrk_top = (char*)sbrk_top + size;
if (((char*)sbrk_top - (char*)upperHeapLimit) >= 0) {
// TODO: Consider using grow() and .maximum Memory settings.
abort();
}
return old_sbrk_top;
}
// dlmalloc wants to know the page size.
long getpagesize() {
return WASM_PAGESIZE;
}
#else
void* moreCore(int size) {
return sbrk(size);
}
long getpagesize() {
return sysconf(_SC_PAGESIZE);
}
#endif
#endif
} // namespace konan
extern "C" {
#ifdef KONAN_WASM
extern void Konan_abort(const char*);
// TODO: get rid of these.
void _ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv(void) {
Konan_abort("TODO: throw_length_error not implemented.");
}
void _ZNKSt3__221__basic_string_commonILb1EE20__throw_length_errorEv(void) {
Konan_abort("TODO: throw_length_error not implemented.");
}
int _ZNSt3__212__next_primeEm(unsigned long n) {
static unsigned long primes[] = {
11UL,
101UL,
1009UL,
10007UL,
100003UL,
1000003UL,
10000019UL,
100000007UL,
1000000007UL
};
int table_length = sizeof(primes)/sizeof(unsigned long);
if (n > primes[table_length - 1]) konan::abort();
unsigned long prime = primes[0];
for (unsigned long i=0; i< table_length; i++) {
prime = primes[i];
if (prime >= n) break;
}
return prime;
}
void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) {
char buf[1024];
konan::snprintf(buf, sizeof(buf), "%s:%d in %s: runtime assert: %s\n", file, line, function, assertion);
Konan_abort(buf);
}
int* __errno_location() {
static int theErrno = 0;
return &theErrno;
}
// Some math.h functions.
double pow(double x, double y) {
return __builtin_pow(x, y);
}
// Some string.h functions.
void *memcpy(void *dst, const void *src, size_t n) {
for (long i = 0; i != n; ++i)
*((char*)dst + i) = *((char*)src + i);
return dst;
}
void *memmove(void *dst, const void *src, size_t len) {
if (src < dst) {
for (long i = len; i != 0; --i) {
*((char*)dst + i - 1) = *((char*)src + i - 1);
}
} else {
memcpy(dst, src, len);
}
return dst;
}
int memcmp(const void *s1, const void *s2, size_t n) {
for (long i = 0; i != n; ++i) {
if (*((char*)s1 + i) != *((char*)s2 + i)) {
return *((char*)s1 + i) - *((char*)s2 + i);
}
}
return 0;
}
void *memset(void *b, int c, size_t len) {
for (long i = 0; i != len; ++i) {
*((char*)b + i) = c;
}
return b;
}
size_t strlen(const char *s) {
for (long i = 0;; ++i) {
if (s[i] == 0) return i;
}
}
size_t strnlen(const char *s, size_t maxlen) {
for (long i = 0; i<=maxlen; ++i) {
if (s[i] == 0) return i;
}
return maxlen;
}
#endif
}
+4 -4
View File
@@ -82,7 +82,7 @@ OBJ_GETTER(Kotlin_Any_toString, KConstRef thiz) {
OBJ_GETTER(Kotlin_Byte_toString, KByte value) {
char cstring[8];
snprintf(cstring, sizeof(cstring), "%d", value);
konan::snprintf(cstring, sizeof(cstring), "%d", value);
RETURN_RESULT_OF(CreateStringFromCString, cstring);
}
@@ -95,13 +95,13 @@ OBJ_GETTER(Kotlin_Char_toString, KChar value) {
OBJ_GETTER(Kotlin_Short_toString, KShort value) {
char cstring[8];
snprintf(cstring, sizeof(cstring), "%d", value);
konan::snprintf(cstring, sizeof(cstring), "%d", value);
RETURN_RESULT_OF(CreateStringFromCString, cstring);
}
OBJ_GETTER(Kotlin_Int_toString, KInt value) {
char cstring[16];
snprintf(cstring, sizeof(cstring), "%d", value);
konan::snprintf(cstring, sizeof(cstring), "%d", value);
RETURN_RESULT_OF(CreateStringFromCString, cstring);
}
@@ -111,7 +111,7 @@ OBJ_GETTER(Kotlin_Int_toStringRadix, KInt value, KInt radix) {
OBJ_GETTER(Kotlin_Long_toString, KLong value) {
char cstring[32];
snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value));
konan::snprintf(cstring, sizeof(cstring), "%lld", static_cast<long long>(value));
RETURN_RESULT_OF(CreateStringFromCString, cstring);
}
+9 -1
View File
@@ -525,14 +525,22 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
/**** Start of Konan-specific dlmalloc configuration. ****/
#define USE_DL_PREFIX 1
#if !KONAN_WASM
#if KONAN_WASM
#define USE_LOCKS 0
#define LACKS_TIME_H 1
#define NO_MALLOC_STATS 1
#define HAVE_MMAP 0 // don't try to allocate large chunks of memory using mmap().
// It will go to malloc->calloc->sbrk->morecore chain anyways.
#else
#define USE_LOCKS 1
#endif
#define DLMALLOC_EXPORT extern "C"
#define HAVE_MORECORE 1
#define MORECORE konan::moreCore
#define malloc_getpagesize konan::getpagesize()
namespace konan {
extern void* moreCore(int size);
extern long getpagesize();
} // namespace konan
/**** End of Konan-specific dlmalloc configuration. ****/
+2 -2
View File
@@ -173,8 +173,8 @@ static const KDouble tens[] = {
}
#define ERROR_OCCURED(x) (HIGH_I32_FROM_VAR(x) < 0)
#define allocateU64(x, n) if (!((x) = (U_64*) malloc((n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) free((r));
#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) konan::free((r));
/*NB the Number converter methods are synchronized so it is possible to
*have global data for use by bigIntDigitGenerator */
+2 -2
View File
@@ -121,8 +121,8 @@ static const U_32 tens[] = {
} \
}
#define allocateU64(x, n) if (!((x) = (U_64*) malloc((n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) free((r));
#define allocateU64(x, n) if (!((x) = (U_64*) konan::calloc(1, (n) * sizeof(U_64)))) goto OutOfMemory;
#define release(r) if ((r)) konan::free((r));
KFloat
createFloat (const char *s, KInt e)
@@ -163,6 +163,26 @@
* <http://www.jhweiss.de/software/snprintf.html>.
*/
#if KONAN_INTERNAL_SNPRINTF
/**** Start of Konan-specific c99-snprintf configuration. ****/
#define HAVE_FLOAT_H 1
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDLIB_H 1
#define HAVE_SNPRINTF 1
#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
#define HAVE_LONG_LONG_INT 1
#define HAVE_UNSIGNED_LONG_LONG_INT 1
#include <stddef.h>
#include <stdarg.h>
extern "C" int rpl_vsnprintf(char *, size_t, const char *, va_list);
#define malloc(size) konan:calloc(1, size)
/**** End of Konan-specific c99-snprintf configuration. ****/
#if HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
@@ -831,7 +851,7 @@ rpl_vsnprintf(char *str, size_t size, const char *format, va_list args)
* characters, in an implementation-defined
* manner." (C99: 7.19.6.1, 8)
*/
if ((strvalue = va_arg(args, void *)) == NULL)
if ((strvalue = (char*)va_arg(args, void *)) == NULL)
/*
* We use the glibc format. BSD prints
* "0x0", SysV "0".
@@ -1472,8 +1492,8 @@ mypow10(int exponent)
void *
mymemcpy(void *dst, void *src, size_t len)
{
const char *from = src;
char *to = dst;
const char *from = (char*)src;
char *to = (char*)dst;
/* No need for optimization, we use this only to replace va_copy(3). */
while (len-- > 0)
@@ -1492,7 +1512,7 @@ rpl_vasprintf(char **ret, const char *format, va_list ap)
VA_COPY(aq, ap);
len = vsnprintf(NULL, 0, format, aq);
VA_END_COPY(aq);
if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
if (len < 0 || (*ret = (char*)malloc(size = len + 1)) == NULL)
return -1;
return vsnprintf(*ret, size, format, ap);
}
@@ -2092,4 +2112,5 @@ do { \
}
#endif /* TEST_SNPRINTF */
#endif // KONAN_INTERNAL_SNPRINTF
/* vim: set joinspaces noexpandtab textwidth=80 cinoptions=(4,u0: */
@@ -60,6 +60,11 @@ fun ThrowUninitializedPropertyAccessException(): Nothing {
throw UninitializedPropertyAccessException()
}
@ExportForCppRuntime
fun PrintThrowable(throwable: Throwable) {
println(throwable)
}
@ExportForCppRuntime
internal fun TheEmptyString() = ""
@@ -95,4 +100,4 @@ fun getProgressionLast(start: Char, end: Char, step: Int): Char =
getProgressionLast(start.toInt(), end.toInt(), step).toChar()
fun getProgressionLast(start: Int, end: Int, step: Int): Int = getProgressionLastElement(start, end, step)
fun getProgressionLast(start: Long, end: Long, step: Long): Long = getProgressionLastElement(start, end, step)
fun getProgressionLast(start: Long, end: Long, step: Long): Long = getProgressionLastElement(start, end, step)
@@ -69,8 +69,8 @@ class ClangTarget(val target: KonanTarget, konanProperties: KonanProperties) {
KonanTarget.WASM32 ->
listOf("-target", targetArg!!, "-O1", "-fno-rtti", "-fno-exceptions", "-DKONAN_WASM=1",
"-D_LIBCPP_ABI_VERSION=2", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1",
"-DKONAN_INTERNAL_DLMALLOC=1",
"-D_LIBCPP_ABI_VERSION=2", "-D_LIBCPP_NO_EXCEPTIONS=1", "-DKONAN_NO_FFI=1", "-DKONAN_NO_THREADS=1", "-DKONAN_NO_EXCEPTIONS=1",
"-DKONAN_INTERNAL_DLMALLOC=1", "-DKONAN_INTERNAL_SNPRINTF=1", "-DKONAN_INTERNAL_NOW=1",
"-nostdinc", "-Xclang", "-nobuiltininc", "-Xclang", "-nostdsysteminc",
"-Xclang", "-isystem$sysRoot/include/libcxx", "-Xclang", "-isystem$sysRoot/lib/libcxxabi/include",
"-Xclang", "-isystem$sysRoot/include/compat", "-Xclang", "-isystem$sysRoot/include/libc")
@@ -43,6 +43,7 @@ class KonanProperties(val target: KonanTarget, val properties: Properties, val b
val linkerKonanFlags get() = targetList("linkerKonanFlags")
val linkerDebugFlags get() = targetList("linkerDebugFlags")
val llvmDebugOptFlags get() = targetList("llvmDebugOptFlags")
val s2wasmFlags get() = targetList("s2wasmFlags")
val targetSysRoot get() = targetString("targetSysRoot")
val libffiDir get() = targetString("libffiDir")
@@ -25,7 +25,7 @@ enum class KonanTarget(val targetSuffix: String, val programSuffix: String, var
MINGW("mingw", "exe"),
MACBOOK("osx", "kexe"),
RASPBERRYPI("raspberrypi", "kexe"),
WASM32("wasm32", "kexe");
WASM32("wasm32", "wasm");
val userName get() = name.toLowerCase()
}