[JS IR BE] Right support for inc and dec on primitive numbers

This commit is contained in:
Zalim Bashorov
2018-04-25 23:38:57 +03:00
parent 6725f085c7
commit 5c40892c57
6 changed files with 37 additions and 20 deletions
@@ -9,7 +9,7 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.lower.IntrinsicifyBuiltinOperationsLowering import org.jetbrains.kotlin.ir.backend.js.lower.IntrinsicifyCallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.SecondaryCtorLowering import org.jetbrains.kotlin.ir.backend.js.lower.SecondaryCtorLowering
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -62,5 +62,5 @@ fun JsIrBackendContext.lower(file: IrFile) {
InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file) InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file)
SecondaryCtorLowering(this).lower(file) SecondaryCtorLowering(this).lower(file)
IntrinsicifyBuiltinOperationsLowering(this).lower(file) IntrinsicifyCallsLowering(this).lower(file)
} }
@@ -6,15 +6,18 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass 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.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.name import org.jetbrains.kotlin.ir.backend.js.utils.name
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall 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.IrExpression
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl 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.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name 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.types.SimpleType
import org.jetbrains.kotlin.util.OperatorNameConventions 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? // TODO: should/can we unify these maps?
private val primitiveNumberIntrinsics: Map<SimpleMemberKey, IrSimpleFunction> private val memberToTransformer: Map<SimpleMemberKey, (IrCall) -> IrCall>
private val comparisonIntrinsics: Map<IrFunctionSymbol, IrSimpleFunction> private val memberToIrFunction: Map<SimpleMemberKey, IrSimpleFunction>
private val symbolToIrFunction: Map<IrFunctionSymbol, IrSimpleFunction>
init { init {
primitiveNumberIntrinsics = mutableMapOf() memberToIrFunction = mutableMapOf()
comparisonIntrinsics = 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) { for (type in primitiveNumbers) {
op(type, OperatorNameConventions.UNARY_PLUS, context.intrinsics.jsUnaryPlus) op(type, OperatorNameConventions.UNARY_PLUS, context.intrinsics.jsUnaryPlus)
op(type, OperatorNameConventions.UNARY_MINUS, context.intrinsics.jsUnaryMinus) 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.PLUS, context.intrinsics.jsPlus)
op(type, OperatorNameConventions.MINUS, context.intrinsics.jsMinus) op(type, OperatorNameConventions.MINUS, context.intrinsics.jsMinus)
op(type, OperatorNameConventions.TIMES, context.intrinsics.jsMult) 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) add(context.irBuiltIns.eqeqeqSymbol, context.intrinsics.jsEqeqeq)
// TODO: implement it a right way // TODO: implement it a right way
add(context.irBuiltIns.eqeqSymbol, context.intrinsics.jsEqeq) 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.greaterFunByOperandType, context.intrinsics.jsGt)
add(context.irBuiltIns.greaterOrEqualFunByOperandType, context.intrinsics.jsGtEq) 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) { override fun lower(irFile: IrFile) {
@@ -93,17 +110,21 @@ class IntrinsicifyBuiltinOperationsLowering(private val context: JsIrBackendCont
if (call is IrCall) { if (call is IrCall) {
val symbol = call.symbol val symbol = call.symbol
comparisonIntrinsics[symbol]?.let { symbolToIrFunction[symbol]?.let {
return irCall(call, it.symbol) return irCall(call, it.symbol)
} }
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let { (symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
val key = SimpleMemberKey(it.type, symbol.name) 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 // TODO: don't apply intrinsics when type of receiver or argument is Long
return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true) return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true)
} }
memberToTransformer[key]?.let {
return it(call)
}
} }
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1110 // EXPECTED_REACHABLE_NODES: 1110
package foo package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1122 // EXPECTED_REACHABLE_NODES: 1122
package foo package foo
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1121 // EXPECTED_REACHABLE_NODES: 1121
package foo package foo
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1112 // EXPECTED_REACHABLE_NODES: 1112
package foo package foo