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.
This commit is contained in:
Ilya Matveev
2017-07-24 16:42:11 +07:00
committed by ilmat192
parent 0e67fbb7ad
commit 12f815eabb
5 changed files with 50 additions and 19 deletions
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.util.SymbolTable
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.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
// This is what Context collects about IR. // This is what Context collects about IR.
@@ -40,6 +40,10 @@ internal class KonanLower(val context: Context) {
fun lowerModule(irModule: IrModuleFragment) { fun lowerModule(irModule: IrModuleFragment) {
val phaser = PhaseManager(context) val phaser = PhaseManager(context)
phaser.phase(KonanPhase.LOWER_SPECIAL_CALLS) {
irModule.files.forEach(SpecialCallsLowering(context)::lower)
}
phaser.phase(KonanPhase.LOWER_INLINE_CONSTRUCTORS) { phaser.phase(KonanPhase.LOWER_INLINE_CONSTRUCTORS) {
InlineConstructorsTransformation(context).lower(irModule) InlineConstructorsTransformation(context).lower(irModule)
} }
@@ -28,8 +28,9 @@ enum class KonanPhase(val description: String,
/* */ SERIALIZER("Serialize descriptor tree and inline IR bodies"), /* */ SERIALIZER("Serialize descriptor tree and inline IR bodies"),
/* */ BACKEND("All backend"), /* */ BACKEND("All backend"),
/* ... */ LOWER("IR Lowering"), /* ... */ LOWER("IR Lowering"),
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation"), /* ... ... */ LOWER_SPECIAL_CALLS("Special calls processing before inlining"),
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS), /* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_SPECIAL_CALLS),
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_SPECIAL_CALLS),
/* ... ... ... */ 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),
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"), /* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
@@ -19,23 +19,20 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.atMostOne import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.backend.konan.Context 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.backend.konan.isValueType
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor 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.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.ir.util.isNullConst
import org.jetbrains.kotlin.ir.util.type import org.jetbrains.kotlin.ir.util.type
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.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.isUnit
/** /**
* This lowering pass lowers some calls to [IrBuiltinOperatorDescriptor]s. * 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 builtIns = context.builtIns
private val irBuiltins = context.irModule!!.irBuiltins 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 { override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val descriptor = expression.descriptor 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) { if (descriptor is IrBuiltinOperatorDescriptor) {
return transformBuiltinOperator(expression) return transformBuiltinOperator(expression)
} }
@@ -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
}
})
}
}