diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstantObject.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstantObject.kt new file mode 100644 index 00000000000..68befcbfdf3 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstantObject.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.expressions + +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.types.IrType + +abstract class IrConstantValue : IrExpression() { + abstract fun contentEquals(other: IrConstantValue) : Boolean + abstract fun contentHashCode(): Int +} + +abstract class IrConstantPrimitive : IrConstantValue() { + abstract var value: IrConst<*> +} + +abstract class IrConstantObject : IrConstantValue() { + abstract val constructor: IrConstructorSymbol + abstract val valueArguments: List + abstract val typeArguments: List + abstract fun putArgument(index: Int, value: IrConstantValue) +} + +abstract class IrConstantArray : IrConstantValue() { + abstract val elements: List + abstract fun putElement(index: Int, value: IrConstantValue) +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstantObjectImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstantObjectImpl.kt new file mode 100644 index 00000000000..a4f132c0714 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstantObjectImpl.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.expressions.impl + +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.constructedClassType +import org.jetbrains.kotlin.ir.util.transformInPlace +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.utils.SmartList + +class IrConstantPrimitiveImpl( + override val startOffset: Int, + override val endOffset: Int, + override var value: IrConst<*>, +) : IrConstantPrimitive() { + override fun contentEquals(other: IrConstantValue) = + other is IrConstantPrimitive && + value.type == other.value.type && + value.kind == other.value.kind && + value.value == other.value + + override fun contentHashCode() = + (value.type.hashCode() * 31 + value.kind.hashCode()) * 31 + value.value.hashCode() + + override var type = value.type + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + value.accept(visitor, data) + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + value = value.transform(transformer, data) as IrConst<*> + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitConstantPrimitive(this, data) + } +} + +class IrConstantObjectImpl constructor( + override val startOffset: Int, + override val endOffset: Int, + override val constructor: IrConstructorSymbol, + initArguments: List, + override val typeArguments: List, + override var type: IrType = constructor.owner.constructedClassType, +) : IrConstantObject() { + override val valueArguments = SmartList(initArguments) + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitConstantObject(this, data) + } + + override fun putArgument(index: Int, value: IrConstantValue) { + valueArguments[index] = value + } + + override fun contentEquals(other: IrConstantValue): Boolean = + other is IrConstantObject && + other.type == type && + other.constructor == constructor && + valueArguments.size == other.valueArguments.size && + typeArguments.size == other.typeArguments.size && + valueArguments.indices.all { index -> valueArguments[index].contentEquals(other.valueArguments[index]) } && + typeArguments.indices.all { index -> typeArguments[index] == other.typeArguments[index] } + + + override fun contentHashCode(): Int { + var res = type.hashCode() * 31 + constructor.hashCode() + for (value in valueArguments) { + res = res * 31 + value.contentHashCode() + } + for (value in typeArguments) { + res = res * 31 + value.hashCode() + } + return res + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + valueArguments.forEach { value -> value.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + valueArguments.transformInPlace { it.transform(transformer, data) } + } +} + +class IrConstantArrayImpl( + override val startOffset: Int, + override val endOffset: Int, + override var type: IrType, + initElements: List, +) : IrConstantArray() { + override val elements = SmartList(initElements) + override fun putElement(index: Int, value: IrConstantValue) { + elements[index] = value + } + + override fun contentEquals(other: IrConstantValue): Boolean = + other is IrConstantArray && + other.type == type && + elements.size == other.elements.size && + elements.indices.all { elements[it].contentEquals(other.elements[it]) } + + override fun contentHashCode(): Int { + var res = type.hashCode() + for (value in elements) { + res = res * 31 + value.contentHashCode() + } + return res + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitConstantArray(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + elements.forEach { value -> value.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + elements.transformInPlace { value -> value.transform(transformer, data) } + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index 479a10e87ad..744f564acd1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -410,6 +410,28 @@ open class DeepCopyIrTreeWithSymbols( override fun visitConst(expression: IrConst): IrConst = expression.shallowCopy().copyAttributes(expression) + override fun visitConstantObject(expression: IrConstantObject): IrConstantValue = + IrConstantObjectImpl( + expression.startOffset, expression.endOffset, + symbolRemapper.getReferencedConstructor(expression.constructor), + expression.valueArguments.transform(), + expression.typeArguments.map { it.remapType() }, + expression.type.remapType() + ).copyAttributes(expression) + + override fun visitConstantPrimitive(expression: IrConstantPrimitive): IrConstantValue = + IrConstantPrimitiveImpl( + expression.startOffset, expression.endOffset, + expression.value.transform() + ).copyAttributes(expression) + + override fun visitConstantArray(expression: IrConstantArray): IrConstantValue = + IrConstantArrayImpl( + expression.startOffset, expression.endOffset, + expression.type.remapType(), + expression.elements.transform(), + ).copyAttributes(expression) + override fun visitVararg(expression: IrVararg): IrVararg = IrVarargImpl( expression.startOffset, expression.endOffset, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 6f4350e0b0d..5df52ff244a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -344,6 +344,22 @@ class DumpIrTreeVisitor( } } + override fun visitConstantArray(expression: IrConstantArray, data: String) { + expression.dumpLabeledElementWith(data) { + for ((i, value) in expression.elements.withIndex()) { + value.accept(this, i.toString()) + } + } + } + + override fun visitConstantObject(expression: IrConstantObject, data: String) { + expression.dumpLabeledElementWith(data) { + for ((index, argument) in expression.valueArguments.withIndex()) { + argument.accept(this, expression.constructor.owner.valueParameters[index].name.toString()) + } + } + } + private inline fun IrElement.dumpLabeledElementWith(label: String, body: () -> Unit) { printer.println(accept(elementRenderer, null).withLabel(label)) indented(body) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 159d736fe02..f18e521c4ee 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -727,6 +727,16 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false, privat override fun visitErrorCallExpression(expression: IrErrorCallExpression, data: Nothing?): String = "ERROR_CALL '${expression.description}' type=${expression.type.render()}" + override fun visitConstantArray(expression: IrConstantArray, data: Nothing?): String = + "CONSTANT_ARRAY type=${expression.type.render()}" + + override fun visitConstantObject(expression: IrConstantObject, data: Nothing?): String = + "CONSTANT_OBJECT type=${expression.type.render()} constructor=${expression.constructor.renderReference()}" + + override fun visitConstantPrimitive(expression: IrConstantPrimitive, data: Nothing?): String = + "CONSTANT_PRIMITIVE type=${expression.type.render()}" + + private val descriptorRendererForErrorDeclarations = DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt index 03ba316c0df..b843fe37ca4 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt @@ -81,6 +81,14 @@ interface IrElementTransformer : IrElementVisitor { override fun visitConst(expression: IrConst, data: D) = visitExpression(expression, data) override fun visitVararg(expression: IrVararg, data: D) = visitExpression(expression, data) + override fun visitConstantValue(expression: IrConstantValue, data: D) : IrConstantValue { + expression.transformChildren(this, data) + return expression + } + + override fun visitConstantObject(expression: IrConstantObject, data: D) = visitConstantValue(expression, data) + override fun visitConstantPrimitive(expression: IrConstantPrimitive, data: D) = visitConstantValue(expression, data) + override fun visitConstantArray(expression: IrConstantArray, data: D) = visitConstantValue(expression, data) override fun visitSpreadElement(spread: IrSpreadElement, data: D): IrSpreadElement { spread.transformChildren(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt index 1e0eaf13f05..81f6eaa6b54 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformerVoid.kt @@ -137,6 +137,22 @@ abstract class IrElementTransformerVoid : IrElementTransformer { open fun visitConst(expression: IrConst) = visitExpression(expression) final override fun visitConst(expression: IrConst, data: Nothing?) = visitConst(expression) + open fun visitConstantValue(expression: IrConstantValue) : IrConstantValue { + expression.transformChildren(this, null) + return expression + } + + final override fun visitConstantValue(expression: IrConstantValue, data: Nothing?) = visitConstantValue(expression) + + open fun visitConstantObject(expression: IrConstantObject) = visitConstantValue(expression) + final override fun visitConstantObject(expression: IrConstantObject, data: Nothing?) = visitConstantObject(expression) + + open fun visitConstantPrimitive(expression: IrConstantPrimitive) = visitConstantValue(expression) + final override fun visitConstantPrimitive(expression: IrConstantPrimitive, data: Nothing?) = visitConstantPrimitive(expression) + + open fun visitConstantArray(expression: IrConstantArray) = visitConstantValue(expression) + final override fun visitConstantArray(expression: IrConstantArray, data: Nothing?) = visitConstantArray(expression) + open fun visitVararg(expression: IrVararg) = visitExpression(expression) final override fun visitVararg(expression: IrVararg, data: Nothing?) = visitVararg(expression) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index b76ae7c4c9c..4309600ad83 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -53,6 +53,10 @@ interface IrElementVisitor { fun visitExpression(expression: IrExpression, data: D) = visitElement(expression, data) fun visitConst(expression: IrConst, data: D) = visitExpression(expression, data) + fun visitConstantValue(expression: IrConstantValue, data: D) = visitExpression(expression, data) + fun visitConstantObject(expression: IrConstantObject, data: D) = visitConstantValue(expression, data) + fun visitConstantPrimitive(expression: IrConstantPrimitive, data: D) = visitConstantValue(expression, data) + fun visitConstantArray(expression: IrConstantArray, data: D) = visitConstantValue(expression, data) fun visitVararg(expression: IrVararg, data: D) = visitExpression(expression, data) fun visitSpreadElement(spread: IrSpreadElement, data: D) = visitElement(spread, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt index 59cc860b1bb..aa1ed3a2058 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt @@ -107,6 +107,18 @@ interface IrElementVisitorVoid : IrElementVisitor { fun visitConst(expression: IrConst) = visitExpression(expression) override fun visitConst(expression: IrConst, data: Nothing?) = visitConst(expression) + fun visitConstantValue(expression: IrConstantValue) = visitExpression(expression) + override fun visitConstantValue(expression: IrConstantValue, data: Nothing?) = visitConstantValue(expression) + + fun visitConstantObject(expression: IrConstantObject) = visitConstantValue(expression) + override fun visitConstantObject(expression: IrConstantObject, data: Nothing?) = visitConstantObject(expression) + + fun visitConstantPrimitive(expression: IrConstantPrimitive) = visitConstantValue(expression) + override fun visitConstantPrimitive(expression: IrConstantPrimitive, data: Nothing?) = visitConstantPrimitive(expression) + + fun visitConstantArray(expression: IrConstantArray) = visitConstantValue(expression) + override fun visitConstantArray(expression: IrConstantArray, data: Nothing?) = visitConstantArray(expression) + fun visitVararg(expression: IrVararg) = visitExpression(expression) override fun visitVararg(expression: IrVararg, data: Nothing?) = visitVararg(expression) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt index d6ccfaca704..90a5b5d37b9 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractValueUsageTransformer.kt @@ -16,9 +16,13 @@ import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.isBoxedArray import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import java.lang.IllegalStateException /** @@ -269,6 +273,30 @@ internal abstract class AbstractValueUsageTransformer( return declaration } + override fun visitConstantArray(expression: IrConstantArray): IrConstantValue { + expression.transformChildrenVoid(this) + + val elementType = if (expression.type.isBoxedArray) + irBuiltIns.anyNType + else + irBuiltIns.primitiveArrayElementTypes[expression.type.getClass()?.symbol] + ?: throw IllegalStateException("Unexpected array type ${expression.type.render()}") + + expression.elements.forEachIndexed { index, it -> + expression.putElement(index, it.useAs(elementType) as IrConstantValue) + } + return expression + } + + override fun visitConstantObject(expression: IrConstantObject): IrConstantValue { + expression.transformChildrenVoid(this) + + expression.valueArguments.forEachIndexed { index, arg -> + expression.putArgument(index, arg.useAsArgument(expression.constructor.owner.valueParameters[index]) as IrConstantValue) + } + return expression + } + // TODO: IrStringConcatenation, IrEnumEntry? }