Inline: set correct containing declaration + some fixes
1. Containing declaration can be computed as parent from the IR.
2. Sometimes we need to substitute FunctionDescriptor which is defined
inside an inline function call but nevertheless leaks to the outside:
public inline fun <T, R> T.myLet(f: (T) -> R): R = f(this)
interface foo {
fun bar(): String
}
fun box(): String {
val baz = "OK".myLet {
object : foo {
override fun bar() = it
}
}
return baz.bar()
}
This commit is contained in:
committed by
KonstantinAnisimov
parent
3c2b5a9762
commit
db50381bc9
+77
-58
@@ -23,20 +23,20 @@ import org.jetbrains.kotlin.backend.konan.ir.IrInlineFunctionBody
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.*
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallableReferenceImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
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.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
|
|||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
|
|
||||||
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?, val context: Context) {
|
internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?, val context: Context) {
|
||||||
|
|
||||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||||
private var typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
private var typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
||||||
@@ -58,20 +58,64 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
inlinedFunctionName = functionName
|
inlinedFunctionName = functionName
|
||||||
descriptorSubstituteMap.clear()
|
descriptorSubstituteMap.clear()
|
||||||
irElement.acceptChildrenVoid(DescriptorCollector())
|
irElement.acceptChildrenVoid(DescriptorCollector())
|
||||||
|
// Transform calls to object that might be returned from inline function call.
|
||||||
|
targetScope.irElement.transformChildrenVoid(descriptorSubstitutorForExternalScope)
|
||||||
return irElement.accept(InlineCopyIr(), null)
|
return irElement.accept(InlineCopyIr(), null)
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
inner class DescriptorCollector: IrElementVisitorVoid {
|
val descriptorSubstitutorForExternalScope = object : IrElementTransformerVoid() {
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass) {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
val oldExpression = super.visitCall(expression) as IrCall
|
||||||
|
|
||||||
|
return when (oldExpression) {
|
||||||
|
is IrCallImpl -> copyIrCallImpl(oldExpression)
|
||||||
|
else -> oldExpression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyIrCallImpl(oldExpression: IrCallImpl): IrCallImpl {
|
||||||
|
val oldDescriptor = oldExpression.descriptor
|
||||||
|
val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor.original,
|
||||||
|
oldDescriptor) as FunctionDescriptor
|
||||||
|
|
||||||
|
val oldSuperQualifier = oldExpression.superQualifier
|
||||||
|
val newSuperQualifier = oldSuperQualifier?.let { (descriptorSubstituteMap[it] ?: it) as ClassDescriptor }
|
||||||
|
|
||||||
|
val newExpression = IrCallImpl(
|
||||||
|
oldExpression.startOffset,
|
||||||
|
oldExpression.endOffset,
|
||||||
|
substituteType(oldExpression.type)!!,
|
||||||
|
newDescriptor,
|
||||||
|
substituteTypeArguments(oldExpression.typeArguments),
|
||||||
|
oldExpression.origin,
|
||||||
|
newSuperQualifier
|
||||||
|
).apply {
|
||||||
|
oldExpression.descriptor.valueParameters.forEach {
|
||||||
|
val valueArgument = oldExpression.getValueArgument(it)
|
||||||
|
putValueArgument(it.index, valueArgument)
|
||||||
|
}
|
||||||
|
extensionReceiver = oldExpression.extensionReceiver
|
||||||
|
dispatchReceiver = oldExpression.dispatchReceiver
|
||||||
|
}
|
||||||
|
|
||||||
|
return newExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
inner class DescriptorCollector: IrElementVisitorVoidWithContext() {
|
||||||
|
|
||||||
|
override fun visitClassNew(declaration: IrClass) {
|
||||||
|
|
||||||
val oldDescriptor = declaration.descriptor
|
val oldDescriptor = declaration.descriptor
|
||||||
val newDescriptor = copyClassDescriptor(oldDescriptor)
|
val newDescriptor = copyClassDescriptor(oldDescriptor)
|
||||||
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter
|
descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter
|
||||||
super.visitClass(declaration)
|
super.visitClassNew(declaration)
|
||||||
|
|
||||||
val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor ->
|
val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor ->
|
||||||
descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor
|
descriptorSubstituteMap[oldConstructorDescriptor] as ClassConstructorDescriptor
|
||||||
@@ -110,30 +154,30 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty) {
|
override fun visitPropertyNew(declaration: IrProperty) {
|
||||||
copyPropertyOrField(declaration.descriptor)
|
copyPropertyOrField(declaration.descriptor)
|
||||||
super.visitProperty(declaration)
|
super.visitPropertyNew(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(declaration: IrField) {
|
override fun visitFieldNew(declaration: IrField) {
|
||||||
val oldDescriptor = declaration.descriptor
|
val oldDescriptor = declaration.descriptor
|
||||||
if (descriptorSubstituteMap[oldDescriptor] == null) {
|
if (descriptorSubstituteMap[oldDescriptor] == null) {
|
||||||
// A field without a property or a field of a delegated property.
|
// A field without a property or a field of a delegated property.
|
||||||
copyPropertyOrField(oldDescriptor)
|
copyPropertyOrField(oldDescriptor)
|
||||||
}
|
}
|
||||||
super.visitField(declaration)
|
super.visitFieldNew(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction) {
|
override fun visitFunctionNew(declaration: IrFunction) {
|
||||||
|
|
||||||
val oldDescriptor = declaration.descriptor
|
val oldDescriptor = declaration.descriptor
|
||||||
if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property.
|
if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property.
|
||||||
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
|
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
|
||||||
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||||
}
|
}
|
||||||
super.visitFunction(declaration)
|
super.visitFunctionNew(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
@@ -143,7 +187,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
val descriptor = expression.descriptor as FunctionDescriptor
|
val descriptor = expression.descriptor as FunctionDescriptor
|
||||||
if (descriptor.isFunctionInvoke) {
|
if (descriptor.isFunctionInvoke) {
|
||||||
val oldDescriptor = descriptor as SimpleFunctionDescriptor
|
val oldDescriptor = descriptor as SimpleFunctionDescriptor
|
||||||
val containingDeclaration = targetFunction.descriptor
|
// Containing declaration for value parameter is not that important - other lowerings should not rely on it.
|
||||||
|
val containingDeclaration = (targetScope.scope.scopeOwner as? CallableDescriptor) ?: oldDescriptor
|
||||||
val newReturnType = substituteType(oldDescriptor.returnType)!!
|
val newReturnType = substituteType(oldDescriptor.returnType)!!
|
||||||
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration)
|
val newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration)
|
||||||
val newDescriptor = oldDescriptor.newCopyBuilder().apply {
|
val newDescriptor = oldDescriptor.newCopyBuilder().apply {
|
||||||
@@ -163,7 +208,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
|
|
||||||
val oldDescriptor = declaration.descriptor
|
val oldDescriptor = declaration.descriptor
|
||||||
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
||||||
targetFunction.descriptor,
|
targetScope.scope.scopeOwner,
|
||||||
generateName(oldDescriptor.name),
|
generateName(oldDescriptor.name),
|
||||||
substituteType(oldDescriptor.type)!!,
|
substituteType(oldDescriptor.type)!!,
|
||||||
oldDescriptor.isVar)
|
oldDescriptor.isVar)
|
||||||
@@ -181,7 +226,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
|
|
||||||
private fun generateName(name: Name): Name {
|
private fun generateName(name: Name): Name {
|
||||||
|
|
||||||
val containingName = targetFunction.descriptor.name.toString() // Name of inline target (function we inline in)
|
val containingName = targetScope.scope.scopeOwner.name.toString() // Name of inline target (function we inline in)
|
||||||
val declarationName = name.toString() // Name of declaration
|
val declarationName = name.toString() // Name of declaration
|
||||||
val indexStr = (nameIndex++).toString() // Unique for inline target index
|
val indexStr = (nameIndex++).toString() // Unique for inline target index
|
||||||
return Name.identifier(containingName + "_" + inlinedFunctionName + "_" + declarationName + "_" + indexStr)
|
return Name.identifier(containingName + "_" + inlinedFunctionName + "_" + declarationName + "_" + indexStr)
|
||||||
@@ -202,8 +247,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
|
|
||||||
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
|
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
|
||||||
|
|
||||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration // TODO should target function to be containing declaration
|
val newContainingDeclaration = parentScope?.let { descriptorSubstituteMap[it.scope.scopeOwner] } ?: targetScope.scope.scopeOwner
|
||||||
val newContainingDeclaration = descriptorSubstituteMap[oldContainingDeclaration] ?: targetFunction.descriptor
|
|
||||||
|
|
||||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||||
newContainingDeclaration,
|
newContainingDeclaration,
|
||||||
@@ -239,10 +283,9 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
|
|
||||||
private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor {
|
private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor {
|
||||||
|
|
||||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
val containingDeclaration = parentScope?.let { descriptorSubstituteMap[it.scope.scopeOwner] } as ClassDescriptor
|
||||||
val containingDeclaration = descriptorSubstituteMap[oldContainingDeclaration]
|
|
||||||
val newDescriptor = ClassConstructorDescriptorImpl.create(
|
val newDescriptor = ClassConstructorDescriptorImpl.create(
|
||||||
containingDeclaration as ClassDescriptor,
|
containingDeclaration,
|
||||||
oldDescriptor.annotations,
|
oldDescriptor.annotations,
|
||||||
oldDescriptor.isPrimary,
|
oldDescriptor.isPrimary,
|
||||||
oldDescriptor.source
|
oldDescriptor.source
|
||||||
@@ -270,8 +313,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun copyPropertyDescriptor(oldDescriptor: PropertyDescriptor): PropertyDescriptor {
|
private fun copyPropertyDescriptor(oldDescriptor: PropertyDescriptor): PropertyDescriptor {
|
||||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
val memberOwner = currentClass?.let { descriptorSubstituteMap[it.scope.scopeOwner] } as ClassDescriptor
|
||||||
val memberOwner = descriptorSubstituteMap[oldContainingDeclaration] as ClassDescriptor
|
|
||||||
val newDescriptor = PropertyDescriptorImpl.create(
|
val newDescriptor = PropertyDescriptorImpl.create(
|
||||||
memberOwner,
|
memberOwner,
|
||||||
oldDescriptor.annotations,
|
oldDescriptor.annotations,
|
||||||
@@ -349,9 +391,14 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
|
|
||||||
val oldSuperClass = oldDescriptor.getSuperClassOrAny()
|
val oldSuperClass = oldDescriptor.getSuperClassOrAny()
|
||||||
val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) as ClassDescriptor
|
val newSuperClass = descriptorSubstituteMap.getOrDefault(oldSuperClass, oldSuperClass) as ClassDescriptor
|
||||||
|
val newContainingDeclaration = parentScope?.let { descriptorSubstituteMap[it.scope.scopeOwner] } ?: targetScope.scope.scopeOwner
|
||||||
|
val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name.
|
||||||
|
oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering.
|
||||||
|
else
|
||||||
|
generateName(oldDescriptor.name)
|
||||||
return ClassDescriptorImpl(
|
return ClassDescriptorImpl(
|
||||||
targetFunction.descriptor,
|
newContainingDeclaration,
|
||||||
generateName(oldDescriptor.name),
|
newName,
|
||||||
oldDescriptor.modality,
|
oldDescriptor.modality,
|
||||||
oldDescriptor.kind,
|
oldDescriptor.kind,
|
||||||
listOf(newSuperClass.defaultType),
|
listOf(newSuperClass.defaultType),
|
||||||
@@ -401,35 +448,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
|||||||
val oldExpression = super.visitCall(expression) as IrCall
|
val oldExpression = super.visitCall(expression) as IrCall
|
||||||
if (oldExpression !is IrCallImpl) return oldExpression // TODO what other kinds of call can we meet?
|
if (oldExpression !is IrCallImpl) return oldExpression // TODO what other kinds of call can we meet?
|
||||||
|
|
||||||
val oldDescriptor = oldExpression.descriptor
|
return copyIrCallImpl(oldExpression)
|
||||||
val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor,
|
|
||||||
oldDescriptor) as FunctionDescriptor
|
|
||||||
|
|
||||||
val oldSuperQualifier = oldExpression.superQualifier
|
|
||||||
var newSuperQualifier: ClassDescriptor? = oldSuperQualifier
|
|
||||||
if (newSuperQualifier != null) {
|
|
||||||
newSuperQualifier = descriptorSubstituteMap.getOrDefault(newSuperQualifier,
|
|
||||||
newSuperQualifier) as ClassDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
val newExpression = IrCallImpl(
|
|
||||||
oldExpression.startOffset,
|
|
||||||
oldExpression.endOffset,
|
|
||||||
substituteType(oldExpression.type)!!,
|
|
||||||
newDescriptor,
|
|
||||||
substituteTypeArguments(oldExpression.typeArguments),
|
|
||||||
oldExpression.origin,
|
|
||||||
newSuperQualifier
|
|
||||||
).apply {
|
|
||||||
oldExpression.descriptor.valueParameters.forEach {
|
|
||||||
val valueArgument = oldExpression.getValueArgument(it)
|
|
||||||
putValueArgument(it.index, valueArgument)
|
|
||||||
}
|
|
||||||
extensionReceiver = oldExpression.extensionReceiver
|
|
||||||
dispatchReceiver = oldExpression.dispatchReceiver
|
|
||||||
}
|
|
||||||
|
|
||||||
return newExpression
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
//---------------------------------------------------------------------//
|
||||||
|
|||||||
+133
-25
@@ -16,49 +16,157 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.builders.Scope
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
|
||||||
abstract class IrElementTransformerVoidWithContext(): IrElementTransformerVoid() {
|
private fun <E> MutableList<E>.push(element: E) = this.add(element)
|
||||||
private fun <E> MutableList<E>.push(element: E) = this.add(element)
|
|
||||||
|
|
||||||
private fun <E> MutableList<E>.pop() = this.removeAt(size - 1)
|
private fun <E> MutableList<E>.pop() = this.removeAt(size - 1)
|
||||||
|
|
||||||
private fun <E> MutableList<E>.peek(): E? = if (size == 0) null else this[size - 1]
|
private fun <E> MutableList<E>.peek(): E? = if (size == 0) null else this[size - 1]
|
||||||
|
|
||||||
private val functionsStack = mutableListOf<FunctionDescriptor>()
|
internal class ScopeWithIr(val scope: Scope, val irElement: IrElement)
|
||||||
private val functionDeclarationsStack = mutableListOf<IrFunction>()
|
|
||||||
private val classesStack = mutableListOf<ClassDescriptor>()
|
|
||||||
|
|
||||||
override final fun visitFunction(declaration: IrFunction): IrStatement {
|
abstract internal class IrElementTransformerVoidWithContext : IrElementTransformerVoid() {
|
||||||
functionsStack.push(declaration.descriptor)
|
|
||||||
functionDeclarationsStack.push(declaration)
|
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||||
val result = visitFunctionNew(declaration)
|
|
||||||
functionDeclarationsStack.pop()
|
override final fun visitFile(declaration: IrFile): IrFile {
|
||||||
functionsStack.pop()
|
scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration))
|
||||||
|
val result = visitFileNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override final fun visitClass(declaration: IrClass): IrStatement {
|
override final fun visitClass(declaration: IrClass): IrStatement {
|
||||||
classesStack.push(declaration.descriptor)
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
val result = visitClassNew(declaration)
|
val result = visitClassNew(declaration)
|
||||||
classesStack.pop()
|
scopeStack.pop()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val currentFunction get() = functionsStack.peek()
|
override final fun visitProperty(declaration: IrProperty): IrStatement {
|
||||||
protected val currentFunctionDeclaration get() = functionDeclarationsStack.peek()
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
protected val currentClass get() = classesStack.peek()
|
val result = visitPropertyNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
open fun visitFunctionNew(declaration: IrFunction) : IrStatement {
|
override final fun visitField(declaration: IrField): IrStatement {
|
||||||
|
val isDelegated = declaration.descriptor.isDelegated
|
||||||
|
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
val result = visitFieldNew(declaration)
|
||||||
|
if (isDelegated) scopeStack.pop()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override final fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
val result = visitFunctionNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val currentFile get() = scopeStack.lastOrNull { it.scope.scopeOwner is PackageFragmentDescriptor }
|
||||||
|
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]
|
||||||
|
|
||||||
|
fun printScopeStack() {
|
||||||
|
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFileNew(declaration: IrFile): IrFile {
|
||||||
|
return super.visitFile(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitClassNew(declaration: IrClass): IrStatement {
|
||||||
|
return super.visitClass(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFunctionNew(declaration: IrFunction): IrStatement {
|
||||||
return super.visitFunction(declaration)
|
return super.visitFunction(declaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun visitClassNew(declaration: IrClass) : IrStatement {
|
open fun visitPropertyNew(declaration: IrProperty): IrStatement {
|
||||||
return super.visitClass(declaration)
|
return super.visitProperty(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFieldNew(declaration: IrField): IrStatement {
|
||||||
|
return super.visitField(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||||
|
|
||||||
|
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||||
|
|
||||||
|
override final fun visitFile(declaration: IrFile) {
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration))
|
||||||
|
visitFileNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override final fun visitClass(declaration: IrClass) {
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
visitClassNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override final fun visitProperty(declaration: IrProperty) {
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
visitPropertyNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override final fun visitField(declaration: IrField) {
|
||||||
|
val isDelegated = declaration.descriptor.isDelegated
|
||||||
|
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
visitFieldNew(declaration)
|
||||||
|
if (isDelegated) scopeStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override final fun visitFunction(declaration: IrFunction) {
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
|
visitFunctionNew(declaration)
|
||||||
|
scopeStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val currentFile get() = scopeStack.lastOrNull { it.scope.scopeOwner is PackageFragmentDescriptor }
|
||||||
|
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]
|
||||||
|
|
||||||
|
fun printScopeStack() {
|
||||||
|
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFileNew(declaration: IrFile) {
|
||||||
|
super.visitFile(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitClassNew(declaration: IrClass) {
|
||||||
|
super.visitClass(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFunctionNew(declaration: IrFunction) {
|
||||||
|
super.visitFunction(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitPropertyNew(declaration: IrProperty) {
|
||||||
|
super.visitProperty(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitFieldNew(declaration: IrField) {
|
||||||
|
super.visitField(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-30
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDescriptors
|
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDescriptors
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
||||||
@@ -43,11 +44,8 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
internal class FunctionInlining(val context: Context): IrElementTransformerVoid() {
|
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
private var currentFile : IrFile? = null
|
|
||||||
private var currentFunction : IrFunction? = null
|
|
||||||
private var currentScope : Scope? = null
|
|
||||||
private var copyWithDescriptors: DeepCopyIrTreeWithDescriptors? = null
|
private var copyWithDescriptors: DeepCopyIrTreeWithDescriptors? = null
|
||||||
private val deserializer = DeserializerDriver(context)
|
private val deserializer = DeserializerDriver(context)
|
||||||
|
|
||||||
@@ -61,28 +59,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitFile(declaration: IrFile): IrFile {
|
|
||||||
currentFile = declaration
|
|
||||||
return super.visitFile(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty): IrStatement {
|
|
||||||
currentScope = Scope(declaration.descriptor)
|
|
||||||
return super.visitProperty(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
|
||||||
currentFunction = declaration
|
|
||||||
currentScope = Scope(declaration.descriptor)
|
|
||||||
return super.visitFunction(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
val irCall = super.visitCall(expression) as IrCall
|
val irCall = super.visitCall(expression) as IrCall
|
||||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||||
@@ -94,12 +70,12 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun createInlineFunctionBody(functionDeclaration: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): IrInlineFunctionBody? {
|
private fun createInlineFunctionBody(functionDeclaration: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): IrInlineFunctionBody? {
|
||||||
functionDeclaration.transformChildrenVoid(this) // TODO recursive inline is already processed in visitCall. Check
|
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||||
|
|
||||||
val originBlockBody = functionDeclaration.body
|
val originBlockBody = functionDeclaration.body
|
||||||
if (originBlockBody == null) return null // TODO workaround
|
if (originBlockBody == null) return null // TODO workaround
|
||||||
|
|
||||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeArgsMap, context)
|
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentScope!!, typeArgsMap, context)
|
||||||
val functionName = functionDeclaration.descriptor.name.toString()
|
val functionName = functionDeclaration.descriptor.name.toString()
|
||||||
|
|
||||||
val copyBlockBody = copyWithDescriptors!!.copy(originBlockBody, functionName) as IrBlockBody // Create copy of original function body.
|
val copyBlockBody = copyWithDescriptors!!.copy(originBlockBody, functionName) as IrBlockBody // Create copy of original function body.
|
||||||
@@ -321,8 +297,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
val varName = currentScope!!.scopeOwner.name.toString() + "_inline"
|
val varName = currentScope!!.scope.scopeOwner.name.toString() + "_inline"
|
||||||
val newVar = currentScope!!.createTemporaryVariable(argument, varName, false) // Create new variable and init it with the parameter expression.
|
val newVar = currentScope!!.scope.createTemporaryVariable(argument, varName, false) // Create new variable and init it with the parameter expression.
|
||||||
statements.add(newVar) // Add initialization of the new variable in statement list.
|
statements.add(newVar) // Add initialization of the new variable in statement list.
|
||||||
|
|
||||||
val getVal = IrGetValueImpl(0, 0, newVar.descriptor) // Create new IR element representing access the new variable.
|
val getVal = IrGetValueImpl(0, 0, newVar.descriptor) // Create new IR element representing access the new variable.
|
||||||
|
|||||||
+1
-1
@@ -106,7 +106,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
|
|
||||||
if (implicitThisClass == classDescriptor) return expression
|
if (implicitThisClass == classDescriptor) return expression
|
||||||
|
|
||||||
val constructorDescriptor = currentFunction!! as? ConstructorDescriptor
|
val constructorDescriptor = currentFunction!!.scope.scopeOwner as? ConstructorDescriptor
|
||||||
|
|
||||||
val startOffset = expression.startOffset
|
val startOffset = expression.startOffset
|
||||||
val endOffset = expression.endOffset
|
val endOffset = expression.endOffset
|
||||||
|
|||||||
Reference in New Issue
Block a user