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.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -216,40 +217,10 @@ open class DefaultParameterInjector(
|
|||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
private fun visitFunctionAccessExpression(
|
||||||
super.visitDelegatingConstructorCall(expression)
|
expression: IrFunctionAccessExpression,
|
||||||
|
builder: (IrFunctionSymbol) -> IrFunctionAccessExpression
|
||||||
val declaration = expression.symbol.owner as IrFunction
|
): IrExpression {
|
||||||
|
|
||||||
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)
|
|
||||||
val functionDeclaration = expression.symbol.owner
|
val functionDeclaration = expression.symbol.owner
|
||||||
|
|
||||||
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
if (!functionDeclaration.needsDefaultArgumentsLowering(skipInline, skipExternalMethods))
|
||||||
@@ -268,30 +239,66 @@ open class DefaultParameterInjector(
|
|||||||
}
|
}
|
||||||
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } }
|
declaration.typeParameters.forEach { log { "$declaration[${it.index}] : $it" } }
|
||||||
|
|
||||||
return IrCallImpl(
|
return builder(symbol).apply {
|
||||||
startOffset = expression.startOffset,
|
this.copyTypeArgumentsFrom(expression)
|
||||||
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)
|
|
||||||
|
|
||||||
params.forEach {
|
params.forEach {
|
||||||
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
|
||||||
putValueArgument(it.first.index, 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)}" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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? {
|
private fun IrFunction.findSuperMethodWithDefaultArguments(): IrFunction? {
|
||||||
|
|||||||
+11
-1
@@ -183,6 +183,16 @@ class InlineClassLowering(val context: BackendContext) {
|
|||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
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 {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
val function = expression.symbol.owner
|
val function = expression.symbol.owner
|
||||||
@@ -208,7 +218,7 @@ class InlineClassLowering(val context: BackendContext) {
|
|||||||
val klass = function.parentAsClass
|
val klass = function.parentAsClass
|
||||||
return when {
|
return when {
|
||||||
!klass.isInline -> expression
|
!klass.isInline -> expression
|
||||||
function.isPrimary -> irCall(expression, function)
|
function.isPrimary -> irConstructorCall(expression, function)
|
||||||
else -> irCall(expression, getOrCreateStaticMethod(function)).apply {
|
else -> irCall(expression, getOrCreateStaticMethod(function)).apply {
|
||||||
(0 until expression.valueArgumentsCount).forEach {
|
(0 until expression.valueArgumentsCount).forEach {
|
||||||
putValueArgument(it, expression.getValueArgument(it)!!)
|
putValueArgument(it, expression.getValueArgument(it)!!)
|
||||||
|
|||||||
+2
-1
@@ -48,7 +48,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
|||||||
|
|
||||||
val constructorSymbol = closureBoxConstructorDeclaration.symbol
|
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)
|
putValueArgument(0, initializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +132,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
|||||||
|
|
||||||
descriptor.bind(declaration)
|
descriptor.bind(declaration)
|
||||||
declaration.parent = implicitDeclarationsFile
|
declaration.parent = implicitDeclarationsFile
|
||||||
|
// TODO: substitute
|
||||||
closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList())
|
closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList())
|
||||||
declaration.thisReceiver =
|
declaration.thisReceiver =
|
||||||
JsIrBuilder.buildValueParameter(Name.special("<this>"), -1, closureBoxType, IrDeclarationOrigin.INSTANCE_RECEIVER).apply {
|
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.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
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.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
|
|
||||||
@@ -23,9 +27,11 @@ class ArrayConstructorTransformer(
|
|||||||
it.inlineConstructor to it.sizeConstructor
|
it.inlineConstructor to it.sizeConstructor
|
||||||
}
|
}
|
||||||
|
|
||||||
fun transformCall(expression: IrCall): IrCall {
|
fun transformConstructorCall(expression: IrConstructorCall): IrFunctionAccessExpression {
|
||||||
if (expression.symbol == context.intrinsics.array.inlineConstructor) {
|
if (expression.symbol == context.intrinsics.array.inlineConstructor) {
|
||||||
return irCall(expression, context.intrinsics.jsArray)
|
return irCall(expression, context.intrinsics.jsArray).apply {
|
||||||
|
copyTypeArgumentsFrom(expression)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
primitiveArrayInlineToSizeConstructorMap[expression.symbol]?.let { sizeConstructor ->
|
primitiveArrayInlineToSizeConstructorMap[expression.symbol]?.let { sizeConstructor ->
|
||||||
return IrCallImpl(
|
return IrCallImpl(
|
||||||
@@ -34,7 +40,7 @@ class ArrayConstructorTransformer(
|
|||||||
expression.type,
|
expression.type,
|
||||||
context.intrinsics.jsFillArray
|
context.intrinsics.jsFillArray
|
||||||
).apply {
|
).apply {
|
||||||
putValueArgument(0, IrCallImpl(
|
putValueArgument(0, IrConstructorCallImpl.fromSymbolOwner(
|
||||||
expression.startOffset,
|
expression.startOffset,
|
||||||
expression.endOffset,
|
expression.endOffset,
|
||||||
expression.type,
|
expression.type,
|
||||||
|
|||||||
+3
-1
@@ -29,6 +29,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
|
|||||||
override fun IrExpression.useAs(type: IrType): IrExpression {
|
override fun IrExpression.useAs(type: IrType): IrExpression {
|
||||||
|
|
||||||
val actualType = when (this) {
|
val actualType = when (this) {
|
||||||
|
is IrConstructorCall -> symbol.owner.returnType
|
||||||
is IrCall -> {
|
is IrCall -> {
|
||||||
val function = this.symbol.owner
|
val function = this.symbol.owner
|
||||||
if (function.let { it is IrSimpleFunction && it.isSuspend }) {
|
if (function.let { it is IrSimpleFunction && it.isSuspend }) {
|
||||||
@@ -127,8 +128,9 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
|
|||||||
|
|
||||||
private val IrFunctionAccessExpression.target: IrFunction
|
private val IrFunctionAccessExpression.target: IrFunction
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
is IrCall -> this.callTarget
|
is IrConstructorCall -> this.symbol.owner
|
||||||
is IrDelegatingConstructorCall -> this.symbol.owner
|
is IrDelegatingConstructorCall -> this.symbol.owner
|
||||||
|
is IrCall -> this.callTarget
|
||||||
else -> TODO(this.render())
|
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.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
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.expressions.impl.IrVarargImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
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 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 cp = 0
|
||||||
var gp = 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.IrConstKind
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
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.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.constructors
|
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.util.isUnsigned
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -31,7 +33,7 @@ class ConstTransformer(private val context: JsIrBackendContext) : IrElementTrans
|
|||||||
): IrExpression {
|
): IrExpression {
|
||||||
val constructor = irClass.constructors.single()
|
val constructor = irClass.constructors.single()
|
||||||
val argType = constructor.owner.valueParameters.first().type
|
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) {
|
for (i in args.indices) {
|
||||||
putValueArgument(i, carrierFactory(UNDEFINED_OFFSET, UNDEFINED_OFFSET, argType, args[i]))
|
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 oldCtorToNewMap = context.secondaryConstructorToFactoryCache
|
||||||
private val defaultThrowableConstructor = context.defaultThrowableCtor
|
private val defaultThrowableConstructor = context.defaultThrowableCtor
|
||||||
|
|
||||||
private val IrFunction.isSecondaryConstructorCall
|
private val IrConstructor.isSecondaryConstructorCall
|
||||||
get() =
|
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 visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: IrFunction?): IrElement {
|
override fun visitConstructorCall(expression: IrConstructorCall, data: IrFunction?): IrElement {
|
||||||
super.visitCall(expression, data)
|
super.visitConstructorCall(expression, data)
|
||||||
|
|
||||||
val target = expression.symbol.owner
|
val target = expression.symbol.owner
|
||||||
return if (target.isSecondaryConstructorCall) {
|
return if (target.isSecondaryConstructorCall) {
|
||||||
val constructor = target as IrConstructor
|
val ctor = oldCtorToNewMap.getOrPut(target) {
|
||||||
val ctor = oldCtorToNewMap.getOrPut(constructor) {
|
buildConstructorStubDeclarations(target, target.parentAsClass)
|
||||||
buildConstructorStubDeclarations(constructor, constructor.parentAsClass)
|
|
||||||
}
|
}
|
||||||
replaceSecondaryConstructorWithFactoryFunction(expression, ctor.stub.symbol)
|
replaceSecondaryConstructorWithFactoryFunction(expression, ctor.stub.symbol)
|
||||||
} else expression
|
} 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.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
@@ -135,7 +136,7 @@ class TestGenerator(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
JsIrBuilder.buildGetObjectValue(defaultType, symbol)
|
JsIrBuilder.buildGetObjectValue(defaultType, symbol)
|
||||||
} else {
|
} else {
|
||||||
declarations.asSequence().filterIsInstance<IrConstructor>().single { it.isPrimary }.let { constructor ->
|
declarations.asSequence().filterIsInstance<IrConstructor>().single { it.isPrimary }.let { constructor ->
|
||||||
JsIrBuilder.buildCall(constructor.symbol).also {
|
IrConstructorCallImpl.fromSymbolOwner(defaultType, constructor.symbol).also {
|
||||||
if (isInner) {
|
if (isInner) {
|
||||||
it.dispatchReceiver = (parent as IrClass).instance()
|
it.dispatchReceiver = (parent as IrClass).instance()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -108,8 +108,8 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
|
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
||||||
if (expression.symbol !in throwableConstructors) return super.visitCall(expression)
|
if (expression.symbol !in throwableConstructors) return super.visitConstructorCall(expression)
|
||||||
|
|
||||||
expression.transformChildrenVoid(this)
|
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.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
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.impl.IrCallImpl
|
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.IrGetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
@@ -67,7 +65,7 @@ private class VarargTransformer(
|
|||||||
if (inlineClass == null)
|
if (inlineClass == null)
|
||||||
this
|
this
|
||||||
else
|
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)
|
it.putValueArgument(0, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +163,7 @@ private class VarargTransformer(
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression {
|
||||||
expression.transformChildrenVoid()
|
expression.transformChildrenVoid()
|
||||||
val size = expression.valueArgumentsCount
|
val size = expression.valueArgumentsCount
|
||||||
|
|
||||||
@@ -179,4 +177,7 @@ private class VarargTransformer(
|
|||||||
|
|
||||||
return expression
|
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.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.util.hasAnnotation
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -36,11 +36,11 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
return super.visitFunction(declaration)
|
return super.visitFunction(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
|
||||||
val call = super.visitCall(expression)
|
val call = super.visitFunctionAccess(expression)
|
||||||
if (call is IrCall) {
|
if (call is IrFunctionAccessExpression) {
|
||||||
for (transformer in transformers) {
|
for (transformer in transformers) {
|
||||||
val newCall = transformer.transformCall(call)
|
val newCall = transformer.transformFunctionAccess(call)
|
||||||
if (newCall !== call) {
|
if (newCall !== call) {
|
||||||
return newCall
|
return newCall
|
||||||
}
|
}
|
||||||
@@ -53,5 +53,5 @@ class CallsLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CallsTransformer {
|
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.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.SimpleType
|
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) {
|
internal fun SymbolToTransformer.add(from: Map<SimpleType, IrFunctionSymbol>, to: IrFunctionSymbol) {
|
||||||
from.forEach { _, func ->
|
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 ->
|
from.forEach { _, func ->
|
||||||
add(func, to)
|
add(func, to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrCall) -> IrExpression) {
|
internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: (IrFunctionAccessExpression) -> IrExpression) {
|
||||||
put(from, to)
|
put(from, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,15 +37,15 @@ internal fun SymbolToTransformer.add(from: IrFunctionSymbol, to: IrFunctionSymbo
|
|||||||
put(from) { call -> irCall(call, to, dispatchReceiverAsFirstArgument) }
|
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,
|
from: K,
|
||||||
predicate: (IrCall) -> Boolean,
|
predicate: (IrFunctionAccessExpression) -> Boolean,
|
||||||
action: (IrCall) -> IrExpression
|
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) {
|
internal fun MemberToTransformer.add(type: IrType, name: Name, v: IrFunctionSymbol) {
|
||||||
add(type, name) { irCall(it, v, dispatchReceiverAsFirstArgument = true) }
|
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)
|
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)
|
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.declarations.isStaticMethodOfClass
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.getClass
|
||||||
import org.jetbrains.kotlin.ir.types.isString
|
import org.jetbrains.kotlin.ir.types.isString
|
||||||
import org.jetbrains.kotlin.ir.util.findDeclaration
|
import org.jetbrains.kotlin.ir.util.findDeclaration
|
||||||
@@ -20,7 +21,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
|
|
||||||
class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
||||||
private fun transformEnumTopLevelIntrinsic(
|
private fun transformEnumTopLevelIntrinsic(
|
||||||
call: IrCall,
|
call: IrFunctionAccessExpression,
|
||||||
staticMethodPredicate: (IrSimpleFunction) -> Boolean
|
staticMethodPredicate: (IrSimpleFunction) -> Boolean
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
val enum = call.getTypeArgument(0)?.getClass() ?: return call
|
val enum = call.getTypeArgument(0)?.getClass() ?: return call
|
||||||
@@ -32,17 +33,17 @@ class EnumIntrinsicsTransformer(private val context: JsIrBackendContext) : Calls
|
|||||||
return irCall(call, staticMethod.symbol)
|
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.name == Name.identifier("valueOf") &&
|
||||||
it.valueParameters.count() == 1 &&
|
it.valueParameters.count() == 1 &&
|
||||||
it.valueParameters[0].type.isString()
|
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
|
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.enumValueOfIntrinsic -> transformEnumValueOfIntrinsic(call)
|
||||||
context.intrinsics.enumValuesIntrinsic -> transformEnumValuesIntrinsic(call)
|
context.intrinsics.enumValuesIntrinsic -> transformEnumValuesIntrinsic(call)
|
||||||
else -> 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.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
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(
|
IrCallImpl(
|
||||||
call.startOffset,
|
call.startOffset,
|
||||||
call.endOffset,
|
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
|
val symbol = call.symbol
|
||||||
symbolToTransformer[symbol]?.let {
|
symbolToTransformer[symbol]?.let {
|
||||||
return it(call)
|
return it(call)
|
||||||
@@ -65,12 +66,12 @@ class EqualityAndComparisonCallsTransformer(context: JsIrBackendContext) : Calls
|
|||||||
|
|
||||||
return when (symbol.owner.name) {
|
return when (symbol.owner.name) {
|
||||||
Name.identifier("compareTo") -> transformCompareToMethodCall(call)
|
Name.identifier("compareTo") -> transformCompareToMethodCall(call)
|
||||||
Name.identifier("equals") -> transformEqualsMethodCall(call)
|
Name.identifier("equals") -> transformEqualsMethodCall(call as IrCall)
|
||||||
else -> call
|
else -> call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformEqeqOperator(call: IrCall): IrExpression {
|
private fun transformEqeqOperator(call: IrFunctionAccessExpression): IrExpression {
|
||||||
val lhs = call.getValueArgument(0)!!
|
val lhs = call.getValueArgument(0)!!
|
||||||
val rhs = call.getValueArgument(1)!!
|
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() ->
|
call.allValueArgumentsAreNullable() ->
|
||||||
irCall(call, intrinsics.jsEqeq)
|
irCall(call, intrinsics.jsEqeq)
|
||||||
else ->
|
else ->
|
||||||
irCall(call, intrinsics.jsEqeqeq)
|
irCall(call, intrinsics.jsEqeqeq)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrCall.allValueArgumentsAreNullable() =
|
private fun IrFunctionAccessExpression.allValueArgumentsAreNullable() =
|
||||||
(0 until valueArgumentsCount).all { getValueArgument(it)!!.type.isNullable() }
|
(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
|
val function = call.symbol.owner as IrSimpleFunction
|
||||||
if (function.parent !is IrClass) return call
|
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.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.util.irCall
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.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.ir.util.kotlinPackageFqn
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.util.irCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.IrDynamicType
|
||||||
import org.jetbrains.kotlin.ir.types.isAny
|
import org.jetbrains.kotlin.ir.types.isAny
|
||||||
import org.jetbrains.kotlin.ir.types.isArray
|
import org.jetbrains.kotlin.ir.types.isArray
|
||||||
@@ -21,14 +22,14 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
|
|
||||||
class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
|
class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
|
||||||
private val intrinsics = context.intrinsics
|
private val intrinsics = context.intrinsics
|
||||||
private val nameToTransformer: Map<Name, (IrCall) -> IrExpression>
|
private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
nameToTransformer = mutableMapOf()
|
nameToTransformer = mutableMapOf()
|
||||||
nameToTransformer.run {
|
nameToTransformer.run {
|
||||||
put(Name.identifier("toString")) { call ->
|
put(Name.identifier("toString")) { call ->
|
||||||
if (shouldReplaceToStringWithRuntimeCall(call)) {
|
if (shouldReplaceToStringWithRuntimeCall(call)) {
|
||||||
if (call.isSuperToAny()) {
|
if ((call as IrCall).isSuperToAny()) {
|
||||||
irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsFirstArgument = true)
|
irCall(call, intrinsics.jsAnyToString, dispatchReceiverAsFirstArgument = true)
|
||||||
} else {
|
} else {
|
||||||
irCall(call, intrinsics.jsToString, dispatchReceiverAsFirstArgument = true)
|
irCall(call, intrinsics.jsToString, dispatchReceiverAsFirstArgument = true)
|
||||||
@@ -40,7 +41,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
|
|||||||
|
|
||||||
put(Name.identifier("hashCode")) { call ->
|
put(Name.identifier("hashCode")) { call ->
|
||||||
if (call.symbol.owner.isFakeOverriddenFromAny()) {
|
if (call.symbol.owner.isFakeOverriddenFromAny()) {
|
||||||
if (call.isSuperToAny()) {
|
if ((call as IrCall).isSuperToAny()) {
|
||||||
irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true)
|
irCall(call, intrinsics.jsGetObjectHashCode, dispatchReceiverAsFirstArgument = true)
|
||||||
} else {
|
} else {
|
||||||
irCall(call, intrinsics.jsHashCode, dispatchReceiverAsFirstArgument = true)
|
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
|
val symbol = call.symbol
|
||||||
nameToTransformer[symbol.owner.name]?.let {
|
nameToTransformer[symbol.owner.name]?.let {
|
||||||
return it(call)
|
return it(call)
|
||||||
@@ -62,7 +63,7 @@ class MethodsOfAnyCallsTransformer(context: JsIrBackendContext) : CallsTransform
|
|||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldReplaceToStringWithRuntimeCall(call: IrCall): Boolean {
|
private fun shouldReplaceToStringWithRuntimeCall(call: IrFunctionAccessExpression): Boolean {
|
||||||
// TODO: (KOTLIN-CR-2079)
|
// TODO: (KOTLIN-CR-2079)
|
||||||
// - User defined extension functions Any?.toString() call can be lost during lowering.
|
// - User defined extension functions Any?.toString() call can be lost during lowering.
|
||||||
// - Use direct method call for dynamic types???
|
// - 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.backend.js.utils.ConversionNames
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
|
|
||||||
class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
|
class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
|
||||||
private val intrinsics = context.intrinsics
|
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
|
val function = call.symbol.owner
|
||||||
function.dispatchReceiverParameter?.also {
|
function.dispatchReceiverParameter?.also {
|
||||||
val key = SimpleMemberKey(it.type, function.name)
|
val key = SimpleMemberKey(it.type, function.name)
|
||||||
@@ -85,7 +86,7 @@ class NumberConversionCallsTransformer(context: JsIrBackendContext) : CallsTrans
|
|||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun useDispatchReceiver(call: IrCall): IrExpression {
|
private fun useDispatchReceiver(call: IrFunctionAccessExpression): IrExpression {
|
||||||
return JsIrBuilder.buildImplicitCast(call.dispatchReceiver!!, call.type)
|
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.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
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
|
val function = call.symbol.owner
|
||||||
function.dispatchReceiverParameter?.also {
|
function.dispatchReceiverParameter?.also {
|
||||||
val key = SimpleMemberKey(it.type, function.name)
|
val key = SimpleMemberKey(it.type, function.name)
|
||||||
@@ -82,7 +83,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformRangeTo(call: IrCall): IrExpression {
|
private fun transformRangeTo(call: IrFunctionAccessExpression): IrExpression {
|
||||||
if (call.valueArgumentsCount != 1) return call
|
if (call.valueArgumentsCount != 1) return call
|
||||||
return with(call.symbol.owner.valueParameters[0].type) {
|
return with(call.symbol.owner.valueParameters[0].type) {
|
||||||
when {
|
when {
|
||||||
@@ -96,7 +97,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun irBinaryOp(
|
private fun irBinaryOp(
|
||||||
call: IrCall,
|
call: IrFunctionAccessExpression,
|
||||||
intrinsic: IrFunctionSymbol,
|
intrinsic: IrFunctionSymbol,
|
||||||
toInt32: Boolean = false
|
toInt32: Boolean = false
|
||||||
): IrExpression {
|
): IrExpression {
|
||||||
@@ -106,7 +107,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
return newCall
|
return newCall
|
||||||
}
|
}
|
||||||
|
|
||||||
class BinaryOp(call: IrCall) {
|
class BinaryOp(call: IrFunctionAccessExpression) {
|
||||||
val function = call.symbol.owner
|
val function = call.symbol.owner
|
||||||
val name = function.name
|
val name = function.name
|
||||||
val lhs = function.dispatchReceiverParameter!!.type
|
val lhs = function.dispatchReceiverParameter!!.type
|
||||||
@@ -117,13 +118,13 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
result.isInt() && (lhs.isInt() || rhs.isInt())
|
result.isInt() && (lhs.isInt() || rhs.isInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformAdd(call: IrCall) =
|
private fun transformAdd(call: IrFunctionAccessExpression) =
|
||||||
irBinaryOp(call, intrinsics.jsPlus, toInt32 = BinaryOp(call).canAddOrSubOverflow())
|
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())
|
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 {
|
when {
|
||||||
result.isInt() -> 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())
|
irBinaryOp(call, intrinsics.jsDiv, toInt32 = BinaryOp(call).result.isInt())
|
||||||
|
|
||||||
private fun transformRem(call: IrCall) =
|
private fun transformRem(call: IrFunctionAccessExpression) =
|
||||||
irBinaryOp(call, intrinsics.jsMod)
|
irBinaryOp(call, intrinsics.jsMod)
|
||||||
|
|
||||||
private fun transformIncrement(call: IrCall) =
|
private fun transformIncrement(call: IrFunctionAccessExpression) =
|
||||||
transformCrement(call, intrinsics.jsPlus)
|
transformCrement(call, intrinsics.jsPlus)
|
||||||
|
|
||||||
private fun transformDecrement(call: IrCall) =
|
private fun transformDecrement(call: IrFunctionAccessExpression) =
|
||||||
transformCrement(call, intrinsics.jsMinus)
|
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 {
|
val operation = irCall(call, correspondingBinaryOp, dispatchReceiverAsFirstArgument = true).apply {
|
||||||
putValueArgument(1, buildInt(1))
|
putValueArgument(1, buildInt(1))
|
||||||
}
|
}
|
||||||
@@ -158,7 +159,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
return convertResultToPrimitiveType(operation, call.type)
|
return convertResultToPrimitiveType(operation, call.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformUnaryMinus(call: IrCall) =
|
private fun transformUnaryMinus(call: IrFunctionAccessExpression) =
|
||||||
convertResultToPrimitiveType(
|
convertResultToPrimitiveType(
|
||||||
irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsFirstArgument = true),
|
irCall(call, intrinsics.jsUnaryMinus, dispatchReceiverAsFirstArgument = true),
|
||||||
call.type
|
call.type
|
||||||
@@ -171,7 +172,7 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
|
|||||||
else -> e
|
else -> e
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun withLongCoercion(default: (IrCall) -> IrExpression): (IrCall) -> IrExpression = { call ->
|
private fun withLongCoercion(default: (IrFunctionAccessExpression) -> IrExpression): (IrFunctionAccessExpression) -> IrExpression = { call ->
|
||||||
assert(call.valueArgumentsCount == 1)
|
assert(call.valueArgumentsCount == 1)
|
||||||
val arg = call.getValueArgument(0)!!
|
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.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
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.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
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.getSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
|
|
||||||
@@ -56,13 +59,13 @@ class PrimitiveContainerMemberCallTransformer(private val context: JsIrBackendCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transformCall(call: IrCall): IrExpression {
|
override fun transformFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
|
||||||
val symbol = call.symbol
|
val symbol = expression.symbol
|
||||||
symbolToTransformer[symbol]?.let {
|
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.backend.js.utils.Namer
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.ir.types.isSubtypeOfClass
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
|
||||||
class ReflectionCallsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
class ReflectionCallsTransformer(private val context: JsIrBackendContext) : CallsTransformer {
|
||||||
private val nameToTransformer: Map<Name, (IrCall) -> IrExpression>
|
private val nameToTransformer: Map<Name, (IrFunctionAccessExpression) -> IrExpression>
|
||||||
|
|
||||||
init {
|
init {
|
||||||
nameToTransformer = mutableMapOf()
|
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
|
val symbol = call.symbol
|
||||||
nameToTransformer[symbol.owner.name]?.let {
|
nameToTransformer[symbol.owner.name]?.let {
|
||||||
return it(call)
|
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.builders.irReturn
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
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.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
@@ -48,8 +45,22 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
|
|
||||||
private val arrayConstructorTransformer = ArrayConstructorTransformer(context)
|
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 {
|
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)
|
if (!callSite.symbol.owner.needsInlining)
|
||||||
return callSite
|
return callSite
|
||||||
@@ -102,7 +113,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
|
|
||||||
private val IrFunction.needsInlining get() = isInlineConstructor || (this.isInline && !this.isExternal)
|
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 callee: IrFunction,
|
||||||
val currentScope: ScopeWithIr,
|
val currentScope: ScopeWithIr,
|
||||||
val parent: IrDeclarationParent?,
|
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 copiedCallee = copyIrElement.copy(callee) as IrFunction
|
||||||
|
|
||||||
val evaluationStatements = evaluateArguments(callSite, copiedCallee)
|
val evaluationStatements = evaluateArguments(callSite, copiedCallee)
|
||||||
@@ -240,11 +251,15 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||||
val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver.
|
val valueParameters = expression.getArgumentsWithIr().drop(1) // Skip dispatch receiver.
|
||||||
|
|
||||||
val immediateCall = IrCallImpl(
|
val newCall = expression.run {
|
||||||
expression.startOffset, expression.endOffset,
|
if (function is IrConstructor) {
|
||||||
expression.type,
|
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, function.symbol)
|
||||||
functionArgument.symbol
|
} else {
|
||||||
).apply {
|
IrCallImpl(startOffset, endOffset, type, functionArgument.symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val immediateCall = newCall.apply {
|
||||||
functionParameters.forEach {
|
functionParameters.forEach {
|
||||||
val argument =
|
val argument =
|
||||||
if (it !in unboundArgsSet)
|
if (it !in unboundArgsSet)
|
||||||
@@ -261,7 +276,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
for (index in 0 until functionArgument.typeArgumentsCount)
|
for (index in 0 until functionArgument.typeArgumentsCount)
|
||||||
putTypeArgument(index, functionArgument.getTypeArgument(index))
|
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)
|
if (functionArgument !is IrBlock)
|
||||||
return super.visitCall(expression)
|
return super.visitCall(expression)
|
||||||
@@ -276,7 +297,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
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 callee = irCall.symbol.owner
|
||||||
val dispatchReceiver = callee.dispatchReceiverParameter ?: return false
|
val dispatchReceiver = callee.dispatchReceiverParameter ?: return false
|
||||||
assert(!dispatchReceiver.type.isKFunction())
|
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>()
|
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 parameterToArgumentOld = buildParameterToArgument(callSite, callee)
|
||||||
val evaluationStatements = mutableListOf<IrStatement>()
|
val evaluationStatements = mutableListOf<IrStatement>()
|
||||||
|
|||||||
+28
@@ -133,6 +133,34 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
|||||||
return JsInvocation(callFuncRef, listOf(thisRef) + arguments)
|
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 {
|
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
|
||||||
val function = expression.symbol.owner.realOverrideTarget
|
val function = expression.symbol.owner.realOverrideTarget
|
||||||
val symbol = function.symbol
|
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.backend.js.utils.Namer
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
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.expressions.IrFunctionReference
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
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.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
|
typealias IrCallTransformer = (IrFunctionAccessExpression, context: JsGenerationContext) -> JsExpression
|
||||||
|
|
||||||
class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
||||||
private val transformers: Map<IrSymbol, IrCallTransformer>
|
private val transformers: Map<IrSymbol, IrCallTransformer>
|
||||||
@@ -120,7 +121,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addIfNotNull(intrinsics.jsCode) { call, context ->
|
addIfNotNull(intrinsics.jsCode) { call, context ->
|
||||||
val jsCode = translateJsCode(call, context.currentScope)
|
val jsCode = translateJsCode(call as IrCall, context.currentScope)
|
||||||
|
|
||||||
when (jsCode) {
|
when (jsCode) {
|
||||||
is JsExpression -> 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 args = translateCallArguments(call, context)
|
||||||
val receiver = args[0]
|
val receiver = args[0]
|
||||||
JsNameRef(Namer.KCALLABLE_NAME, receiver)
|
JsNameRef(Namer.KCALLABLE_NAME, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
add(intrinsics.jsPropertyGet) { call: IrCall, context ->
|
add(intrinsics.jsPropertyGet) { call, context ->
|
||||||
val args = translateCallArguments(call, context)
|
val args = translateCallArguments(call, context)
|
||||||
val reference = args[0]
|
val reference = args[0]
|
||||||
val receiver = args[1]
|
val receiver = args[1]
|
||||||
JsInvocation(JsNameRef(Namer.KPROPERTY_GET, reference), listOf(receiver))
|
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 args = translateCallArguments(call, context)
|
||||||
val reference = args[0]
|
val reference = args[0]
|
||||||
val receiver = args[1]
|
val receiver = args[1]
|
||||||
@@ -198,14 +199,14 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add(intrinsics.jsBoxIntrinsic) { call: IrCall, context ->
|
add(intrinsics.jsBoxIntrinsic) { call, context ->
|
||||||
val arg = translateCallArguments(call, context).single()
|
val arg = translateCallArguments(call as IrCall, context).single()
|
||||||
val inlineClass = call.getTypeArgument(0)!!.getInlinedClass()!!
|
val inlineClass = call.getTypeArgument(0)!!.getInlinedClass()!!
|
||||||
val constructor = inlineClass.declarations.filterIsInstance<IrConstructor>().single { it.isPrimary }
|
val constructor = inlineClass.declarations.filterIsInstance<IrConstructor>().single { it.isPrimary }
|
||||||
JsNew(context.getNameForConstructor(constructor).makeRef(), listOf(arg))
|
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 arg = translateCallArguments(call, context).single()
|
||||||
val inlineClass = call.getTypeArgument(1)!!.getInlinedClass()!!
|
val inlineClass = call.getTypeArgument(1)!!.getInlinedClass()!!
|
||||||
val field = getInlineClassBackingField(inlineClass)
|
val field = getInlineClassBackingField(inlineClass)
|
||||||
@@ -213,10 +214,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
|||||||
JsNameRef(fieldName, arg)
|
JsNameRef(fieldName, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
add(intrinsics.jsBind) { call: IrCall, context: JsGenerationContext ->
|
add(intrinsics.jsBind) { call, context: JsGenerationContext ->
|
||||||
val receiver = call.getValueArgument(0)!!
|
val receiver = call.getValueArgument(0)!!
|
||||||
val reference = call.getValueArgument(1) as IrFunctionReference
|
val reference = call.getValueArgument(1) as IrFunctionReference
|
||||||
val superClass = call.superQualifierSymbol!!
|
val superClass = (call as IrCall).superQualifierSymbol!!
|
||||||
|
|
||||||
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
|
val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context)
|
||||||
val functionName = context.getNameForMemberFunction(reference.symbol.owner as IrSimpleFunction)
|
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.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
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.expressions.impl.IrTypeOperatorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
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
|
* [dispatchReceiverAsFirstArgument]: optionally convert call with dispatch receiver to static call
|
||||||
* [firstArgumentAsDispatchReceiver]: optionally convert static call to call with dispatch receiver
|
* [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(
|
fun irCall(
|
||||||
call: IrMemberAccessExpression,
|
call: IrMemberAccessExpression,
|
||||||
newFunction: IrFunction,
|
newFunction: IrFunction,
|
||||||
@@ -427,7 +463,7 @@ fun irCall(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrCall.copyTypeAndValueArgumentsFrom(
|
private fun IrMemberAccessExpression.copyTypeAndValueArgumentsFrom(
|
||||||
call: IrMemberAccessExpression,
|
call: IrMemberAccessExpression,
|
||||||
dispatchReceiverAsFirstArgument: Boolean = false,
|
dispatchReceiverAsFirstArgument: Boolean = false,
|
||||||
firstArgumentAsDispatchReceiver: Boolean = false
|
firstArgumentAsDispatchReceiver: Boolean = false
|
||||||
|
|||||||
Reference in New Issue
Block a user