From a71305c1d9d9890d7d365940ea9a992948c784cb Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Mon, 24 Jun 2019 19:52:15 +0300 Subject: [PATCH] Turned on IR validation --- .../jetbrains/kotlin/backend/konan/Context.kt | 8 --- .../backend/konan/KonanLoweringPhases.kt | 44 +++++---------- .../kotlin/backend/konan/ToplevelPhases.kt | 54 +++++++++++++------ .../org/jetbrains/kotlin/ir/util/IrUtils2.kt | 33 ------------ 4 files changed, 53 insertions(+), 86 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index db01232b510..37f457ce83e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -10,10 +10,8 @@ import llvm.LLVMModuleRef import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor -import org.jetbrains.kotlin.backend.common.validateIrModule import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.KonanIr -import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD @@ -351,11 +349,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { moduleDescriptor.deepPrint() } - fun verifyIr() { - val module = irModule ?: return - validateIrModule(this, module) - } - fun printIr() { if (irModule == null) return separator("IR:") @@ -418,7 +411,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { fun verify() { verifyDescriptors() - verifyIr() verifyBitCode() } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt index cb628860134..109375b05cf 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanLoweringPhases.kt @@ -10,22 +10,24 @@ import org.jetbrains.kotlin.backend.konan.lower.InitializersLowering import org.jetbrains.kotlin.backend.konan.lower.loops.ForLoopsLowering import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.ir.util.checkDeclarationParents -import org.jetbrains.kotlin.ir.util.patchDeclarationParents + +private val validateAll = false +private val filePhaseActions = if (validateAll) setOf(defaultDumper, ::fileValidationCallback) else setOf(defaultDumper) +private val modulePhaseActions = if (validateAll) setOf(defaultDumper, ::moduleValidationCallback) else setOf(defaultDumper) private fun makeKonanFileLoweringPhase( lowering: (Context) -> FileLoweringPass, name: String, description: String, prerequisite: Set = emptySet() -) = makeIrFilePhase(lowering, name, description, prerequisite) +) = makeIrFilePhase(lowering, name, description, prerequisite, actions = filePhaseActions) private fun makeKonanModuleLoweringPhase( lowering: (Context) -> FileLoweringPass, name: String, description: String, prerequisite: Set = emptySet() -) = makeIrModulePhase(lowering, name, description, prerequisite) +) = makeIrModulePhase(lowering, name, description, prerequisite, actions = modulePhaseActions) internal fun makeKonanFileOpPhase( op: (Context, IrFile) -> Unit, @@ -39,7 +41,8 @@ internal fun makeKonanFileOpPhase( op(context, input) return input } - } + }, + actions = filePhaseActions ) internal fun makeKonanModuleOpPhase( @@ -54,7 +57,8 @@ internal fun makeKonanModuleOpPhase( op(context, input) return input } - } + }, + actions = modulePhaseActions ) internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase( @@ -79,7 +83,8 @@ internal val inlinePhase = namedIrModulePhase( name = "Inline", description = "Functions inlining", prerequisite = setOf(lowerBeforeInlinePhase), - nlevels = 0 + nlevels = 0, + actions = modulePhaseActions ) internal val lowerAfterInlinePhase = makeKonanModuleOpPhase( @@ -99,24 +104,6 @@ internal val interopPart1Phase = makeKonanModuleLoweringPhase( prerequisite = setOf(inlinePhase) ) -internal val patchDeclarationParents1Phase = makeKonanModuleOpPhase( - { _, irModule -> irModule.patchDeclarationParents() }, - name = "PatchDeclarationParents1", - description = "Patch declaration parents 1" -) - -internal val checkDeclarationParentsPhase = makeKonanModuleOpPhase( - { _, irModule -> irModule.checkDeclarationParents() }, - name = "CheckDeclarationParents", - description = "Check declaration parents" -) - -internal val validateIrModulePhase = makeKonanModuleOpPhase( - { context, irModule -> validateIrModule(context, irModule) }, - name = "ValidateIrModule", - description = "Validate generated module" -) - /* IrFile phases */ internal val lateinitPhase = makeKonanFileLoweringPhase( @@ -284,11 +271,8 @@ internal val bridgesPhase = makeKonanFileOpPhase( prerequisite = setOf(coroutinesPhase) ) -internal val autoboxPhase = makeKonanFileOpPhase( - { context, irFile -> - // validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished. - Autoboxing(context).lower(irFile) - }, +internal val autoboxPhase = makeKonanFileLoweringPhase( + ::Autoboxing, name = "Autobox", description = "Autoboxing of primitive types", prerequisite = setOf(bridgesPhase, coroutinesPhase) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index fb6df8fe867..340b7dc84d0 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -1,6 +1,6 @@ package org.jetbrains.kotlin.backend.konan -import org.jetbrains.kotlin.backend.common.LoggingContext +import org.jetbrains.kotlin.backend.common.* import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable @@ -20,12 +20,47 @@ import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.SymbolTable -import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import java.util.Collections.emptySet +internal fun moduleValidationCallback(state: ActionState, module: IrModuleFragment, context: Context) { + val validatorConfig = IrValidatorConfig( + abortOnError = false, + ensureAllNodesAreDifferent = true, + checkTypes = true, + checkDescriptors = false + ) + try { + module.accept(IrValidator(context, validatorConfig), null) + module.accept(CheckDeclarationParentsVisitor, null) + } catch (t: Throwable) { + // TODO: Add reference to source. + if (validatorConfig.abortOnError) + throw IllegalStateException("Failed IR validation ${state.beforeOrAfter} ${state.phase}", t) + else context.reportCompilationWarning("[IR VALIDATION] ${state.beforeOrAfter} ${state.phase}: ${t.message}") + } +} + +internal fun fileValidationCallback(state: ActionState, irFile: IrFile, context: Context) { + val validatorConfig = IrValidatorConfig( + abortOnError = false, + ensureAllNodesAreDifferent = true, + checkTypes = true, + checkDescriptors = false + ) + try { + irFile.accept(IrValidator(context, validatorConfig), null) + irFile.accept(CheckDeclarationParentsVisitor, null) + } catch (t: Throwable) { + // TODO: Add reference to source. + if (validatorConfig.abortOnError) + throw IllegalStateException("Failed IR validation ${state.beforeOrAfter} ${state.phase}", t) + else context.reportCompilationWarning("[IR VALIDATION] ${state.beforeOrAfter} ${state.phase}: ${t.message}") + } +} + internal fun konanUnitPhase( name: String, description: String, @@ -128,8 +163,6 @@ internal val psiToIrPhase = konanUnitPhase( irModule = module irModules = deserializer.modules ir.symbols = symbols - -// validateIrModule(this, module) }, name = "Psi2Ir", description = "Psi to IR conversion", @@ -169,12 +202,6 @@ internal val copyDefaultValuesToActualPhase = konanUnitPhase( description = "Copy default values from expect to actual declarations" ) -internal val patchDeclarationParents0Phase = konanUnitPhase( - op = { irModule!!.patchDeclarationParents() }, // why do we need it? - name = "PatchDeclarationParents0", - description = "Patch declaration parents" -) - internal val serializerPhase = konanUnitPhase( op = { val declarationTable = KonanDeclarationTable(irModule!!.irBuiltins, DescriptorTable()) @@ -213,7 +240,6 @@ internal val allLoweringsPhase = namedIrModulePhase( inlinePhase then lowerAfterInlinePhase then interopPart1Phase then - patchDeclarationParents1Phase then performByIrFile( name = "IrLowerByFile", description = "IR Lowering by file", @@ -242,9 +268,8 @@ internal val allLoweringsPhase = namedIrModulePhase( bridgesPhase then autoboxPhase then returnsInsertionPhase - ) then - checkDeclarationParentsPhase -// validateIrModulePhase // Temporarily disabled until moving to new IR finished. + ), + actions = setOf(defaultDumper, ::moduleValidationCallback) ) internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper( @@ -313,7 +338,6 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase( destroySymbolTablePhase then irGeneratorPluginsPhase then copyDefaultValuesToActualPhase then - patchDeclarationParents0Phase then serializerPhase then namedUnitPhase( name = "Backend", diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt index e35d06c0549..1f4a8cf2e00 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt @@ -123,39 +123,6 @@ object SetDeclarationsParentVisitor : IrElementVisitor { - - override fun visitElement(element: IrElement, data: IrDeclarationParent?) { - element.acceptChildren(this, element as? IrDeclarationParent ?: data) - } - - override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent?) { - if (declaration !is IrVariable && declaration !is IrValueParameter && declaration !is IrTypeParameter) { - checkParent(declaration, data) - } else { - // Don't check IrVariable parent. - } - - super.visitDeclaration(declaration, data) - } - - private fun checkParent(declaration: IrDeclaration, expectedParent: IrDeclarationParent?) { - val parent = try { - declaration.parent - } catch (e: Throwable) { - error("$declaration for ${declaration.descriptor} has no parent") - } - - if (parent != expectedParent) { - error("$declaration for ${declaration.descriptor} has unexpected parent $parent") - } - } -} - tailrec fun IrDeclaration.getContainingFile(): IrFile? { val parent = this.parent