[K/Wasm] Allow to export unsigned numbers

This commit is contained in:
Artem Kobzar
2023-12-08 09:06:19 +00:00
committed by Space Team
parent a3c1f4ea12
commit 2eb1e65bbf
19 changed files with 528 additions and 24 deletions
@@ -133,6 +133,12 @@ class WasmSymbols(
val voidType by lazy { voidClass.defaultType }
private val consumeAnyIntoVoid = getInternalFunction("consumeAnyIntoVoid")
val uByteType by lazy { getIrClass(FqName("kotlin.UByte")).defaultType }
val uShortType by lazy { getIrClass(FqName("kotlin.UShort")).defaultType }
val uIntType by lazy { getIrClass(FqName("kotlin.UInt")).defaultType }
val uLongType by lazy { getIrClass(FqName("kotlin.ULong")).defaultType }
private val consumePrimitiveIntoVoid = mapOf(
context.irBuiltIns.booleanType to getInternalFunction("consumeBooleanIntoVoid"),
context.irBuiltIns.byteType to getInternalFunction("consumeByteIntoVoid"),
@@ -325,6 +331,11 @@ class WasmSymbols(
val externRefToKotlinFloatAdapter = getInternalFunction("externRefToKotlinFloatAdapter")
val externRefToKotlinDoubleAdapter = getInternalFunction("externRefToKotlinDoubleAdapter")
val externRefToKotlinUByteAdapter = getInternalFunction("externRefToKotlinUByteAdapter")
val externRefToKotlinUShortAdapter = getInternalFunction("externRefToKotlinUShortAdapter")
val externRefToKotlinUIntAdapter = getInternalFunction("externRefToKotlinUIntAdapter")
val externRefToKotlinULongAdapter = getInternalFunction("externRefToKotlinULongAdapter")
val kotlinIntToExternRefAdapter = getInternalFunction("kotlinIntToExternRefAdapter")
val kotlinBooleanToExternRefAdapter = getInternalFunction("kotlinBooleanToExternRefAdapter")
val kotlinLongToExternRefAdapter = getInternalFunction("kotlinLongToExternRefAdapter")
@@ -333,6 +344,11 @@ class WasmSymbols(
val kotlinByteToExternRefAdapter = getInternalFunction("kotlinByteToExternRefAdapter")
val kotlinShortToExternRefAdapter = getInternalFunction("kotlinShortToExternRefAdapter")
val kotlinCharToExternRefAdapter = getInternalFunction("kotlinCharToExternRefAdapter")
val kotlinUByteToJsNumber = getInternalFunction("kotlinUByteToJsNumber")
val kotlinUShortToJsNumber = getInternalFunction("kotlinUShortToJsNumber")
val kotlinUIntToJsNumber = getInternalFunction("kotlinUIntToJsNumber")
val kotlinULongToJsBigInt = getInternalFunction("kotlinULongToJsBigInt")
}
inner class JsRelatedSymbols {
@@ -210,13 +210,19 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
val primitivesToExternRefAdapters: Map<IrType, InteropTypeAdapter> by lazy {
mapOf(
builtIns.byteType to adapters.kotlinByteToExternRefAdapter,
symbols.uByteType to adapters.kotlinUByteToJsNumber,
builtIns.shortType to adapters.kotlinShortToExternRefAdapter,
symbols.uShortType to adapters.kotlinUShortToJsNumber,
builtIns.charType to adapters.kotlinCharToExternRefAdapter,
builtIns.intType to adapters.kotlinIntToExternRefAdapter,
symbols.uIntType to adapters.kotlinUIntToJsNumber,
builtIns.longType to adapters.kotlinLongToExternRefAdapter,
symbols.uLongType to adapters.kotlinULongToJsBigInt,
builtIns.floatType to adapters.kotlinFloatToExternRefAdapter,
builtIns.doubleType to adapters.kotlinDoubleToExternRefAdapter,
).mapValues { FunctionBasedAdapter(it.value.owner) }
).mapValues {
FunctionBasedAdapter(it.value.owner)
}
}
private fun IrType.kotlinToJsAdapterIfNeeded(isReturn: Boolean): InteropTypeAdapter? {
@@ -263,6 +269,11 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
builtIns.anyType -> return FunctionBasedAdapter(adapters.kotlinToJsAnyAdapter.owner)
builtIns.numberType -> return FunctionBasedAdapter(adapters.numberToDoubleAdapter.owner)
symbols.uByteType -> return FunctionBasedAdapter(adapters.kotlinUByteToJsNumber.owner)
symbols.uShortType -> return FunctionBasedAdapter(adapters.kotlinUShortToJsNumber.owner)
symbols.uIntType -> return FunctionBasedAdapter(adapters.kotlinUIntToJsNumber.owner)
symbols.uLongType -> return FunctionBasedAdapter(adapters.kotlinULongToJsBigInt.owner)
builtIns.byteType,
builtIns.shortType,
builtIns.charType,
@@ -320,16 +331,28 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
return SendKotlinObjectToJsAdapter(this)
}
private fun createNullableAdapter(notNullType: IrType, isPrimitive: Boolean, valueAdapter: InteropTypeAdapter?): InteropTypeAdapter? {
return if (isPrimitive) { //nullable primitive should be checked and adapt to target type
private fun createNullableAdapter(
notNullType: IrType,
isPrimitiveOrUnsigned: Boolean,
valueAdapter: InteropTypeAdapter?
): InteropTypeAdapter? {
return if (isPrimitiveOrUnsigned) { //nullable primitive should be checked and adapt to target type
val externRefToPrimitiveAdapter = when (notNullType) {
builtIns.floatType -> adapters.externRefToKotlinFloatAdapter.owner
builtIns.doubleType -> adapters.externRefToKotlinDoubleAdapter.owner
builtIns.longType -> adapters.externRefToKotlinLongAdapter.owner
builtIns.booleanType -> adapters.externRefToKotlinBooleanAdapter.owner
symbols.uByteType -> adapters.externRefToKotlinUByteAdapter.owner
symbols.uShortType -> adapters.externRefToKotlinUShortAdapter.owner
symbols.uIntType -> adapters.externRefToKotlinUIntAdapter.owner
symbols.uLongType -> adapters.externRefToKotlinULongAdapter.owner
else -> adapters.externRefToKotlinIntAdapter.owner
}
val externalToPrimitiveAdapter = FunctionBasedAdapter(externRefToPrimitiveAdapter)
NullOrAdapter(
adapter = valueAdapter?.let { CombineAdapter(it, externalToPrimitiveAdapter) } ?: externalToPrimitiveAdapter
)
@@ -342,9 +365,13 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
}
}
private fun createNotNullAdapter(notNullType: IrType, isPrimitive: Boolean, valueAdapter: InteropTypeAdapter?): InteropTypeAdapter? {
private fun createNotNullAdapter(
notNullType: IrType,
isPrimitiveOrUnsigned: Boolean,
valueAdapter: InteropTypeAdapter?
): InteropTypeAdapter? {
// !nullable primitive checked by wasm signature
if (isPrimitive) return valueAdapter
if (isPrimitiveOrUnsigned) return valueAdapter
// !nullable reference should be null checked
// notNullAdapter((undefined -> null)!!)
@@ -367,12 +394,12 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
val notNullType = makeNotNull()
val valueAdapter = notNullType.jsToKotlinAdapterIfNeededNotNullable(isReturn)
val isPrimitive = valueAdapter?.fromType?.isPrimitiveType() ?: notNullType.isPrimitiveType()
val isPrimitiveOrUnsigned = (valueAdapter?.fromType ?: notNullType).let { it.isPrimitiveType() || it.isUnsigned() }
return if (isNullable())
createNullableAdapter(notNullType, isPrimitive, valueAdapter)
createNullableAdapter(notNullType, isPrimitiveOrUnsigned, valueAdapter)
else
createNotNullAdapter(notNullType, isPrimitive, valueAdapter)
createNotNullAdapter(notNullType, isPrimitiveOrUnsigned, valueAdapter)
}
private fun IrType.jsToKotlinAdapterIfNeededNotNullable(isReturn: Boolean): InteropTypeAdapter? {
@@ -386,12 +413,16 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
builtIns.shortType -> return FunctionBasedAdapter(adapters.jsToKotlinShortAdapter.owner)
builtIns.charType -> return FunctionBasedAdapter(adapters.jsToKotlinCharAdapter.owner)
symbols.uByteType,
symbols.uShortType,
symbols.uIntType,
symbols.uLongType,
builtIns.booleanType,
builtIns.intType,
builtIns.longType,
builtIns.floatType,
builtIns.doubleType,
context.wasmSymbols.voidType ->
symbols.voidType ->
return null
}