New copier for inliner
This commit is contained in:
+198
-17
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.createExtensionReceiver
|
||||
@@ -19,37 +20,217 @@ import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
|
||||
val parent: IrDeclarationParent?) : IrCopierForInliner {
|
||||
|
||||
override fun copy(irElement: IrElement): IrElement {
|
||||
// Create new symbols.
|
||||
irElement.acceptVoid(symbolRemapper)
|
||||
|
||||
// Make symbol remapper aware of the callsite's type arguments.
|
||||
symbolRemapper.typeArguments = typeArguments
|
||||
|
||||
// Copy IR.
|
||||
val result = irElement.transform(copier, data = null)
|
||||
|
||||
// Bind newly created IR with wrapped descriptors.
|
||||
result.acceptVoid(object: IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
(declaration.descriptor as WrappedClassDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
(declaration.descriptor as WrappedClassConstructorDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(declaration: IrEnumEntry) {
|
||||
(declaration.descriptor as WrappedClassDescriptor).bind(
|
||||
declaration.correspondingClass ?: declaration.parentAsClass)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
(declaration.descriptor as WrappedPropertyDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
(declaration.descriptor as WrappedSimpleFunctionDescriptor).bind(declaration as IrSimpleFunction)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitValueParameter(declaration: IrValueParameter) {
|
||||
(declaration.descriptor as? WrappedValueParameterDescriptor)?.bind(declaration)
|
||||
(declaration.descriptor as? WrappedReceiverParameterDescriptor)?.bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(declaration: IrTypeParameter) {
|
||||
(declaration.descriptor as WrappedTypeParameterDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable) {
|
||||
(declaration.descriptor as WrappedVariableDescriptor).bind(declaration)
|
||||
declaration.acceptChildrenVoid(this)
|
||||
}
|
||||
})
|
||||
|
||||
result.patchDeclarationParents(parent)
|
||||
return result
|
||||
}
|
||||
|
||||
private var nameIndex = 0
|
||||
|
||||
private fun generateCopyName(name: Name) = Name.identifier(name.toString() + "_" + (nameIndex++).toString())
|
||||
|
||||
private inner class InlinerSymbolRenamer : SymbolRenamer {
|
||||
private val map = mutableMapOf<IrSymbol, Name>()
|
||||
|
||||
override fun getClassName(symbol: IrClassSymbol) = map.getOrPut(symbol) { generateCopyName(symbol.owner.name) }
|
||||
override fun getFunctionName(symbol: IrSimpleFunctionSymbol) = map.getOrPut(symbol) { generateCopyName(symbol.owner.name) }
|
||||
override fun getFieldName(symbol: IrFieldSymbol) = symbol.owner.name
|
||||
override fun getFileName(symbol: IrFileSymbol) = symbol.owner.fqName
|
||||
override fun getExternalPackageFragmentName(symbol: IrExternalPackageFragmentSymbol) = symbol.owner.fqName
|
||||
override fun getEnumEntryName(symbol: IrEnumEntrySymbol) = symbol.owner.name
|
||||
override fun getVariableName(symbol: IrVariableSymbol) = map.getOrPut(symbol) { generateCopyName(symbol.owner.name) }
|
||||
override fun getTypeParameterName(symbol: IrTypeParameterSymbol) = symbol.owner.name
|
||||
override fun getValueParameterName(symbol: IrValueParameterSymbol) = symbol.owner.name
|
||||
}
|
||||
|
||||
private inner class DescriptorsToIrRemapper : DescriptorsRemapper {
|
||||
override fun remapDeclaredClass(descriptor: ClassDescriptor) =
|
||||
WrappedClassDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredConstructor(descriptor: ClassConstructorDescriptor) =
|
||||
WrappedClassConstructorDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredEnumEntry(descriptor: ClassDescriptor) =
|
||||
WrappedClassDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredField(descriptor: PropertyDescriptor) =
|
||||
WrappedPropertyDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredSimpleFunction(descriptor: FunctionDescriptor) =
|
||||
WrappedSimpleFunctionDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredTypeParameter(descriptor: TypeParameterDescriptor) =
|
||||
WrappedTypeParameterDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredVariable(descriptor: VariableDescriptor) =
|
||||
WrappedVariableDescriptor(descriptor.annotations, descriptor.source)
|
||||
|
||||
override fun remapDeclaredValueParameter(descriptor: ParameterDescriptor): ParameterDescriptor =
|
||||
if (descriptor is ReceiverParameterDescriptor)
|
||||
WrappedReceiverParameterDescriptor(descriptor.annotations, descriptor.source)
|
||||
else
|
||||
WrappedValueParameterDescriptor(descriptor.annotations, descriptor.source)
|
||||
}
|
||||
|
||||
private inner class InlinerTypeRemapper(val symbolRemapper: SymbolRemapper,
|
||||
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?) : TypeRemapper {
|
||||
|
||||
override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) { }
|
||||
|
||||
override fun leaveScope() { }
|
||||
|
||||
private fun remapTypeArguments(arguments: List<IrTypeArgument>) =
|
||||
arguments.map { argument ->
|
||||
(argument as? IrTypeProjection)?.let { makeTypeProjection(remapType(it.type), it.variance) }
|
||||
?: argument
|
||||
}
|
||||
|
||||
override fun remapType(type: IrType): IrType {
|
||||
if (type !is IrSimpleType) return type
|
||||
|
||||
val substitutedType = typeArguments?.get(type.classifier)
|
||||
if (substitutedType != null) {
|
||||
substitutedType as IrSimpleType
|
||||
return IrSimpleTypeImpl(
|
||||
kotlinType = null,
|
||||
classifier = substitutedType.classifier,
|
||||
hasQuestionMark = type.hasQuestionMark or substitutedType.isMarkedNullable(),
|
||||
arguments = substitutedType.arguments,
|
||||
annotations = substitutedType.annotations
|
||||
)
|
||||
}
|
||||
|
||||
return IrSimpleTypeImpl(
|
||||
kotlinType = null,
|
||||
classifier = symbolRemapper.getReferencedClassifier(type.classifier),
|
||||
hasQuestionMark = type.hasQuestionMark,
|
||||
arguments = remapTypeArguments(type.arguments),
|
||||
annotations = type.annotations.map { it.transform(copier, null) as IrCall }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) { }
|
||||
|
||||
private class SymbolRemapperImpl(descriptorsRemapper: DescriptorsRemapper)
|
||||
: DeepCopySymbolRemapper(descriptorsRemapper) {
|
||||
|
||||
var typeArguments: Map<IrTypeParameterSymbol, IrType?>? = null
|
||||
set(value) {
|
||||
if (field != null) return
|
||||
field = value?.asSequence()?.associate {
|
||||
(getReferencedClassifier(it.key) as IrTypeParameterSymbol) to it.value
|
||||
}
|
||||
}
|
||||
|
||||
override fun getReferencedClassifier(symbol: IrClassifierSymbol): IrClassifierSymbol {
|
||||
val result = super.getReferencedClassifier(symbol)
|
||||
if (result !is IrTypeParameterSymbol)
|
||||
return result
|
||||
return typeArguments?.get(result)?.classifierOrNull ?: result
|
||||
}
|
||||
}
|
||||
|
||||
private val symbolRemapper = SymbolRemapperImpl(DescriptorsToIrRemapper())
|
||||
private val copier = DeepCopyIrTreeWithSymbols(
|
||||
symbolRemapper,
|
||||
InlinerTypeRemapper(symbolRemapper, typeArguments),
|
||||
InlinerSymbolRenamer()
|
||||
)
|
||||
}
|
||||
|
||||
internal interface IrCopierForInliner {
|
||||
fun copy(irElement: IrElement): IrElement
|
||||
fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>)
|
||||
}
|
||||
|
||||
internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescriptor,
|
||||
val parentDescriptor: DeclarationDescriptor,
|
||||
val context: Context) {
|
||||
val context: Context,
|
||||
val typeSubstitutor: TypeSubstitutor?) : IrCopierForInliner {
|
||||
|
||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||
private var typeSubstitutor: TypeSubstitutor? = null
|
||||
private var nameIndex = 0
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun copy(irElement: IrElement, typeSubstitutor: TypeSubstitutor?): IrElement {
|
||||
this.typeSubstitutor = typeSubstitutor
|
||||
override fun copy(irElement: IrElement): IrElement {
|
||||
// Create all class descriptors and all necessary descriptors in order to create KotlinTypes.
|
||||
irElement.acceptVoid(DescriptorCollectorCreatePhase())
|
||||
// Initialize all created descriptors possibly using previously created types.
|
||||
@@ -762,7 +943,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) {
|
||||
override fun addCurrentSubstituteMap(globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>) {
|
||||
descriptorSubstituteMap.forEach { t, u ->
|
||||
globalSubstituteMap[t] = SubstitutedDescriptor(targetDescriptor, u)
|
||||
}
|
||||
|
||||
+227
-161
@@ -9,6 +9,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2stringWhole
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||
@@ -16,26 +17,23 @@ import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
@@ -44,70 +42,154 @@ import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
//-----------------------------------------------------------------------------//
|
||||
abstract class IrElementTransformerWithContext<D> : IrElementTransformer<D> {
|
||||
|
||||
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
|
||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||
|
||||
final override fun visitFile(declaration: IrFile, data: D): IrFile {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
val result = visitFileNew(declaration, data)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun visitClass(declaration: IrClass, data: D): IrStatement {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
val result = visitClassNew(declaration, data)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun visitProperty(declaration: IrProperty, data: D): IrStatement {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
val result = visitPropertyNew(declaration, data)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun visitField(declaration: IrField, data: D): IrStatement {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
val result = visitFieldNew(declaration, data)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
final override fun visitFunction(declaration: IrFunction, data: D): IrStatement {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
val result = visitFunctionNew(declaration, data)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
protected val currentFile get() = scopeStack.lastOrNull { it.irElement is IrFile }!!.irElement as IrFile
|
||||
protected val currentClass get() = scopeStack.lastOrNull { it.scope.scopeOwner is ClassDescriptor }
|
||||
protected val currentFunction get() = scopeStack.lastOrNull { it.scope.scopeOwner is FunctionDescriptor }
|
||||
protected val currentProperty get() = scopeStack.lastOrNull { it.scope.scopeOwner is PropertyDescriptor }
|
||||
protected val currentScope get() = scopeStack.peek()
|
||||
protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2]
|
||||
protected val allScopes get() = scopeStack
|
||||
|
||||
fun printScopeStack() {
|
||||
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||
}
|
||||
|
||||
open fun visitFileNew(declaration: IrFile, data: D): IrFile {
|
||||
return super.visitFile(declaration, data)
|
||||
}
|
||||
|
||||
open fun visitClassNew(declaration: IrClass, data: D): IrStatement {
|
||||
return super.visitClass(declaration, data)
|
||||
}
|
||||
|
||||
open fun visitFunctionNew(declaration: IrFunction, data: D): IrStatement {
|
||||
return super.visitFunction(declaration, data)
|
||||
}
|
||||
|
||||
open fun visitPropertyNew(declaration: IrProperty, data: D): IrStatement {
|
||||
return super.visitProperty(declaration, data)
|
||||
}
|
||||
|
||||
open fun visitFieldNew(declaration: IrField, data: D): IrStatement {
|
||||
return super.visitField(declaration, data)
|
||||
}
|
||||
}
|
||||
|
||||
internal class Ref<T>(var value: T)
|
||||
|
||||
internal class FunctionInlining(val context: Context): IrElementTransformerWithContext<Ref<Boolean>>() {
|
||||
|
||||
private val deserializer = DeserializerDriver(context)
|
||||
private val globalSubstituteMap = mutableMapOf<DeclarationDescriptor, SubstitutedDescriptor>()
|
||||
private val inlineFunctions = mutableMapOf<FunctionDescriptor, Boolean>()
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun inline(irModule: IrModuleFragment): IrElement {
|
||||
val transformedModule = irModule.accept(this, null)
|
||||
val transformedModule = irModule.accept(this, Ref(false))
|
||||
DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
||||
return transformedModule
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
override fun visitFunctionNew(declaration: IrFunction, data: Ref<Boolean>): IrStatement {
|
||||
val descriptor = declaration.descriptor
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
val localData = Ref(inlineFunctions[descriptor] ?: false)
|
||||
val result = super.visitFunctionNew(declaration, localData)
|
||||
data.value = data.value or localData.value
|
||||
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
val functionDescriptor = irCall.descriptor
|
||||
if (!functionDescriptor.needsInlining || functionDescriptor == context.ir.symbols.isInitializedGetterDescriptor) {
|
||||
return irCall // This call does not need inlining.
|
||||
}
|
||||
if (descriptor.needsInlining)
|
||||
inlineFunctions[descriptor] = localData.value
|
||||
return result
|
||||
}
|
||||
|
||||
val functionDeclaration = getFunctionDeclaration(functionDescriptor) // Get declaration of the function to be inlined.
|
||||
if (functionDeclaration == null) { // We failed to get the declaration.
|
||||
override fun visitCall(expression: IrCall, data: Ref<Boolean>): IrExpression {
|
||||
|
||||
val argsAreBad = Ref(false)
|
||||
val callSite = super.visitCall(expression, argsAreBad) as IrCall
|
||||
data.value = data.value or argsAreBad.value
|
||||
if (!callSite.descriptor.needsInlining)
|
||||
return callSite
|
||||
val functionDescriptor = callSite.descriptor.resolveFakeOverride().original
|
||||
if (functionDescriptor == context.ir.symbols.isInitializedGetterDescriptor)
|
||||
return callSite
|
||||
|
||||
val callee = getFunctionDeclaration(functionDescriptor)
|
||||
if (callee == null) {
|
||||
val message = "Inliner failed to obtain function declaration: " +
|
||||
functionDescriptor.fqNameSafe.toString()
|
||||
context.reportWarning(message, currentFile, irCall) // Report warning.
|
||||
return irCall
|
||||
context.reportWarning(message, currentFile, callSite)
|
||||
return callSite
|
||||
}
|
||||
data.value = data.value or callee.second
|
||||
|
||||
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||
val inliner = Inliner(globalSubstituteMap, functionDeclaration, currentScope!!, context, this) // Create inliner for this scope.
|
||||
return inliner.inline(irCall) // Return newly created IrInlineBody instead of IrCall.
|
||||
val childIsBad = Ref(inlineFunctions[functionDescriptor] ?: false)
|
||||
callee.first.transformChildren(this, childIsBad) // Process recursive inline.
|
||||
inlineFunctions[functionDescriptor] = childIsBad.value
|
||||
data.value = data.value or childIsBad.value
|
||||
|
||||
val currentCalleeIsBad = argsAreBad.value or childIsBad.value or callee.second
|
||||
val inliner = Inliner(globalSubstituteMap, callSite, callee.first, !currentCalleeIsBad, currentScope!!,
|
||||
allScopes.map { it.irElement }.filterIsInstance<IrDeclarationParent>().lastOrNull(), context, this)
|
||||
return inliner.inline()
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun getFunctionDeclaration(descriptor: FunctionDescriptor): IrFunction? =
|
||||
descriptor.resolveFakeOverride().original.let {
|
||||
when {
|
||||
it.isBuiltInIntercepted(context.config.configuration.languageVersionSettings) ->
|
||||
error("Continuation.intercepted is not available with release coroutines")
|
||||
private fun getFunctionDeclaration(descriptor: FunctionDescriptor): Pair<IrFunction, Boolean>? =
|
||||
when {
|
||||
descriptor.isBuiltInIntercepted(context.config.configuration.languageVersionSettings) ->
|
||||
error("Continuation.intercepted is not available with release coroutines")
|
||||
|
||||
it.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings) ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
|
||||
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings) ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanSuspendCoroutineUninterceptedOrReturn.descriptor)
|
||||
|
||||
it == context.ir.symbols.coroutineContextGetter ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanCoroutineContextGetter.descriptor)
|
||||
descriptor == context.ir.symbols.coroutineContextGetter ->
|
||||
getFunctionDeclaration(context.ir.symbols.konanCoroutineContextGetter.descriptor)
|
||||
|
||||
else -> {
|
||||
val functionDeclaration =
|
||||
context.ir.originalModuleIndex.functions[it] ?: // If function is declared in the current module.
|
||||
deserializer.deserializeInlineBody(it) // Function is declared in another module.
|
||||
functionDeclaration as IrFunction?
|
||||
}
|
||||
}
|
||||
else ->
|
||||
context.ir.originalModuleIndex.functions[descriptor]?.let { it to false }
|
||||
?: deserializer.deserializeInlineBody(descriptor)?.let { it as IrFunction to true }
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
||||
}
|
||||
|
||||
private val inlineConstructor = FqName("kotlin.native.internal.InlineConstructor")
|
||||
@@ -116,22 +198,34 @@ private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnota
|
||||
//-----------------------------------------------------------------------------//
|
||||
|
||||
private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>,
|
||||
val functionDeclaration: IrFunction, // Function to substitute.
|
||||
val callSite: IrCall,
|
||||
val callee: IrFunction,
|
||||
val local: Boolean,
|
||||
val currentScope: ScopeWithIr,
|
||||
val parent: IrDeclarationParent?,
|
||||
val context: Context,
|
||||
val owner: FunctionInlining /*TODO: make inner*/) {
|
||||
|
||||
val copyIrElement = DeepCopyIrTreeWithDescriptors(functionDeclaration.descriptor, currentScope.scope.scopeOwner, context) // Create DeepCopy for current scope.
|
||||
val copyIrElement =
|
||||
if (!local)
|
||||
DeepCopyIrTreeWithDescriptors(callee.descriptor, currentScope.scope.scopeOwner,
|
||||
context, createTypeSubstitutor(callSite))
|
||||
else {
|
||||
val typeParameters =
|
||||
if (callee is IrConstructor)
|
||||
callee.parentAsClass.typeParameters
|
||||
else callee.typeParameters
|
||||
val typeArguments =
|
||||
(0 until callSite.typeArgumentsCount).map {
|
||||
typeParameters[it].symbol to callSite.getTypeArgument(it)
|
||||
}.associate { it }
|
||||
DeepCopyIrTreeWithSymbolsForInliner(context, typeArguments, parent)
|
||||
}
|
||||
|
||||
val substituteMap = mutableMapOf<ValueDescriptor, IrExpression>()
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
fun inline() = inlineFunction(callSite, callee)
|
||||
|
||||
fun inline(irCall: IrCall): IrReturnableBlockImpl { // Call to be substituted.
|
||||
val inlineFunctionBody = inlineFunction(irCall, functionDeclaration)
|
||||
return inlineFunctionBody
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
/**
|
||||
* TODO: JVM inliner crashed on attempt inline this function from transform.kt with:
|
||||
* j.l.IllegalStateException: Couldn't obtain compiled function body for
|
||||
@@ -143,29 +237,23 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
}
|
||||
}
|
||||
|
||||
private fun inlineFunction(callee: IrCall, // Call to be substituted.
|
||||
caller: IrFunction): IrReturnableBlockImpl { // Function to substitute.
|
||||
private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlockImpl {
|
||||
val copiedCallee = copyIrElement.copy(callee) as IrFunction
|
||||
|
||||
val copyFunctionDeclaration = copyIrElement.copy( // Create copy of original function.
|
||||
irElement = caller, // Descriptors declared inside the function will be copied.
|
||||
typeSubstitutor = createTypeSubstitutor(callee) // Type parameters will be substituted with type arguments.
|
||||
) as IrFunction
|
||||
val evaluationStatements = evaluateArguments(callSite, copiedCallee)
|
||||
val statements = (copiedCallee.body as IrBlockBody).statements
|
||||
|
||||
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copyFunctionDeclaration.descriptor.original)
|
||||
val irReturnableBlockSymbol = IrReturnableBlockSymbolImpl(copiedCallee.descriptor.original)
|
||||
val descriptor = callee.descriptor.original
|
||||
val startOffset = callee.startOffset
|
||||
val endOffset = callee.endOffset
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
|
||||
val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements.
|
||||
|
||||
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
|
||||
|
||||
val startOffset = caller.startOffset
|
||||
val endOffset = caller.endOffset
|
||||
val descriptor = caller.descriptor.original
|
||||
if (descriptor.isInlineConstructor) {
|
||||
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol, callee.type,
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol, callSite.type,
|
||||
constructorDescriptor.typeParameters.map { delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
||||
}
|
||||
@@ -180,31 +268,36 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
}
|
||||
}
|
||||
|
||||
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[caller.descriptor.original]?:""
|
||||
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[callee.descriptor.original] ?: ""
|
||||
|
||||
// Update globalSubstituteMap before computing return type.
|
||||
// This is needed because of nested inlining.
|
||||
copyIrElement.addCurrentSubstituteMap(globalSubstituteMap)
|
||||
|
||||
val transformer = ParameterSubstitutor()
|
||||
statements.transform { it.transform(transformer, data = null) }
|
||||
statements.addAll(0, evaluationStatements)
|
||||
val oldDescriptor = (copyFunctionDeclaration.returnType.classifierOrNull as? IrClassSymbol)?.descriptor
|
||||
val substitutedDescriptor = oldDescriptor?.let { globalSubstituteMap[it] }
|
||||
val returnType = substitutedDescriptor?.let { context.ir.translateErased((it.descriptor as ClassDescriptor).defaultType) }
|
||||
?: copyFunctionDeclaration.returnType
|
||||
|
||||
val isCoroutineIntrinsicCall = callee.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(context.config.configuration.languageVersionSettings)
|
||||
val isCoroutineIntrinsicCall = callSite.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(
|
||||
context.config.configuration.languageVersionSettings)
|
||||
|
||||
return IrReturnableBlockImpl( // Create new IR element to replace "call".
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = returnType,
|
||||
symbol = irReturnableBlockSymbol,
|
||||
origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null,
|
||||
statements = statements,
|
||||
return IrReturnableBlockImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = copiedCallee.returnType,
|
||||
symbol = irReturnableBlockSymbol,
|
||||
origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null,
|
||||
statements = statements,
|
||||
sourceFileName = sourceFileName
|
||||
)
|
||||
).apply {
|
||||
transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (expression.returnTargetSymbol == copiedCallee.symbol)
|
||||
return irBuilder.irReturn(expression.value)
|
||||
return expression
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
@@ -214,14 +307,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val newExpression = super.visitGetValue(expression) as IrGetValue
|
||||
val descriptor = newExpression.descriptor
|
||||
val argument = substituteMap[descriptor] // Find expression to replace this parameter.
|
||||
if (argument == null) return newExpression // If there is no such expression - do nothing.
|
||||
val argument = substituteMap[descriptor]
|
||||
|
||||
argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution.
|
||||
return copyIrElement.copy( // Make copy of argument expression.
|
||||
irElement = argument,
|
||||
typeSubstitutor = null
|
||||
) as IrExpression
|
||||
if (argument == null) return newExpression
|
||||
|
||||
argument.transformChildrenVoid(this) // Default argument can contain subjects for substitution.
|
||||
return copyIrElement.copy(argument) as IrExpression
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------//
|
||||
@@ -267,14 +358,14 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||
}
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size, { "Not all arguments of <invoke> are used" })
|
||||
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||
}
|
||||
return owner.visitCall(super.visitCall(immediateCall) as IrCall)
|
||||
return owner.visitCall(super.visitCall(immediateCall) as IrCall, Ref(false))
|
||||
}
|
||||
if (functionArgument !is IrBlock)
|
||||
return super.visitCall(expression)
|
||||
|
||||
val functionDeclaration = getLambdaFunction(functionArgument)
|
||||
val functionDeclaration = functionArgument.statements[0] as IrFunction
|
||||
val newExpression = inlineFunction(expression, functionDeclaration) // Inline the lambda. Lambda parameters will be substituted with lambda arguments.
|
||||
return newExpression.transform(this, null) // Substitute lambda arguments with target function arguments.
|
||||
}
|
||||
@@ -284,22 +375,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
||||
}
|
||||
|
||||
//--- Helpers -------------------------------------------------------------//
|
||||
|
||||
private fun isLambdaCall(irCall: IrCall) : Boolean {
|
||||
if (!irCall.descriptor.isFunctionInvoke) return false // Lambda mast be called by "invoke".
|
||||
if (irCall.dispatchReceiver !is IrGetValue) return false // Dispatch receiver mast be IrGetValue.
|
||||
return true // It is lambda call.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun getLambdaFunction(lambdaArgument: IrBlock): IrFunction {
|
||||
val statements = lambdaArgument.statements
|
||||
return statements[0] as IrFunction
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
||||
|
||||
private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? {
|
||||
if (irCall.typeArgumentsCount == 0) return null
|
||||
@@ -344,45 +420,43 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun buildParameterToArgument(irCall : IrCall, // Call site.
|
||||
irFunction: IrFunction // Function to be called.
|
||||
): List<ParameterToArgument> {
|
||||
private fun buildParameterToArgument(callSite: IrCall, callee: IrFunction): List<ParameterToArgument> {
|
||||
|
||||
val parameterToArgument = mutableListOf<ParameterToArgument>() // Result list.
|
||||
val parameterToArgument = mutableListOf<ParameterToArgument>()
|
||||
|
||||
if (irCall.dispatchReceiver != null && // Only if there are non null dispatch receivers both
|
||||
irFunction.dispatchReceiverParameter != null) // on call site and in function declaration.
|
||||
if (callSite.dispatchReceiver != null && // Only if there are non null dispatch receivers both
|
||||
callee.dispatchReceiverParameter != null) // on call site and in function declaration.
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameter = irFunction.dispatchReceiverParameter!!,
|
||||
argumentExpression = irCall.dispatchReceiver!!
|
||||
parameter = callee.dispatchReceiverParameter!!,
|
||||
argumentExpression = callSite.dispatchReceiver!!
|
||||
)
|
||||
|
||||
val valueArguments =
|
||||
irCall.descriptor.valueParameters.map { irCall.getValueArgument(it) }.toMutableList()
|
||||
callSite.descriptor.valueParameters.map { callSite.getValueArgument(it) }.toMutableList()
|
||||
|
||||
if (irFunction.extensionReceiverParameter != null) {
|
||||
if (callee.extensionReceiverParameter != null) {
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameter = irFunction.extensionReceiverParameter!!,
|
||||
argumentExpression = if (irCall.extensionReceiver != null) {
|
||||
irCall.extensionReceiver!!
|
||||
parameter = callee.extensionReceiverParameter!!,
|
||||
argumentExpression = if (callSite.extensionReceiver != null) {
|
||||
callSite.extensionReceiver!!
|
||||
} else {
|
||||
// Special case: lambda with receiver is called as usual lambda:
|
||||
valueArguments.removeAt(0)!!
|
||||
}
|
||||
)
|
||||
} else if (irCall.extensionReceiver != null) {
|
||||
} else if (callSite.extensionReceiver != null) {
|
||||
// Special case: usual lambda is called as lambda with receiver:
|
||||
valueArguments.add(0, irCall.extensionReceiver!!)
|
||||
valueArguments.add(0, callSite.extensionReceiver!!)
|
||||
}
|
||||
|
||||
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
||||
irFunction.valueParameters.forEach { parameter -> // Iterate value parameters.
|
||||
val argument = valueArguments[parameter.index] // Get appropriate argument from call site.
|
||||
for (parameter in callee.valueParameters) {
|
||||
val argument = valueArguments[parameter.index]
|
||||
when {
|
||||
argument != null -> { // Argument is good enough.
|
||||
parameterToArgument += ParameterToArgument( // Associate current parameter with the argument.
|
||||
parameter = parameter,
|
||||
argumentExpression = argument
|
||||
argument != null -> {
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameter = parameter,
|
||||
argumentExpression = argument
|
||||
)
|
||||
}
|
||||
|
||||
@@ -390,43 +464,41 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
// are represented correctly in IR.
|
||||
parameter.defaultValue != null -> { // There is no argument - try default value.
|
||||
parametersWithDefaultToArgument += ParameterToArgument(
|
||||
parameter = parameter,
|
||||
argumentExpression = parameter.defaultValue!!.expression
|
||||
parameter = parameter,
|
||||
argumentExpression = parameter.defaultValue!!.expression
|
||||
)
|
||||
}
|
||||
|
||||
parameter.varargElementType != null -> {
|
||||
val emptyArray = IrVarargImpl(
|
||||
startOffset = irCall.startOffset,
|
||||
endOffset = irCall.endOffset,
|
||||
type = parameter.type,
|
||||
varargElementType = parameter.varargElementType!!
|
||||
startOffset = callSite.startOffset,
|
||||
endOffset = callSite.endOffset,
|
||||
type = parameter.type,
|
||||
varargElementType = parameter.varargElementType!!
|
||||
)
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameter = parameter,
|
||||
argumentExpression = emptyArray
|
||||
parameter = parameter,
|
||||
argumentExpression = emptyArray
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val message = "Incomplete expression: call to ${irFunction.descriptor} " +
|
||||
"has no argument at index ${parameter.index}"
|
||||
val message = "Incomplete expression: call to ${callee.descriptor} " +
|
||||
"has no argument at index ${parameter.index}"
|
||||
throw Error(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameterToArgument + parametersWithDefaultToArgument // All arguments except default are evaluated at callsite,
|
||||
// but default arguments are evaluated inside callee.
|
||||
return parameterToArgument + parametersWithDefaultToArgument // All arguments except default are evaluated at callsite,
|
||||
// but default arguments are evaluated inside callee.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateArguments(irCall : IrCall, // Call site.
|
||||
functionDeclaration: IrFunction // Function to be called.
|
||||
): List<IrStatement> {
|
||||
private fun evaluateArguments(callSite: IrCall, callee: IrFunction): List<IrStatement> {
|
||||
|
||||
val parameterToArgumentOld = buildParameterToArgument(irCall, functionDeclaration) // Create map parameter_descriptor -> original_argument_expression.
|
||||
val evaluationStatements = mutableListOf<IrStatement>() // List of evaluation statements.
|
||||
val parameterToArgumentOld = buildParameterToArgument(callSite, callee)
|
||||
val evaluationStatements = mutableListOf<IrStatement>()
|
||||
val substitutor = ParameterSubstitutor()
|
||||
parameterToArgumentOld.forEach {
|
||||
val parameterDescriptor = it.parameter.descriptor
|
||||
@@ -446,26 +518,20 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val newVariable = currentScope.scope.createTemporaryVariable( // Create new variable and init it with the parameter expression.
|
||||
val newVariable = currentScope.scope.createTemporaryVariable(
|
||||
irExpression = it.argumentExpression.transform(substitutor, data = null), // Arguments may reference the previous ones - substitute them.
|
||||
nameHint = functionDeclaration.descriptor.name.toString(),
|
||||
nameHint = callee.descriptor.name.toString(),
|
||||
isMutable = false)
|
||||
|
||||
evaluationStatements.add(newVariable) // Add initialization of the new variable in statement list.
|
||||
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
|
||||
evaluationStatements.add(newVariable)
|
||||
val getVal = IrGetValueImpl(
|
||||
startOffset = currentScope.irElement.startOffset,
|
||||
endOffset = currentScope.irElement.endOffset,
|
||||
type = newVariable.type,
|
||||
symbol = newVariable.symbol
|
||||
)
|
||||
substituteMap[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
|
||||
substituteMap[parameterDescriptor] = getVal
|
||||
}
|
||||
return evaluationStatements
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
+4
-6
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.createDispatchReceiverParameter
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
||||
@@ -88,7 +86,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
}
|
||||
|
||||
private fun createInitializerMethod(): IrSimpleFunctionSymbol? {
|
||||
if (irClass.descriptor.hasPrimaryConstructor())
|
||||
if (irClass.declarations.any { it is IrConstructor && it.isPrimary })
|
||||
return null // Place initializers in the primary constructor.
|
||||
val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ irClass.descriptor,
|
||||
@@ -125,9 +123,8 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
initializer.dispatchReceiverParameter!!.type,
|
||||
initializer.dispatchReceiverParameter!!.symbol
|
||||
)
|
||||
} else {
|
||||
return expression
|
||||
}
|
||||
return expression
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -191,6 +188,7 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
declaration.parent = irClass
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
+3
-4
@@ -1309,10 +1309,9 @@ internal class IrDeserializer(val context: Context,
|
||||
(key,value) ->
|
||||
key to value}
|
||||
|
||||
return DeepCopyIrTreeWithDescriptors(rootFunction, rootFunction.parents.first(), context).copy(
|
||||
irElement = declaration,
|
||||
typeSubstitutor = TypeSubstitutor.create(substitutionContext)
|
||||
) as IrFunction
|
||||
return DeepCopyIrTreeWithDescriptors(rootFunction, rootFunction.parents.first(), context,
|
||||
TypeSubstitutor.create(substitutionContext)
|
||||
).copy(declaration) as IrFunction
|
||||
}
|
||||
|
||||
private val extractInlineProto: KonanProtoBuf.InlineIrBody
|
||||
|
||||
Reference in New Issue
Block a user