|
|
|
@@ -6,15 +6,18 @@
|
|
|
|
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
|
|
|
|
|
|
|
|
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|
|
|
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
|
|
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
|
|
|
|
import org.jetbrains.kotlin.ir.backend.js.utils.name
|
|
|
|
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
|
|
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
|
|
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
|
|
|
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
|
|
|
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
|
|
|
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
|
|
|
import org.jetbrains.kotlin.name.Name
|
|
|
|
@@ -22,27 +25,25 @@ import org.jetbrains.kotlin.types.KotlinType
|
|
|
|
|
import org.jetbrains.kotlin.types.SimpleType
|
|
|
|
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
|
|
|
|
|
|
|
|
class IntrinsicifyBuiltinOperationsLowering(private val context: JsIrBackendContext) : FileLoweringPass {
|
|
|
|
|
class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileLoweringPass {
|
|
|
|
|
|
|
|
|
|
// TODO: should/can we unify these maps?
|
|
|
|
|
private val primitiveNumberIntrinsics: Map<SimpleMemberKey, IrSimpleFunction>
|
|
|
|
|
private val comparisonIntrinsics: Map<IrFunctionSymbol, IrSimpleFunction>
|
|
|
|
|
private val memberToTransformer: Map<SimpleMemberKey, (IrCall) -> IrCall>
|
|
|
|
|
private val memberToIrFunction: Map<SimpleMemberKey, IrSimpleFunction>
|
|
|
|
|
private val symbolToIrFunction: Map<IrFunctionSymbol, IrSimpleFunction>
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
|
primitiveNumberIntrinsics = mutableMapOf()
|
|
|
|
|
comparisonIntrinsics = mutableMapOf()
|
|
|
|
|
memberToIrFunction = mutableMapOf()
|
|
|
|
|
symbolToIrFunction = mutableMapOf()
|
|
|
|
|
memberToTransformer = mutableMapOf()
|
|
|
|
|
|
|
|
|
|
primitiveNumberIntrinsics.run {
|
|
|
|
|
val primitiveNumbers = context.irBuiltIns.run { listOf(int, short, byte, float, double) }
|
|
|
|
|
val primitiveNumbers = context.irBuiltIns.run { listOf(int, short, byte, float, double) }
|
|
|
|
|
|
|
|
|
|
memberToIrFunction.run {
|
|
|
|
|
for (type in primitiveNumbers) {
|
|
|
|
|
op(type, OperatorNameConventions.UNARY_PLUS, context.intrinsics.jsUnaryPlus)
|
|
|
|
|
op(type, OperatorNameConventions.UNARY_MINUS, context.intrinsics.jsUnaryMinus)
|
|
|
|
|
|
|
|
|
|
// TODO: inc & dec are mapped wrongly
|
|
|
|
|
op(type, OperatorNameConventions.INC, context.intrinsics.jsPrefixInc)
|
|
|
|
|
op(type, OperatorNameConventions.DEC, context.intrinsics.jsPrefixDec)
|
|
|
|
|
|
|
|
|
|
op(type, OperatorNameConventions.PLUS, context.intrinsics.jsPlus)
|
|
|
|
|
op(type, OperatorNameConventions.MINUS, context.intrinsics.jsMinus)
|
|
|
|
|
op(type, OperatorNameConventions.TIMES, context.intrinsics.jsMult)
|
|
|
|
@@ -69,7 +70,7 @@ class IntrinsicifyBuiltinOperationsLowering(private val context: JsIrBackendCont
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
comparisonIntrinsics.run {
|
|
|
|
|
symbolToIrFunction.run {
|
|
|
|
|
add(context.irBuiltIns.eqeqeqSymbol, context.intrinsics.jsEqeqeq)
|
|
|
|
|
// TODO: implement it a right way
|
|
|
|
|
add(context.irBuiltIns.eqeqSymbol, context.intrinsics.jsEqeq)
|
|
|
|
@@ -83,6 +84,22 @@ class IntrinsicifyBuiltinOperationsLowering(private val context: JsIrBackendCont
|
|
|
|
|
add(context.irBuiltIns.greaterFunByOperandType, context.intrinsics.jsGt)
|
|
|
|
|
add(context.irBuiltIns.greaterOrEqualFunByOperandType, context.intrinsics.jsGtEq)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memberToTransformer.run {
|
|
|
|
|
for (type in primitiveNumbers) {
|
|
|
|
|
// TODO: use increment and decrement when it's possible
|
|
|
|
|
op(type, OperatorNameConventions.INC) {
|
|
|
|
|
irCall(it, context.intrinsics.jsPlus.symbol, dispatchReceiverAsFirstArgument = true).apply {
|
|
|
|
|
putValueArgument(1, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.int, IrConstKind.Int, 1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
op(type, OperatorNameConventions.DEC) {
|
|
|
|
|
irCall(it, context.intrinsics.jsMinus.symbol, dispatchReceiverAsFirstArgument = true).apply {
|
|
|
|
|
putValueArgument(1, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.int, IrConstKind.Int, 1))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun lower(irFile: IrFile) {
|
|
|
|
@@ -93,17 +110,21 @@ class IntrinsicifyBuiltinOperationsLowering(private val context: JsIrBackendCont
|
|
|
|
|
if (call is IrCall) {
|
|
|
|
|
val symbol = call.symbol
|
|
|
|
|
|
|
|
|
|
comparisonIntrinsics[symbol]?.let {
|
|
|
|
|
symbolToIrFunction[symbol]?.let {
|
|
|
|
|
return irCall(call, it.symbol)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
|
|
|
|
|
val key = SimpleMemberKey(it.type, symbol.name)
|
|
|
|
|
|
|
|
|
|
primitiveNumberIntrinsics[key]?.let {
|
|
|
|
|
memberToIrFunction[key]?.let {
|
|
|
|
|
// TODO: don't apply intrinsics when type of receiver or argument is Long
|
|
|
|
|
return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memberToTransformer[key]?.let {
|
|
|
|
|
return it(call)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|