JVM_IR. Support compile time constants

This commit is contained in:
Georgy Bronnikov
2018-09-18 14:49:43 +03:00
parent 985934a40a
commit 055215c54f
39 changed files with 35 additions and 42 deletions
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
@@ -22,6 +24,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass { class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(this) irFile.transformChildrenVoid(this)
} }
@@ -36,6 +39,12 @@ class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrEle
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
val irProperty = (expression.symbol.owner as? IrSimpleFunction)?.correspondingProperty ?: return super.visitCall(expression)
if (irProperty.isConst) {
(irProperty.backingField?.initializer?.expression as? IrConst<*>)?.let { return it }
}
val descriptor = expression.descriptor as? PropertyAccessorDescriptor ?: return super.visitCall(expression) val descriptor = expression.descriptor as? PropertyAccessorDescriptor ?: return super.visitCall(expression)
val property = descriptor.correspondingProperty val property = descriptor.correspondingProperty
@@ -65,7 +74,7 @@ class ConstAndJvmFieldPropertiesLowering(val context: JvmBackendContext) : IrEle
) )
} }
private fun substituteGetter(descriptor: PropertyGetterDescriptor, expression: IrCall): IrGetFieldImpl { private fun substituteGetter(descriptor: PropertyGetterDescriptor, expression: IrCall): IrExpression {
return IrGetFieldImpl( return IrGetFieldImpl(
expression.startOffset, expression.startOffset,
expression.endOffset, expression.endOffset,
@@ -79,14 +79,21 @@ class DeclarationStubGenerator(
throw AssertionError("Unexpected member descriptor: $descriptor") throw AssertionError("Unexpected member descriptor: $descriptor")
} }
internal fun generatePropertyStub(descriptor: PropertyDescriptor, bindingContext: BindingContext? = null): IrProperty = internal fun generatePropertyStub(
descriptor: PropertyDescriptor,
bindingContext: BindingContext? = null
): IrProperty =
IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty -> IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty ->
if (descriptor.hasBackingField(bindingContext)) { if (descriptor.hasBackingField(bindingContext)) {
irProperty.backingField = generateFieldStub(descriptor) irProperty.backingField = generateFieldStub(descriptor)
} }
irProperty.getter = descriptor.getter?.let { generateFunctionStub(it) } irProperty.getter = descriptor.getter?.let { generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
irProperty.setter = descriptor.setter?.let { generateFunctionStub(it) } correspondingProperty = irProperty
}
irProperty.setter = descriptor.setter?.let { generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingProperty = irProperty
}
} }
private fun generateFieldStub(descriptor: PropertyDescriptor): IrField { private fun generateFieldStub(descriptor: PropertyDescriptor): IrField {
@@ -117,12 +124,19 @@ class DeclarationStubGenerator(
} }
} }
fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction { fun generateFunctionStub(descriptor: FunctionDescriptor, createPropertyIfNeeded: Boolean = true): IrSimpleFunction {
val referenced = symbolTable.referenceSimpleFunction(descriptor) val referenced = symbolTable.referenceSimpleFunction(descriptor)
if (referenced.isBound) { if (referenced.isBound) {
return referenced.owner return referenced.owner
} }
if (createPropertyIfNeeded && descriptor is PropertyGetterDescriptor) {
return generatePropertyStub(descriptor.correspondingProperty).getter!!
}
if (createPropertyIfNeeded && descriptor is PropertySetterDescriptor) {
return generatePropertyStub(descriptor.correspondingProperty).setter!!
}
val origin = val origin =
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
IrDeclarationOrigin.FAKE_OVERRIDE IrDeclarationOrigin.FAKE_OVERRIDE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun box(): String { fun box(): String {
val c1: Char = Char.MIN_VALUE val c1: Char = Char.MIN_VALUE
val c2 = c1 - 1 val c2 = c1 - 1
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
fun box(): String { fun box(): String {
val i1: Int = Int.MAX_VALUE val i1: Int = Int.MAX_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
fun box(): String { fun box(): String {
val a: Long = 2147483647 + 1 val a: Long = 2147483647 + 1
+1
View File
@@ -1,3 +1,4 @@
// !LANGUAGE: -NoConstantValueAttributeForNonConstVals
// IGNORE_BACKEND: JVM_IR // IGNORE_BACKEND: JVM_IR
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: NATIVE // IGNORE_BACKEND: NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE // IGNORE_BACKEND: JS, NATIVE
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
fun test(i: Int): Int { fun test(i: Int): Int {
return i return i
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
fun test(i: Int): Int { fun test(i: Int): Int {
return i return i
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
val MAX_LONG = "9223372036854775807" val MAX_LONG = "9223372036854775807"
val PREFIX = "max = " val PREFIX = "max = "
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") } fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") } fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") } fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") } fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") } fun <T> assertEquals(a: T, b: T) { if (a != b) throw AssertionError("$a != $b") }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS // IGNORE_BACKEND: JS
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS // IGNORE_BACKEND: JS
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not // TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS // IGNORE_BACKEND: JS
@@ -1,5 +1,4 @@
// TODO: muted automatically, investigate should it be ran for JVM_IR or not // TODO: muted automatically, investigate should it be ran for JVM_IR or not
// IGNORE_BACKEND: JVM_IR
// Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT! // Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT!
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -1,5 +1,4 @@
// WITH_RUNTIME // WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
const val M = Char.MIN_VALUE const val M = Char.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Char.MIN_VALUE const val M = Char.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Int.MIN_VALUE const val M = Int.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Int.MIN_VALUE const val M = Int.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Long.MIN_VALUE const val M = Long.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Long.MIN_VALUE const val M = Long.MIN_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
const val M = Char.MAX_VALUE const val M = Char.MAX_VALUE
fun box(): String { fun box(): String {
@@ -11,4 +10,4 @@ fun box(): String {
} }
if (count != 1) throw AssertionError("Should be executed once") if (count != 1) throw AssertionError("Should be executed once")
return "OK" return "OK"
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Char.MAX_VALUE const val M = Char.MAX_VALUE
@@ -13,4 +12,4 @@ fun box(): String {
} }
if (count != 1) throw AssertionError("Should be executed once") if (count != 1) throw AssertionError("Should be executed once")
return "OK" return "OK"
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
const val M = Int.MAX_VALUE const val M = Int.MAX_VALUE
fun box(): String { fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Int.MAX_VALUE const val M = Int.MAX_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
const val M = Long.MAX_VALUE const val M = Long.MAX_VALUE
fun box(): String { fun box(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Long.MAX_VALUE const val M = Long.MAX_VALUE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
const val M = Int.MIN_VALUE const val M = Int.MIN_VALUE
@@ -1,5 +1,4 @@
// TODO: muted automatically, investigate should it be ran for JVM_IR or not // TODO: muted automatically, investigate should it be ran for JVM_IR or not
// IGNORE_BACKEND: JVM_IR
// Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT! // Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT!
// WITH_RUNTIME // WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// FILE: 1.kt // FILE: 1.kt
package test package test
@@ -221,24 +221,28 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ
EXPRESSION_BODY EXPRESSION_BODY
CONST Int type=kotlin.Int value=2147483647 CONST Int type=kotlin.Int value=2147483647
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-MAX_VALUE> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags: FUN IR_EXTERNAL_DECLARATION_STUB name:<get-MAX_VALUE> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags:
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MAX_VALUE visibility:public modality:FINAL flags:const,val
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags: $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags:
PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE visibility:public modality:FINAL flags:const,val PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE visibility:public modality:FINAL flags:const,val
FIELD IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE type:kotlin.Int visibility:public flags:final FIELD IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE type:kotlin.Int visibility:public flags:final
EXPRESSION_BODY EXPRESSION_BODY
CONST Int type=kotlin.Int value=-2147483648 CONST Int type=kotlin.Int value=-2147483648
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-MIN_VALUE> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags: FUN IR_EXTERNAL_DECLARATION_STUB name:<get-MIN_VALUE> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags:
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE visibility:public modality:FINAL flags:const,val
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags: $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags:
PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL flags:const,val PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL flags:const,val
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public flags:final FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public flags:final
EXPRESSION_BODY EXPRESSION_BODY
CONST Int type=kotlin.Int value=32 CONST Int type=kotlin.Int value=32
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BITS> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags: FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BITS> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags:
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL flags:const,val
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags: $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags:
PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES visibility:public modality:FINAL flags:const,val PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES visibility:public modality:FINAL flags:const,val
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public flags:final FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public flags:final
EXPRESSION_BODY EXPRESSION_BODY
CONST Int type=kotlin.Int value=4 CONST Int type=kotlin.Int value=4
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BYTES> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags: FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BYTES> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int flags:
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES visibility:public modality:FINAL flags:const,val
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags: $this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion flags:
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags: FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
overridden: overridden: