Fix JS_IR IrConstructorCall support
This commit is contained in:
committed by
Dmitry Petrov
parent
2a3ce8e9f1
commit
c545481db9
+63
-56
@@ -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? {
|
||||
|
||||
+11
-1
@@ -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)!!)
|
||||
|
||||
+2
-1
@@ -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
-3
@@ -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,
|
||||
|
||||
+3
-1
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -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
|
||||
|
||||
+3
-1
@@ -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]))
|
||||
}
|
||||
|
||||
+6
-7
@@ -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
|
||||
|
||||
+2
-1
@@ -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()
|
||||
}
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
|
||||
+7
-6
@@ -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)
|
||||
}
|
||||
|
||||
+6
-6
@@ -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
|
||||
}
|
||||
|
||||
+10
-9
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+5
-4
@@ -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
|
||||
|
||||
+8
-7
@@ -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
|
||||
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
|
||||
+6
-5
@@ -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???
|
||||
|
||||
+3
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+15
-14
@@ -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)!!
|
||||
|
||||
|
||||
+7
-4
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -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)
|
||||
|
||||
+37
-16
@@ -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>()
|
||||
|
||||
+28
@@ -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
|
||||
|
||||
+11
-10
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user