Merged InlinedConstructorTransformer into ordinary inliner.
The benefits are - removed big amount of copy/paste; fixed bug with recursive inline touching inline constructors.
This commit is contained in:
-4
@@ -56,10 +56,6 @@ internal class KonanLower(val context: Context) {
|
|||||||
irModule.files.forEach(PreInlineLowering(context)::lower)
|
irModule.files.forEach(PreInlineLowering(context)::lower)
|
||||||
}
|
}
|
||||||
|
|
||||||
phaser.phase(KonanPhase.LOWER_INLINE_CONSTRUCTORS) {
|
|
||||||
InlineConstructorsTransformation(context).lower(irModule)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inlining must be run before other phases.
|
// Inlining must be run before other phases.
|
||||||
phaser.phase(KonanPhase.LOWER_INLINE) {
|
phaser.phase(KonanPhase.LOWER_INLINE) {
|
||||||
FunctionInlining(context).inline(irModule)
|
FunctionInlining(context).inline(irModule)
|
||||||
|
|||||||
+1
-2
@@ -32,8 +32,7 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... ... */ REMOVE_EXPECT_DECLARATIONS("Expect declarations removing"),
|
/* ... ... */ REMOVE_EXPECT_DECLARATIONS("Expect declarations removing"),
|
||||||
/* ... ... */ TEST_PROCESSOR("Unit test processor"),
|
/* ... ... */ TEST_PROCESSOR("Unit test processor"),
|
||||||
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
|
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
|
||||||
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_BEFORE_INLINE),
|
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_BEFORE_INLINE),
|
||||||
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_BEFORE_INLINE),
|
|
||||||
/* ... ... */ LOWER_AFTER_INLINE("Special operations processing after inlining"),
|
/* ... ... */ LOWER_AFTER_INLINE("Special operations processing after inlining"),
|
||||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||||
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
||||||
|
|||||||
+42
-16
@@ -20,6 +20,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
import org.jetbrains.kotlin.backend.common.ScopeWithIr
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.reportWarning
|
import org.jetbrains.kotlin.backend.common.reportWarning
|
||||||
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
|
||||||
@@ -27,23 +28,21 @@ import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor
|
import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irCall
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
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.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.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrMemberAccessExpressionBase
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||||
@@ -103,6 +102,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
override fun visitElement(element: IrElement) = element.accept(this, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val inlineConstructor = FqName("konan.internal.InlineConstructor")
|
||||||
|
private val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>,
|
private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor, SubstitutedDescriptor>,
|
||||||
@@ -123,22 +125,46 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun inlineFunction(irCall : IrCall, // Call to be substituted.
|
private fun inlineFunction(callee: IrCall, // Call to be substituted.
|
||||||
functionDeclaration: IrFunction): IrReturnableBlockImpl { // Function to substitute.
|
caller: IrFunction): IrReturnableBlockImpl { // Function to substitute.
|
||||||
|
|
||||||
val copyFunctionDeclaration = copyIrElement.copy( // Create copy of original function.
|
val copyFunctionDeclaration = copyIrElement.copy( // Create copy of original function.
|
||||||
irElement = functionDeclaration, // Descriptors declared inside the function will be copied.
|
irElement = caller, // Descriptors declared inside the function will be copied.
|
||||||
typeSubstitutor = createTypeSubstitutor(irCall) // Type parameters will be substituted with type arguments.
|
typeSubstitutor = createTypeSubstitutor(callee) // Type parameters will be substituted with type arguments.
|
||||||
) as IrFunction
|
) as IrFunction
|
||||||
|
|
||||||
val evaluationStatements = evaluateArguments(irCall, copyFunctionDeclaration) // And list of evaluation statements.
|
val evaluationStatements = evaluateArguments(callee, copyFunctionDeclaration) // And list of evaluation statements.
|
||||||
|
|
||||||
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
|
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
|
||||||
|
|
||||||
|
val startOffset = caller.startOffset
|
||||||
|
val endOffset = caller.endOffset
|
||||||
|
val descriptor = caller.descriptor.original
|
||||||
|
if (descriptor.isInlineConstructor) {
|
||||||
|
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||||
|
val irBuilder = context.createIrBuilder(copyFunctionDeclaration.symbol, startOffset, endOffset)
|
||||||
|
irBuilder.run {
|
||||||
|
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||||
|
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
||||||
|
constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||||
|
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
||||||
|
}
|
||||||
|
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
|
||||||
|
val newThis = currentScope.scope.createTemporaryVariable(
|
||||||
|
irExpression = constructorCall,
|
||||||
|
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
||||||
|
)
|
||||||
|
statements[0] = newThis
|
||||||
|
substituteMap[oldThis] = irGet(newThis.symbol)
|
||||||
|
statements.add(irReturn(irGet(newThis.symbol)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
|
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
|
||||||
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[functionDeclaration.descriptor.original]?:""
|
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[caller.descriptor.original]?:""
|
||||||
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
||||||
startOffset = copyFunctionDeclaration.startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = copyFunctionDeclaration.endOffset,
|
endOffset = endOffset,
|
||||||
type = returnType,
|
type = returnType,
|
||||||
descriptor = copyFunctionDeclaration.descriptor.original,
|
descriptor = copyFunctionDeclaration.descriptor.original,
|
||||||
origin = null,
|
origin = null,
|
||||||
|
|||||||
-175
@@ -1,175 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("FoldInitializerAndIfToElvis")
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.reportWarning
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private val inlineConstructor by lazy { FqName("konan.internal.InlineConstructor") }
|
|
||||||
|
|
||||||
internal val FunctionDescriptor.isInlineConstructor get() = annotations.hasAnnotation(inlineConstructor)
|
|
||||||
|
|
||||||
internal class InlineConstructorsTransformation(val context: Context): IrElementTransformerVoidWithContext() {
|
|
||||||
|
|
||||||
private val deserializer by lazy { DeserializerDriver(context) }
|
|
||||||
private val substituteMap by lazy { mutableMapOf<ValueDescriptor, IrExpression>() }
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
fun lower(irModule: IrModuleFragment) = irModule.accept(this, null)
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
|
|
||||||
val irCall = super.visitCall(expression) as IrCall
|
|
||||||
val functionDescriptor = irCall.descriptor
|
|
||||||
if (!functionDescriptor.isInlineConstructor) return irCall // This call does not need inlining.
|
|
||||||
|
|
||||||
val functionDeclaration = getFunctionDeclaration(irCall) // Get declaration of the function to be inlined.
|
|
||||||
if (functionDeclaration == null) { // We failed to get the declaration.
|
|
||||||
val message = "Inliner failed to obtain function declaration: " +
|
|
||||||
functionDescriptor.fqNameSafe.toString()
|
|
||||||
context.reportWarning(message, currentFile, irCall) // Report warning.
|
|
||||||
return irCall
|
|
||||||
}
|
|
||||||
|
|
||||||
val statements = (functionDeclaration.body as IrBlockBody).statements
|
|
||||||
replaceDelegatingConstructorCall(statements, functionDescriptor)
|
|
||||||
functionDeclaration.transformChildrenVoid(ValueSubstitutor())
|
|
||||||
context.ir.originalModuleIndex.functions[functionDescriptor.original] = functionDeclaration
|
|
||||||
|
|
||||||
return irCall
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
|
|
||||||
|
|
||||||
val functionDescriptor = irCall.descriptor
|
|
||||||
val originalDescriptor = functionDescriptor.resolveFakeOverride().original
|
|
||||||
val functionDeclaration =
|
|
||||||
context.ir.originalModuleIndex.functions[originalDescriptor] ?: // If function is declared in the current module.
|
|
||||||
deserializer.deserializeInlineBody(originalDescriptor) // Function is declared in another module.
|
|
||||||
return functionDeclaration as IrFunction?
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun replaceDelegatingConstructorCall(statements: MutableList<IrStatement>, functionDescriptor: FunctionDescriptor) {
|
|
||||||
|
|
||||||
val delegatingCall = statements[0]
|
|
||||||
if (delegatingCall !is IrDelegatingConstructorCallImpl) return
|
|
||||||
|
|
||||||
val thisVariable = generateIrCall(delegatingCall)
|
|
||||||
|
|
||||||
val newThisGetValue = IrGetValueImpl( // Create new expression, representing access the new variable.
|
|
||||||
startOffset = 0,
|
|
||||||
endOffset = 0,
|
|
||||||
symbol = createValueSymbol(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, createFunctionSymbol(functionDescriptor), block)
|
|
||||||
|
|
||||||
statements.clear()
|
|
||||||
statements += returnThis
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun generateIrCall(expression: IrDelegatingConstructorCallImpl): IrVariable {
|
|
||||||
|
|
||||||
val newExpression = IrCallImpl(
|
|
||||||
expression.startOffset,
|
|
||||||
expression.endOffset,
|
|
||||||
expression.descriptor.returnType,
|
|
||||||
expression.symbol,
|
|
||||||
expression.descriptor,
|
|
||||||
expression.typeArguments,
|
|
||||||
expression.origin
|
|
||||||
).apply {
|
|
||||||
expression.descriptor.valueParameters.forEach {
|
|
||||||
val valueArgument = expression.getValueArgument(it)
|
|
||||||
putValueArgument(it.index, valueArgument)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentScope!!.scope.createTemporaryVariable( // Create new variable and init it with constructor call.
|
|
||||||
irExpression = newExpression,
|
|
||||||
nameHint = newExpression.descriptor.fqNameSafe.toString() + ".this",
|
|
||||||
isMutable = false)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private inner class ValueSubstitutor: IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
|
||||||
val newExpression = super.visitGetValue(expression) as IrGetValue
|
|
||||||
val descriptor = newExpression.descriptor
|
|
||||||
val argument = substituteMap[descriptor] // Find expression to replace this parameter.
|
|
||||||
if (argument == null) return newExpression // If there is no such expression - do nothing.
|
|
||||||
return argument
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------//
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-8
@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.ir.util.getArguments
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -375,18 +374,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
super.visitSetField(expression)
|
super.visitSetField(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hack to overcome bad code in InlineConstructorsTransformation.
|
|
||||||
private val FQ_NAME_INLINE_CONSTRUCTOR = FqName("konan.internal.InlineConstructor")
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn) {
|
override fun visitReturn(expression: IrReturn) {
|
||||||
val returnableBlock = returnableBlocks[expression.returnTarget]
|
val returnableBlock = returnableBlocks[expression.returnTarget]
|
||||||
if (returnableBlock != null) {
|
if (returnableBlock != null) {
|
||||||
returnableBlockValues[returnableBlock]!!.add(expression.value)
|
returnableBlockValues[returnableBlock]!!.add(expression.value)
|
||||||
} else { // Non-local return.
|
} else { // Non-local return.
|
||||||
if (!expression.type.isUnit()) {
|
if (!expression.type.isUnit())
|
||||||
if (!expression.returnTarget.annotations.hasAnnotation(FQ_NAME_INLINE_CONSTRUCTOR)) // Not inline constructor.
|
returnValues += expression.value
|
||||||
returnValues += expression.value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.visitReturn(expression)
|
super.visitReturn(expression)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user