WASM: Implement wasm-native strings part 1
There are several changes here but they all required for at least one test to pass. - Implemented String class and several utility functions using built-in CharArray - Added new constant memory segment to hold string literals and required funcs to work with them - Added very crude mostly incorrect rudimentary ability to pass strings back to javascript
This commit is contained in:
committed by
TeamCityServer
parent
9ccdffe8ad
commit
0f84525bdc
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package kotlin.wasm.internal
|
||||
|
||||
// This is called when exported function returns a string. It writes [i32 length, [i16 chars ...]] into a temporary raw memory area and
|
||||
// returns pointer to the start of it.
|
||||
// Note: currently there is a single temporary raw memory area so it's not possible to export more than one string at a time.
|
||||
internal fun exportStringRet(src: String): Int {
|
||||
val retAddr = unsafeGetScratchRawMemory(INT_SIZE_BYTES + src.length * CHAR_SIZE_BYTES)
|
||||
wasm_i32_store(retAddr, src.length)
|
||||
unsafeCharArrayToRawMemory(src.toCharArray(), retAddr + INT_SIZE_BYTES)
|
||||
return retAddr
|
||||
}
|
||||
|
||||
// See importStringToJs for the JS-side import for strings
|
||||
@@ -5,10 +5,34 @@
|
||||
|
||||
package kotlin.wasm.internal
|
||||
|
||||
@WasmImport("runtime", "String_getLiteral")
|
||||
internal fun stringLiteral(index: Int): String =
|
||||
internal const val CHAR_SIZE_BYTES = 2
|
||||
internal const val INT_SIZE_BYTES = 4
|
||||
|
||||
internal fun unsafeRawMemoryToChar(addr: Int) = wasm_i32_load16_u(addr).toChar()
|
||||
|
||||
internal fun unsafeRawMemoryToCharArray(startAddr: Int, length: Int): CharArray {
|
||||
val ret = CharArray(length)
|
||||
for (i in 0 until length) {
|
||||
ret[i] = unsafeRawMemoryToChar(startAddr + i * CHAR_SIZE_BYTES)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Returns a pointer into a temporary scratch segment in the raw wasm memory. Aligned by 4.
|
||||
// Note: currently there is single such segment for a whole wasm module, so use with care.
|
||||
@ExcludedFromCodegen
|
||||
internal fun unsafeGetScratchRawMemory(sizeBytes: Int): Int =
|
||||
implementedAsIntrinsic
|
||||
|
||||
// Assumes there is enough space at the destination, fails with wasm trap otherwise.
|
||||
internal fun unsafeCharArrayToRawMemory(src: CharArray, dstAddr: Int) {
|
||||
var curAddr = dstAddr
|
||||
for (i in src) {
|
||||
wasm_i32_store16(curAddr, i)
|
||||
curAddr += CHAR_SIZE_BYTES
|
||||
}
|
||||
}
|
||||
|
||||
@WasmReinterpret
|
||||
internal fun unsafeNotNull(x: Any?): Any =
|
||||
implementedAsIntrinsic
|
||||
|
||||
@@ -308,4 +308,13 @@ public external fun wasm_i64_trunc_sat_f32_s(a: Float): Long
|
||||
public external fun wasm_i64_trunc_sat_f64_s(a: Double): Long
|
||||
|
||||
@WasmOp(WasmOp.I32_LOAD)
|
||||
public external fun wasm_i32_load(x: Int): Int
|
||||
public external fun wasm_i32_load(x: Int): Int
|
||||
|
||||
@WasmOp(WasmOp.I32_LOAD16_U)
|
||||
public external fun wasm_i32_load16_u(x: Int): Int
|
||||
|
||||
@WasmOp(WasmOp.I32_STORE)
|
||||
public external fun wasm_i32_store(addr: Int, i: Int): Unit
|
||||
|
||||
@WasmOp(WasmOp.I32_STORE16)
|
||||
public external fun wasm_i32_store16(addr: Int, c: Char): Unit
|
||||
@@ -12,7 +12,3 @@ fun wasm_i32_compareTo(x: Int, y: Int): Int =
|
||||
|
||||
fun wasm_i64_compareTo(x: Long, y: Long): Int =
|
||||
wasm_i64_ge_s(x, y).toInt() - wasm_i64_le_s(x, y).toInt()
|
||||
|
||||
@WasmImport("runtime", "String_equals")
|
||||
fun wasm_string_eq(x: String, y: String): Boolean =
|
||||
implementedAsIntrinsic
|
||||
Reference in New Issue
Block a user