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.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor 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.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.KonanIr 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.library.SerializedMetadata
import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
@@ -351,11 +349,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
moduleDescriptor.deepPrint() moduleDescriptor.deepPrint()
} }
fun verifyIr() {
val module = irModule ?: return
validateIrModule(this, module)
}
fun printIr() { fun printIr() {
if (irModule == null) return if (irModule == null) return
separator("IR:") separator("IR:")
@@ -418,7 +411,6 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
fun verify() { fun verify() {
verifyDescriptors() verifyDescriptors()
verifyIr()
verifyBitCode() 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.backend.konan.lower.loops.ForLoopsLowering
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment 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( private fun makeKonanFileLoweringPhase(
lowering: (Context) -> FileLoweringPass, lowering: (Context) -> FileLoweringPass,
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet() prerequisite: Set<AnyNamedPhase> = emptySet()
) = makeIrFilePhase(lowering, name, description, prerequisite) ) = makeIrFilePhase(lowering, name, description, prerequisite, actions = filePhaseActions)
private fun makeKonanModuleLoweringPhase( private fun makeKonanModuleLoweringPhase(
lowering: (Context) -> FileLoweringPass, lowering: (Context) -> FileLoweringPass,
name: String, name: String,
description: String, description: String,
prerequisite: Set<AnyNamedPhase> = emptySet() prerequisite: Set<AnyNamedPhase> = emptySet()
) = makeIrModulePhase(lowering, name, description, prerequisite) ) = makeIrModulePhase(lowering, name, description, prerequisite, actions = modulePhaseActions)
internal fun makeKonanFileOpPhase( internal fun makeKonanFileOpPhase(
op: (Context, IrFile) -> Unit, op: (Context, IrFile) -> Unit,
@@ -39,7 +41,8 @@ internal fun makeKonanFileOpPhase(
op(context, input) op(context, input)
return input return input
} }
} },
actions = filePhaseActions
) )
internal fun makeKonanModuleOpPhase( internal fun makeKonanModuleOpPhase(
@@ -54,7 +57,8 @@ internal fun makeKonanModuleOpPhase(
op(context, input) op(context, input)
return input return input
} }
} },
actions = modulePhaseActions
) )
internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase( internal val removeExpectDeclarationsPhase = makeKonanModuleLoweringPhase(
@@ -79,7 +83,8 @@ internal val inlinePhase = namedIrModulePhase(
name = "Inline", name = "Inline",
description = "Functions inlining", description = "Functions inlining",
prerequisite = setOf(lowerBeforeInlinePhase), prerequisite = setOf(lowerBeforeInlinePhase),
nlevels = 0 nlevels = 0,
actions = modulePhaseActions
) )
internal val lowerAfterInlinePhase = makeKonanModuleOpPhase( internal val lowerAfterInlinePhase = makeKonanModuleOpPhase(
@@ -99,24 +104,6 @@ internal val interopPart1Phase = makeKonanModuleLoweringPhase(
prerequisite = setOf(inlinePhase) 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 */ /* IrFile phases */
internal val lateinitPhase = makeKonanFileLoweringPhase( internal val lateinitPhase = makeKonanFileLoweringPhase(
@@ -284,11 +271,8 @@ internal val bridgesPhase = makeKonanFileOpPhase(
prerequisite = setOf(coroutinesPhase) prerequisite = setOf(coroutinesPhase)
) )
internal val autoboxPhase = makeKonanFileOpPhase( internal val autoboxPhase = makeKonanFileLoweringPhase(
{ context, irFile -> ::Autoboxing,
// validateIrFile(context, irFile) // Temporarily disabled until moving to new IR finished.
Autoboxing(context).lower(irFile)
},
name = "Autobox", name = "Autobox",
description = "Autoboxing of primitive types", description = "Autoboxing of primitive types",
prerequisite = setOf(bridgesPhase, coroutinesPhase) prerequisite = setOf(bridgesPhase, coroutinesPhase)
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan 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.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable 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.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.SymbolTable 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.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import java.util.Collections.emptySet 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( internal fun konanUnitPhase(
name: String, name: String,
description: String, description: String,
@@ -128,8 +163,6 @@ internal val psiToIrPhase = konanUnitPhase(
irModule = module irModule = module
irModules = deserializer.modules irModules = deserializer.modules
ir.symbols = symbols ir.symbols = symbols
// validateIrModule(this, module)
}, },
name = "Psi2Ir", name = "Psi2Ir",
description = "Psi to IR conversion", description = "Psi to IR conversion",
@@ -169,12 +202,6 @@ internal val copyDefaultValuesToActualPhase = konanUnitPhase(
description = "Copy default values from expect to actual declarations" 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( internal val serializerPhase = konanUnitPhase(
op = { op = {
val declarationTable = KonanDeclarationTable(irModule!!.irBuiltins, DescriptorTable()) val declarationTable = KonanDeclarationTable(irModule!!.irBuiltins, DescriptorTable())
@@ -213,7 +240,6 @@ internal val allLoweringsPhase = namedIrModulePhase(
inlinePhase then inlinePhase then
lowerAfterInlinePhase then lowerAfterInlinePhase then
interopPart1Phase then interopPart1Phase then
patchDeclarationParents1Phase then
performByIrFile( performByIrFile(
name = "IrLowerByFile", name = "IrLowerByFile",
description = "IR Lowering by file", description = "IR Lowering by file",
@@ -242,9 +268,8 @@ internal val allLoweringsPhase = namedIrModulePhase(
bridgesPhase then bridgesPhase then
autoboxPhase then autoboxPhase then
returnsInsertionPhase returnsInsertionPhase
) then ),
checkDeclarationParentsPhase actions = setOf(defaultDumper, ::moduleValidationCallback)
// validateIrModulePhase // Temporarily disabled until moving to new IR finished.
) )
internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper( internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper(
@@ -313,7 +338,6 @@ val toplevelPhase: CompilerPhase<*, Unit, Unit> = namedUnitPhase(
destroySymbolTablePhase then destroySymbolTablePhase then
irGeneratorPluginsPhase then irGeneratorPluginsPhase then
copyDefaultValuesToActualPhase then copyDefaultValuesToActualPhase then
patchDeclarationParents0Phase then
serializerPhase then serializerPhase then
namedUnitPhase( namedUnitPhase(
name = "Backend", 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? { tailrec fun IrDeclaration.getContainingFile(): IrFile? {
val parent = this.parent val parent = this.parent