Generate artificial return for inlined constructor

This commit is contained in:
Konstantin Anisimov
2017-05-16 15:27:41 +07:00
committed by KonstantinAnisimov
parent e15878bfe9
commit 3e35db5a51
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.getDefault import org.jetbrains.kotlin.ir.declarations.getDefault
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.*
@@ -129,7 +130,7 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
) as IrFunction ) as IrFunction
val copyStatements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy. val copyStatements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
val statements = replaceDelegatingConstructorCall(copyStatements) val statements = replaceDelegatingConstructorCall(copyStatements, irCall)
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type. val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call". val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
startOffset = copyFunctionDeclaration.startOffset, startOffset = copyFunctionDeclaration.startOffset,
@@ -358,19 +359,44 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun replaceDelegatingConstructorCall(statements: List<IrStatement>): List<IrStatement> { private fun replaceDelegatingConstructorCall(statements: List<IrStatement>, irCall: IrCall): List<IrStatement> {
return statements.map { statement -> if (!isInlineConstructor) return statements
if (statement is IrDelegatingConstructorCallImpl) generateIrCall(statement)
else statement val delegatingCall = statements[0]
} if (delegatingCall !is IrDelegatingConstructorCallImpl) return statements
val thisVariable = generateIrCall(delegatingCall)
val newThisGetValue = IrGetValueImpl( // Create new expression, representing access the new variable.
startOffset = currentScope.irElement.startOffset,
endOffset = currentScope.irElement.endOffset,
descriptor = thisVariable.descriptor
)
val classDescriptor = delegatingCall.descriptor.constructedClass
val oldThisGetValue = classDescriptor.thisAsReceiverParameter
substituteMap[oldThisGetValue] = newThisGetValue
val newStatements = statements.toMutableList()
newStatements[0] = thisVariable
newStatements += newThisGetValue
val block = IrBlockImpl(
startOffset = 0,
endOffset = 0,
type = newThisGetValue.type,
origin = null,
statements = newStatements
)
val returnThis = IrReturnImpl(0, 0, irCall.descriptor, block)
return listOf(returnThis)
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun generateIrCall(expression: IrDelegatingConstructorCallImpl): IrStatement { fun generateIrCall(expression: IrDelegatingConstructorCallImpl): IrVariable {
if (!isInlineConstructor) return expression
val newExpression = IrCallImpl( val newExpression = IrCallImpl(
expression.startOffset, expression.startOffset,
@@ -391,16 +417,6 @@ private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
nameHint = newExpression.descriptor.fqNameSafe.toString() + ".this", nameHint = newExpression.descriptor.fqNameSafe.toString() + ".this",
isMutable = false) isMutable = false)
val newThis = IrGetValueImpl( // Create new expression, representing access the new variable.
startOffset = currentScope.irElement.startOffset,
endOffset = currentScope.irElement.endOffset,
descriptor = newVariable.descriptor
)
val classDescriptor = expression.descriptor.constructedClass
val oldThis = classDescriptor.thisAsReceiverParameter
substituteMap[oldThis] = newThis
return newVariable return newVariable
} }
} }