Turned on IR validation

This commit is contained in:
Igor Chevdar
2019-06-24 19:52:15 +03:00
parent a7e2e4622c
commit a71305c1d9
4 changed files with 53 additions and 86 deletions
@@ -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()
}
@@ -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<AnyNamedPhase> = 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<AnyNamedPhase> = 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)
@@ -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",
@@ -123,39 +123,6 @@ object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent
}
}
fun IrModuleFragment.checkDeclarationParents() {
this.accept(CheckDeclarationParentsVisitor, null)
}
object CheckDeclarationParentsVisitor : IrElementVisitor<Unit, IrDeclarationParent?> {
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