[JS IR BE] Validate parents

This commit is contained in:
Svyatoslav Kuzmich
2018-11-20 16:16:43 +03:00
parent 39cdee8d6c
commit 59032c384e
15 changed files with 87 additions and 17 deletions
@@ -19,8 +19,7 @@ package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
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.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -85,3 +86,32 @@ class IrValidator(val context: CommonBackendContext, val config: IrValidatorConf
element.acceptChildrenVoid(this)
}
}
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?) {
checkParent(declaration, data)
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")
}
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.common.ir
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.descriptors.WrappedTypeParameterDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
@@ -44,6 +45,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import java.io.StringWriter
@@ -164,13 +166,15 @@ fun IrValueParameter.copyTo(
): IrValueParameter {
val descriptor = WrappedValueParameterDescriptor(symbol.descriptor.annotations, symbol.descriptor.source)
val symbol = IrValueParameterSymbolImpl(descriptor)
val defaultValueCopy = defaultValue?.deepCopyWithVariables()
defaultValueCopy?.patchDeclarationParents(irFunction)
return IrValueParameterImpl(
startOffset, endOffset, origin, symbol,
name, shift + index, type, varargElementType, isCrossinline, isNoinline
).also {
descriptor.bind(it)
it.parent = irFunction
it.defaultValue = defaultValue
it.defaultValue = defaultValueCopy
}
}
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -106,6 +107,7 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
}, irInt(0))
val expressionBody = valueParameter.defaultValue!!
expressionBody.patchDeclarationParents(newIrFunction)
expressionBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
@@ -126,6 +128,7 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
}
val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString())
temporaryVariable.parent = newIrFunction
params.add(temporaryVariable)
variables[valueParameter] = temporaryVariable
@@ -19,12 +19,16 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
@@ -55,6 +59,7 @@ class InitializersLowering(
val staticInitializerStatements = handleStatics(irClass)
if (clinitNeeded && staticInitializerStatements.isNotEmpty())
createStaticInitializationMethod(irClass, staticInitializerStatements)
irClass.patchDeclarationParents(irClass.parent)
}
fun handleNonStatics(irClass: IrClass) =
@@ -75,6 +75,7 @@ class InlineClassLowering(val context: BackendContext) {
typeHint = irClass.defaultType.toKotlinType(),
irType = irClass.defaultType
)
thisVar.parent = result
}
}
@@ -88,6 +89,13 @@ class InlineClassLowering(val context: BackendContext) {
return expression
}
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
declaration.transformChildrenVoid(this)
if (declaration.parent == irConstructor)
declaration.parent = result
return declaration
}
override fun visitReturn(expression: IrReturn): IrExpression {
expression.transformChildrenVoid()
if (expression.returnTargetSymbol == irConstructor.symbol) {
@@ -121,9 +129,7 @@ class InlineClassLowering(val context: BackendContext) {
function.body!!.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
declaration.transformChildrenVoid(this)
// TODO: Variable parents might not be initialized
if (declaration !is IrVariable && declaration.parent == function)
if (declaration.parent == function)
declaration.parent = staticMethod
return declaration
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -101,7 +102,7 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
delegatingConstructorCall.startOffset, delegatingConstructorCall.endOffset, outerThisValueParameter
)
}
blockBody.patchDeclarationParents(loweredConstructor)
loweredConstructor.body = blockBody
return loweredConstructor
}
@@ -111,6 +111,7 @@ class LateinitLowering(
val resultVar = scope.createTemporaryVariable(
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
)
resultVar.parent = getter
body.statements.add(resultVar)
val throwIfNull = irIfThenElse(
context.irBuiltIns.nothingType,
@@ -29,8 +29,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -215,7 +215,11 @@ open class LocalDeclarationsLowering(
rewriteDeclarations()
return collectRewrittenDeclarations()
val rewrittenDeclarations = collectRewrittenDeclarations()
rewrittenDeclarations.forEach {
it.patchDeclarationParents(memberDeclaration.parent)
}
return rewrittenDeclarations
}
private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> =
@@ -105,6 +105,7 @@ private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment, dependenc
val validateIr = {
val visitor = IrValidator(this, validatorConfig)
moduleFragment.acceptVoid(visitor)
moduleFragment.checkDeclarationParents()
}
validateIr()
ThrowableSuccessorsLowering(this).lower(moduleFragment)
@@ -144,7 +145,8 @@ private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment, dependenc
validateIr()
AutoboxingTransformer(this).lower(moduleFragment)
BlockDecomposerLowering(this).runOnFilesPostfix(moduleFragment)
// TODO: Fix BlockDecomposerLowering parents
moduleFragment.patchDeclarationParents()
ClassReferenceLowering(this).lower(moduleFragment)
PrimitiveCompanionLowering(this).lower(moduleFragment)
ConstLowering(this).lower(moduleFragment)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.getInlinedClass
import org.jetbrains.kotlin.ir.util.isInlined
import org.jetbrains.kotlin.ir.util.isNullable
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
// Copied and adapted from Kotlin/Native
@@ -24,6 +25,9 @@ import org.jetbrains.kotlin.ir.util.isNullable
class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsageTransformer(context.irBuiltIns), FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid()
// TODO: Track & insert parents for temporary variables
irFile.patchDeclarationParents()
}
override fun IrExpression.useAs(type: IrType): IrExpression {
@@ -101,6 +105,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
if (!actualType.isNullable())
return call(arg)
return JsIrBuilder.run {
// TODO: Set parent of local variables
val tmp = buildVar(actualType, parent = null, initializer = arg)
val nullCheck = buildIfElse(
type = resultType,
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -47,6 +48,7 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
}
private fun IrExpressionBody.toBlockBody(containingFunction: IrFunction): IrBlockBody {
expression.patchDeclarationParents(containingFunction)
val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType)
return IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
statements += returnStatement
@@ -63,7 +65,7 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
)
val newBody = toBlockBody(initFunction)
newBody.patchDeclarationParents(initFunction)
initFunction.body = newBody
lower(initFunction)
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import java.util.*
@@ -332,6 +333,9 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
for ((entry, instanceVar) in enumEntries.zip(entryInstances)) {
+irSetVar(instanceVar.symbol, entry.initializerExpression!!)
}
}.also {
// entry.initializerExpression can have local declarations
it.acceptVoid(PatchDeclarationParentsVisitor(irClass))
}
private fun createEntryInstancesInitializedVar(): IrVariable {
@@ -429,6 +433,8 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
copyParameterDeclarationsFrom(enumConstructor)
body = enumConstructor.body
loweredEnumConstructors[enumConstructor.symbol] = this
this.acceptVoid(PatchDeclarationParentsVisitor(enumClass))
}
}
@@ -11,9 +11,9 @@ import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBranchImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl
@@ -58,8 +58,9 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
override fun lower(irFile: IrFile) {
irFile.transformChildren(object : IrElementTransformer<IrDeclarationParent> {
override fun visitFunction(declaration: IrFunction, data: IrDeclarationParent): IrStatement {
return super.visitFunction(declaration, declaration)
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent): IrStatement {
val parent = (declaration as? IrDeclarationParent) ?: data
return super.visitDeclaration(declaration, parent)
}
override fun visitTry(aTry: IrTry, data: IrDeclarationParent): IrExpression {
@@ -258,8 +258,9 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
})
}
}
return coroutine.coroutineClass
val coroutineClass = coroutine.coroutineClass
coroutineClass.patchDeclarationParents(coroutineClass.parent)
return coroutineClass
}
private class BuiltCoroutine(