Introduce new ir nodes for constant values
This commit is contained in:
@@ -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<IrConstantValue>
|
||||
abstract val typeArguments: List<IrType>
|
||||
abstract fun putArgument(index: Int, value: IrConstantValue)
|
||||
}
|
||||
|
||||
abstract class IrConstantArray : IrConstantValue() {
|
||||
abstract val elements: List<IrConstantValue>
|
||||
abstract fun putElement(index: Int, value: IrConstantValue)
|
||||
}
|
||||
+131
@@ -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 <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
value.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
value = value.transform(transformer, data) as IrConst<*>
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, 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<IrConstantValue>,
|
||||
override val typeArguments: List<IrType>,
|
||||
override var type: IrType = constructor.owner.constructedClassType,
|
||||
) : IrConstantObject() {
|
||||
override val valueArguments = SmartList(initArguments)
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, 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 <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
valueArguments.forEach { value -> value.accept(visitor, data) }
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
valueArguments.transformInPlace { it.transform(transformer, data) }
|
||||
}
|
||||
}
|
||||
|
||||
class IrConstantArrayImpl(
|
||||
override val startOffset: Int,
|
||||
override val endOffset: Int,
|
||||
override var type: IrType,
|
||||
initElements: List<IrConstantValue>,
|
||||
) : 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 <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
return visitor.visitConstantArray(this, data)
|
||||
}
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
elements.forEach { value -> value.accept(visitor, data) }
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
elements.transformInPlace { value -> value.transform(transformer, data) }
|
||||
}
|
||||
}
|
||||
@@ -410,6 +410,28 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
override fun <T> visitConst(expression: IrConst<T>): IrConst<T> =
|
||||
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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,14 @@ interface IrElementTransformer<in D> : IrElementVisitor<IrElement, D> {
|
||||
|
||||
override fun <T> visitConst(expression: IrConst<T>, 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)
|
||||
|
||||
@@ -137,6 +137,22 @@ abstract class IrElementTransformerVoid : IrElementTransformer<Nothing?> {
|
||||
open fun <T> visitConst(expression: IrConst<T>) = visitExpression(expression)
|
||||
final override fun <T> visitConst(expression: IrConst<T>, 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)
|
||||
|
||||
|
||||
@@ -53,6 +53,10 @@ interface IrElementVisitor<out R, in D> {
|
||||
|
||||
fun visitExpression(expression: IrExpression, data: D) = visitElement(expression, data)
|
||||
fun <T> visitConst(expression: IrConst<T>, 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)
|
||||
|
||||
|
||||
@@ -107,6 +107,18 @@ interface IrElementVisitorVoid : IrElementVisitor<Unit, Nothing?> {
|
||||
fun <T> visitConst(expression: IrConst<T>) = visitExpression(expression)
|
||||
override fun <T> visitConst(expression: IrConst<T>, 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)
|
||||
|
||||
|
||||
+28
@@ -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?
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user