Objects (singletons) lowering.
This commit is contained in:
@@ -25,6 +25,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
|||||||
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL")
|
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL")
|
||||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||||
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
||||||
|
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.jvm
|
|||||||
import org.jetbrains.kotlin.backend.jvm.lower.*
|
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
@@ -34,6 +33,7 @@ class JvmLower(val context: JvmBackendContext) {
|
|||||||
InterfaceLowering(context.state).runOnFile(irFile)
|
InterfaceLowering(context.state).runOnFile(irFile)
|
||||||
InterfaceDelegationLowering(context.state).runOnFile(irFile)
|
InterfaceDelegationLowering(context.state).runOnFile(irFile)
|
||||||
EnumClassLowering(context).runOnFile(irFile)
|
EnumClassLowering(context).runOnFile(irFile)
|
||||||
|
ObjectClassLowering(context).runOnFile(irFile)
|
||||||
InitializersLowering().runOnFile(irFile)
|
InitializersLowering().runOnFile(irFile)
|
||||||
SingletonReferencesLowering(context).runOnFile(irFile)
|
SingletonReferencesLowering(context).runOnFile(irFile)
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptor
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
||||||
@@ -137,7 +138,13 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
|||||||
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags.or(calcModalityFlag())
|
flags = flags.or(calcModalityFlag())
|
||||||
|
|
||||||
|
if (this is JvmSpecialDescriptor) {
|
||||||
|
flags = flags or extraFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MemberDescriptor.calcModalityFlag(): Int {
|
private fun MemberDescriptor.calcModalityFlag(): Int {
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ class JvmPropertyDescriptorImpl(
|
|||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createVal(
|
fun createStaticVal(
|
||||||
name: Name,
|
name: Name,
|
||||||
type: KotlinType,
|
type: KotlinType,
|
||||||
containingDeclaration: DeclarationDescriptor,
|
containingDeclaration: DeclarationDescriptor,
|
||||||
|
|||||||
+25
-4
@@ -16,22 +16,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.descriptors
|
package org.jetbrains.kotlin.backend.jvm.descriptors
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
|
||||||
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptorImpl
|
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.ir.SourceManager
|
import org.jetbrains.kotlin.ir.SourceManager
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
||||||
private val enumEntryFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
||||||
|
|
||||||
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||||
enumEntryFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
||||||
createEnumEntryFieldDescriptor(enumEntryDescriptor)
|
createEnumEntryFieldDescriptor(enumEntryDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
|||||||
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
|
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
|
||||||
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"}
|
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"}
|
||||||
|
|
||||||
return JvmPropertyDescriptorImpl.createVal(
|
return JvmPropertyDescriptorImpl.createStaticVal(
|
||||||
enumEntryDescriptor.name,
|
enumEntryDescriptor.name,
|
||||||
enumClassDescriptor.defaultType,
|
enumClassDescriptor.defaultType,
|
||||||
enumClassDescriptor,
|
enumClassDescriptor,
|
||||||
@@ -60,4 +62,23 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
|||||||
enumEntryDescriptor.source
|
enumEntryDescriptor.source
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||||
|
singletonFieldDescriptors.getOrPut(objectDescriptor) {
|
||||||
|
createObjectInstanceFieldDescriptor(objectDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor {
|
||||||
|
assert(objectDescriptor.kind == ClassKind.OBJECT) { "Should be an object: $objectDescriptor" }
|
||||||
|
|
||||||
|
val instanceFieldDescriptor = PropertyDescriptorImpl.create(
|
||||||
|
objectDescriptor,
|
||||||
|
Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false,
|
||||||
|
Name.identifier("INSTANCE"),
|
||||||
|
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, false, false
|
||||||
|
)
|
||||||
|
instanceFieldDescriptor.setType(objectDescriptor.defaultType, listOf(), null as ReceiverParameterDescriptor?, null as ReceiverParameterDescriptor?)
|
||||||
|
|
||||||
|
return instanceFieldDescriptor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -246,7 +246,7 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
})
|
})
|
||||||
|
|
||||||
private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl {
|
private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl {
|
||||||
return JvmPropertyDescriptorImpl.createVal(
|
return JvmPropertyDescriptorImpl.createStaticVal(
|
||||||
Name.identifier("\$VALUES"),
|
Name.identifier("\$VALUES"),
|
||||||
valuesArrayType,
|
valuesArrayType,
|
||||||
irClass.descriptor,
|
irClass.descriptor,
|
||||||
|
|||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||||
|
|
||||||
|
class ObjectClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||||
|
override fun lower(irClass: IrClass) {
|
||||||
|
if (irClass.descriptor.kind != ClassKind.OBJECT) return
|
||||||
|
|
||||||
|
val instanceFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForObjectInstance(irClass.descriptor)
|
||||||
|
|
||||||
|
val constructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?:
|
||||||
|
throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}")
|
||||||
|
val instanceInitializer = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, constructor)
|
||||||
|
|
||||||
|
val instanceField = IrFieldImpl(
|
||||||
|
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE,
|
||||||
|
instanceFieldDescriptor,
|
||||||
|
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, instanceInitializer)
|
||||||
|
)
|
||||||
|
|
||||||
|
irClass.declarations.add(instanceField)
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrGetObjectValue
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -34,4 +35,9 @@ class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLowering
|
|||||||
val enumValueFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(expression.descriptor)
|
val enumValueFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(expression.descriptor)
|
||||||
return IrGetFieldImpl(expression.startOffset, expression.endOffset, enumValueFieldDescriptor)
|
return IrGetFieldImpl(expression.startOffset, expression.endOffset, enumValueFieldDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||||
|
val instanceFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForObjectInstance(expression.descriptor)
|
||||||
|
return IrGetFieldImpl(expression.startOffset, expression.endOffset, instanceFieldDescriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
object Test {
|
||||||
|
val ok = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String =
|
||||||
|
Test.ok
|
||||||
@@ -52,4 +52,10 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/fileClassInitializers.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/fileClassInitializers.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectClass.kt")
|
||||||
|
public void testObjectClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/objectClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user