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.impl.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
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.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
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.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
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.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 var typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
||||
@@ -58,20 +58,64 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
inlinedFunctionName = functionName
|
||||
descriptorSubstituteMap.clear()
|
||||
irElement.acceptChildrenVoid(DescriptorCollector())
|
||||
// Transform calls to object that might be returned from inline function call.
|
||||
targetScope.irElement.transformChildrenVoid(descriptorSubstitutorForExternalScope)
|
||||
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 newDescriptor = copyClassDescriptor(oldDescriptor)
|
||||
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||
descriptorSubstituteMap[oldDescriptor.thisAsReceiverParameter] = newDescriptor.thisAsReceiverParameter
|
||||
super.visitClass(declaration)
|
||||
super.visitClassNew(declaration)
|
||||
|
||||
val constructors = oldDescriptor.constructors.map { oldConstructorDescriptor ->
|
||||
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)
|
||||
super.visitProperty(declaration)
|
||||
super.visitPropertyNew(declaration)
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
override fun visitFieldNew(declaration: IrField) {
|
||||
val oldDescriptor = declaration.descriptor
|
||||
if (descriptorSubstituteMap[oldDescriptor] == null) {
|
||||
// A field without a property or a field of a delegated property.
|
||||
copyPropertyOrField(oldDescriptor)
|
||||
}
|
||||
super.visitField(declaration)
|
||||
super.visitFieldNew(declaration)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
override fun visitFunctionNew(declaration: IrFunction) {
|
||||
|
||||
val oldDescriptor = declaration.descriptor
|
||||
if (oldDescriptor !is PropertyAccessorDescriptor) { // Property accessors are copied along with their property.
|
||||
val newDescriptor = copyFunctionDescriptor(oldDescriptor)
|
||||
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
|
||||
if (descriptor.isFunctionInvoke) {
|
||||
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 newValueParameters = copyValueParameters(oldDescriptor.valueParameters, containingDeclaration)
|
||||
val newDescriptor = oldDescriptor.newCopyBuilder().apply {
|
||||
@@ -163,7 +208,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
|
||||
val oldDescriptor = declaration.descriptor
|
||||
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
||||
targetFunction.descriptor,
|
||||
targetScope.scope.scopeOwner,
|
||||
generateName(oldDescriptor.name),
|
||||
substituteType(oldDescriptor.type)!!,
|
||||
oldDescriptor.isVar)
|
||||
@@ -181,7 +226,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
|
||||
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 indexStr = (nameIndex++).toString() // Unique for inline target index
|
||||
return Name.identifier(containingName + "_" + inlinedFunctionName + "_" + declarationName + "_" + indexStr)
|
||||
@@ -202,8 +247,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
|
||||
private fun copySimpleFunctionDescriptor(oldDescriptor: SimpleFunctionDescriptor) : FunctionDescriptor {
|
||||
|
||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration // TODO should target function to be containing declaration
|
||||
val newContainingDeclaration = descriptorSubstituteMap[oldContainingDeclaration] ?: targetFunction.descriptor
|
||||
val newContainingDeclaration = parentScope?.let { descriptorSubstituteMap[it.scope.scopeOwner] } ?: targetScope.scope.scopeOwner
|
||||
|
||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
newContainingDeclaration,
|
||||
@@ -239,10 +283,9 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
|
||||
private fun copyConstructorDescriptor(oldDescriptor: ConstructorDescriptor) : FunctionDescriptor {
|
||||
|
||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||
val containingDeclaration = descriptorSubstituteMap[oldContainingDeclaration]
|
||||
val containingDeclaration = parentScope?.let { descriptorSubstituteMap[it.scope.scopeOwner] } as ClassDescriptor
|
||||
val newDescriptor = ClassConstructorDescriptorImpl.create(
|
||||
containingDeclaration as ClassDescriptor,
|
||||
containingDeclaration,
|
||||
oldDescriptor.annotations,
|
||||
oldDescriptor.isPrimary,
|
||||
oldDescriptor.source
|
||||
@@ -270,8 +313,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun copyPropertyDescriptor(oldDescriptor: PropertyDescriptor): PropertyDescriptor {
|
||||
val oldContainingDeclaration = oldDescriptor.containingDeclaration
|
||||
val memberOwner = descriptorSubstituteMap[oldContainingDeclaration] as ClassDescriptor
|
||||
val memberOwner = currentClass?.let { descriptorSubstituteMap[it.scope.scopeOwner] } as ClassDescriptor
|
||||
val newDescriptor = PropertyDescriptorImpl.create(
|
||||
memberOwner,
|
||||
oldDescriptor.annotations,
|
||||
@@ -349,9 +391,14 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
|
||||
val oldSuperClass = oldDescriptor.getSuperClassOrAny()
|
||||
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(
|
||||
targetFunction.descriptor,
|
||||
generateName(oldDescriptor.name),
|
||||
newContainingDeclaration,
|
||||
newName,
|
||||
oldDescriptor.modality,
|
||||
oldDescriptor.kind,
|
||||
listOf(newSuperClass.defaultType),
|
||||
@@ -401,35 +448,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typ
|
||||
val oldExpression = super.visitCall(expression) as IrCall
|
||||
if (oldExpression !is IrCallImpl) return oldExpression // TODO what other kinds of call can we meet?
|
||||
|
||||
val oldDescriptor = oldExpression.descriptor
|
||||
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
|
||||
return copyIrCallImpl(oldExpression)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
+133
-25
@@ -16,49 +16,157 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.builders.Scope
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
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>()
|
||||
private val functionDeclarationsStack = mutableListOf<IrFunction>()
|
||||
private val classesStack = mutableListOf<ClassDescriptor>()
|
||||
internal class ScopeWithIr(val scope: Scope, val irElement: IrElement)
|
||||
|
||||
override final fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
functionsStack.push(declaration.descriptor)
|
||||
functionDeclarationsStack.push(declaration)
|
||||
val result = visitFunctionNew(declaration)
|
||||
functionDeclarationsStack.pop()
|
||||
functionsStack.pop()
|
||||
abstract internal class IrElementTransformerVoidWithContext : IrElementTransformerVoid() {
|
||||
|
||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||
|
||||
override final fun visitFile(declaration: IrFile): IrFile {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration))
|
||||
val result = visitFileNew(declaration)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
override final fun visitClass(declaration: IrClass): IrStatement {
|
||||
classesStack.push(declaration.descriptor)
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
val result = visitClassNew(declaration)
|
||||
classesStack.pop()
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
protected val currentFunction get() = functionsStack.peek()
|
||||
protected val currentFunctionDeclaration get() = functionDeclarationsStack.peek()
|
||||
protected val currentClass get() = classesStack.peek()
|
||||
override final fun visitProperty(declaration: IrProperty): IrStatement {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
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)
|
||||
}
|
||||
|
||||
open fun visitClassNew(declaration: IrClass) : IrStatement {
|
||||
return super.visitClass(declaration)
|
||||
open fun visitPropertyNew(declaration: IrProperty): IrStatement {
|
||||
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
|
||||
|
||||
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.descriptors.isFunctionInvoke
|
||||
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 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 {
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
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? {
|
||||
functionDeclaration.transformChildrenVoid(this) // TODO recursive inline is already processed in visitCall. Check
|
||||
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||
|
||||
val originBlockBody = functionDeclaration.body
|
||||
if (originBlockBody == null) return null // TODO workaround
|
||||
|
||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeArgsMap, context)
|
||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentScope!!, typeArgsMap, context)
|
||||
val functionName = functionDeclaration.descriptor.name.toString()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
val varName = currentScope!!.scopeOwner.name.toString() + "_inline"
|
||||
val newVar = currentScope!!.createTemporaryVariable(argument, varName, false) // Create new variable and init it with the parameter expression.
|
||||
val varName = currentScope!!.scope.scopeOwner.name.toString() + "_inline"
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
val constructorDescriptor = currentFunction!! as? ConstructorDescriptor
|
||||
val constructorDescriptor = currentFunction!!.scope.scopeOwner as? ConstructorDescriptor
|
||||
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
|
||||
Reference in New Issue
Block a user