[IR] Run lowerings before the inliner on all inline functions
Since inlining is a cross-module operation (we need to know the bodies of inline functions), all lowerings that are supposed to run before the inliner, need to be run on all inline functions.
This commit is contained in:
+2
@@ -66,6 +66,8 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
private val loweredEnums = mutableMapOf<IrClass, LoweredEnum>()
|
||||
private val ordinals = mutableMapOf<ClassDescriptor, Map<ClassDescriptor, Int>>()
|
||||
|
||||
val loweredInlineFunctions = mutableSetOf<IrFunction>()
|
||||
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ internal val extractLocalClassesFromInlineBodies = namedIrModulePhase(
|
||||
internal val inlinePhase = namedIrModulePhase(
|
||||
lower = object : SameTypeCompilerPhase<Context, IrModuleFragment> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<IrModuleFragment>, context: Context, input: IrModuleFragment): IrModuleFragment {
|
||||
FunctionInlining(context).run {
|
||||
FunctionInlining(context, NativeInlineFunctionResolver(context)).run {
|
||||
input.files.forEach { lower(it) }
|
||||
}
|
||||
return input
|
||||
|
||||
+3
-5
@@ -25,11 +25,7 @@ import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.util.addFile
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||
@@ -320,6 +316,7 @@ internal val linkerPhase = konanUnitPhase(
|
||||
internal val allLoweringsPhase = namedIrModulePhase(
|
||||
name = "IrLowering",
|
||||
description = "IR Lowering",
|
||||
// TODO: The lowerings before inlinePhase should be aligned with [NativeInlineFunctionResolver.kt]
|
||||
lower = removeExpectDeclarationsPhase then
|
||||
stripTypeAliasDeclarationsPhase then
|
||||
lowerBeforeInlinePhase then
|
||||
@@ -392,6 +389,7 @@ internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper(
|
||||
?: return@forEach
|
||||
input.files += libModule.files
|
||||
}
|
||||
|
||||
input.files += files
|
||||
|
||||
return input
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.inline.DefaultInlineFunctionResolver
|
||||
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering
|
||||
import org.jetbrains.kotlin.backend.common.runPostfix
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
|
||||
// TODO: This is a bit hacky. Think about adopting persistent IR ideas.
|
||||
internal class NativeInlineFunctionResolver(override val context: Context) : DefaultInlineFunctionResolver(context) {
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val function = super.getFunctionDeclaration(symbol)
|
||||
val body = function.body ?: return function
|
||||
|
||||
if (function in context.specialDeclarationsFactory.loweredInlineFunctions)
|
||||
return function
|
||||
|
||||
context.specialDeclarationsFactory.loweredInlineFunctions.add(function)
|
||||
|
||||
PreInlineLowering(context).lower(body, function)
|
||||
|
||||
ArrayConstructorLowering(context).lower(body, function)
|
||||
|
||||
NullableFieldsForLateinitCreationLowering(context).lowerWithLocalDeclarations(function)
|
||||
NullableFieldsDeclarationLowering(context).lowerWithLocalDeclarations(function)
|
||||
LateinitUsageLowering(context).lower(body, function)
|
||||
|
||||
SharedVariablesLowering(context).lower(body, function)
|
||||
|
||||
LocalClassesInInlineLambdasLowering(context).lower(body, function)
|
||||
|
||||
if (context.llvmModuleSpecification.containsDeclaration(function)) {
|
||||
// Do not extract local classes off of inline functions from cached libraries.
|
||||
LocalClassesInInlineFunctionsLowering(context).lower(body, function)
|
||||
LocalClassesExtractionFromInlineFunctionsLowering(context).lower(body, function)
|
||||
}
|
||||
|
||||
return function
|
||||
}
|
||||
|
||||
private fun DeclarationTransformer.lowerWithLocalDeclarations(function: IrFunction) {
|
||||
if (runPostfix(true).transformFlat(function) != null)
|
||||
error("Unexpected transformation of function ${function.dump()}")
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -5,11 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
@@ -20,15 +21,15 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
* This pass runs before inlining and performs the following additional transformations over some operations:
|
||||
* - Assertion call removal.
|
||||
*/
|
||||
internal class PreInlineLowering(val context: Context) : FileLoweringPass {
|
||||
internal class PreInlineLowering(val context: Context) : BodyLoweringPass {
|
||||
|
||||
private val symbols get() = context.ir.symbols
|
||||
|
||||
private val asserts = symbols.asserts
|
||||
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
irBody.transformChildrenVoid(object : IrBuildingTransformer(context) {
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
@@ -3302,6 +3302,18 @@ linkTest("inline_defaultArgs_linkTest") {
|
||||
lib = "codegen/inline/defaultArgs_linkTest_lib.kt"
|
||||
}
|
||||
|
||||
linkTest("inline_sharedVar_linkTest") {
|
||||
goldValue = "6\n"
|
||||
source = "codegen/inline/sharedVar_linkTest_main.kt"
|
||||
lib = "codegen/inline/sharedVar_linkTest_lib.kt"
|
||||
}
|
||||
|
||||
linkTest("inline_lateinitProperty_linkTest") {
|
||||
goldValue = "OK\n"
|
||||
source = "codegen/inline/lateinitProperty_linkTest_main.kt"
|
||||
lib = "codegen/inline/lateinitProperty_linkTest_lib.kt"
|
||||
}
|
||||
|
||||
def generateWithSpaceDefFile() {
|
||||
def mapOption = "--Map \"${buildDir}/cutom map.map\""
|
||||
if (isAppleTarget(project)) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package a
|
||||
|
||||
fun IntArray.forEachNoInline(block: (Int) -> Unit) = this.forEach { block(it) }
|
||||
|
||||
inline fun foo(values: IntArray, crossinline block: (Int, Int, Int) -> Int): Int {
|
||||
val o = object {
|
||||
lateinit var s: String
|
||||
var x: Int = 42
|
||||
}
|
||||
values.forEachNoInline {
|
||||
o.x = block(o.x, o.s.length, it)
|
||||
}
|
||||
return o.x
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import a.*
|
||||
|
||||
fun main() {
|
||||
try {
|
||||
val res = foo(intArrayOf(1, 2, 3)) { x, y, z -> x + y - z }
|
||||
println(res)
|
||||
} catch (t: UninitializedPropertyAccessException) {
|
||||
println("OK")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package a
|
||||
|
||||
fun IntArray.forEachNoInline(block: (Int) -> Unit) = this.forEach { block(it) }
|
||||
|
||||
inline fun fold(initial: Int, values: IntArray, crossinline block: (Int, Int) -> Int): Int {
|
||||
var res = initial
|
||||
values.forEachNoInline {
|
||||
res = block(res, it)
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
import a.*
|
||||
|
||||
fun main() {
|
||||
println(fold(0, intArrayOf(1, 2, 3)) { x, y -> x + y })
|
||||
}
|
||||
Reference in New Issue
Block a user