From 783f27c554457bc2a0c790ec3d3178cbe57198c4 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Wed, 10 Oct 2018 20:50:01 +0300 Subject: [PATCH] [JS IR BE] Support Number.to(Byte|Short|Int|Float|Double|Long) --- .../kotlin/ir/backend/js/JsIntrinsics.kt | 3 +++ .../js/lower/calls/CallsLoweringUtils.kt | 13 +++++----- .../calls/NumberConversionCallsTransformer.kt | 26 +++++++++++-------- .../kotlin/ir/descriptors/IrBuiltIns.kt | 4 +++ .../stdlib/js/irRuntime/numberConversion.kt | 8 +++--- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt index 439612e4b6f..144f559aea9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl +import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.getPropertyGetter import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -101,6 +102,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC val jsNumberToInt = getInternalFunction("numberToInt") val jsNumberToShort = getInternalFunction("numberToShort") val jsNumberToLong = getInternalFunction("numberToLong") + val jsNumberToChar = getInternalFunction("numberToChar") val jsToByte = getInternalFunction("toByte") val jsToShort = getInternalFunction("toShort") val jsToLong = getInternalFunction("toLong") @@ -174,6 +176,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC ) val charClassSymbol = getInternalClassWithoutPackage("kotlin.Char") + val charConstructor = charClassSymbol.constructors.single().owner val uByteClassSymbol = getInternalClassWithoutPackage("kotlin.UByte") val uShortClassSymbol = getInternalClassWithoutPackage("kotlin.UShort") diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt index 13fd26f2915..e0c308d529c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/CallsLoweringUtils.kt @@ -6,11 +6,10 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls import org.jetbrains.kotlin.ir.backend.js.ir.irCall -import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol -import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.name.Name @@ -18,13 +17,13 @@ import org.jetbrains.kotlin.types.SimpleType typealias SymbolToTransformer = MutableMap IrExpression> -internal fun SymbolToTransformer.add(from: Map, to: IrSimpleFunction) { +internal fun SymbolToTransformer.add(from: Map, to: IrFunction) { from.forEach { _, func -> add(func.symbol, to) } } -internal fun SymbolToTransformer.add(from: Map, to: (IrCall) -> IrExpression) { +internal fun SymbolToTransformer.add(from: Map, to: (IrCall) -> IrExpression) { from.forEach { _, func -> add(func.symbol, to) } @@ -34,7 +33,7 @@ internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrCall) -> IrE put(from, to) } -internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrSimpleFunction, dispatchReceiverAsFirstArgument: Boolean = false) { +internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrFunction, dispatchReceiverAsFirstArgument: Boolean = false) { put(from) { call -> irCall(call, to.symbol, dispatchReceiverAsFirstArgument) } } @@ -48,11 +47,11 @@ internal fun MutableMap IrExpression>.addWithPredicate( internal typealias MemberToTransformer = HashMap IrExpression> -internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrSimpleFunctionSymbol) { +internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) { add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) } } -internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrSimpleFunction) { +internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) { add(type, name, v.symbol) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt index 4f81d9f573e..987552f6ab2 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/calls/NumberConversionCallsTransformer.kt @@ -64,21 +64,25 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans add(it, ConversionNames.TO_LONG, intrinsics.jsToLong) } - for (type in arrayOf(irBuiltIns.byteType, irBuiltIns.intType)) { - add(type, ConversionNames.TO_CHAR) { - irCall(it, intrinsics.charClassSymbol.constructors.single(), dispatchReceiverAsFirstArgument = true) - } + + irBuiltIns.numberType.let { + add(it, ConversionNames.TO_BYTE, intrinsics.jsNumberToByte) + add(it, ConversionNames.TO_DOUBLE, intrinsics.jsNumberToDouble) + add(it, ConversionNames.TO_FLOAT, intrinsics.jsNumberToDouble) + add(it, ConversionNames.TO_INT, intrinsics.jsNumberToInt) + add(it, ConversionNames.TO_SHORT, intrinsics.jsNumberToShort) + add(it, ConversionNames.TO_LONG, intrinsics.jsNumberToLong) } - for (type in arrayOf(irBuiltIns.floatType, irBuiltIns.doubleType)) { - add(type, ConversionNames.TO_CHAR) { - JsIrBuilder.buildCall(intrinsics.charClassSymbol.constructors.single()).apply { - putValueArgument(0, irCall(it, intrinsics.jsNumberToInt, dispatchReceiverAsFirstArgument = true)) - } - } + for (type in arrayOf(irBuiltIns.byteType, irBuiltIns.shortType, irBuiltIns.intType)) { + add(type, ConversionNames.TO_CHAR, intrinsics.charConstructor) } - add(irBuiltIns.charType, ConversionNames.TO_CHAR) { it.dispatchReceiver!! } + for (type in arrayOf(irBuiltIns.floatType, irBuiltIns.doubleType, irBuiltIns.numberType)) { + add(type, ConversionNames.TO_CHAR, intrinsics.jsNumberToChar) + } + + add(irBuiltIns.charType, ConversionNames.TO_CHAR, ::useDispatchReceiver) } override fun transformCall(call: IrCall): IrExpression { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index ead0770c06f..5668661e2de 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -86,6 +86,10 @@ class IrBuiltIns( val charType = char.toIrType() val charClass = builtIns.char.toIrSymbol() + val number = builtIns.number.defaultType + val numberType = number.toIrType() + val numberClass = builtIns.number.toIrSymbol() + val byte = builtIns.byteType val byteType = byte.toIrType() val byteClass = builtIns.byte.toIrSymbol() diff --git a/libraries/stdlib/js/irRuntime/numberConversion.kt b/libraries/stdlib/js/irRuntime/numberConversion.kt index 024b3bbb611..acfdbff8e6e 100644 --- a/libraries/stdlib/js/irRuntime/numberConversion.kt +++ b/libraries/stdlib/js/irRuntime/numberConversion.kt @@ -9,7 +9,7 @@ fun numberToByte(a: dynamic): Byte = toByte(numberToInt(a)) fun numberToDouble(a: dynamic): Double = js("+a").unsafeCast() -fun numberToInt(a: dynamic): Int = doubleToInt(a) +fun numberToInt(a: dynamic): Int = if (a is Long) a.toInt() else doubleToInt(a) fun numberToShort(a: dynamic): Short = toShort(numberToInt(a)) @@ -17,7 +17,7 @@ fun numberToShort(a: dynamic): Short = toShort(numberToInt(a)) fun toByte(a: dynamic): Byte = js("a << 24 >> 24").unsafeCast() fun toShort(a: dynamic): Short = js("a << 16 >> 16").unsafeCast() -fun numberToLong(a: dynamic): Long = fromNumber(a) +fun numberToLong(a: dynamic): Long = if (a is Long) a else fromNumber(a) fun toLong(a: dynamic): Long = fromInt(a) @@ -25,4 +25,6 @@ fun doubleToInt(a: dynamic) = js(""" if (a > 2147483647) return 2147483647; if (a < -2147483648) return -2147483648; return a | 0; -""").unsafeCast() \ No newline at end of file +""").unsafeCast() + +fun numberToChar(a: dynamic) = Char(numberToInt(a)) \ No newline at end of file