Replace all usages of inlineFunctionSymbol with inlineFunction

This commit is contained in:
Ivan Kylchik
2022-12-15 16:09:19 +01:00
committed by Space Team
parent 1d30a68285
commit ef78196cbc
14 changed files with 117 additions and 58 deletions
@@ -16,13 +16,11 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.types.getClass import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.util.explicitParameters import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isVararg
import org.jetbrains.kotlin.ir.util.statements
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
sealed class IrInlinable sealed class IrInlinable
@@ -127,3 +125,37 @@ fun IrInlinable.inline(target: IrDeclarationParent, arguments: List<IrValueDecla
} }
} }
} }
val IrInlinedFunctionBlock.inlineDeclaration: IrDeclaration
get() = when (val element = inlinedElement) {
is IrFunction -> element
is IrFunctionExpression -> element.function
is IrFunctionReference -> element.symbol.owner
is IrPropertyReference -> element.symbol.owner
else -> throw AssertionError("Not supported ir element for inlining ${element.dump()}")
}
private val IrInlinedFunctionBlock.inlineFunction: IrFunction?
get() = when (val element = inlinedElement) {
is IrFunction -> element
is IrFunctionExpression -> element.function
is IrFunctionReference -> element.symbol.owner.takeIf { it.isInline }
else -> null
}
fun IrInlinedFunctionBlock.isFunctionInlining(): Boolean {
return this.inlinedElement is IrFunction
}
fun IrInlinedFunctionBlock.isLambdaInlining(): Boolean {
return !isFunctionInlining()
}
val IrContainerExpression.innerInlinedBlockOrThis: IrContainerExpression
get() = (this as? IrReturnableBlock)?.statements?.singleOrNull() as? IrInlinedFunctionBlock ?: this
val IrReturnableBlock.inlineFunction: IrFunction?
get() = (this.statements.singleOrNull() as? IrInlinedFunctionBlock)?.inlineFunction
val IrReturnableBlock.sourceFileSymbol: IrFileSymbol?
get() = inlineFunction?.fileOrNull?.symbol
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.ir.innerInlinedBlockOrThis
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -120,20 +121,25 @@ abstract class AbstractValueUsageTransformer(
} }
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression { override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
if (expression is IrInlinedFunctionBlock) {
expression.transformChildrenVoid(this)
return expression
}
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
if (expression.statements.isEmpty()) { if (expression.statements.isEmpty()) {
return expression return expression
} }
val lastIndex = expression.statements.lastIndex val container = expression.innerInlinedBlockOrThis
expression.statements.forEachIndexed { i, irStatement -> val lastIndex = container.statements.lastIndex
container.statements.forEachIndexed { i, irStatement ->
if (irStatement is IrExpression) { if (irStatement is IrExpression) {
expression.statements[i] = container.statements[i] = when (i) {
if (i == lastIndex) lastIndex -> irStatement.useAsResult(expression)
irStatement.useAsResult(expression) else -> irStatement.useAsStatement()
else }
irStatement.useAsStatement()
} }
} }
@@ -162,7 +162,7 @@ class FunctionInlining(
val substituteMap = mutableMapOf<IrValueParameter, IrExpression>() val substituteMap = mutableMapOf<IrValueParameter, IrExpression>()
fun inline() = inlineFunction(callSite, callee, true) fun inline() = inlineFunction(callSite, callee, inlineFunctionResolver.getFunctionSymbol(callee).owner, true)
private fun IrElement.copy(): IrElement { private fun IrElement.copy(): IrElement {
return copyIrElement.copy(this) return copyIrElement.copy(this)
@@ -171,6 +171,7 @@ class FunctionInlining(
private fun inlineFunction( private fun inlineFunction(
callSite: IrFunctionAccessExpression, callSite: IrFunctionAccessExpression,
callee: IrFunction, callee: IrFunction,
originalInlinedElement: IrElement,
performRecursiveInline: Boolean performRecursiveInline: Boolean
): IrReturnableBlock { ): IrReturnableBlock {
val copiedCallee = (callee.copy() as IrFunction).apply { val copiedCallee = (callee.copy() as IrFunction).apply {
@@ -198,18 +199,27 @@ class FunctionInlining(
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, endOffset, endOffset) val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, endOffset, endOffset)
val transformer = ParameterSubstitutor() val transformer = ParameterSubstitutor()
val newStatements = mutableListOf<IrStatement>() val newStatements = statements.map { it.transform(transformer, data = null) as IrStatement }
newStatements.addAll(evaluationStatements) val inlinedBlock = IrInlinedFunctionBlockImpl(
statements.mapTo(newStatements) { it.transform(transformer, data = null) as IrStatement } startOffset = callSite.startOffset,
endOffset = callSite.endOffset,
type = callSite.type,
inlineCall = callSite,
inlinedElement = originalInlinedElement,
origin = null,
statements = evaluationStatements + newStatements
)
// Note: here we wrap `IrInlinedFunctionBlock` inside `IrReturnableBlock` because such way it is easier to
// control special composite blocks that are inside `IrInlinedFunctionBlock`
return IrReturnableBlockImpl( return IrReturnableBlockImpl(
startOffset = callSite.startOffset, startOffset = callSite.startOffset,
endOffset = callSite.endOffset, endOffset = callSite.endOffset,
type = callSite.type, type = callSite.type,
symbol = irReturnableBlockSymbol, symbol = irReturnableBlockSymbol,
origin = null, origin = null,
statements = newStatements, statements = listOf(inlinedBlock),
inlineFunctionSymbol = inlineFunctionResolver.getFunctionSymbol(callee) inlineFunctionSymbol = inlineFunctionResolver.getFunctionSymbol(callee)
).apply { ).apply {
transformChildrenVoid(object : IrElementTransformerVoid() { transformChildrenVoid(object : IrElementTransformerVoid() {
@@ -281,9 +291,7 @@ class FunctionInlining(
fun inlineFunctionExpression(irCall: IrCall, irFunctionExpression: IrFunctionExpression): IrExpression { fun inlineFunctionExpression(irCall: IrCall, irFunctionExpression: IrFunctionExpression): IrExpression {
// Inline the lambda. Lambda parameters will be substituted with lambda arguments. // Inline the lambda. Lambda parameters will be substituted with lambda arguments.
val newExpression = inlineFunction( val newExpression = inlineFunction(
irCall, irCall, irFunctionExpression.function, irFunctionExpression, false
irFunctionExpression.function,
false
) )
// Substitute lambda arguments with target function arguments. // Substitute lambda arguments with target function arguments.
return newExpression.transform(this, null) return newExpression.transform(this, null)
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.dce package org.jetbrains.kotlin.ir.backend.js.dce
import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.hasJsPolyfill import org.jetbrains.kotlin.ir.backend.js.utils.hasJsPolyfill
@@ -54,7 +55,7 @@ abstract class UsefulDeclarationProcessor(
super.visitBlock(expression, data) super.visitBlock(expression, data)
if (expression is IrReturnableBlock) { if (expression is IrReturnableBlock) {
expression.inlineFunctionSymbol?.owner?.addToUsefulPolyfilledDeclarations() expression.inlineFunction?.addToUsefulPolyfilledDeclarations()
} }
} }
@@ -68,7 +68,7 @@ class JsReturnableBlockTransformer(val context: CommonBackendContext) : IrElemen
val builder = context.createIrBuilder(expression.symbol) val builder = context.createIrBuilder(expression.symbol)
expression.type = context.irBuiltIns.unitType expression.type = unitType
return builder.irComposite(expression, expression.origin, variable.type) { return builder.irComposite(expression, expression.origin, variable.type) {
+variable +variable
+expression +expression
@@ -6,9 +6,9 @@
package org.jetbrains.kotlin.ir.backend.js.lower.cleanup package org.jetbrains.kotlin.ir.backend.js.lower.cleanup
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ir.isPure
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.backend.common.ir.isPure
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isNothing
@@ -37,8 +37,8 @@ private class BlockRemover : IrElementVisitorVoid {
private fun process(container: IrStatementContainer) { private fun process(container: IrStatementContainer) {
container.statements.transformFlat { statement -> container.statements.transformFlat { statement ->
when (statement) { when (statement) {
// returnable blocks required for sourcemaps generation, so keep them // returnable and inlined function blocks required for sourcemaps generation, so keep them
is IrReturnableBlock -> null is IrReturnableBlock, is IrInlinedFunctionBlock -> null
is IrStatementContainer -> statement.statements is IrStatementContainer -> statement.statements
else -> null else -> null
} }
@@ -5,11 +5,12 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.utils.isTheLastReturnStatementIn import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.backend.common.ir.innerInlinedBlockOrThis
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
import org.jetbrains.kotlin.ir.backend.js.utils.isTheLastReturnStatementIn
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
@@ -36,11 +37,12 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
} }
override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsStatement { override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsStatement {
val newContext = (expression as? IrReturnableBlock)?.inlineFunctionSymbol?.let { val newContext = (expression as? IrReturnableBlock)?.inlineFunction?.let {
context.newFile(it.owner.file, context.currentFunction, context.localNames) context.newFile(it.file, context.currentFunction, context.localNames)
} ?: context } ?: context
val statements = expression.statements.map { it.accept(this, newContext) } val container = expression.innerInlinedBlockOrThis.statements
val statements = container.map { it.accept(this, newContext) }
return if (expression is IrReturnableBlock) { return if (expression is IrReturnableBlock) {
val label = context.getNameForReturnableBlock(expression) val label = context.getNameForReturnableBlock(expression)
@@ -57,9 +59,9 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
} }
private fun List<JsStatement>.wrapInCommentsInlineFunctionCall(expression: IrReturnableBlock): List<JsStatement> { private fun List<JsStatement>.wrapInCommentsInlineFunctionCall(expression: IrReturnableBlock): List<JsStatement> {
val inlineFunctionSymbol = expression.inlineFunctionSymbol ?: return this val inlineFunction = expression.inlineFunction ?: return this
val correspondingProperty = (inlineFunctionSymbol.owner as? IrSimpleFunction)?.correspondingPropertySymbol val correspondingProperty = (inlineFunction as? IrSimpleFunction)?.correspondingPropertySymbol
val owner = correspondingProperty?.owner ?: inlineFunctionSymbol.owner val owner = correspondingProperty?.owner ?: inlineFunction
val funName = owner.fqNameWhenAvailable ?: owner.name val funName = owner.fqNameWhenAvailable ?: owner.name
return listOf(JsSingleLineComment(" Inline function '$funName' call")) + this return listOf(JsSingleLineComment(" Inline function '$funName' call")) + this
} }
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrInlinedFunctionBlock
import org.jetbrains.kotlin.ir.expressions.IrReturn import org.jetbrains.kotlin.ir.expressions.IrReturn
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
@@ -45,6 +46,10 @@ fun IrDeclaration?.isExportedInterface(context: JsIrBackendContext) =
this is IrClass && kind.isInterface && isExported(context) this is IrClass && kind.isInterface && isExported(context)
fun IrReturn.isTheLastReturnStatementIn(target: IrReturnableBlockSymbol): Boolean { fun IrReturn.isTheLastReturnStatementIn(target: IrReturnableBlockSymbol): Boolean {
val ownerFirstStatement = target.owner.statements.singleOrNull()
if (ownerFirstStatement is IrInlinedFunctionBlock) {
return ownerFirstStatement.statements.lastOrNull() === this
}
return target.owner.statements.lastOrNull() === this return target.owner.statements.lastOrNull() === this
} }
@@ -8,13 +8,7 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.fileOrNull
@Suppress("unused") // Used in kotlin-native
val IrReturnableBlock.sourceFileSymbol: IrFileSymbol?
get() = inlineFunctionSymbol?.owner?.fileOrNull?.symbol
val IrFunctionReference.isWithReflection: Boolean val IrFunctionReference.isWithReflection: Boolean
get() = reflectionTarget != null get() = reflectionTarget != null
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.* import kotlinx.cinterop.*
import llvm.* import llvm.*
import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub
import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint import org.jetbrains.kotlin.backend.common.lower.inline.InlinerExpressionLocationHint
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
@@ -17,9 +18,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation import org.jetbrains.kotlin.backend.konan.llvm.coverage.LLVMCoverageInstrumentation
import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.backend.konan.lower.*
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_STATIC_GLOBAL_INITIALIZER
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_STATIC_STANDALONE_THREAD_LOCAL_INITIALIZER
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_STATIC_THREAD_LOCAL_INITIALIZER
import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
@@ -335,7 +333,7 @@ internal class CodeGeneratorVisitor(
val functionContext = findCodeContext(symbol.owner, currentCodeContext) { val functionContext = findCodeContext(symbol.owner, currentCodeContext) {
val declaration = (this as? FunctionScope)?.declaration val declaration = (this as? FunctionScope)?.declaration
val returnableBlock = (this as? ReturnableBlockScope)?.returnableBlock val returnableBlock = (this as? ReturnableBlockScope)?.returnableBlock
val inlinedFunction = returnableBlock?.inlineFunctionSymbol?.owner val inlinedFunction = returnableBlock?.inlineFunction
declaration == it || inlinedFunction == it declaration == it || inlinedFunction == it
} ?: return null } ?: return null
@@ -1948,7 +1946,7 @@ internal class CodeGeneratorVisitor(
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock, val resultSlot: LLVMValueRef?) : private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock, val resultSlot: LLVMValueRef?) :
FileScope(returnableBlock.inlineFunctionSymbol?.owner?.let { FileScope(returnableBlock.inlineFunction?.let {
generationState.inlineFunctionOrigins[it]?.irFile ?: it.fileOrNull generationState.inlineFunctionOrigins[it]?.irFile ?: it.fileOrNull
} }
?: (currentCodeContext.fileScope() as? FileScope)?.file ?: (currentCodeContext.fileScope() as? FileScope)?.file
@@ -1957,13 +1955,13 @@ internal class CodeGeneratorVisitor(
var bbExit : LLVMBasicBlockRef? = null var bbExit : LLVMBasicBlockRef? = null
var resultPhi : LLVMValueRef? = null var resultPhi : LLVMValueRef? = null
private val functionScope by lazy { private val functionScope by lazy {
returnableBlock.inlineFunctionSymbol?.owner?.let { returnableBlock.inlineFunction?.let {
it.scope(file().fileEntry.line(generationState.inlineFunctionOrigins[it]?.startOffset ?: it.startOffset)) it.scope(file().fileEntry.line(generationState.inlineFunctionOrigins[it]?.startOffset ?: it.startOffset))
} }
} }
private fun getExit(): LLVMBasicBlockRef { private fun getExit(): LLVMBasicBlockRef {
val location = returnableBlock.inlineFunctionSymbol?.owner?.let { val location = returnableBlock.inlineFunction?.let {
location(generationState.inlineFunctionOrigins[it]?.endOffset ?: it.endOffset) location(generationState.inlineFunctionOrigins[it]?.endOffset ?: it.endOffset)
} ?: returnableBlock.statements.lastOrNull()?.let { } ?: returnableBlock.statements.lastOrNull()?.let {
location(it.endOffset) location(it.endOffset)
@@ -2006,7 +2004,7 @@ internal class CodeGeneratorVisitor(
override fun returnableBlockScope(): CodeContext? = this override fun returnableBlockScope(): CodeContext? = this
override fun location(offset: Int): LocationInfo? { override fun location(offset: Int): LocationInfo? {
return if (returnableBlock.inlineFunctionSymbol != null) { return if (returnableBlock.inlineFunction != null) {
val diScope = functionScope ?: return null val diScope = functionScope ?: return null
val inlinedAt = outerContext.location(returnableBlock.startOffset) ?: return null val inlinedAt = outerContext.location(returnableBlock.startOffset) ?: return null
LocationInfo(diScope, file.fileEntry.line(offset), file.fileEntry.column(offset), inlinedAt) LocationInfo(diScope, file.fileEntry.line(offset), file.fileEntry.column(offset), inlinedAt)
@@ -4,6 +4,7 @@
*/ */
package org.jetbrains.kotlin.backend.konan.llvm.coverage package org.jetbrains.kotlin.backend.konan.llvm.coverage
import org.jetbrains.kotlin.backend.common.ir.sourceFileSymbol
import org.jetbrains.kotlin.backend.common.pop import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
@@ -5,8 +5,13 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.inlineDeclaration
import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.peek
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.cgen.* import org.jetbrains.kotlin.backend.konan.cgen.*
import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenFunctions
@@ -15,7 +20,10 @@ import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
import org.jetbrains.kotlin.backend.konan.serialization.resolveFakeOverrideMaybeAbstract import org.jetbrains.kotlin.backend.konan.serialization.resolveFakeOverrideMaybeAbstract
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
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.* import org.jetbrains.kotlin.ir.builders.*
@@ -39,12 +47,12 @@ 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.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.konan.ForeignExceptionMode
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.konan.ForeignExceptionMode
import org.jetbrains.kotlin.konan.library.KonanLibrary
internal class InteropLowering(generationState: NativeGenerationState) : FileLoweringPass { internal class InteropLowering(generationState: NativeGenerationState) : FileLoweringPass {
// TODO: merge these lowerings. // TODO: merge these lowerings.
@@ -693,7 +701,7 @@ private class InteropLoweringPart1(val generationState: NativeGenerationState) :
} }
override fun visitBlock(expression: IrBlock): IrExpression { override fun visitBlock(expression: IrBlock): IrExpression {
if (expression is IrReturnableBlock && expression.inlineFunctionSymbol?.isAutoreleasepool() == true) { if (expression is IrReturnableBlock && expression.inlineFunction?.isAutoreleasepool() == true) {
// Prohibit calling suspend functions from `autoreleasepool {}` block. // Prohibit calling suspend functions from `autoreleasepool {}` block.
// See https://youtrack.jetbrains.com/issue/KT-50786 for more details. // See https://youtrack.jetbrains.com/issue/KT-50786 for more details.
// Note: we can't easily check this in frontend, because we need to prohibit indirect cases like // Note: we can't easily check this in frontend, because we need to prohibit indirect cases like
@@ -722,8 +730,8 @@ private class InteropLoweringPart1(val generationState: NativeGenerationState) :
return super.visitBlock(expression) return super.visitBlock(expression)
} }
private fun IrFunctionSymbol.isAutoreleasepool(): Boolean { private fun IrFunction.isAutoreleasepool(): Boolean {
return this.owner.name.asString() == "autoreleasepool" && this.owner.parent.let { parent -> return this.name.asString() == "autoreleasepool" && this.parent.let { parent ->
parent is IrPackageFragment && parent.fqName == InteropFqNames.packageName parent is IrPackageFragment && parent.fqName == InteropFqNames.packageName
} }
} }
@@ -159,7 +159,7 @@ internal class RedundantCoercionsCleaner(val context: Context) : FileLoweringPas
symbol = newSymbol, symbol = newSymbol,
origin = origin, origin = origin,
statements = statements, statements = statements,
inlineFunctionSymbol = inlineFunctionSymbol) )
} }
/* /*
* Visitor below requires being very careful when changing it. * Visitor below requires being very careful when changing it.
@@ -6,10 +6,13 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.inlineFunction
import org.jetbrains.kotlin.backend.common.ir.innerInlinedBlockOrThis
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -51,10 +54,11 @@ internal class ReturnsInsertionLowering(val context: Context) : FileLoweringPass
override fun visitBlock(expression: IrBlock) { override fun visitBlock(expression: IrBlock) {
expression.acceptChildrenVoid(this) expression.acceptChildrenVoid(this)
if (expression !is IrReturnableBlock) return if (expression !is IrReturnableBlock) return
if (expression.inlineFunctionSymbol?.owner?.returnType == context.irBuiltIns.unitType) { if (expression.inlineFunction?.returnType == context.irBuiltIns.unitType) {
val offset = (expression.statements.lastOrNull() ?: expression).endOffset val container = expression.innerInlinedBlockOrThis.statements
val offset = (container.lastOrNull() ?: expression).endOffset
context.createIrBuilder(expression.symbol, offset, offset).run { context.createIrBuilder(expression.symbol, offset, offset).run {
expression.statements += irReturn(irCall(symbols.theUnitInstance, context.irBuiltIns.unitType)) container += irReturn(irCall(symbols.theUnitInstance, context.irBuiltIns.unitType))
} }
} }
} }