From 12f815eabb160730351947ed929a83485f39c824 Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Mon, 24 Jul 2017 16:42:11 +0700 Subject: [PATCH] backend: Add a call lowering pass before inlining Some inlined calls may require additional processing before the inlining pass. E.g. assert() calls must be removed if assertions are disabled by compiler flags. This patch adds an additional pass before inlining and uses it for assertions removal. --- .../jetbrains/kotlin/backend/common/ir/Ir.kt | 1 - .../kotlin/backend/konan/KonanLower.kt | 4 ++ .../kotlin/backend/konan/KonanPhases.kt | 5 ++- .../konan/lower/BuiltinOperatorLowering.kt | 20 ++-------- .../konan/lower/SpecialCallsLowering.kt | 39 +++++++++++++++++++ 5 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialCallsLowering.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index 7586a8568ca..9b4c52116d8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.util.OperatorNameConventions // This is what Context collects about IR. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt index 38263f69d48..4be73f8d7eb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLower.kt @@ -40,6 +40,10 @@ internal class KonanLower(val context: Context) { fun lowerModule(irModule: IrModuleFragment) { val phaser = PhaseManager(context) + phaser.phase(KonanPhase.LOWER_SPECIAL_CALLS) { + irModule.files.forEach(SpecialCallsLowering(context)::lower) + } + phaser.phase(KonanPhase.LOWER_INLINE_CONSTRUCTORS) { InlineConstructorsTransformation(context).lower(irModule) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt index 04b3a539c17..e2f7d2a49e3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPhases.kt @@ -28,8 +28,9 @@ enum class KonanPhase(val description: String, /* */ SERIALIZER("Serialize descriptor tree and inline IR bodies"), /* */ BACKEND("All backend"), /* ... */ LOWER("IR Lowering"), - /* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation"), - /* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS), + /* ... ... */ LOWER_SPECIAL_CALLS("Special calls processing before inlining"), + /* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_SPECIAL_CALLS), + /* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_SPECIAL_CALLS), /* ... ... ... */ DESERIALIZER("Deserialize inline bodies"), /* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE), /* ... ... */ LOWER_FOR_LOOPS("For loops lowering"), diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt index 61dac26a686..f489b86adf8 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/BuiltinOperatorLowering.kt @@ -19,23 +19,20 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.ENABLE_ASSERTIONS -import org.jetbrains.kotlin.backend.konan.isStdlib import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor -import org.jetbrains.kotlin.ir.expressions.* +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.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf -import org.jetbrains.kotlin.types.typeUtil.isUnit /** * This lowering pass lowers some calls to [IrBuiltinOperatorDescriptor]s. @@ -54,20 +51,11 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf private val builtIns = context.builtIns private val irBuiltins = context.irModule!!.irBuiltins - private val enableAssertions = context.config.configuration.getBoolean(ENABLE_ASSERTIONS) - - private val assertSymbols = context.ir.symbols.asserts override fun visitCall(expression: IrCall): IrExpression { expression.transformChildrenVoid(this) val descriptor = expression.descriptor - // Replace assert() call with an empty composite if assertions are not enabled. - if (!enableAssertions && expression.symbol in assertSymbols) { - assert(expression.type.isUnit()) - return IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type) - } - if (descriptor is IrBuiltinOperatorDescriptor) { return transformBuiltinOperator(expression) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialCallsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialCallsLowering.kt new file mode 100644 index 00000000000..65aa7f87241 --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/SpecialCallsLowering.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlin.backend.konan.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +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.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.types.typeUtil.isUnit + +/** + * This pass runs before inlining and performs the following additional transformations over some calls: + * - Assertion call removal. + */ +internal class SpecialCallsLowering(val context: Context) : FileLoweringPass { + + private val asserts = context.ir.symbols.asserts + private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS) + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object : IrElementTransformerVoid() { + + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + + // Replace assert() call with an empty composite if assertions are not enabled. + if (!enableAssertions && expression.symbol in asserts) { + assert(expression.type.isUnit()) + return IrCompositeImpl(expression.startOffset, expression.endOffset, expression.type) + } + + return expression + } + }) + } +} \ No newline at end of file