IR refactor patch / validate declaration parent
This commit is contained in:
@@ -18,17 +18,20 @@ package org.jetbrains.kotlin.backend.common
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.DeclarationParentsVisitor
|
||||||
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
fun validateIrFile(context: CommonBackendContext, irFile: IrFile) {
|
fun validateIrFile(context: CommonBackendContext, irFile: IrFile) {
|
||||||
val visitor = IrValidator(context, IrValidatorConfig(abortOnError = false, ensureAllNodesAreDifferent = false))
|
val visitor = IrValidator(context, IrValidatorConfig(abortOnError = false, ensureAllNodesAreDifferent = false))
|
||||||
irFile.acceptVoid(visitor)
|
irFile.acceptVoid(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
fun validateIrModule(context: CommonBackendContext, irModule: IrModuleFragment) {
|
fun validateIrModule(context: CommonBackendContext, irModule: IrModuleFragment) {
|
||||||
val visitor = IrValidator(
|
val visitor = IrValidator(
|
||||||
context,
|
context,
|
||||||
@@ -92,31 +95,50 @@ class IrValidator(val context: CommonBackendContext, val config: IrValidatorConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrModuleFragment.checkDeclarationParents() {
|
fun IrElement.checkDeclarationParents() {
|
||||||
this.accept(CheckDeclarationParentsVisitor, null)
|
val checker = CheckDeclarationParentsVisitor()
|
||||||
}
|
acceptVoid(checker)
|
||||||
|
if (checker.errors.isNotEmpty()) {
|
||||||
object CheckDeclarationParentsVisitor : IrElementVisitor<Unit, IrDeclarationParent?> {
|
val expectedParents = LinkedHashSet<IrDeclarationParent>()
|
||||||
|
throw AssertionError(
|
||||||
override fun visitElement(element: IrElement, data: IrDeclarationParent?) {
|
buildString {
|
||||||
element.acceptChildren(this, element as? IrDeclarationParent ?: data)
|
append("Declarations with wrong parent: ")
|
||||||
}
|
append(checker.errors.size)
|
||||||
|
append("\n")
|
||||||
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclarationParent?) {
|
checker.errors.forEach {
|
||||||
checkParent(declaration, data)
|
append("declaration: ")
|
||||||
super.visitDeclaration(declaration, data)
|
append(it.declaration.render())
|
||||||
}
|
append("\n\t")
|
||||||
|
append(it.declaration)
|
||||||
private fun checkParent(declaration: IrDeclaration, expectedParent: IrDeclarationParent?) {
|
append("\nexpectedParent: ")
|
||||||
val parent = try {
|
append(it.expectedParent.render())
|
||||||
declaration.parent
|
append("\nactualParent: ")
|
||||||
} catch (e: Throwable) {
|
append(it.actualParent?.render())
|
||||||
error("$declaration for ${declaration.render()} has no parent")
|
append("\n")
|
||||||
}
|
expectedParents.add(it.expectedParent)
|
||||||
|
}
|
||||||
if (parent != expectedParent) {
|
append("\nExpected parents:\n")
|
||||||
error("$declaration for ${declaration.render()} has unexpected parent $parent")
|
expectedParents.forEach {
|
||||||
}
|
append(it.dump())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CheckDeclarationParentsVisitor : DeclarationParentsVisitor() {
|
||||||
|
class Error(val declaration: IrDeclaration, val expectedParent: IrDeclarationParent, val actualParent: IrDeclarationParent?)
|
||||||
|
|
||||||
|
val errors = ArrayList<Error>()
|
||||||
|
|
||||||
|
override fun handleParent(declaration: IrDeclaration, parent: IrDeclarationParent) {
|
||||||
|
try {
|
||||||
|
val actualParent = declaration.parent
|
||||||
|
if (actualParent != parent) {
|
||||||
|
errors.add(Error(declaration, parent, actualParent))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
errors.add(Error(declaration, parent, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+3
-6
@@ -5,10 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.phaser
|
package org.jetbrains.kotlin.backend.common.phaser
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CheckDeclarationParentsVisitor
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrValidator
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrValidatorConfig
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
@@ -60,7 +57,7 @@ fun <Data, Context> makeVerifyAction(verifier: (Context, Data) -> Unit): Action<
|
|||||||
fun dumpIrElement(actionState: ActionState, data: IrElement, @Suppress("UNUSED_PARAMETER") context: Any?): String {
|
fun dumpIrElement(actionState: ActionState, data: IrElement, @Suppress("UNUSED_PARAMETER") context: Any?): String {
|
||||||
val beforeOrAfterStr = actionState.beforeOrAfter.name.toLowerCaseAsciiOnly()
|
val beforeOrAfterStr = actionState.beforeOrAfter.name.toLowerCaseAsciiOnly()
|
||||||
|
|
||||||
var dumpText: String = ""
|
var dumpText = ""
|
||||||
val elementName: String
|
val elementName: String
|
||||||
|
|
||||||
val dumpStrategy = System.getProperty("org.jetbrains.kotlin.compiler.ir.dump.strategy")
|
val dumpStrategy = System.getProperty("org.jetbrains.kotlin.compiler.ir.dump.strategy")
|
||||||
@@ -143,7 +140,7 @@ fun <Fragment : IrElement> validationCallback(context: CommonBackendContext, fra
|
|||||||
checkProperties = checkProperties,
|
checkProperties = checkProperties,
|
||||||
)
|
)
|
||||||
fragment.accept(IrValidator(context, validatorConfig), null)
|
fragment.accept(IrValidator(context, validatorConfig), null)
|
||||||
fragment.accept(CheckDeclarationParentsVisitor, null)
|
fragment.checkDeclarationParents()
|
||||||
}
|
}
|
||||||
|
|
||||||
val validationAction = makeVerifyAction(::validationCallback)
|
val validationAction = makeVerifyAction(::validationCallback)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.jvm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.checkDeclarationParents
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
import org.jetbrains.kotlin.backend.common.lower.loops.forLoopsPhase
|
||||||
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
import org.jetbrains.kotlin.backend.common.lower.optimizations.foldConstantLoweringPhase
|
||||||
@@ -19,7 +20,9 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
|||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.PatchDeclarationParentsVisitor
|
||||||
|
import org.jetbrains.kotlin.ir.util.isAnonymousObject
|
||||||
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
@@ -28,6 +31,7 @@ import org.jetbrains.kotlin.name.NameUtils
|
|||||||
|
|
||||||
private var patchParentPhases = 0
|
private var patchParentPhases = 0
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
private fun makePatchParentsPhase(): NamedCompilerPhase<CommonBackendContext, IrFile> {
|
private fun makePatchParentsPhase(): NamedCompilerPhase<CommonBackendContext, IrFile> {
|
||||||
val number = patchParentPhases++
|
val number = patchParentPhases++
|
||||||
return makeIrFilePhase(
|
return makeIrFilePhase(
|
||||||
@@ -39,6 +43,7 @@ private fun makePatchParentsPhase(): NamedCompilerPhase<CommonBackendContext, Ir
|
|||||||
|
|
||||||
private var checkParentPhases = 0
|
private var checkParentPhases = 0
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
private fun makeCheckParentsPhase(): NamedCompilerPhase<CommonBackendContext, IrFile> {
|
private fun makeCheckParentsPhase(): NamedCompilerPhase<CommonBackendContext, IrFile> {
|
||||||
val number = checkParentPhases++
|
val number = checkParentPhases++
|
||||||
return makeIrFilePhase(
|
return makeIrFilePhase(
|
||||||
@@ -56,34 +61,7 @@ private class PatchDeclarationParents : FileLoweringPass {
|
|||||||
|
|
||||||
private class CheckDeclarationParents : FileLoweringPass {
|
private class CheckDeclarationParents : FileLoweringPass {
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val checker = CheckDeclarationParentsVisitor()
|
irFile.checkDeclarationParents()
|
||||||
irFile.acceptVoid(checker)
|
|
||||||
if (checker.errors.isNotEmpty()) {
|
|
||||||
val expectedParents = LinkedHashSet<IrDeclarationParent>()
|
|
||||||
throw AssertionError(
|
|
||||||
buildString {
|
|
||||||
append("Declarations with wrong parent: ")
|
|
||||||
append(checker.errors.size)
|
|
||||||
append("\n")
|
|
||||||
checker.errors.forEach {
|
|
||||||
append("declaration: ")
|
|
||||||
append(it.declaration.render())
|
|
||||||
append("\n\t")
|
|
||||||
append(it.declaration)
|
|
||||||
append("\nexpectedParent: ")
|
|
||||||
append(it.expectedParent.render())
|
|
||||||
append("\nactualParent: ")
|
|
||||||
append(it.actualParent?.render())
|
|
||||||
append("\n")
|
|
||||||
expectedParents.add(it.expectedParent)
|
|
||||||
}
|
|
||||||
append("\nExpected parents:\n")
|
|
||||||
expectedParents.forEach {
|
|
||||||
append(it.dump())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
|||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
fun <T : IrElement> T.patchDeclarationParents(initialParent: IrDeclarationParent? = null) =
|
fun <T : IrElement> T.patchDeclarationParents(initialParent: IrDeclarationParent? = null) =
|
||||||
apply {
|
apply {
|
||||||
@@ -19,13 +18,8 @@ fun <T : IrElement> T.patchDeclarationParents(initialParent: IrDeclarationParent
|
|||||||
acceptVoid(visitor)
|
acceptVoid(visitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
class PatchDeclarationParentsVisitor() : IrElementVisitorVoid {
|
abstract class DeclarationParentsVisitor : IrElementVisitorVoid {
|
||||||
|
protected val declarationParentsStack = ArrayDeque<IrDeclarationParent>()
|
||||||
constructor(containingDeclaration: IrDeclarationParent) : this() {
|
|
||||||
declarationParentsStack.push(containingDeclaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val declarationParentsStack = ArrayDeque<IrDeclarationParent>()
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
@@ -38,7 +32,7 @@ class PatchDeclarationParentsVisitor() : IrElementVisitorVoid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclarationBase) {
|
override fun visitDeclaration(declaration: IrDeclarationBase) {
|
||||||
patchParent(declaration)
|
handleParent(declaration, declarationParentsStack.peekFirst())
|
||||||
|
|
||||||
if (declaration is IrDeclarationParent) {
|
if (declaration is IrDeclarationParent) {
|
||||||
declarationParentsStack.push(declaration)
|
declarationParentsStack.push(declaration)
|
||||||
@@ -51,58 +45,16 @@ class PatchDeclarationParentsVisitor() : IrElementVisitorVoid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun patchParent(declaration: IrDeclaration) {
|
protected abstract fun handleParent(declaration: IrDeclaration, parent: IrDeclarationParent)
|
||||||
declaration.parent = declarationParentsStack.peekFirst()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PatchDeclarationParentsVisitor() : DeclarationParentsVisitor() {
|
||||||
class CheckDeclarationParentsVisitor() : IrElementVisitorVoid {
|
|
||||||
|
|
||||||
constructor(containingDeclaration: IrDeclarationParent) : this() {
|
constructor(containingDeclaration: IrDeclarationParent) : this() {
|
||||||
declarationParentsStack.push(containingDeclaration)
|
declarationParentsStack.push(containingDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val declarationParentsStack = ArrayDeque<IrDeclarationParent>()
|
override fun handleParent(declaration: IrDeclaration, parent: IrDeclarationParent) {
|
||||||
|
declaration.parent = parent
|
||||||
class Data(val declaration: IrDeclaration, val expectedParent: IrDeclarationParent, val actualParent: IrDeclarationParent?)
|
|
||||||
|
|
||||||
val errors = ArrayList<Data>()
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
element.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitPackageFragment(declaration: IrPackageFragment) {
|
|
||||||
declarationParentsStack.push(declaration)
|
|
||||||
super.visitPackageFragment(declaration)
|
|
||||||
declarationParentsStack.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclarationBase) {
|
|
||||||
checkParent(declaration)
|
|
||||||
|
|
||||||
if (declaration is IrDeclarationParent) {
|
|
||||||
declarationParentsStack.push(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.visitDeclaration(declaration)
|
|
||||||
|
|
||||||
if (declaration is IrDeclarationParent) {
|
|
||||||
declarationParentsStack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkParent(declaration: IrDeclaration) {
|
|
||||||
val expectedParent = declarationParentsStack.peekFirst()
|
|
||||||
try {
|
|
||||||
val actualParent = declaration.parent
|
|
||||||
if (actualParent != expectedParent) {
|
|
||||||
errors.add(Data(declaration, expectedParent, actualParent))
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
errors.add(Data(declaration, expectedParent, null))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user