New scheme for copy descriptors names
This commit is contained in:
committed by
KonstantinAnisimov
parent
34e49ffb82
commit
8235c8b2be
+10
-13
@@ -49,15 +49,13 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
|
||||
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
|
||||
private var typeSubstitutor: TypeSubstitutor? = null
|
||||
private var inlinedFunctionName = ""
|
||||
private var nameIndex = 0
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun copy(irElement: IrElement, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?, functionName: String): IrElement {
|
||||
fun copy(irElement: IrElement, typeArgumentsMap: Map <TypeParameterDescriptor, KotlinType>?): IrElement {
|
||||
|
||||
typeSubstitutor = createTypeSubstitutor(typeArgsMap)
|
||||
inlinedFunctionName = functionName
|
||||
typeSubstitutor = createTypeSubstitutor(typeArgumentsMap)
|
||||
descriptorSubstituteMap.clear()
|
||||
irElement.acceptChildrenVoid(DescriptorCollector())
|
||||
// Transform calls to object that might be returned from inline function call.
|
||||
@@ -220,7 +218,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
val oldDescriptor = declaration.descriptor
|
||||
val newDescriptor = IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = targetScope.scope.scopeOwner,
|
||||
name = generateName(oldDescriptor.name),
|
||||
name = generateCopyName(oldDescriptor.name),
|
||||
outType = substituteType(oldDescriptor.type)!!,
|
||||
isMutable = oldDescriptor.isVar)
|
||||
descriptorSubstituteMap[oldDescriptor] = newDescriptor
|
||||
@@ -230,12 +228,11 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
|
||||
//--- Copy descriptors ------------------------------------------------//
|
||||
|
||||
private fun generateName(name: Name): Name {
|
||||
private fun generateCopyName(name: Name): Name {
|
||||
|
||||
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)
|
||||
return Name.identifier(declarationName + "_" + indexStr)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
@@ -258,7 +255,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
return SimpleFunctionDescriptorImpl.create(
|
||||
/* containingDeclaration = */ newContainingDeclaration,
|
||||
/* annotations = */ oldDescriptor.annotations,
|
||||
/* name = */ generateName(oldDescriptor.name),
|
||||
/* name = */ generateCopyName(oldDescriptor.name),
|
||||
/* kind = */ oldDescriptor.kind,
|
||||
/* source = */ oldDescriptor.source
|
||||
).apply {
|
||||
@@ -401,7 +398,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
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)
|
||||
generateCopyName(oldDescriptor.name)
|
||||
return ClassDescriptorImpl(
|
||||
/* containingDeclaration = */ newContainingDeclaration,
|
||||
/* name = */ newName,
|
||||
@@ -601,10 +598,10 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun createTypeSubstitutor(typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? {
|
||||
private fun createTypeSubstitutor(typeArgumentsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? {
|
||||
|
||||
if (typeArgsMap == null) return null
|
||||
val substitutionContext = typeArgsMap.entries.associate {
|
||||
if (typeArgumentsMap == null) return null
|
||||
val substitutionContext = typeArgumentsMap.entries.associate {
|
||||
(typeParameter, typeArgument) ->
|
||||
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
|
||||
}
|
||||
|
||||
+60
-85
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||
|
||||
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
|
||||
|
||||
private var copyWithDescriptors: DeepCopyIrTreeWithDescriptors? = null
|
||||
private var copyIrElement: DeepCopyIrTreeWithDescriptors? = null
|
||||
private val deserializer = DeserializerDriver(context)
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -61,13 +61,11 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
if (functionDescriptor.needsInlining) {
|
||||
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentScope!!, context)
|
||||
copyIrElement = DeepCopyIrTreeWithDescriptors(currentScope!!, context)
|
||||
val functionDeclaration = getFunctionDeclaration(irCall)
|
||||
if (functionDeclaration == null) return irCall
|
||||
|
||||
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||
|
||||
|
||||
return inlineFunction(irCall, functionDeclaration) // Return newly created IrInlineBody instead of IrCall.
|
||||
}
|
||||
|
||||
@@ -78,57 +76,28 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
|
||||
private fun inlineFunction(irCall: IrCall, functionDeclaration: IrFunction): IrExpression {
|
||||
|
||||
|
||||
val evaluatedParameters = evaluateParameters(irCall, functionDeclaration)
|
||||
val parameterToArgument = evaluatedParameters.parameters
|
||||
val parameterSubstituteMap = evaluatedParameters.parameters
|
||||
val evaluationStatements = evaluatedParameters.statements
|
||||
|
||||
val statements = (functionDeclaration.body as IrBlockBody).statements
|
||||
val returnType = functionDeclaration.descriptor.returnType!!
|
||||
val inlineFunctionBody1 = IrInlineFunctionBody(
|
||||
startOffset = functionDeclaration.startOffset,
|
||||
endOffset = functionDeclaration.endOffset,
|
||||
val typeArgumentsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
|
||||
val copyFunctionDeclaration = copyIrElement!!.copy( // Create copy of original function.
|
||||
functionDeclaration,
|
||||
typeArgumentsMap
|
||||
) as IrFunction
|
||||
|
||||
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements
|
||||
val returnType = copyFunctionDeclaration.descriptor.returnType!!
|
||||
val inlineFunctionBody = IrInlineFunctionBody(
|
||||
startOffset = copyFunctionDeclaration.startOffset,
|
||||
endOffset = copyFunctionDeclaration.endOffset,
|
||||
type = returnType,
|
||||
descriptor = functionDeclaration.descriptor.original,
|
||||
descriptor = copyFunctionDeclaration.descriptor.original,
|
||||
origin = null,
|
||||
statements = statements
|
||||
)
|
||||
|
||||
val functionName = functionDeclaration.descriptor.name.toString()
|
||||
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
|
||||
val inlineFunctionBody = copyWithDescriptors!!.copy(inlineFunctionBody1, typeArgsMap, functionName) as IrInlineFunctionBody // Create copy of original function body.
|
||||
|
||||
val transformer = ParameterSubstitutor(parameterToArgument)
|
||||
inlineFunctionBody.transformChildrenVoid(transformer) // Replace parameters with expression.
|
||||
inlineFunctionBody.statements.addAll(0, evaluationStatements)
|
||||
|
||||
return inlineFunctionBody // Replace call site with InlineFunctionBody.
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun inlineLambda(irCall: IrCall, functionDeclaration: IrFunction): IrExpression {
|
||||
|
||||
val evaluatedParameters = evaluateParameters(irCall, functionDeclaration)
|
||||
val parameterToArgument = evaluatedParameters.parameters
|
||||
val evaluationStatements = evaluatedParameters.statements
|
||||
|
||||
val statements = (functionDeclaration.body as IrBlockBody).statements
|
||||
val returnType = functionDeclaration.descriptor.returnType!!
|
||||
val inlineFunctionBody1 = IrInlineFunctionBody(
|
||||
startOffset = functionDeclaration.startOffset,
|
||||
endOffset = functionDeclaration.endOffset,
|
||||
type = returnType,
|
||||
descriptor = functionDeclaration.descriptor.original,
|
||||
origin = null,
|
||||
statements = statements
|
||||
)
|
||||
|
||||
val functionName = functionDeclaration.descriptor.name.toString()
|
||||
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
|
||||
val inlineFunctionBody = copyWithDescriptors!!.copy(inlineFunctionBody1, typeArgsMap, functionName) as IrInlineFunctionBody // Create copy of original function body.
|
||||
|
||||
val transformer = ParameterSubstitutor(parameterToArgument)
|
||||
val transformer = ParameterSubstitutor(parameterSubstituteMap)
|
||||
inlineFunctionBody.transformChildrenVoid(transformer) // Replace parameters with expression.
|
||||
inlineFunctionBody.statements.addAll(0, evaluationStatements)
|
||||
|
||||
@@ -150,7 +119,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
val argument = substituteMap[descriptor] // Find expression to replace this parameter.
|
||||
if (argument == null) return newExpression // If there is no such expression - do nothing
|
||||
|
||||
val newArgument = copyWithDescriptors!!.copy(argument, null, "lambda")
|
||||
val newArgument = copyIrElement!!.copy(argument, null)
|
||||
return newArgument as IrExpression
|
||||
}
|
||||
|
||||
@@ -170,7 +139,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
val functionDeclaration = getLambdaFunction(lambdaArgument)
|
||||
if (functionDeclaration == null) return return super.visitCall(expression) // TODO
|
||||
|
||||
val newExpression = inlineLambda(expression, functionDeclaration)
|
||||
val newExpression = inlineFunction(expression, functionDeclaration)
|
||||
return newExpression.transform(this, null)
|
||||
}
|
||||
}
|
||||
@@ -194,8 +163,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
return null
|
||||
}
|
||||
|
||||
// TODO: the following checks must be asserts, however it is not sane until the bugs are fixed.
|
||||
|
||||
val statements = lambdaArgument.statements
|
||||
if (statements.size != 2) return null
|
||||
|
||||
@@ -233,39 +200,61 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private class ArgumentWithValue(val descriptor: ValueDescriptor, val value: IrExpression)
|
||||
private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
|
||||
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
val originalDescriptor = functionDescriptor.original
|
||||
val functionDeclaration =
|
||||
(context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
|
||||
deserializer.deserializeInlineBody(originalDescriptor) as IrFunction?) // Function is declared in another module.
|
||||
return functionDeclaration
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private class ParameterWithArgument(
|
||||
val parameterDescriptor: ValueDescriptor,
|
||||
val argument : IrExpression
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private class EvaluatedParameters(
|
||||
val parameters: MutableMap<ValueDescriptor, IrExpression>,
|
||||
val statements: MutableList<IrStatement>
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
private fun getArguments(irCall: IrCall, declaration: IrFunction): MutableList<ArgumentWithValue> {
|
||||
private fun buildParameterToArgumentMap(irCall: IrCall, declaration: IrFunction): MutableList<ParameterWithArgument> {
|
||||
|
||||
val result = mutableListOf<ArgumentWithValue>()
|
||||
val result = mutableListOf<ParameterWithArgument>()
|
||||
val descriptor = declaration.descriptor.original
|
||||
|
||||
if (irCall.dispatchReceiver != null && descriptor.dispatchReceiverParameter != null)
|
||||
result += ArgumentWithValue(descriptor.dispatchReceiverParameter!!, irCall.dispatchReceiver!!)
|
||||
result += ParameterWithArgument(descriptor.dispatchReceiverParameter!!, irCall.dispatchReceiver!!)
|
||||
|
||||
if (irCall.extensionReceiver != null && descriptor.extensionReceiverParameter != null)
|
||||
result += ArgumentWithValue(descriptor.extensionReceiverParameter!!, irCall.extensionReceiver!!)
|
||||
result += ParameterWithArgument(descriptor.extensionReceiverParameter!!, irCall.extensionReceiver!!)
|
||||
|
||||
descriptor.valueParameters.forEach { parameter ->
|
||||
val argument = irCall.getValueArgument(parameter.index)
|
||||
descriptor.valueParameters.forEach { parameterDescriptor ->
|
||||
val argument = irCall.getValueArgument(parameterDescriptor.index)
|
||||
when {
|
||||
argument != null -> {
|
||||
result += ArgumentWithValue(parameter, argument)
|
||||
result += ParameterWithArgument(parameterDescriptor, argument)
|
||||
}
|
||||
|
||||
parameter.hasDefaultValue() -> {
|
||||
val defaultArgument = declaration.getDefault(parameter)!!.expression
|
||||
result += ArgumentWithValue(parameter, defaultArgument)
|
||||
parameterDescriptor.hasDefaultValue() -> {
|
||||
val defaultArgument = declaration.getDefault(parameterDescriptor)!!.expression
|
||||
result += ParameterWithArgument(parameterDescriptor, defaultArgument)
|
||||
}
|
||||
|
||||
parameter.varargElementType != null -> {
|
||||
val emptyArray = IrVarargImpl(irCall.startOffset, irCall.endOffset, parameter.type, parameter.varargElementType!!)
|
||||
result += ArgumentWithValue(parameter, emptyArray)
|
||||
parameterDescriptor.varargElementType != null -> {
|
||||
val emptyArray = IrVarargImpl(irCall.startOffset, irCall.endOffset, parameterDescriptor.type, parameterDescriptor.varargElementType!!)
|
||||
result += ParameterWithArgument(parameterDescriptor, emptyArray)
|
||||
}
|
||||
|
||||
else -> throw Error("Incomplete expression: call to $descriptor has no argument at index ${parameter.index}")
|
||||
else -> throw Error("Incomplete expression: call to $descriptor has no argument at index ${parameterDescriptor.index}")
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -273,19 +262,17 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private class EvaluatedParameters(val parameters: MutableMap<ValueDescriptor, IrExpression>, val statements: MutableList<IrStatement>)
|
||||
|
||||
private fun evaluateParameters(irCall: IrCall, functionDeclaration: IrFunction): EvaluatedParameters {
|
||||
|
||||
val parametersOld = getArguments(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
||||
val parametersOld = buildParameterToArgumentMap(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
||||
val parametersNew = mutableMapOf<ValueDescriptor, IrExpression> ()
|
||||
val statements = mutableListOf<IrStatement>()
|
||||
parametersOld.forEach {
|
||||
val parameter = it.descriptor.original as ValueDescriptor
|
||||
val argument = it.value
|
||||
val parameterDescriptor = it.parameterDescriptor.original as ValueDescriptor
|
||||
val argument = it.argument
|
||||
|
||||
if (!needsEvaluation(argument)) {
|
||||
parametersNew[parameter] = argument
|
||||
parametersNew[parameterDescriptor] = argument
|
||||
return@forEach
|
||||
}
|
||||
|
||||
@@ -297,22 +284,10 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
val startOffset = currentScope.irElement.startOffset
|
||||
val endOffset = currentScope.irElement.endOffset
|
||||
val getVal = IrGetValueImpl(startOffset, endOffset, newVar.descriptor) // Create new IR element representing access the new variable.
|
||||
parametersNew[parameter] = getVal // Parameter will be replaced with the new variable.
|
||||
parametersNew[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
|
||||
}
|
||||
return EvaluatedParameters(parametersNew, statements)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
|
||||
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
val originalDescriptor = functionDescriptor.original
|
||||
val functionDeclaration =
|
||||
(context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
|
||||
deserializer.deserializeInlineBody(originalDescriptor) as IrFunction?) // Function is declared in another module.
|
||||
return functionDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user