[Wasm] Support packed integer array elements
This commit is contained in:
+1
-1
@@ -176,7 +176,7 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVis
|
|||||||
nameStr,
|
nameStr,
|
||||||
WasmStructFieldDeclaration(
|
WasmStructFieldDeclaration(
|
||||||
name = "field",
|
name = "field",
|
||||||
type = context.transformType(wasmArrayAnnotation.type),
|
type = context.transformFieldType(wasmArrayAnnotation.type),
|
||||||
isMutable = true
|
isMutable = true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -35,17 +35,17 @@ internal fun byteArrayIterator(array: ByteArray) = object : ByteIterator() {
|
|||||||
|
|
||||||
|
|
||||||
public class CharArray(size: Int) {
|
public class CharArray(size: Int) {
|
||||||
private var storage = WasmShortArray(size)
|
private var storage = WasmCharArray(size)
|
||||||
|
|
||||||
public constructor(size: Int, init: (Int) -> Char) : this(size) {
|
public constructor(size: Int, init: (Int) -> Char) : this(size) {
|
||||||
storage.fill(size) { init(it).toShort() }
|
storage.fill(size) { init(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
public operator fun get(index: Int): Char =
|
public operator fun get(index: Int): Char =
|
||||||
storage.get(index).toChar()
|
storage.get(index)
|
||||||
|
|
||||||
public operator fun set(index: Int, value: Char) {
|
public operator fun set(index: Int, value: Char) {
|
||||||
storage.set(index, value.toShort())
|
storage.set(index, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
public val size: Int
|
public val size: Int
|
||||||
@@ -200,17 +200,17 @@ internal fun doubleArrayIterator(array: DoubleArray) = object : DoubleIterator()
|
|||||||
|
|
||||||
|
|
||||||
public class BooleanArray(size: Int) {
|
public class BooleanArray(size: Int) {
|
||||||
private var storage = WasmBooleanArray(size)
|
private var storage = WasmByteArray(size)
|
||||||
|
|
||||||
public constructor(size: Int, init: (Int) -> Boolean) : this(size) {
|
public constructor(size: Int, init: (Int) -> Boolean) : this(size) {
|
||||||
storage.fill(size, init)
|
storage.fill(size) { init(it).toInt().reinterpretAsByte() }
|
||||||
}
|
}
|
||||||
|
|
||||||
public operator fun get(index: Int): Boolean =
|
public operator fun get(index: Int): Boolean =
|
||||||
storage.get(index)
|
storage.get(index).reinterpretAsInt().reinterpretAsBoolean()
|
||||||
|
|
||||||
public operator fun set(index: Int, value: Boolean) {
|
public operator fun set(index: Int, value: Boolean) {
|
||||||
storage.set(index, value)
|
storage.set(index, value.toInt().reinterpretAsByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
public val size: Int
|
public val size: Int
|
||||||
|
|||||||
@@ -33,32 +33,9 @@ internal inline fun WasmAnyArray.fill(size: Int, init: (Int) -> Any?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@WasmArrayOf(Boolean::class, isNullable = false)
|
|
||||||
internal class WasmBooleanArray(size: Int) {
|
|
||||||
@WasmOp(WasmOp.ARRAY_GET)
|
|
||||||
fun get(index: Int): Boolean =
|
|
||||||
implementedAsIntrinsic
|
|
||||||
|
|
||||||
@WasmOp(WasmOp.ARRAY_SET)
|
|
||||||
fun set(index: Int, value: Boolean): Unit =
|
|
||||||
implementedAsIntrinsic
|
|
||||||
|
|
||||||
@WasmOp(WasmOp.ARRAY_LEN)
|
|
||||||
fun len(): Int =
|
|
||||||
implementedAsIntrinsic
|
|
||||||
}
|
|
||||||
|
|
||||||
internal inline fun WasmBooleanArray.fill(size: Int, init: (Int) -> Boolean) {
|
|
||||||
var i = 0
|
|
||||||
while (i < size) {
|
|
||||||
set(i, init(i))
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@WasmArrayOf(Byte::class, isNullable = false)
|
@WasmArrayOf(Byte::class, isNullable = false)
|
||||||
internal class WasmByteArray(size: Int) {
|
internal class WasmByteArray(size: Int) {
|
||||||
@WasmOp(WasmOp.ARRAY_GET)
|
@WasmOp(WasmOp.ARRAY_GET_S)
|
||||||
fun get(index: Int): Byte =
|
fun get(index: Int): Byte =
|
||||||
implementedAsIntrinsic
|
implementedAsIntrinsic
|
||||||
|
|
||||||
@@ -79,9 +56,32 @@ internal inline fun WasmByteArray.fill(size: Int, init: (Int) -> Byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WasmArrayOf(Char::class, isNullable = false)
|
||||||
|
internal class WasmCharArray(size: Int) {
|
||||||
|
@WasmOp(WasmOp.ARRAY_GET_U)
|
||||||
|
fun get(index: Int): Char =
|
||||||
|
implementedAsIntrinsic
|
||||||
|
|
||||||
|
@WasmOp(WasmOp.ARRAY_SET)
|
||||||
|
fun set(index: Int, value: Char): Unit =
|
||||||
|
implementedAsIntrinsic
|
||||||
|
|
||||||
|
@WasmOp(WasmOp.ARRAY_LEN)
|
||||||
|
fun len(): Int =
|
||||||
|
implementedAsIntrinsic
|
||||||
|
}
|
||||||
|
|
||||||
|
internal inline fun WasmCharArray.fill(size: Int, init: (Int) -> Char) {
|
||||||
|
var i = 0
|
||||||
|
while (i < size) {
|
||||||
|
set(i, init(i))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@WasmArrayOf(Short::class, isNullable = false)
|
@WasmArrayOf(Short::class, isNullable = false)
|
||||||
internal class WasmShortArray(size: Int) {
|
internal class WasmShortArray(size: Int) {
|
||||||
@WasmOp(WasmOp.ARRAY_GET)
|
@WasmOp(WasmOp.ARRAY_GET_S)
|
||||||
fun get(index: Int): Short =
|
fun get(index: Int): Short =
|
||||||
implementedAsIntrinsic
|
implementedAsIntrinsic
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.wasm.ir.WasmOp
|
|||||||
import templates.COMMON_AUTOGENERATED_WARNING
|
import templates.COMMON_AUTOGENERATED_WARNING
|
||||||
import templates.COPYRIGHT_NOTICE
|
import templates.COPYRIGHT_NOTICE
|
||||||
import templates.PrimitiveType
|
import templates.PrimitiveType
|
||||||
|
import templates.isUnsigned
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
|
|
||||||
@@ -56,20 +57,41 @@ fun generateWasmArrays(targetDir: File) {
|
|||||||
writer.generateStandardWasmInternalHeader()
|
writer.generateStandardWasmInternalHeader()
|
||||||
|
|
||||||
writer.appendLine(wasmArrayForType("Any", true))
|
writer.appendLine(wasmArrayForType("Any", true))
|
||||||
writer.appendLine(wasmArrayForType("Boolean", false))
|
PrimitiveType.descendingByDomainCapacity.reversed().forEach { primitive ->
|
||||||
PrimitiveType.numericPrimitives.sortedBy { it.capacity }.forEach { primitive ->
|
val isPacked = primitive in setOf(
|
||||||
writer.appendLine(wasmArrayForType(primitive.name, false))
|
PrimitiveType.Byte,
|
||||||
|
PrimitiveType.Short,
|
||||||
|
PrimitiveType.Char,
|
||||||
|
)
|
||||||
|
val isUnsigned = primitive.isUnsigned() || primitive == PrimitiveType.Char
|
||||||
|
|
||||||
|
writer.appendLine(
|
||||||
|
wasmArrayForType(
|
||||||
|
primitive.name,
|
||||||
|
false, isPacked, isUnsigned
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun wasmArrayForType(klass: String, isNullable: Boolean): String {
|
fun wasmArrayForType(
|
||||||
|
klass: String,
|
||||||
|
isNullable: Boolean,
|
||||||
|
isPacked: Boolean = false,
|
||||||
|
isUnsigned: Boolean = false,
|
||||||
|
): String {
|
||||||
val type = klass + if (isNullable) "?" else ""
|
val type = klass + if (isNullable) "?" else ""
|
||||||
val name = "Wasm${klass}Array"
|
val name = "Wasm${klass}Array"
|
||||||
|
val getSuffix = when {
|
||||||
|
isPacked && isUnsigned -> "_U"
|
||||||
|
isPacked && !isUnsigned -> "_S"
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
return """
|
return """
|
||||||
@WasmArrayOf($klass::class, isNullable = $isNullable)
|
@WasmArrayOf($klass::class, isNullable = $isNullable)
|
||||||
internal class $name(size: Int) {
|
internal class $name(size: Int) {
|
||||||
@WasmOp(WasmOp.ARRAY_GET)
|
@WasmOp(WasmOp.ARRAY_GET${getSuffix})
|
||||||
fun get(index: Int): $type =
|
fun get(index: Int): $type =
|
||||||
implementedAsIntrinsic
|
implementedAsIntrinsic
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user