Supported IrConstructorCall

(cherry picked from commit 315362b0fc3ddec049955b67f1df876d5569aa22)
This commit is contained in:
Igor Chevdar
2019-04-29 13:20:55 +03:00
committed by Vasily Levchenko
parent 6708e4df80
commit 2138b37dc9
19 changed files with 149 additions and 155 deletions
@@ -99,7 +99,7 @@ private fun KotlinToCCallBuilder.addArgument(
if (!variadic) cFunctionBuilder.addParameter(cArgument.type)
}
private fun KotlinToCCallBuilder.buildKotlinBridgeCall(transformCall: (IrCall) -> IrExpression = { it }): IrExpression =
private fun KotlinToCCallBuilder.buildKotlinBridgeCall(transformCall: (IrMemberAccessExpression) -> IrExpression = { it }): IrExpression =
bridgeCallBuilder.build(
bridgeBuilder.buildKotlinBridge().also {
this.stubs.addKotlin(it)
@@ -16,6 +16,8 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
@@ -128,8 +130,9 @@ private fun createKotlinBridge(
)
bridgeDescriptor.bind(bridge)
if (isExternal) {
val constructor = symbols.filterExceptions.owner.constructors.single()
bridge.annotations +=
irCall(startOffset, endOffset, symbols.filterExceptions.owner.constructors.single(), emptyList())
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, constructor.returnType, constructor.symbol)
}
return bridge
}
@@ -185,7 +188,7 @@ internal class KotlinCallBuilder(private val irBuilder: IrBuilderWithScope, priv
fun build(
function: IrFunction,
transformCall: (IrCall) -> IrExpression = { it }
transformCall: (IrMemberAccessExpression) -> IrExpression = { it }
): IrExpression {
val arguments = this.arguments.toMutableList()
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
@@ -21,9 +20,9 @@ import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.types.*
@@ -36,14 +35,6 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
private val elementProperty = refClass.owner.declarations.filterIsInstance<IrProperty>().single()
private fun refConstructor(elementType: KotlinType): ClassConstructorDescriptor {
val typeParameter = refClassConstructor.descriptor.typeParameters[0]
return refClassConstructor.descriptor.substitute(TypeSubstitutor.create(
mapOf(typeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, elementType))
))!!
}
private fun refType(elementType: KotlinType): KotlinType {
return refClass.descriptor.defaultType.replace(listOf(TypeProjectionImpl(elementType)))
}
@@ -66,10 +57,10 @@ internal class KonanSharedVariablesManager(val context: KonanBackendContext) : S
val valueType = originalDeclaration.type
val refConstructorCall = IrCallImpl(
val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner(
originalDeclaration.startOffset, originalDeclaration.endOffset,
refClass.typeWith(valueType),
refClassConstructor, refConstructor(valueType.toKotlinType()), 1
refClassConstructor
).apply {
putTypeArgument(0, valueType)
}
@@ -97,7 +97,7 @@ class IrFileImpl(entry: SourceManager.FileEntry) : IrFile {
override val metadata: MetadataSource.File?
get() = TODO("not implemented")
override val annotations: MutableList<IrCall>
override val annotations: MutableList<IrConstructorCall>
get() = TODO("not implemented")
override val fqName: FqName
get() = TODO("not implemented")
@@ -92,13 +92,6 @@ val IrClass.isFinalClass: Boolean
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
private val IrCall.annotationClass
get() = (this.symbol.owner as IrConstructor).constructedClass
fun List<IrCall>.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull {
it.annotationClass.fqNameSafe == fqName
}
fun <T> IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? {
val annotation = this.annotations.findAnnotation(fqName)
if (annotation == null) {
@@ -8,7 +8,6 @@ import org.jetbrains.kotlin.backend.konan.llvm.objc.genObjCSelector
import org.jetbrains.kotlin.backend.konan.reportCompilationError
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.getClass
@@ -147,8 +146,8 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
}
IntrinsicType.OBJC_INIT_BY -> {
val receiver = environment.evaluateExpression(callSite.extensionReceiver!!)
val irConstructorCall = callSite.getValueArgument(0) as IrCall
val constructorDescriptor = irConstructorCall.symbol.owner as IrConstructor
val irConstructorCall = callSite.getValueArgument(0) as IrConstructorCall
val constructorDescriptor = irConstructorCall.symbol.owner
val constructorArgs = environment.evaluateExplicitArgs(irConstructorCall)
val args = listOf(receiver) + constructorArgs
environment.evaluateCall(constructorDescriptor, args, Lifetime.IRRELEVANT)
@@ -159,7 +158,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
environment.functionGenerationContext.genObjCSelector(selector)
}
IntrinsicType.INIT_INSTANCE -> {
val initializer = callSite.getValueArgument(1) as IrCall
val initializer = callSite.getValueArgument(1) as IrConstructorCall
val thiz = environment.evaluateExpression(callSite.getValueArgument(0)!!)
environment.evaluateCall(
initializer.symbol.owner,
@@ -760,6 +760,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
is IrCall -> return evaluateCall (value)
is IrDelegatingConstructorCall ->
return evaluateCall (value)
is IrConstructorCall -> return evaluateCall (value)
is IrInstanceInitializerCall ->
return evaluateInstanceInitializerCall(value)
is IrGetValue -> return evaluateGetValue (value)
@@ -1751,6 +1752,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
updateBuilderDebugLocation(value)
return when (value) {
is IrDelegatingConstructorCall -> delegatingConstructorCall(value.symbol.owner, args)
is IrConstructorCall -> evaluateConstructorCall(value, args)
else -> evaluateFunctionCall(value as IrCall, args, resultLifetime(value))
}
}
@@ -2016,7 +2018,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
return when {
function.isTypedIntrinsic -> intrinsicGenerator.evaluateCall(callee, args)
function.symbol in context.irBuiltIns.irBuiltInsSymbols -> evaluateOperatorCall(callee, argsWithContinuationIfNeeded)
function is IrConstructor -> evaluateConstructorCall(callee, argsWithContinuationIfNeeded)
else -> evaluateSimpleFunctionCall(function, argsWithContinuationIfNeeded, resultLifetime, callee.superQualifierSymbol?.owner)
}
}
@@ -2045,34 +2046,40 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
return lifetimes.getOrElse(callee) { /* TODO: make IRRELEVANT */ Lifetime.GLOBAL }
}
private fun evaluateConstructorCall(callee: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
private fun evaluateConstructorCall(callee: IrConstructorCall, args: List<LLVMValueRef>): LLVMValueRef {
context.log{"evaluateConstructorCall : ${ir2string(callee)}"}
return memScoped {
val constructedClass = (callee.symbol as IrConstructorSymbol).owner.constructedClass
val thisValue = if (constructedClass.isArray) {
assert(args.isNotEmpty() && args[0].type == int32Type)
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0],
resultLifetime(callee), currentCodeContext.exceptionHandler)
} else if (constructedClass == context.ir.symbols.string.owner) {
// TODO: consider returning the empty string literal instead.
assert(args.isEmpty())
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero,
lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler)
} else if (constructedClass.isObjCClass()) {
assert(constructedClass.isKotlinObjCClass()) // Calls to other ObjC class constructors must be lowered.
val symbols = context.ir.symbols
val rawPtr = callDirect(
symbols.interopAllocObjCObject.owner,
listOf(genGetObjCClass(constructedClass)),
Lifetime.IRRELEVANT
)
callDirect(symbols.interopInterpretObjCPointer.owner, listOf(rawPtr), resultLifetime(callee)).also {
// Balance pointer retained by alloc:
callDirect(symbols.interopObjCRelease.owner, listOf(rawPtr), Lifetime.IRRELEVANT)
val constructedClass = callee.symbol.owner.constructedClass
val thisValue = when {
constructedClass.isArray -> {
assert(args.isNotEmpty() && args[0].type == int32Type)
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), args[0],
resultLifetime(callee), currentCodeContext.exceptionHandler)
}
} else {
functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
constructedClass == context.ir.symbols.string.owner -> {
// TODO: consider returning the empty string literal instead.
assert(args.isEmpty())
functionGenerationContext.allocArray(codegen.typeInfoValue(constructedClass), count = kImmZero,
lifetime = resultLifetime(callee), exceptionHandler = currentCodeContext.exceptionHandler)
}
constructedClass.isObjCClass() -> {
assert(constructedClass.isKotlinObjCClass()) // Calls to other ObjC class constructors must be lowered.
val symbols = context.ir.symbols
val rawPtr = callDirect(
symbols.interopAllocObjCObject.owner,
listOf(genGetObjCClass(constructedClass)),
Lifetime.IRRELEVANT
)
callDirect(symbols.interopInterpretObjCPointer.owner, listOf(rawPtr), resultLifetime(callee)).also {
// Balance pointer retained by alloc:
callDirect(symbols.interopObjCRelease.owner, listOf(rawPtr), Lifetime.IRRELEVANT)
}
}
else -> functionGenerationContext.allocInstance(constructedClass, resultLifetime(callee))
}
evaluateSimpleFunctionCall(callee.symbol.owner,
listOf(thisValue) + args, Lifetime.IRRELEVANT /* constructor doesn't return anything */)
@@ -2223,8 +2230,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
private fun delegatingConstructorCall(
constructor: IrConstructor, args: List<LLVMValueRef>): LLVMValueRef {
private fun delegatingConstructorCall(constructor: IrConstructor, args: List<LLVMValueRef>): LLVMValueRef {
val constructedClass = functionGenerationContext.constructedClass!!
val thisPtr = currentCodeContext.genGetValue(constructedClass.thisReceiver!!)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.target
import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -32,8 +33,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addIfNotNull
@@ -131,6 +131,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
private val IrFunctionAccessExpression.target: IrFunction get() = when (this) {
is IrCall -> this.callTarget
is IrDelegatingConstructorCall -> this.symbol.owner
is IrConstructorCall -> this.symbol.owner
else -> TODO(this.render())
}
@@ -266,12 +267,12 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT
}
}
override fun visitCall(expression: IrCall): IrExpression {
super.visitCall(expression)
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
super.visitConstructorCall(expression)
val function = expression.symbol.owner
return if (function is IrConstructor && function.constructedClass.isInlined()) {
builder.lowerConstructorCallToValue(expression, function)
val constructor = expression.symbol.owner
return if (constructor.constructedClass.isInlined()) {
builder.lowerConstructorCallToValue(expression, constructor)
} else {
expression
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -171,7 +172,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
classifier = symbolRemapper.getReferencedClassifier(type.classifier),
hasQuestionMark = type.hasQuestionMark,
arguments = remapTypeArguments(type.arguments),
annotations = type.annotations.map { it.transform(copier, null) as IrCall }
annotations = type.annotations.map { it.transform(copier, null) as IrConstructorCall }
)
}
}
@@ -220,14 +220,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
.map {
val initializer = it.initializerExpression
val entryConstructorCall = when {
initializer is IrCall -> initializer
initializer is IrConstructorCall -> initializer
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL ->
initializer.statements.last() as IrCall
initializer.statements.last() as IrConstructorCall
else -> error("Unexpected initializer: $initializer")
}
val entryClass = (entryConstructorCall.symbol.owner as IrConstructor).constructedClass
val entryClass = entryConstructorCall.symbol.owner.constructedClass
irCall(startOffset, endOffset,
createUninitializedInstance,
@@ -265,7 +265,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val startOffset = irClass.startOffset
val endOffset = irClass.endOffset
fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrCall): IrCall =
fun IrBlockBuilder.initInstanceCall(instance: IrCall, constructor: IrConstructorCall): IrCall =
irCall(initInstanceSymbol).apply {
putValueArgument(0, instance)
putValueArgument(1, constructor)
@@ -288,11 +288,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val initializer = it.value.initializerExpression!!
initializer.patchDeclarationParents(constructor)
when {
initializer is IrCall -> +initInstanceCall(instance, initializer)
initializer is IrConstructorCall -> +initInstanceCall(instance, initializer)
initializer is IrBlock && initializer.origin == ARGUMENTS_REORDERING_FOR_CALL -> {
val statements = initializer.statements
val constructorCall = statements.last() as IrCall
val constructorCall = statements.last() as IrConstructorCall
statements[statements.lastIndex] = initInstanceCall(instance, constructorCall)
+initializer
}
@@ -270,21 +270,13 @@ internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPas
}
private inner class InEnumEntryClassConstructor(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
override fun createConstructorCall(
startOffset: Int,
endOffset: Int,
loweredConstructor: IrConstructorSymbol
) = IrDelegatingConstructorCallImpl(
startOffset,
endOffset,
context.irBuiltIns.unitType,
loweredConstructor
)
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) =
IrDelegatingConstructorCallImpl(startOffset, endOffset, context.irBuiltIns.unitType, loweredConstructor)
}
private inner class InEnumEntryInitializer(enumEntry: IrEnumEntry) : InEnumEntry(enumEntry) {
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol) =
IrCallImpl(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor)
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, loweredConstructor.owner.returnType, loweredConstructor)
}
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
@@ -32,13 +32,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPass {
override fun lower(irFile: IrFile) {
// All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`.
irFile.declarations.removeAll {
if (it.descriptor.isExpectMember) {
true
} else {
false
}
}
irFile.declarations.removeAll { it.descriptor.isExpectMember }
}
}
@@ -36,19 +36,24 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
fun inline(irModule: IrModuleFragment) = irModule.accept(this, data = null)
override fun visitCall(expression: IrCall): IrExpression {
val callSite = super.visitCall(expression) as IrCall
if (!callSite.symbol.owner.needsInlining)
return callSite
if (Symbols.isLateinitIsInitializedPropertyGetter(callSite.symbol))
return callSite
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
expression.transformChildrenVoid(this)
val callee = when (expression) {
is IrCall -> expression.symbol.owner
is IrConstructorCall -> expression.symbol.owner
else -> return expression
}
if (!callee.needsInlining)
return expression
if (Symbols.isLateinitIsInitializedPropertyGetter(callee.symbol))
return expression
val callee = getFunctionDeclaration(callSite.symbol)
val actualCallee = getFunctionDeclaration(callee.symbol)
callee.transformChildrenVoid(this) // Process recursive inline.
actualCallee.transformChildrenVoid(this) // Process recursive inline.
val parent = allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull()
val inliner = Inliner(callSite, callee, currentScope!!, parent, context)
val inliner = Inliner(expression, actualCallee, currentScope!!, parent, context)
return inliner.inline()
}
@@ -76,7 +81,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
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?,
@@ -109,7 +114,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
}
}
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)
@@ -126,12 +131,13 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
val constructedClass = callee.parentAsClass
copiedCallee.parent = constructedClass
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
// TODO: Try use type parameters from callee.
irBuilder.run {
val constructorCall = IrCallImpl(
val constructorCall = IrConstructorCallImpl(
startOffset, endOffset,
callSite.type,
delegatingConstructorCall.symbol, delegatingConstructorCall.descriptor,
constructedClass.typeParameters.size,
constructedClass.typeParameters.size, 0,
delegatingConstructorCall.symbol.owner.valueParameters.size
).apply {
delegatingConstructorCall.symbol.owner.valueParameters.forEach {
@@ -216,11 +222,12 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
val unboundArgsSet = unboundFunctionParameters.toSet()
val valueParameters = expression.getArguments().drop(1) // Skip dispatch receiver.
val immediateCall = IrCallImpl(
expression.startOffset, expression.endOffset,
expression.type,
functionArgument.symbol, functionArgument.descriptor
).apply {
val immediateCall = with(expression) {
if (function is IrConstructor)
IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, type, function.symbol)
else
IrCallImpl(startOffset, endOffset, type, functionArgument.symbol)
}.apply {
functionParameters.forEach {
val argument =
if (!unboundArgsSet.contains(it))
@@ -237,7 +244,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
for (index in 0 until functionArgument.typeArgumentsCount)
putTypeArgument(index, functionArgument.getTypeArgument(index))
}
return this@FunctionInlining.visitCall(super.visitCall(immediateCall) as IrCall)
return this@FunctionInlining.visitExpression(super.visitExpression(immediateCall))
}
if (functionArgument !is IrBlock)
return super.visitCall(expression)
@@ -292,7 +299,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
//-------------------------------------------------------------------------//
private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List<ParameterToArgument> {
private fun buildParameterToArgument(callSite: IrFunctionAccessExpression, callee: IrFunction): List<ParameterToArgument> {
val parameterToArgument = mutableListOf<ParameterToArgument>()
@@ -367,7 +374,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
//-------------------------------------------------------------------------//
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>()
@@ -649,28 +649,31 @@ internal class InteropLoweringPart1(val context: Context) : BaseInteropIrTransfo
)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
expression.transformChildrenVoid()
val descriptor = expression.descriptor.original
val callee = expression.symbol.owner
val initMethod = callee.getObjCInitMethod() ?: return expression
val arguments = descriptor.valueParameters.map { expression.getValueArgument(it) }
assert(expression.extensionReceiver == null)
assert(expression.dispatchReceiver == null)
val constructedClass = callee.constructedClass
val initMethodInfo = initMethod.getExternalObjCMethodInfo()!!
return builder.at(expression).run {
val classPtr = getObjCClass(constructedClass.symbol)
irForceNotNull(callAllocAndInit(classPtr, initMethodInfo, arguments, expression, initMethod))
}
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid()
val descriptor = expression.descriptor.original
val callee = expression.symbol.owner
if (callee is IrConstructor) {
val initMethod = callee.getObjCInitMethod()
if (initMethod != null) {
val arguments = descriptor.valueParameters.map { expression.getValueArgument(it) }
assert(expression.extensionReceiver == null)
assert(expression.dispatchReceiver == null)
val constructedClass = callee.constructedClass
val initMethodInfo = initMethod.getExternalObjCMethodInfo()!!
return builder.at(expression).run {
val classPtr = getObjCClass(constructedClass.symbol)
irForceNotNull(callAllocAndInit(classPtr, initMethodInfo, arguments, expression, initMethod))
}
}
}
descriptor.getObjCFactoryInitMethodInfo()?.let { initMethodInfo ->
val arguments = (0 until expression.valueArgumentsCount)
@@ -858,6 +861,17 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
private fun generateCFunctionPointer(function: IrSimpleFunction, expression: IrExpression): IrExpression =
generateWithStubs { generateCFunctionPointer(function, function, expression) }
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
expression.transformChildrenVoid(this)
val function = expression.symbol.owner
val inlinedClass = function.returnType.getInlinedClassNative()
if (inlinedClass?.descriptor == interop.cPointer || inlinedClass?.descriptor == interop.nativePointed) {
throw Error("Native interop types constructors must not be called directly")
}
return expression
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
@@ -865,13 +879,6 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
val descriptor = expression.descriptor.original
val function = expression.symbol.owner
if (function is IrConstructor) {
val inlinedClass = function.returnType.getInlinedClassNative()
if (inlinedClass?.descriptor == interop.cPointer || inlinedClass?.descriptor == interop.nativePointed) {
throw Error("Native interop types constructors must not be called directly")
}
}
if (descriptor == interop.nativePointedRawPtrGetter ||
OverridingUtil.overrides(descriptor, interop.nativePointedRawPtrGetter)) {
@@ -1029,8 +1036,7 @@ private class InteropTransformer(val context: Context, override val irFile: IrFi
val intrinsic = interop.objCObjectInitBy.name
val argument = expression.getValueArgument(0)!!
val constructedClass =
((argument as? IrCall)?.descriptor as? ClassConstructorDescriptor)?.constructedClass
val constructedClass = (argument as? IrConstructorCall)?.symbol?.owner?.constructedClass?.descriptor
if (constructedClass == null) {
context.reportCompilationError("Argument of '$intrinsic' must be a constructor call",
@@ -1068,7 +1068,7 @@ internal class SuspendFunctionsLowering(val context: Context): FileLoweringPass
}
}
fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrCall {
fun IrBlockBodyBuilder.irSuccess(value: IrExpression): IrMemberAccessExpression {
val createResult = symbols.kotlinResult.owner.constructors.single { it.isPrimary }
return irCall(createResult).apply {
putValueArgument(0, value)
@@ -87,12 +87,7 @@ internal class VarargInjectionLowering constructor(val context: KonanBackendCont
expression.transformChildrenVoid(this)
}
override fun visitCall(expression: IrCall): IrExpression {
replaceEmptyParameterWithEmptyArray(expression)
return expression
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression {
replaceEmptyParameterWithEmptyArray(expression)
return expression
}
@@ -557,6 +557,17 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
else symbolTable.mapFunction(value.symbol.owner.constructors.single())
)
is IrConstructorCall -> {
val callee = value.symbol.owner
val arguments = value.getArguments().map { expressionToEdge(it.second) }
DataFlowIR.Node.NewObject(
symbolTable.mapFunction(callee),
arguments,
symbolTable.mapClassReferenceType(callee.constructedClass, false),
value
)
}
is IrCall -> when (value.symbol) {
getContinuationSymbol -> getContinuation()
@@ -573,9 +584,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
initInstanceSymbol -> {
val thiz = expressionToEdge(value.getValueArgument(0)!!)
val initializer = value.getValueArgument(1) as IrCall
val initializer = value.getValueArgument(1) as IrConstructorCall
val arguments = listOf(thiz) + initializer.getArguments().map { expressionToEdge(it.second) }
val callee = initializer.symbol.owner as IrConstructor
val callee = initializer.symbol.owner
DataFlowIR.Node.StaticCall(
symbolTable.mapFunction(callee),
arguments,
@@ -595,12 +606,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
it
}
if (callee is IrConstructor) {
DataFlowIR.Node.NewObject(
symbolTable.mapFunction(callee),
arguments,
symbolTable.mapClassReferenceType(callee.constructedClass, false),
value
)
error("Constructor call should be done with IrConstructorCall")
} else {
callee as IrSimpleFunction
if (callee.isOverridable && value.superQualifier == null) {
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
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.IrGetField
import org.jetbrains.kotlin.ir.types.IrType
@@ -233,7 +234,8 @@ internal object DataFlowIR {
: Call(callee, arguments, irCallSite)
// TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove.
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type, override val irCallSite: IrCall?)
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type,
override val irCallSite: IrConstructorCall?)
: Call(constructor, arguments, irCallSite)
open class VirtualCall(callee: FunctionSymbol, arguments: List<Edge>,
@@ -491,12 +491,10 @@ private fun IrFunction.substitutedReturnType(typeArguments: List<IrType>): IrTyp
// TODO: this function must be avoided since it takes symbol's owner implicitly.
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<IrType> = emptyList()) =
irCall(symbol.owner, typeArguments)
this.irCall(symbol, symbol.owner.substitutedReturnType(typeArguments), typeArguments)
fun IrBuilderWithScope.irCall(
irFunction: IrFunction,
typeArguments: List<IrType> = emptyList()
): IrCall = irCall(this.startOffset, this.endOffset, irFunction, typeArguments)
fun IrBuilderWithScope.irCall(irFunction: IrFunction, typeArguments: List<IrType> = emptyList()) =
irCall(irFunction.symbol, typeArguments)
internal fun irCall(startOffset: Int, endOffset: Int, irFunction: IrFunction, typeArguments: List<IrType>): IrCall =
IrCallImpl(
@@ -512,7 +510,7 @@ fun IrBuilderWithScope.irCallOp(
callee: IrFunction,
dispatchReceiver: IrExpression,
argument: IrExpression
): IrCall =
) =
irCall(callee).apply {
this.dispatchReceiver = dispatchReceiver
putValueArgument(0, argument)