Turned on IR validation
This commit is contained in:
-8
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-30
@@ -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)
|
||||||
|
|||||||
+39
-15
@@ -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",
|
||||||
|
|||||||
-33
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user