Objects (singletons) lowering.
This commit is contained in:
@@ -25,6 +25,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL")
|
||||
object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY")
|
||||
object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES")
|
||||
object FIELD_FOR_OBJECT_INSTANCE : IrDeclarationOriginImpl("FIELD_FOR_OBJECT_INSTANCE")
|
||||
}
|
||||
|
||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.backend.jvm
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
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.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
@@ -34,6 +33,7 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
InterfaceLowering(context.state).runOnFile(irFile)
|
||||
InterfaceDelegationLowering(context.state).runOnFile(irFile)
|
||||
EnumClassLowering(context).runOnFile(irFile)
|
||||
ObjectClassLowering(context).runOnFile(irFile)
|
||||
InitializersLowering().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 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.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
|
||||
@@ -137,7 +138,13 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
|
||||
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 {
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ class JvmPropertyDescriptorImpl(
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun createVal(
|
||||
fun createStaticVal(
|
||||
name: Name,
|
||||
type: KotlinType,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
|
||||
+25
-4
@@ -16,22 +16,24 @@
|
||||
|
||||
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.FileClassDescriptorImpl
|
||||
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.ir.SourceManager
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import java.util.*
|
||||
|
||||
class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
||||
private val enumEntryFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
||||
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
|
||||
|
||||
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||
enumEntryFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
||||
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
||||
createEnumEntryFieldDescriptor(enumEntryDescriptor)
|
||||
}
|
||||
|
||||
@@ -49,7 +51,7 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
||||
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
|
||||
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"}
|
||||
|
||||
return JvmPropertyDescriptorImpl.createVal(
|
||||
return JvmPropertyDescriptorImpl.createStaticVal(
|
||||
enumEntryDescriptor.name,
|
||||
enumClassDescriptor.defaultType,
|
||||
enumClassDescriptor,
|
||||
@@ -60,4 +62,23 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
|
||||
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 {
|
||||
return JvmPropertyDescriptorImpl.createVal(
|
||||
return JvmPropertyDescriptorImpl.createStaticVal(
|
||||
Name.identifier("\$VALUES"),
|
||||
valuesArrayType,
|
||||
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.IrExpression
|
||||
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.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -34,4 +35,9 @@ class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLowering
|
||||
val enumValueFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(expression.descriptor)
|
||||
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");
|
||||
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