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:
Igor Chevdar
2017-04-06 18:55:54 +03:00
committed by KonstantinAnisimov
parent 3c2b5a9762
commit db50381bc9
4 changed files with 217 additions and 114 deletions
@@ -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
} }
//---------------------------------------------------------------------// //---------------------------------------------------------------------//
@@ -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)
} }
} }
@@ -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.
@@ -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