Fix JS_IR IrConstructorCall support

This commit is contained in:
Roman Artemev
2019-04-12 18:29:44 +03:00
committed by Dmitry Petrov
parent 2a3ce8e9f1
commit c545481db9
25 changed files with 295 additions and 161 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -216,40 +217,10 @@ open class DefaultParameterInjector(
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
super.visitDelegatingConstructorCall(expression)
val declaration = expression.symbol.owner as IrFunction
if (!declaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
return expression
val argumentsCount = argumentCount(expression)
if (argumentsCount == declaration.valueParameters.size)
return expression
val (symbolForCall, params) = parametersForCall(expression)
return IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = context.irBuiltIns.unitType,
symbol = symbolForCall as IrConstructorSymbol,
descriptor = symbolForCall.descriptor,
typeArgumentsCount = expression.typeArgumentsCount
)
.apply {
copyTypeArgumentsFrom(expression)
params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
putValueArgument(it.first.index, it.second)
}
dispatchReceiver = expression.dispatchReceiver
}
}
override fun visitCall(expression: IrCall): IrExpression {
super.visitCall(expression)
private fun visitFunctionAccessExpression(
expression: IrFunctionAccessExpression,
builder: (IrFunctionSymbol) -> IrFunctionAccessExpression
): IrExpression {
val functionDeclaration = expression.symbol.owner
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
@@ -268,30 +239,66 @@ open class DefaultParameterInjector(
}
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } }
return IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = symbol.owner.returnType,
symbol = symbol,
descriptor = descriptor,
typeArgumentsCount = expression.typeArgumentsCount,
origin = DEFAULT_DISPATCH_CALL,
superQualifierSymbol = expression.superQualifierSymbol
)
.apply {
this.copyTypeArgumentsFrom(expression)
return builder(symbol).apply {
this.copyTypeArgumentsFrom(expression)
params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
putValueArgument(it.first.index, it.second)
}
dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
params.forEach {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
putValueArgument(it.first.index, it.second)
}
dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
}
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
super.visitDelegatingConstructorCall(expression)
return visitFunctionAccessExpression(expression) {
IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = context.irBuiltIns.unitType,
symbol = it as IrConstructorSymbol,
descriptor = it.descriptor,
typeArgumentsCount = expression.typeArgumentsCount
)
}
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
super.visitConstructorCall(expression)
return visitFunctionAccessExpression(expression) {
IrConstructorCallImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
it.owner.returnType,
it as IrConstructorSymbol,
DEFAULT_DISPATCH_CALL
)
}
}
override fun visitCall(expression: IrCall): IrExpression {
super.visitCall(expression)
return visitFunctionAccessExpression(expression) {
IrCallImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = it.owner.returnType,
symbol = it,
descriptor = it.descriptor,
typeArgumentsCount = expression.typeArgumentsCount,
origin = DEFAULT_DISPATCH_CALL,
superQualifierSymbol = expression.superQualifierSymbol
)
}
}
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
@@ -183,6 +183,16 @@ class InlineClassLowering(val context: BackendContext) {
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
expression.transformChildrenVoid(this)
val function = expression.symbol.owner
if (!function.parentAsClass.isInline || function.isPrimary) {
return expression
}
return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsFirstArgument = false)
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
val function = expression.symbol.owner
@@ -208,7 +218,7 @@ class InlineClassLowering(val context: BackendContext) {
val klass = function.parentAsClass
return when {
!klass.isInline -> expression
function.isPrimary -> irCall(expression, function)
function.isPrimary -> irConstructorCall(expression, function)
else -> irCall(expression, getOrCreateStaticMethod(function)).apply {
(0 until expression.valueArgumentsCount).forEach {
putValueArgument(it, expression.getValueArgument(it)!!)
@@ -48,7 +48,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
val constructorSymbol = closureBoxConstructorDeclaration.symbol
val irCall = IrCallImpl(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol).apply {
val irCall = IrConstructorCallImpl.fromSymbolDescriptor(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol).apply {
putValueArgument(0, initializer)
}
@@ -132,6 +132,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
descriptor.bind(declaration)
declaration.parent = implicitDeclarationsFile
// TODO: substitute
closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList())
declaration.thisReceiver =
JsIrBuilder.buildValueParameter(Name.special("<this>"), -1, closureBoxType, IrDeclarationOrigin.INSTANCE_RECEIVER).apply {
@@ -9,7 +9,11 @@ import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.util.irCall
@@ -23,9 +27,11 @@ class ArrayConstructorTransformer(
it.inlineConstructor to it.sizeConstructor
}
fun transformCall(expression: IrCall): IrCall {
fun transformConstructorCall(expression: IrConstructorCall): IrFunctionAccessExpression {
if (expression.symbol == context.intrinsics.array.inlineConstructor) {
return irCall(expression, context.intrinsics.jsArray)
return irCall(expression, context.intrinsics.jsArray).apply {
copyTypeArgumentsFrom(expression)
}
} else {
primitiveArrayInlineToSizeConstructorMap[expression.symbol]?.let { sizeConstructor ->
return IrCallImpl(
@@ -34,7 +40,7 @@ class ArrayConstructorTransformer(
expression.type,
context.intrinsics.jsFillArray
).apply {
putValueArgument(0, IrCallImpl(
putValueArgument(0, IrConstructorCallImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
expression.type,
@@ -29,6 +29,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
override fun IrExpression.useAs(type: IrType): IrExpression {
val actualType = when (this) {
is IrConstructorCall -> symbol.owner.returnType
is IrCall -> {
val function = this.symbol.owner
if (function.let { it is IrSimpleFunction && it.isSuspend }) {
@@ -127,8 +128,9 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
private val IrFunctionAccessExpression.target: IrFunction
get() = when (this) {
is IrCall -> this.callTarget
is IrConstructorCall -> this.symbol.owner
is IrDelegatingConstructorCall -> this.symbol.owner
is IrCall -> this.callTarget
else -> TODO(this.render())
}
@@ -21,7 +21,9 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
@@ -517,7 +519,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val callTarget = context.ir.defaultParameterDeclarationsCache[declaration] ?: declaration
val irCall = JsIrBuilder.buildCall(callTarget.symbol, type = returnType)
val target = callTarget.symbol
val irCall =
if (target is IrConstructorSymbol) IrConstructorCallImpl.fromSymbolOwner(returnType, target) else JsIrBuilder.buildCall(
callTarget.symbol,
type = returnType
)
var cp = 0
var gp = 0
@@ -14,10 +14,12 @@ import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.isUnsigned
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -31,7 +33,7 @@ class ConstTransformer(private val context: JsIrBackendContext) : IrElementTrans
): IrExpression {
val constructor = irClass.constructors.single()
val argType = constructor.owner.valueParameters.first().type
return JsIrBuilder.buildCall(constructor).apply {
return IrConstructorCallImpl.fromSymbolOwner(irClass.owner.defaultType, constructor).apply {
for (i in args.indices) {
putValueArgument(i, carrierFactory(UNDEFINED_OFFSET, UNDEFINED_OFFSET, argType, args[i]))
}
@@ -192,20 +192,19 @@ private class CallsiteRedirectionTransformer(context: JsIrBackendContext) : IrEl
private val oldCtorToNewMap = context.secondaryConstructorToFactoryCache
private val defaultThrowableConstructor = context.defaultThrowableCtor
private val IrFunction.isSecondaryConstructorCall
private val IrConstructor.isSecondaryConstructorCall
get() =
this is IrConstructor && !isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline
!isPrimary && this != defaultThrowableConstructor && !isExternal && !parentAsClass.isInline
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
override fun visitCall(expression: IrCall, data: IrFunction?): IrElement {
super.visitCall(expression, data)
override fun visitConstructorCall(expression: IrConstructorCall, data: IrFunction?): IrElement {
super.visitConstructorCall(expression, data)
val target = expression.symbol.owner
return if (target.isSecondaryConstructorCall) {
val constructor = target as IrConstructor
val ctor = oldCtorToNewMap.getOrPut(constructor) {
buildConstructorStubDeclarations(constructor, constructor.parentAsClass)
val ctor = oldCtorToNewMap.getOrPut(target) {
buildConstructorStubDeclarations(target, target.parentAsClass)
}
replaceSecondaryConstructorWithFactoryFunction(expression, ctor.stub.symbol)
} else expression
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.defaultType
@@ -135,7 +136,7 @@ class TestGenerator(val context: JsIrBackendContext) : FileLoweringPass {
JsIrBuilder.buildGetObjectValue(defaultType, symbol)
} else {
declarations.asSequence().filterIsInstance<IrConstructor>().single { it.isPrimary }.let { constructor ->
JsIrBuilder.buildCall(constructor.symbol).also {
IrConstructorCallImpl.fromSymbolOwner(defaultType, constructor.symbol).also {
if (isInner) {
it.dispatchReceiver = (parent as IrClass).instance()
}
@@ -108,8 +108,8 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
}
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
if (expression.symbol !in throwableConstructors) return super.visitCall(expression)
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
if (expression.symbol !in throwableConstructors) return super.visitConstructorCall(expression)
expression.transformChildrenVoid(this)
@@ -10,11 +10,9 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrSpreadElement
import org.jetbrains.kotlin.ir.expressions.IrVararg
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.IrType
@@ -67,7 +65,7 @@ private class VarargTransformer(
if (inlineClass == null)
this
else
IrCallImpl(startOffset, endOffset, inlineClass.defaultType, inlineClass.constructors.single { it.isPrimary }.symbol).also {
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, inlineClass.defaultType, inlineClass.constructors.single { it.isPrimary }.symbol).also {
it.putValueArgument(0, this)
}
@@ -165,7 +163,7 @@ private class VarargTransformer(
res
}
override fun visitCall(expression: IrCall): IrExpression {
private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression {
expression.transformChildrenVoid()
val size = expression.valueArgumentsCount
@@ -179,4 +177,7 @@ private class VarargTransformer(
return expression
}
override fun visitCall(expression: IrCall) = transformFunctionAccessExpression(expression)
override fun visitConstructorCall(expression: IrConstructorCall) = transformFunctionAccessExpression(expression)
}
@@ -10,8 +10,8 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile
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.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -36,11 +36,11 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass {
return super.visitFunction(declaration)
}
override fun visitCall(expression: IrCall): IrExpression {
val call = super.visitCall(expression)
if (call is IrCall) {
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
val call = super.visitFunctionAccess(expression)
if (call is IrFunctionAccessExpression) {
for (transformer in transformers) {
val newCall = transformer.transformCall(call)
val newCall = transformer.transformFunctionAccess(call)
if (newCall !== call) {
return newCall
}
@@ -53,5 +53,5 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
interface CallsTransformer {
fun transformCall(call: IrCall): IrExpression
fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression
}
@@ -8,13 +8,14 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
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.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SimpleType
typealias SymbolToTransformer = MutableMap<IrFunctionSymbol, (IrCall) -> IrExpression>
typealias SymbolToTransformer = MutableMap<IrFunctionSymbol, (IrFunctionAccessExpression) -> IrExpression>
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunctionSymbol>, to: IrFunctionSymbol) {
from.forEach { _, func ->
@@ -22,13 +23,13 @@ internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunctionSymbol>, to
}
}
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunctionSymbol>, to: (IrCall) -> IrExpression) {
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunctionSymbol>, to: (IrFunctionAccessExpression) -> IrExpression) {
from.forEach { _, func ->
add(func, to)
}
}
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrCall) -> IrExpression) {
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrFunctionAccessExpression) -> IrExpression) {
put(from, to)
}
@@ -36,15 +37,15 @@ internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrFunctionSymbo
put(from) { call -> irCall(call, to, dispatchReceiverAsFirstArgument) }
}
internal fun <K> MutableMap<K, (IrCall) -> IrExpression>.addWithPredicate(
internal fun <K> MutableMap<K, (IrFunctionAccessExpression) -> IrExpression>.addWithPredicate(
from: K,
predicate: (IrCall) -> Boolean,
action: (IrCall) -> IrExpression
predicate: (IrFunctionAccessExpression) -> Boolean,
action: (IrFunctionAccessExpression) -> IrExpression
) {
put(from) { call: IrCall -> if (predicate(call)) action(call) else call }
put(from) { call: IrFunctionAccessExpression -> if (predicate(call)) action(call) else call }
}
internal typealias MemberToTransformer = HashMap<SimpleMemberKey, (IrCall) -> IrExpression>
internal typealias MemberToTransformer = HashMap<SimpleMemberKey, (IrFunctionAccessExpression) -> IrExpression>
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) {
add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) }
@@ -54,7 +55,7 @@ internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunction) {
add(type, name, v.symbol)
}
internal fun MemberToTransformer.add(type: IrType, name: Name, v: (IrCall) -> IrExpression) {
internal fun MemberToTransformer.add(type: IrType, name: Name, v: (IrFunctionAccessExpression) -> IrExpression) {
put(SimpleMemberKey(type, name), v)
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.isStaticMethodOfClass
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isString
import org.jetbrains.kotlin.ir.util.findDeclaration
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.name.Name
class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
private fun transformEnumTopLevelIntrinsic(
call: IrCall,
call: IrFunctionAccessExpression,
staticMethodPredicate: (IrSimpleFunction) -> Boolean
): IrExpression {
val enum = call.getTypeArgument(0)?.getClass() ?: return call
@@ -32,17 +33,17 @@ class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : Calls
return irCall(call, staticMethod.symbol)
}
private fun transformEnumValueOfIntrinsic(call: IrCall) = transformEnumTopLevelIntrinsic(call) {
private fun transformEnumValueOfIntrinsic(call: IrFunctionAccessExpression) = transformEnumTopLevelIntrinsic(call) {
it.name == Name.identifier("valueOf") &&
it.valueParameters.count() == 1 &&
it.valueParameters[0].type.isString()
}
private fun transformEnumValuesIntrinsic(call: IrCall) = transformEnumTopLevelIntrinsic(call) {
private fun transformEnumValuesIntrinsic(call: IrFunctionAccessExpression) = transformEnumTopLevelIntrinsic(call) {
it.name == Name.identifier("values") && it.valueParameters.count() == 0
}
override fun transformCall(call: IrCall) = when (call.symbol) {
override fun transformFunctionAccess(call: IrFunctionAccessExpression) = when (call.symbol) {
context.intrinsics.enumValueOfIntrinsic -> transformEnumValueOfIntrinsic(call)
context.intrinsics.enumValuesIntrinsic -> transformEnumValuesIntrinsic(call)
else -> call
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
@@ -45,7 +46,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
}
}
private fun transformLongComparison(comparator: IrSimpleFunctionSymbol): (IrCall) -> IrExpression = { call ->
private fun transformLongComparison(comparator: IrSimpleFunctionSymbol): (IrFunctionAccessExpression) -> IrExpression = { call ->
IrCallImpl(
call.startOffset,
call.endOffset,
@@ -57,7 +58,7 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
}
}
override fun transformCall(call: IrCall): IrExpression {
override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression {
val symbol = call.symbol
symbolToTransformer[symbol]?.let {
return it(call)
@@ -65,12 +66,12 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
return when (symbol.owner.name) {
Name.identifier("compareTo") -> transformCompareToMethodCall(call)
Name.identifier("equals") -> transformEqualsMethodCall(call)
Name.identifier("equals") -> transformEqualsMethodCall(call as IrCall)
else -> call
}
}
private fun transformEqeqOperator(call: IrCall): IrExpression {
private fun transformEqeqOperator(call: IrFunctionAccessExpression): IrExpression {
val lhs = call.getValueArgument(0)!!
val rhs = call.getValueArgument(1)!!
@@ -101,17 +102,17 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
}
}
private fun chooseEqualityOperatorForPrimitiveTypes(call: IrCall): IrExpression = when {
private fun chooseEqualityOperatorForPrimitiveTypes(call: IrFunctionAccessExpression): IrExpression = when {
call.allValueArgumentsAreNullable() ->
irCall(call, intrinsics.jsEqeq)
else ->
irCall(call, intrinsics.jsEqeqeq)
}
private fun IrCall.allValueArgumentsAreNullable() =
private fun IrFunctionAccessExpression.allValueArgumentsAreNullable() =
(0 until valueArgumentsCount).all { getValueArgument(it)!!.type.isNullable() }
private fun transformCompareToMethodCall(call: IrCall): IrExpression {
private fun transformCompareToMethodCall(call: IrFunctionAccessExpression): IrExpression {
val function = call.symbol.owner as IrSimpleFunction
if (function.parent !is IrClass) return call
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -26,5 +27,5 @@ class ExceptionHelperCallsTransformer(private val context: JsIrBackendContext) :
)
override fun transformCall(call: IrCall) = helperMapping[call.symbol]?.let { irCall(call, it) } ?: call
override fun transformFunctionAccess(call: IrFunctionAccessExpression) = helperMapping[call.symbol]?.let { irCall(call, it) } ?: call
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isArray
@@ -21,14 +22,14 @@ import org.jetbrains.kotlin.name.Name
class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
private val intrinsics = context.intrinsics
private val nameToTransformer: Map<Name, (IrCall) -> IrExpression>
private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression>
init {
nameToTransformer = mutableMapOf()
nameToTransformer.run {
put(Name.identifier("toString")) { call ->
if (shouldReplaceToStringWithRuntimeCall(call)) {
if (call.isSuperToAny()) {
if ((call as IrCall).isSuperToAny()) {
irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsFirstArgument = true)
} else {
irCall(call, intrinsics.jsToString, dispatchReceiverAsFirstArgument = true)
@@ -40,7 +41,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
put(Name.identifier("hashCode")) { call ->
if (call.symbol.owner.isFakeOverriddenFromAny()) {
if (call.isSuperToAny()) {
if ((call as IrCall).isSuperToAny()) {
irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true)
} else {
irCall(call, intrinsics.jsHashCode, dispatchReceiverAsFirstArgument = true)
@@ -53,7 +54,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
}
override fun transformCall(call: IrCall): IrExpression {
override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression {
val symbol = call.symbol
nameToTransformer[symbol.owner.name]?.let {
return it(call)
@@ -62,7 +63,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
return call
}
private fun shouldReplaceToStringWithRuntimeCall(call: IrCall): Boolean {
private fun shouldReplaceToStringWithRuntimeCall(call: IrFunctionAccessExpression): Boolean {
// TODO: (KOTLIN-CR-2079)
// - User defined extension functions Any?.toString() call can be lost during lowering.
// - Use direct method call for dynamic types???
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.ConversionNames
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
private val intrinsics = context.intrinsics
@@ -74,7 +75,7 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans
}
}
override fun transformCall(call: IrCall): IrExpression {
override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression {
val function = call.symbol.owner
function.dispatchReceiverParameter?.also {
val key = SimpleMemberKey(it.type, function.name)
@@ -85,7 +86,7 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans
return call
}
private fun useDispatchReceiver(call: IrCall): IrExpression {
private fun useDispatchReceiver(call: IrFunctionAccessExpression): IrExpression {
return JsIrBuilder.buildImplicitCast(call.dispatchReceiver!!, call.type)
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
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.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
@@ -71,7 +72,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
}
}
override fun transformCall(call: IrCall): IrExpression {
override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression {
val function = call.symbol.owner
function.dispatchReceiverParameter?.also {
val key = SimpleMemberKey(it.type, function.name)
@@ -82,7 +83,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
return call
}
private fun transformRangeTo(call: IrCall): IrExpression {
private fun transformRangeTo(call: IrFunctionAccessExpression): IrExpression {
if (call.valueArgumentsCount != 1) return call
return with(call.symbol.owner.valueParameters[0].type) {
when {
@@ -96,7 +97,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
}
private fun irBinaryOp(
call: IrCall,
call: IrFunctionAccessExpression,
intrinsic: IrFunctionSymbol,
toInt32: Boolean = false
): IrExpression {
@@ -106,7 +107,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
return newCall
}
class BinaryOp(call: IrCall) {
class BinaryOp(call: IrFunctionAccessExpression) {
val function = call.symbol.owner
val name = function.name
val lhs = function.dispatchReceiverParameter!!.type
@@ -117,13 +118,13 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
result.isInt() && (lhs.isInt() || rhs.isInt())
}
private fun transformAdd(call: IrCall) =
private fun transformAdd(call: IrFunctionAccessExpression) =
irBinaryOp(call, intrinsics.jsPlus, toInt32 = BinaryOp(call).canAddOrSubOverflow())
private fun transformSub(call: IrCall) =
private fun transformSub(call: IrFunctionAccessExpression) =
irBinaryOp(call, intrinsics.jsMinus, toInt32 = BinaryOp(call).canAddOrSubOverflow())
private fun transformMul(call: IrCall) = BinaryOp(call).run {
private fun transformMul(call: IrFunctionAccessExpression) = BinaryOp(call).run {
when {
result.isInt() -> when {
@@ -138,19 +139,19 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
}
}
private fun transformDiv(call: IrCall) =
private fun transformDiv(call: IrFunctionAccessExpression) =
irBinaryOp(call, intrinsics.jsDiv, toInt32 = BinaryOp(call).result.isInt())
private fun transformRem(call: IrCall) =
private fun transformRem(call: IrFunctionAccessExpression) =
irBinaryOp(call, intrinsics.jsMod)
private fun transformIncrement(call: IrCall) =
private fun transformIncrement(call: IrFunctionAccessExpression) =
transformCrement(call, intrinsics.jsPlus)
private fun transformDecrement(call: IrCall) =
private fun transformDecrement(call: IrFunctionAccessExpression) =
transformCrement(call, intrinsics.jsMinus)
private fun transformCrement(call: IrCall, correspondingBinaryOp: IrFunctionSymbol): IrExpression {
private fun transformCrement(call: IrFunctionAccessExpression, correspondingBinaryOp: IrFunctionSymbol): IrExpression {
val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsFirstArgument = true).apply {
putValueArgument(1, buildInt(1))
}
@@ -158,7 +159,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
return convertResultToPrimitiveType(operation, call.type)
}
private fun transformUnaryMinus(call: IrCall) =
private fun transformUnaryMinus(call: IrFunctionAccessExpression) =
convertResultToPrimitiveType(
irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsFirstArgument = true),
call.type
@@ -171,7 +172,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
else -> e
}
private fun withLongCoercion(default: (IrCall) -> IrExpression): (IrCall) -> IrExpression = { call ->
private fun withLongCoercion(default: (IrFunctionAccessExpression) -> IrExpression): (IrFunctionAccessExpression) -> IrExpression = { call ->
assert(call.valueArgumentsCount == 1)
val arg = call.getValueArgument(0)!!
@@ -8,9 +8,12 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.getSimpleFunction
import org.jetbrains.kotlin.ir.util.getPropertyGetter
@@ -56,13 +59,13 @@ class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendCo
}
}
override fun transformCall(call: IrCall): IrExpression {
val symbol = call.symbol
override fun transformFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
val symbol = expression.symbol
symbolToTransformer[symbol]?.let {
return it(call)
return it(expression)
}
return call
return expression
}
}
@@ -10,12 +10,13 @@ import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.name.Name
class ReflectionCallsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
private val nameToTransformer: Map<Name, (IrCall) -> IrExpression>
private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression>
init {
nameToTransformer = mutableMapOf()
@@ -45,7 +46,7 @@ class ReflectionCallsTransformer(private val context: JsIrBackendContext) : Call
}
}
override fun transformCall(call: IrCall): IrExpression {
override fun transformFunctionAccess(call: IrFunctionAccessExpression): IrExpression {
val symbol = call.symbol
nameToTransformer[symbol.owner.name]?.let {
return it(call)
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.util.*
@@ -48,8 +45,22 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
private val arrayConstructorTransformer = ArrayConstructorTransformer(context)
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val callSite = arrayConstructorTransformer.transformConstructorCall(super.visitConstructorCall(expression) as IrConstructorCall)
if (!callSite.symbol.owner.needsInlining)
return callSite
val callee = getFunctionDeclaration(callSite.symbol) // Get declaration of the function to be inlined.
callee.transformChildrenVoid(this) // Process recursive inline.
val parent = allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull()
val inliner = Inliner(callSite, callee, currentScope!!, parent, context)
return inliner.inline()
}
override fun visitCall(expression: IrCall): IrExpression {
val callSite = arrayConstructorTransformer.transformCall(super.visitCall(expression) as IrCall)
val callSite = super.visitCall(expression) as IrCall
if (!callSite.symbol.owner.needsInlining)
return callSite
@@ -102,7 +113,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
private val IrFunction.needsInlining get() = isInlineConstructor || (this.isInline && !this.isExternal)
private inner class Inliner(val callSite: IrCall,
private inner class Inliner(val callSite: IrFunctionAccessExpression,
val callee: IrFunction,
val currentScope: ScopeWithIr,
val parent: IrDeclarationParent?,
@@ -135,7 +146,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
}
}
private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlock {
private fun inlineFunction(callSite: IrFunctionAccessExpression, callee: IrFunction): IrReturnableBlock {
val copiedCallee = copyIrElement.copy(callee) as IrFunction
val evaluationStatements = evaluateArguments(callSite, copiedCallee)
@@ -240,11 +251,15 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val unboundArgsSet = unboundFunctionParameters.toSet()
val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver.
val immediateCall = IrCallImpl(
expression.startOffset, expression.endOffset,
expression.type,
functionArgument.symbol
).apply {
val newCall = expression.run {
if (function is IrConstructor) {
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, function.symbol)
} else {
IrCallImpl(startOffset, endOffset, type, functionArgument.symbol)
}
}
val immediateCall = newCall.apply {
functionParameters.forEach {
val argument =
if (it !in unboundArgsSet)
@@ -261,7 +276,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
for (index in 0 until functionArgument.typeArgumentsCount)
putTypeArgument(index, functionArgument.getTypeArgument(index))
}
return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall)
return if (immediateCall is IrCall) {
this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall)
} else {
require(immediateCall is IrConstructorCall)
this@FunctionInlining.visitConstructorCall(super.visitConstructorCall(immediateCall) as IrConstructorCall)
}
}
if (functionArgument !is IrBlock)
return super.visitCall(expression)
@@ -276,7 +297,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
override fun visitElement(element: IrElement) = element.accept(this, null)
}
private fun isLambdaCall(irCall: IrCall): Boolean {
private fun isLambdaCall(irCall: IrFunctionAccessExpression): Boolean {
val callee = irCall.symbol.owner
val dispatchReceiver = callee.dispatchReceiverParameter ?: return false
assert(!dispatchReceiver.type.isKFunction())
@@ -319,7 +340,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------//
private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List<ParameterToArgument> {
private fun buildParameterToArgument(callSite: IrFunctionAccessExpression, callee: IrFunction): List<ParameterToArgument> {
val parameterToArgument = mutableListOf<ParameterToArgument>()
@@ -394,7 +415,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------//
private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List<IrStatement> {
private fun evaluateArguments(callSite: IrFunctionAccessExpression, callee: IrFunction): List<IrStatement> {
val parameterToArgumentOld = buildParameterToArgument(callSite, callee)
val evaluationStatements = mutableListOf<IrStatement>()
@@ -133,6 +133,34 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
return JsInvocation(callFuncRef, listOf(thisRef) + arguments)
}
override fun visitConstructorCall(expression: IrConstructorCall, context: JsGenerationContext): JsExpression {
val function = expression.symbol.owner
val symbol = expression.symbol
context.staticContext.intrinsics[symbol]?.let {
return it(expression, context)
}
val arguments = translateCallArguments(expression, context)
val klass = function.parentAsClass
return if (klass.isInline) {
assert(function.isPrimary) {
"Inline class secondary constructors must be lowered into static methods"
}
// Argument value constructs unboxed inline class instance
arguments.single()
} else {
val ref = when {
klass.isEffectivelyExternal() ->
context.getRefForExternalClass(klass)
else ->
context.getNameForClass(klass).makeRef()
}
JsNew(ref, arguments)
}
}
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
val function = expression.symbol.owner.realOverrideTarget
val symbol = function.symbol
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.ir.util.getInlinedClass
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.js.backend.ast.*
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
typealias IrCallTransformer = (IrFunctionAccessExpression, context: JsGenerationContext) -> JsExpression
class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
private val transformers: Map<IrSymbol, IrCallTransformer>
@@ -120,7 +121,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
}
addIfNotNull(intrinsics.jsCode) { call, context ->
val jsCode = translateJsCode(call, context.currentScope)
val jsCode = translateJsCode(call as IrCall, context.currentScope)
when (jsCode) {
is JsExpression -> jsCode
@@ -129,20 +130,20 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
}
}
add(intrinsics.jsName) { call: IrCall, context ->
add(intrinsics.jsName) { call, context ->
val args = translateCallArguments(call, context)
val receiver = args[0]
JsNameRef(Namer.KCALLABLE_NAME, receiver)
}
add(intrinsics.jsPropertyGet) { call: IrCall, context ->
add(intrinsics.jsPropertyGet) { call, context ->
val args = translateCallArguments(call, context)
val reference = args[0]
val receiver = args[1]
JsInvocation(JsNameRef(Namer.KPROPERTY_GET, reference), listOf(receiver))
}
add(intrinsics.jsPropertySet) { call: IrCall, context ->
add(intrinsics.jsPropertySet) { call, context ->
val args = translateCallArguments(call, context)
val reference = args[0]
val receiver = args[1]
@@ -198,14 +199,14 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
}
}
add(intrinsics.jsBoxIntrinsic) { call: IrCall, context ->
val arg = translateCallArguments(call, context).single()
add(intrinsics.jsBoxIntrinsic) { call, context ->
val arg = translateCallArguments(call as IrCall, context).single()
val inlineClass = call.getTypeArgument(0)!!.getInlinedClass()!!
val constructor = inlineClass.declarations.filterIsInstance<IrConstructor>().single { it.isPrimary }
JsNew(context.getNameForConstructor(constructor).makeRef(), listOf(arg))
}
add(intrinsics.jsUnboxIntrinsic) { call: IrCall, context ->
add(intrinsics.jsUnboxIntrinsic) { call, context ->
val arg = translateCallArguments(call, context).single()
val inlineClass = call.getTypeArgument(1)!!.getInlinedClass()!!
val field = getInlineClassBackingField(inlineClass)
@@ -213,10 +214,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
JsNameRef(fieldName, arg)
}
add(intrinsics.jsBind) { call: IrCall, context: JsGenerationContext ->
add(intrinsics.jsBind) { call, context: JsGenerationContext ->
val receiver = call.getValueArgument(0)!!
val reference = call.getValueArgument(1) as IrFunctionReference
val superClass = call.superQualifierSymbol!!
val superClass = (call as IrCall).superQualifierSymbol!!
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
val functionName = context.getNameForMemberFunction(reference.symbol.owner as IrSimpleFunction)
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
@@ -395,6 +396,41 @@ fun ReferenceSymbolTable.referenceFunction(callable: CallableDescriptor): IrFunc
* [dispatchReceiverAsFirstArgument]: optionally convert call with dispatch receiver to static call
* [firstArgumentAsDispatchReceiver]: optionally convert static call to call with dispatch receiver
*/
fun irConstructorCall(
call: IrMemberAccessExpression,
newFunction: IrConstructor,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
): IrConstructorCall =
irConstructorCall(call, newFunction.symbol, dispatchReceiverAsFirstArgument, firstArgumentAsDispatchReceiver)
fun irConstructorCall(
call: IrMemberAccessExpression,
newSymbol: IrConstructorSymbol,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false
): IrConstructorCall =
call.run {
IrConstructorCallImpl(
startOffset,
endOffset,
type,
newSymbol,
newSymbol.descriptor,
typeArgumentsCount,
0,
call.valueArgumentsCount,
origin
).apply {
copyTypeAndValueArgumentsFrom(
call,
dispatchReceiverAsFirstArgument,
firstArgumentAsDispatchReceiver
)
}
}
fun irCall(
call: IrMemberAccessExpression,
newFunction: IrFunction,
@@ -427,7 +463,7 @@ fun irCall(
}
}
private fun IrCall.copyTypeAndValueArgumentsFrom(
private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
call: IrMemberAccessExpression,
dispatchReceiverAsFirstArgument: Boolean = false,
firstArgumentAsDispatchReceiver: Boolean = false