Enum classes lowering.
This commit is contained in:
@@ -1246,7 +1246,8 @@ public class KotlinTypeMapper {
|
||||
}
|
||||
|
||||
ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
|
||||
if (descriptor.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
||||
(containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY)) {
|
||||
writeParameter(
|
||||
sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
|
||||
writeParameter(
|
||||
|
||||
@@ -23,8 +23,11 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER")
|
||||
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")
|
||||
}
|
||||
|
||||
interface JvmLoweredStatementOrigin : IrStatementOrigin {
|
||||
object DEFAULT_IMPLS_DELEGATION : IrStatementOrigin.IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION")
|
||||
|
||||
}
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.JvmFileClassProvider
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.SpecialDescriptorsFactory
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
|
||||
class JvmBackendContext(
|
||||
val state: GenerationState,
|
||||
val jvmFileClassProvider: JvmFileClassProvider,
|
||||
val psiSourceManager: PsiSourceManager,
|
||||
val irBuiltIns: IrBuiltIns
|
||||
)
|
||||
) {
|
||||
val builtIns = state.module.builtIns
|
||||
val specialDescriptorsFactory = SpecialDescriptorsFactory(psiSourceManager)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.JvmFileClassProvider
|
||||
import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
|
||||
object JvmBackendFacade {
|
||||
fun compileCorrectFiles(state: GenerationState, errorHandler: CompilationErrorHandler) {
|
||||
@@ -38,12 +35,11 @@ object JvmBackendFacade {
|
||||
|
||||
val psi2ir = Psi2IrTranslator()
|
||||
val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext)
|
||||
val jvmBackendContext = createJvmBackendContext(psi2ir, state, psi2irContext.irBuiltIns)
|
||||
|
||||
val jvmBackend = JvmBackend(jvmBackendContext)
|
||||
|
||||
val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files)
|
||||
|
||||
val jvmBackendContext = JvmBackendContext(state, psi2irContext.sourceManager, psi2irContext.irBuiltIns)
|
||||
val jvmBackend = JvmBackend(jvmBackendContext)
|
||||
|
||||
for (irFile in irModuleFragment.files) {
|
||||
try {
|
||||
jvmBackend.generateFile(irFile)
|
||||
@@ -55,12 +51,4 @@ object JvmBackendFacade {
|
||||
}
|
||||
}
|
||||
|
||||
fun createJvmBackendContext(psi2ir: Psi2IrTranslator, state: GenerationState, irBuiltIns: IrBuiltIns): JvmBackendContext {
|
||||
val jvmFileClassProvider = JvmFileClassProvider()
|
||||
psi2ir.add(jvmFileClassProvider)
|
||||
|
||||
val jvmBackendContext = JvmBackendContext(state, jvmFileClassProvider, irBuiltIns)
|
||||
|
||||
return jvmBackendContext
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,38 +17,62 @@
|
||||
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
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
class JvmLower(val context: JvmBackendContext) {
|
||||
fun lower(irFile: IrFile) {
|
||||
FileClassLowering(context.jvmFileClassProvider).lower(irFile)
|
||||
// TODO run lowering passes as callbacks in bottom-up visitor
|
||||
FileClassLowering(context).lower(irFile)
|
||||
PropertiesLowering().lower(irFile)
|
||||
InitializersLowering().runOnNormalizedFile(irFile)
|
||||
InterfaceLowering(context.state).runOnNormalizedFile(irFile)
|
||||
InterfaceDelegationLowering(context.state).runOnNormalizedFile(irFile)
|
||||
InterfaceLowering(context.state).runOnFile(irFile)
|
||||
InterfaceDelegationLowering(context.state).runOnFile(irFile)
|
||||
EnumClassLowering(context).runOnFile(irFile)
|
||||
InitializersLowering().runOnFile(irFile)
|
||||
SingletonReferencesLowering(context).runOnFile(irFile)
|
||||
}
|
||||
}
|
||||
|
||||
interface FileLoweringPass {
|
||||
fun lower(irFile: IrFile
|
||||
)
|
||||
fun lower(irFile: IrFile)
|
||||
}
|
||||
|
||||
interface ClassLoweringPass {
|
||||
fun lower(irClass: IrClass)
|
||||
}
|
||||
|
||||
fun ClassLoweringPass.runOnNormalizedFile(irFile: IrFile) {
|
||||
fun runPostfix(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.forEach {
|
||||
if (it is IrClass) {
|
||||
runPostfix(it)
|
||||
lower(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
interface BodyLoweringPass {
|
||||
fun lower(irBody: IrBody)
|
||||
}
|
||||
|
||||
runPostfix(irFile)
|
||||
fun ClassLoweringPass.runOnFile(irFile: IrFile) {
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
declaration.acceptChildrenVoid(this)
|
||||
lower(declaration)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun BodyLoweringPass.runOnFile(irFile: IrFile) {
|
||||
irFile.acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitBody(body: IrBody) {
|
||||
body.acceptChildrenVoid(this)
|
||||
lower(body)
|
||||
}
|
||||
})
|
||||
}
|
||||
+2
-1
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_THROWABLE_TYPE
|
||||
@@ -195,7 +196,7 @@ class ExpressionCodegen(
|
||||
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: BlockInfo): StackValue {
|
||||
return none()
|
||||
throw AssertionError("IrInstanceInitializerCall should've been lowered before code generation: ${expression.render()}")
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: BlockInfo): StackValue {
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface JvmSpecialDescriptor {
|
||||
val extraFlags: Int
|
||||
}
|
||||
|
||||
class JvmPropertyDescriptorImpl(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
original: PropertyDescriptor?,
|
||||
annotations: Annotations,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
override val extraFlags: Int,
|
||||
isVar: Boolean,
|
||||
name: Name,
|
||||
kind: CallableMemberDescriptor.Kind,
|
||||
source: SourceElement,
|
||||
isLateInit: Boolean,
|
||||
isConst: Boolean
|
||||
) : JvmSpecialDescriptor, PropertyDescriptorImpl(
|
||||
containingDeclaration, original, annotations, modality, visibility, isVar,
|
||||
name, kind, source, isLateInit, isConst
|
||||
) {
|
||||
override fun createSubstitutedCopy(newOwner: DeclarationDescriptor, newModality: Modality, newVisibility: Visibility, original: PropertyDescriptor?, kind: CallableMemberDescriptor.Kind): PropertyDescriptorImpl =
|
||||
JvmPropertyDescriptorImpl(
|
||||
newOwner, original, annotations, newModality, newVisibility, extraFlags, isVar, name, kind,
|
||||
SourceElement.NO_SOURCE, isLateInit, isConst
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun createVal(
|
||||
name: Name,
|
||||
type: KotlinType,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
annotations: Annotations,
|
||||
modality: Modality,
|
||||
visibility: Visibility,
|
||||
extraFlags: Int,
|
||||
source: SourceElement
|
||||
): PropertyDescriptorImpl =
|
||||
JvmPropertyDescriptorImpl(
|
||||
containingDeclaration, null, annotations, modality, visibility, extraFlags, false, name,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED, source, false, false
|
||||
).setTypeNoReceivers(type)
|
||||
|
||||
private fun PropertyDescriptorImpl.setTypeNoReceivers(type: KotlinType): PropertyDescriptorImpl {
|
||||
setType(type, emptyList(), null as ReceiverParameterDescriptor?, null as ReceiverParameterDescriptor?)
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.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.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
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>()
|
||||
|
||||
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
|
||||
enumEntryFieldDescriptors.getOrPut(enumEntryDescriptor) {
|
||||
createEnumEntryFieldDescriptor(enumEntryDescriptor)
|
||||
}
|
||||
|
||||
fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor {
|
||||
val ktFile = psiSourceManager.getKtFile(fileEntry as PsiSourceManager.PsiFileEntry)
|
||||
?: throw AssertionError("Unexpected file entry: $fileEntry")
|
||||
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile)
|
||||
val sourceElement = KotlinSourceElement(ktFile)
|
||||
return FileClassDescriptorImpl(fileClassInfo.fileClassFqName.shortName(), packageFragment, sourceElement)
|
||||
}
|
||||
|
||||
private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
|
||||
assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" }
|
||||
|
||||
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
|
||||
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"}
|
||||
|
||||
return JvmPropertyDescriptorImpl.createVal(
|
||||
enumEntryDescriptor.name,
|
||||
enumClassDescriptor.defaultType,
|
||||
enumClassDescriptor,
|
||||
enumEntryDescriptor.annotations,
|
||||
Modality.FINAL,
|
||||
Visibilities.PUBLIC,
|
||||
Opcodes.ACC_ENUM,
|
||||
enumEntryDescriptor.source
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
|
||||
class ArrayOf : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
return IrIntrinsicFunction.create(expression, signature, context) {
|
||||
return IrIntrinsicFunction.create(expression, signature, context, signature.returnType) {
|
||||
//do nothing all generated as vararg
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,12 @@ import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
class Clone : IntrinsicMethod() {
|
||||
|
||||
/*TODO return type*/
|
||||
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
return IrIntrinsicFunction.create(expression, signature, context) {
|
||||
val resultType = context.state.typeMapper.mapType(expression.type)
|
||||
val opcode = if (expression is IrCall && expression.superQualifier != null) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL
|
||||
it.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false)
|
||||
it.checkcast(resultType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class IrEnumValueOf : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
val enumType = context.state.typeMapper.mapType(expression.descriptor.returnType!!)
|
||||
val newSignature = context.state.typeMapper.mapSignatureSkipGeneric(expression.descriptor as FunctionDescriptor, OwnerKind.IMPLEMENTATION)
|
||||
val stringType = AsmTypes.JAVA_STRING_TYPE;
|
||||
|
||||
return object : IrIntrinsicFunction(expression, newSignature, context, listOf(stringType)) {
|
||||
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
|
||||
v.tconst(enumType)
|
||||
codegen.gen(expression.getValueArgument(0)!!, stringType, data)
|
||||
v.invokestatic("java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
|
||||
v.checkcast(enumType)
|
||||
return StackValue.onStack(enumType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -36,12 +36,13 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
|
||||
irMapping.put(irBuiltIns.lteq0, compare)
|
||||
irMapping.put(irBuiltIns.gt0, compare)
|
||||
irMapping.put(irBuiltIns.gteq0, compare)
|
||||
irMapping.put(irBuiltIns.enumValueOf, IrEnumValueOf())
|
||||
}
|
||||
|
||||
fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? {
|
||||
return intrinsics.getIntrinsic(descriptor) ?:
|
||||
(if (descriptor is PropertyAccessorDescriptor) intrinsics.getIntrinsic(descriptor.correspondingProperty) else null) ?:
|
||||
irMapping[descriptor]
|
||||
irMapping[descriptor.original]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* 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 gnu.trove.TObjectIntHashMap
|
||||
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.backend.jvm.descriptors.JvmPropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.transform
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.findSingleFunction
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import java.util.*
|
||||
|
||||
class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
val classDescriptor = irClass.descriptor
|
||||
if (classDescriptor.kind != ClassKind.ENUM_CLASS) return
|
||||
|
||||
EnumClassTransformer(irClass).run()
|
||||
}
|
||||
|
||||
private interface EnumConstructorCallTransformer {
|
||||
fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression
|
||||
}
|
||||
|
||||
private val unsubstitutedArrayOfFun = context.builtIns.findSingleFunction(Name.identifier("arrayOf"))
|
||||
|
||||
private fun createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List<IrExpression>): IrExpression {
|
||||
val typeParameter0 = unsubstitutedArrayOfFun.typeParameters[0]
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
|
||||
val substitutedArrayOfFun = unsubstitutedArrayOfFun.substitute(typeSubstitutor)
|
||||
|
||||
val typeArguments = mapOf(typeParameter0 to arrayElementType)
|
||||
|
||||
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
|
||||
val arg0VarargType = valueParameter0.type
|
||||
val arg0VarargElementType = valueParameter0.varargElementType!!
|
||||
val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements)
|
||||
|
||||
return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply {
|
||||
putValueArgument(0, arg0)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EnumClassTransformer(val irClass: IrClass) {
|
||||
private val enumEntryOrdinals = TObjectIntHashMap<ClassDescriptor>()
|
||||
private val loweredEnumConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
|
||||
private val loweredEnumConstructorParameters = HashMap<ValueParameterDescriptor, ValueParameterDescriptor>()
|
||||
private val enumEntriesByField = HashMap<PropertyDescriptor, ClassDescriptor>()
|
||||
private val enumEntryFields = ArrayList<PropertyDescriptor>()
|
||||
|
||||
private lateinit var valuesFieldDescriptor: PropertyDescriptor
|
||||
private lateinit var valuesFunctionDescriptor: FunctionDescriptor
|
||||
private lateinit var valueOfFunctionDescriptor: FunctionDescriptor
|
||||
|
||||
fun run() {
|
||||
assignOrdinalsToEnumEntries()
|
||||
lowerEnumConstructors(irClass)
|
||||
lowerEnumEntries()
|
||||
setupSynthesizedEnumClassMembers()
|
||||
lowerEnumClassBody()
|
||||
}
|
||||
|
||||
private fun assignOrdinalsToEnumEntries() {
|
||||
var ordinal = 0
|
||||
irClass.declarations.forEach {
|
||||
if (it is IrEnumEntry) {
|
||||
enumEntryOrdinals.put(it.descriptor, ordinal)
|
||||
ordinal++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructors(irClass: IrClass) {
|
||||
irClass.declarations.transform { declaration ->
|
||||
if (declaration is IrConstructor)
|
||||
transformEnumConstructor(declaration)
|
||||
else
|
||||
declaration
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor {
|
||||
val constructorDescriptor = enumConstructor.descriptor
|
||||
val loweredConstructorDescriptor = lowerEnumConstructor(constructorDescriptor)
|
||||
val loweredEnumConstructor = IrConstructorImpl(
|
||||
enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin,
|
||||
loweredConstructorDescriptor,
|
||||
enumConstructor.body!! // will be transformed later
|
||||
)
|
||||
return loweredEnumConstructor
|
||||
}
|
||||
|
||||
private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
|
||||
val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
|
||||
constructorDescriptor.containingDeclaration,
|
||||
constructorDescriptor.annotations,
|
||||
constructorDescriptor.isPrimary,
|
||||
constructorDescriptor.source
|
||||
)
|
||||
|
||||
val valueParameters =
|
||||
listOf(
|
||||
loweredConstructorDescriptor.createSpecialParameter(0, "name", context.builtIns.stringType),
|
||||
loweredConstructorDescriptor.createSpecialParameter(1, "ordinal", context.builtIns.intType)
|
||||
) +
|
||||
constructorDescriptor.valueParameters.map {
|
||||
lowerConstructorValueParameter(loweredConstructorDescriptor, it)
|
||||
}
|
||||
loweredConstructorDescriptor.initialize(valueParameters, Visibilities.PROTECTED)
|
||||
|
||||
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
|
||||
|
||||
loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor
|
||||
|
||||
return loweredConstructorDescriptor
|
||||
}
|
||||
|
||||
private fun ClassConstructorDescriptor.createSpecialParameter(index: Int, name: String, type: KotlinType): ValueParameterDescriptor =
|
||||
ValueParameterDescriptorImpl(
|
||||
this, null,
|
||||
index,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier(name),
|
||||
type,
|
||||
false, false, false, false, null, SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
private fun lowerConstructorValueParameter(
|
||||
loweredConstructorDescriptor: ClassConstructorDescriptor,
|
||||
valueParameterDescriptor: ValueParameterDescriptor
|
||||
): ValueParameterDescriptor {
|
||||
val loweredValueParameterDescriptor = valueParameterDescriptor.copy(
|
||||
loweredConstructorDescriptor,
|
||||
valueParameterDescriptor.name,
|
||||
valueParameterDescriptor.index + 2
|
||||
)
|
||||
loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor
|
||||
return loweredValueParameterDescriptor
|
||||
}
|
||||
|
||||
private fun lowerEnumEntries() {
|
||||
irClass.declarations.transformFlat { declaration ->
|
||||
if (declaration is IrEnumEntry) {
|
||||
createFieldForEnumEntry(declaration).singletonList() +
|
||||
lowerEnumEntryClass(declaration.correspondingClass).singletonOrEmptyList()
|
||||
}
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerEnumEntryClass(enumEntryClass: IrClass?): IrClass? {
|
||||
if (enumEntryClass == null) return null
|
||||
|
||||
lowerEnumConstructors(enumEntryClass)
|
||||
|
||||
return enumEntryClass
|
||||
}
|
||||
|
||||
private fun createFieldForEnumEntry(enumEntry: IrEnumEntry): IrField {
|
||||
val fieldPropertyDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(enumEntry.descriptor)
|
||||
|
||||
enumEntriesByField[fieldPropertyDescriptor] = enumEntry.descriptor
|
||||
enumEntryFields.add(fieldPropertyDescriptor)
|
||||
|
||||
val enumEntryInitializer = enumEntry.initializerExpression
|
||||
return IrFieldImpl(
|
||||
enumEntry.startOffset, enumEntry.endOffset, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY,
|
||||
fieldPropertyDescriptor,
|
||||
IrExpressionBodyImpl(enumEntryInitializer.startOffset, enumEntryInitializer.endOffset, enumEntryInitializer)
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupSynthesizedEnumClassMembers() {
|
||||
val irField = createSyntheticValuesFieldDeclaration()
|
||||
|
||||
irClass.declarations.add(irField)
|
||||
|
||||
valuesFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES)
|
||||
valueOfFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||
}
|
||||
|
||||
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): FunctionDescriptor =
|
||||
irClass.declarations
|
||||
.first {
|
||||
it is IrFunction &&
|
||||
it.body.let { body ->
|
||||
body is IrSyntheticBody && body.kind == kind
|
||||
}
|
||||
}
|
||||
.descriptor as FunctionDescriptor
|
||||
|
||||
|
||||
private fun createSyntheticValuesFieldDeclaration(): IrFieldImpl {
|
||||
val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.descriptor.defaultType)
|
||||
valuesFieldDescriptor = createSyntheticValuesFieldDescriptor(valuesArrayType)
|
||||
|
||||
val irValuesInitializer = createSyntheticValuesFieldInitializerExpression()
|
||||
|
||||
val irField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_VALUES,
|
||||
valuesFieldDescriptor,
|
||||
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer))
|
||||
return irField
|
||||
}
|
||||
|
||||
private fun createSyntheticValuesFieldInitializerExpression(): IrExpression =
|
||||
createArrayOfExpression(
|
||||
irClass.descriptor.defaultType,
|
||||
enumEntryFields.map { fieldDescriptor ->
|
||||
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fieldDescriptor)
|
||||
})
|
||||
|
||||
private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl {
|
||||
return JvmPropertyDescriptorImpl.createVal(
|
||||
Name.identifier("\$VALUES"),
|
||||
valuesArrayType,
|
||||
irClass.descriptor,
|
||||
Annotations.EMPTY,
|
||||
Modality.FINAL, Visibilities.PRIVATE, Opcodes.ACC_SYNTHETIC,
|
||||
irClass.descriptor.source
|
||||
)
|
||||
}
|
||||
|
||||
private fun lowerEnumClassBody() {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer())
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) :
|
||||
EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor)
|
||||
|
||||
assert(result.descriptor.valueParameters.size == 2) {
|
||||
"Enum(String, Int) constructor call expected:\n${result.dump()}"
|
||||
}
|
||||
|
||||
val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) {
|
||||
throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) {
|
||||
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
|
||||
}
|
||||
|
||||
result.putValueArgument(0, IrGetVariableImpl(startOffset, endOffset, nameParameter, origin))
|
||||
result.putValueArgument(1, IrGetVariableImpl(startOffset, endOffset, ordinalParameter, origin))
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private abstract inner class InEnumEntry(private val enumEntry: ClassDescriptor) : EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val name = enumEntry.name.asString()
|
||||
val ordinal = enumEntryOrdinals[enumEntry]
|
||||
|
||||
val descriptor = enumConstructorCall.descriptor
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
|
||||
val loweredConstructor = loweredEnumConstructors.getOrElse(descriptor) {
|
||||
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
|
||||
}
|
||||
|
||||
val result = createConstructorCall(startOffset, endOffset, loweredConstructor)
|
||||
|
||||
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name))
|
||||
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal))
|
||||
|
||||
descriptor.valueParameters.forEach { valueParameter ->
|
||||
val i = valueParameter.index
|
||||
result.putValueArgument(i + 2, enumConstructorCall.getValueArgument(i))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor): IrMemberAccessExpression
|
||||
}
|
||||
|
||||
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) =
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) =
|
||||
IrCallImpl(startOffset, endOffset, loweredConstructor)
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
|
||||
private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null
|
||||
|
||||
override fun visitField(declaration: IrField): IrStatement {
|
||||
val enumEntry = enumEntriesByField[declaration.descriptor] ?:
|
||||
return declaration
|
||||
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"}
|
||||
|
||||
enumConstructorCallTransformer = InEnumEntryInitializer(enumEntry)
|
||||
|
||||
val result = super.visitField(declaration)
|
||||
|
||||
enumConstructorCallTransformer = null
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
val constructorDescriptor = declaration.descriptor
|
||||
val containingClass = constructorDescriptor.containingDeclaration
|
||||
|
||||
// TODO local (non-enum) class in enum class constructor?
|
||||
val previous = enumConstructorCallTransformer
|
||||
|
||||
if (containingClass.kind == ClassKind.ENUM_ENTRY) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"}
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass)
|
||||
}
|
||||
else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"}
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor)
|
||||
}
|
||||
|
||||
val result = super.visitConstructor(declaration)
|
||||
|
||||
enumConstructorCallTransformer = previous
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val callTransformer = enumConstructorCallTransformer ?:
|
||||
throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" +
|
||||
irClass.dump())
|
||||
|
||||
return callTransformer.transform(expression)
|
||||
}
|
||||
|
||||
override fun visitGetVariable(expression: IrGetVariable): IrExpression =
|
||||
loweredEnumConstructorParameters[expression.descriptor]?.let { loweredParameter ->
|
||||
IrGetVariableImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin)
|
||||
} ?: expression
|
||||
|
||||
override fun visitSyntheticBody(body: IrSyntheticBody): IrBody {
|
||||
return when (body.kind) {
|
||||
IrSyntheticBodyKind.ENUM_VALUES ->
|
||||
createEnumValuesBody(valuesFieldDescriptor)
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF ->
|
||||
createEnumValueOfBody()
|
||||
else ->
|
||||
body
|
||||
}
|
||||
}
|
||||
|
||||
private fun createEnumValueOfBody(): IrBody {
|
||||
val unsubstitutedValueOf = context.irBuiltIns.enumValueOf
|
||||
val typeParameterT = unsubstitutedValueOf.typeParameters[0]
|
||||
val enumClassType = irClass.descriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
val substitutedValueOf = unsubstitutedValueOf.substitute(typeSubstitutor)
|
||||
|
||||
val irValueOfCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedValueOf, mapOf(typeParameterT to enumClassType))
|
||||
irValueOfCall.putValueArgument(
|
||||
0, IrGetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor.valueParameters[0]))
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor, irValueOfCall))
|
||||
)
|
||||
}
|
||||
|
||||
private fun createEnumValuesBody(valuesFieldDescriptor: PropertyDescriptor): IrBody {
|
||||
val cloneFun = valuesFieldDescriptor.type.memberScope.findSingleFunction(Name.identifier("clone"))
|
||||
|
||||
val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun).apply {
|
||||
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFieldDescriptor)
|
||||
}
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFunctionDescriptor, irCloneValues))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+3
-2
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
@@ -24,7 +25,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||
import java.util.*
|
||||
|
||||
class FileClassLowering(val jvmFileClassProvider: JvmFileClassProvider) : FileLoweringPass {
|
||||
class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val classes = ArrayList<IrClass>()
|
||||
val fileClassMembers = ArrayList<IrDeclaration>()
|
||||
@@ -38,7 +39,7 @@ class FileClassLowering(val jvmFileClassProvider: JvmFileClassProvider) : FileLo
|
||||
|
||||
if (fileClassMembers.isEmpty()) return
|
||||
|
||||
val fileClassDescriptor = jvmFileClassProvider.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor)
|
||||
val fileClassDescriptor = context.specialDescriptorsFactory.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor)
|
||||
val irFileClass = IrClassImpl(0, irFile.fileEntry.maxOffset, IrDeclarationOrigin.DEFINED, fileClassDescriptor, fileClassMembers)
|
||||
classes.add(irFileClass)
|
||||
|
||||
|
||||
+2
-5
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import java.util.*
|
||||
|
||||
@@ -79,7 +80,7 @@ class InitializersLowering : ClassLoweringPass {
|
||||
null, null
|
||||
)
|
||||
|
||||
if (declaration.descriptor.isStatic()) {
|
||||
if (DescriptorUtils.isStaticDeclaration(declaration.descriptor)) {
|
||||
staticInitializerStatements.add(irSetField)
|
||||
}
|
||||
else {
|
||||
@@ -91,10 +92,6 @@ class InitializersLowering : ClassLoweringPass {
|
||||
instanceInitializerStatements.addAll(declaration.body.statements)
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.isStatic() =
|
||||
AsmUtil.isStaticMethod(classMemberOwnerKind, this) // TODO what about properties?
|
||||
|
||||
|
||||
fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) {
|
||||
for (irDeclaration in irClass.declarations) {
|
||||
if (irDeclaration !is IrConstructor) continue
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import java.lang.AssertionError
|
||||
import java.util.*
|
||||
|
||||
class JvmFileClassProvider : Psi2IrTranslator.PostprocessingStep {
|
||||
override fun postprocess(context: GeneratorContext, irElement: IrElement) {
|
||||
when (irElement) {
|
||||
is IrModuleFragment ->
|
||||
irElement.files.forEach { postprocess(context, it) }
|
||||
is IrFile ->
|
||||
recordFileClassInfo(context, irElement)
|
||||
}
|
||||
}
|
||||
|
||||
private val fileClassInfoByFileEntry = HashMap<SourceManager.FileEntry, JvmFileClassInfo>()
|
||||
private val sourceElementByFileEntry = HashMap<SourceManager.FileEntry, SourceElement>()
|
||||
|
||||
private fun recordFileClassInfo(context: GeneratorContext, irFile: IrFile) {
|
||||
context.sourceManager.getKtFile(irFile)?.let { ktFile ->
|
||||
sourceElementByFileEntry[irFile.fileEntry] = KotlinSourceElement(ktFile)
|
||||
}
|
||||
val jvmFileClassInfo = context.sourceManager.getFileClassInfo(irFile) ?: return
|
||||
fileClassInfoByFileEntry[irFile.fileEntry] = jvmFileClassInfo
|
||||
}
|
||||
|
||||
private fun PsiSourceManager.getFileClassInfo(irFile: IrFile): JvmFileClassInfo? {
|
||||
val file = getKtFile(irFile) ?: return null
|
||||
return JvmFileClassUtil.getFileClassInfoNoResolve(file)
|
||||
}
|
||||
|
||||
fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor {
|
||||
val fileClassInfo = fileClassInfoByFileEntry[fileEntry] ?: throw AssertionError("No file class info for ${fileEntry.name})")
|
||||
val sourceElement = sourceElementByFileEntry[fileEntry] ?: SourceElement.NO_SOURCE
|
||||
return FileClassDescriptorImpl(fileClassInfo.fileClassFqName.shortName(), packageFragment, sourceElement)
|
||||
}
|
||||
}
|
||||
+14
-21
@@ -18,13 +18,12 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.FileLoweringPass
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import java.util.*
|
||||
|
||||
class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass {
|
||||
@@ -34,29 +33,23 @@ class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass {
|
||||
|
||||
override fun visitFile(declaration: IrFile): IrFile {
|
||||
declaration.transformChildrenVoid(this)
|
||||
transformDeclarations(declaration.declarations)
|
||||
declaration.declarations.transformFlat { lowerProperty(it) }
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
declaration.transformChildrenVoid(this)
|
||||
transformDeclarations(declaration.declarations)
|
||||
declaration.declarations.transformFlat { lowerProperty(it) }
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun transformDeclarations(declarations: MutableList<IrDeclaration>) {
|
||||
val newDeclarations = ArrayList<IrDeclaration>()
|
||||
for (declaration in declarations) {
|
||||
if (declaration is IrProperty) {
|
||||
newDeclarations.addIfNotNull(declaration.backingField)
|
||||
newDeclarations.addIfNotNull(declaration.getter)
|
||||
newDeclarations.addIfNotNull(declaration.setter)
|
||||
}
|
||||
else {
|
||||
newDeclarations.add(declaration)
|
||||
}
|
||||
}
|
||||
declarations.clear()
|
||||
declarations.addAll(newDeclarations)
|
||||
}
|
||||
private fun lowerProperty(declaration: IrDeclaration): List<IrDeclaration>? =
|
||||
if (declaration is IrProperty)
|
||||
ArrayList<IrDeclaration>(3).apply {
|
||||
addIfNotNull(declaration.backingField)
|
||||
addIfNotNull(declaration.getter)
|
||||
addIfNotNull(declaration.setter)
|
||||
}
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.BodyLoweringPass
|
||||
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.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLoweringPass, IrElementTransformerVoid() {
|
||||
override fun lower(irBody: IrBody) {
|
||||
irBody.transformChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
|
||||
val enumValueFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(expression.descriptor)
|
||||
return IrGetFieldImpl(expression.startOffset, expression.endOffset, enumValueFieldDescriptor)
|
||||
}
|
||||
}
|
||||
@@ -16,8 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -70,3 +72,9 @@ inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableM
|
||||
|
||||
inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
|
||||
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
|
||||
|
||||
fun MemberScope.findSingleFunction(name: Name): FunctionDescriptor =
|
||||
getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).single()
|
||||
|
||||
fun KotlinBuiltIns.findSingleFunction(name: Name): FunctionDescriptor =
|
||||
builtInsPackageScope.findSingleFunction(name)
|
||||
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
import java.lang.AssertionError
|
||||
import java.util.*
|
||||
|
||||
class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: GeneratorContext): GeneratorWithScope {
|
||||
class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: GeneratorContext) : GeneratorWithScope {
|
||||
override val scope = Scope(scopeOwner)
|
||||
private val loopTable = HashMap<KtLoopExpression, IrLoop>()
|
||||
|
||||
@@ -63,7 +63,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
|
||||
|
||||
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrExpressionBody =
|
||||
IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset,
|
||||
createStatementGenerator().generateExpression(ktInitializer))
|
||||
createStatementGenerator().generateExpression(ktInitializer))
|
||||
|
||||
fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody {
|
||||
val statementGenerator = createStatementGenerator()
|
||||
@@ -231,7 +231,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
|
||||
|
||||
private fun generateEnumSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) {
|
||||
val enumConstructor = context.builtIns.enum.constructors.single()
|
||||
irBlockBody.statements.add(IrEnumConstructorCallImpl(ktElement.startOffset, ktElement.endOffset, enumConstructor, null))
|
||||
irBlockBody.statements.add(IrEnumConstructorCallImpl(ktElement.startOffset, ktElement.endOffset, enumConstructor))
|
||||
}
|
||||
|
||||
private fun generateEnumEntrySuperConstructorCall(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression {
|
||||
@@ -253,8 +253,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
|
||||
fun generateEnumEntryInitializer(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression {
|
||||
if (ktEnumEntry.declarations.isNotEmpty()) {
|
||||
val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!!
|
||||
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset,
|
||||
enumEntryConstructor, enumEntryDescriptor)
|
||||
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumEntryConstructor)
|
||||
}
|
||||
|
||||
return generateEnumConstructorCallOrSuperCall(ktEnumEntry, enumEntryDescriptor.containingDeclaration as ClassDescriptor, enumEntryDescriptor)
|
||||
@@ -278,8 +277,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
|
||||
|
||||
// No-argument enum entry constructor
|
||||
val enumClassConstructor = enumClassDescriptor.unsubstitutedPrimaryConstructor!!
|
||||
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset,
|
||||
enumClassConstructor, enumEntryOrNull)
|
||||
return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumClassConstructor)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
|
||||
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder) : IrExpression {
|
||||
val descriptor = call.descriptor
|
||||
if (descriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $descriptor")
|
||||
if (descriptor !is ClassConstructorDescriptor) throw AssertionError("Class constructor expected: $descriptor")
|
||||
|
||||
return call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||
val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, descriptor, getTypeArguments(call.original))
|
||||
@@ -78,7 +78,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
return call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
||||
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
|
||||
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
|
||||
val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorDescriptor, enumEntryDescriptor)
|
||||
val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorDescriptor)
|
||||
addParametersToCall(startOffset, endOffset, call, irCall, constructorDescriptor.returnType)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
@@ -88,7 +89,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
|
||||
if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext)) {
|
||||
return generateSecondaryConstructorWithNestedInitializers(ktConstructor)
|
||||
}
|
||||
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor)
|
||||
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor
|
||||
val irConstructor = IrConstructorImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor)
|
||||
val bodyGenerator = createBodyGenerator(constructorDescriptor)
|
||||
bodyGenerator.generateDefaultParameters(ktConstructor, irConstructor)
|
||||
@@ -98,7 +99,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
|
||||
|
||||
|
||||
private fun generateSecondaryConstructorWithNestedInitializers(ktConstructor: KtSecondaryConstructor): IrFunction {
|
||||
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor)
|
||||
val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor
|
||||
val irConstructor = IrConstructorImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor)
|
||||
val bodyGenerator = createBodyGenerator(constructorDescriptor)
|
||||
bodyGenerator.generateDefaultParameters(ktConstructor, irConstructor)
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
|
||||
|
||||
interface IrConstructor : IrFunction {
|
||||
override val declarationKind: IrDeclarationKind
|
||||
get() = IrDeclarationKind.CONSTRUCTOR
|
||||
|
||||
override val descriptor: ConstructorDescriptor
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
|
||||
interface IrDeclarationContainer {
|
||||
val declarations: MutableList<IrDeclaration>
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -16,16 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
class IrConstructorImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, override val descriptor: ConstructorDescriptor) :
|
||||
IrFunctionBase(startOffset, endOffset, origin), IrConstructor {
|
||||
class IrConstructorImpl(
|
||||
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin,
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
) : IrFunctionBase(startOffset, endOffset, origin), IrConstructor {
|
||||
constructor(
|
||||
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ConstructorDescriptor,
|
||||
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassConstructorDescriptor,
|
||||
body: IrBody
|
||||
) : this(startOffset, endOffset, origin, descriptor) {
|
||||
this.body = body
|
||||
|
||||
@@ -17,32 +17,27 @@
|
||||
package org.jetbrains.kotlin.ir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class IrBuiltIns(val builtIns: KotlinBuiltIns) {
|
||||
val packageFragment = IrBuiltinsPackageFragmentDescriptorImpl(builtIns.builtInsModule)
|
||||
|
||||
class BuiltinsOperatorsBuilder(val packageFragment: PackageFragmentDescriptor, val builtIns: KotlinBuiltIns) {
|
||||
val bool = builtIns.booleanType
|
||||
val any = builtIns.anyType
|
||||
val anyN = builtIns.nullableAnyType
|
||||
val int = builtIns.intType
|
||||
val nothing = builtIns.nothingType
|
||||
|
||||
val eqeqeq: FunctionDescriptor = defineOperator("EQEQEQ", bool, listOf(anyN, anyN))
|
||||
val eqeq: FunctionDescriptor = defineOperator("EQEQ", bool, listOf(anyN, anyN))
|
||||
val lt0: FunctionDescriptor = defineOperator("LT0", bool, listOf(int))
|
||||
val lteq0: FunctionDescriptor = defineOperator("LTEQ0", bool, listOf(int))
|
||||
val gt0: FunctionDescriptor = defineOperator("GT0", bool, listOf(int))
|
||||
val gteq0: FunctionDescriptor = defineOperator("GTEQ0", bool, listOf(int))
|
||||
val throwNpe: FunctionDescriptor = defineOperator("THROW_NPE", nothing, listOf())
|
||||
val booleanNot: FunctionDescriptor = defineOperator("NOT", bool, listOf(bool))
|
||||
|
||||
private fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List<KotlinType>): IrBuiltinOperatorDescriptor {
|
||||
fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List<KotlinType>): IrBuiltinOperatorDescriptor {
|
||||
val operatorDescriptor = IrSimpleBuiltinOperatorDescriptorImpl(packageFragment, Name.identifier(name), returnType)
|
||||
for ((i, valueParameterType) in valueParameterTypes.withIndex()) {
|
||||
operatorDescriptor.addValueParameter(
|
||||
@@ -50,7 +45,44 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) {
|
||||
}
|
||||
return operatorDescriptor
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.findSingleFunction(name: String): FunctionDescriptor =
|
||||
getMemberScope(TypeSubstitution.EMPTY).getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS).single()
|
||||
}
|
||||
|
||||
class IrBuiltIns(val builtIns: KotlinBuiltIns) {
|
||||
private val packageFragment = IrBuiltinsPackageFragmentDescriptorImpl(builtIns.builtInsModule, KOTLIN_INTERNAL_IR_FQN)
|
||||
private val builder = BuiltinsOperatorsBuilder(packageFragment, builtIns)
|
||||
|
||||
val eqeqeq: FunctionDescriptor = builder.run { defineOperator("EQEQEQ", bool, listOf(anyN, anyN)) }
|
||||
val eqeq: FunctionDescriptor = builder.run { defineOperator("EQEQ", bool, listOf(anyN, anyN)) }
|
||||
val lt0: FunctionDescriptor = builder.run { defineOperator("LT0", bool, listOf(int)) }
|
||||
val lteq0: FunctionDescriptor = builder.run { defineOperator("LTEQ0", bool, listOf(int)) }
|
||||
val gt0: FunctionDescriptor = builder.run { defineOperator("GT0", bool, listOf(int)) }
|
||||
val gteq0: FunctionDescriptor = builder.run { defineOperator("GTEQ0", bool, listOf(int)) }
|
||||
val throwNpe: FunctionDescriptor = builder.run { defineOperator("THROW_NPE", nothing, listOf()) }
|
||||
val booleanNot: FunctionDescriptor = builder.run { defineOperator("NOT", bool, listOf(bool)) }
|
||||
|
||||
val enumValueOf: FunctionDescriptor =
|
||||
SimpleFunctionDescriptorImpl.create(
|
||||
packageFragment,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier("enumValueOf"),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
val typeParameterT = TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
this, Annotations.EMPTY, true, Variance.INVARIANT, Name.identifier("T"), 0
|
||||
)
|
||||
|
||||
val valueParameterName = ValueParameterDescriptorImpl(
|
||||
this, null, 0, Annotations.EMPTY, Name.identifier("name"), builtIns.stringType,
|
||||
false, false, false, false, null, org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParameterT.typeConstructor, listOf(), false)
|
||||
|
||||
initialize(null, null, listOf(typeParameterT), listOf(valueParameterName), returnType, Modality.FINAL, Visibilities.PUBLIC)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir")
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -25,9 +25,13 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
interface IrBuiltinsPackageFragmentDescriptor : PackageFragmentDescriptor
|
||||
|
||||
class IrBuiltinsPackageFragmentDescriptorImpl(val containingModule: ModuleDescriptor) : IrBuiltinsPackageFragmentDescriptor {
|
||||
override val fqName: FqName get() = FqName("kotlin.internal.ir")
|
||||
override fun getName(): Name = Name.identifier("ir")
|
||||
class IrBuiltinsPackageFragmentDescriptorImpl(
|
||||
val containingModule: ModuleDescriptor,
|
||||
override val fqName: FqName
|
||||
) : IrBuiltinsPackageFragmentDescriptor {
|
||||
private val shortName = fqName.shortName()
|
||||
|
||||
override fun getName(): Name = shortName
|
||||
|
||||
override fun getContainingDeclaration(): ModuleDescriptor = containingModule
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
|
||||
interface IrBody : IrElement {
|
||||
@@ -29,10 +28,6 @@ interface IrExpressionBody : IrBody {
|
||||
var expression: IrExpression
|
||||
}
|
||||
|
||||
interface IrStatementContainer {
|
||||
val statements: MutableList<IrStatement>
|
||||
}
|
||||
|
||||
interface IrBlockBody : IrBody, IrStatementContainer
|
||||
|
||||
interface IrSyntheticBody : IrBody {
|
||||
|
||||
+2
-2
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
|
||||
interface IrDelegatingConstructorCall : IrMemberAccessExpression {
|
||||
override val descriptor: ConstructorDescriptor
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
}
|
||||
|
||||
|
||||
+2
-8
@@ -16,15 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
|
||||
|
||||
interface IrEnumConstructorCall : IrMemberAccessExpression {
|
||||
override val descriptor: ConstructorDescriptor
|
||||
val enumEntryDescriptor: ClassDescriptor?
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
}
|
||||
|
||||
val IrEnumConstructorCall.isSuper: Boolean
|
||||
get() = enumEntryDescriptor == null
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
|
||||
interface IrStatementContainer {
|
||||
val statements: MutableList<IrStatement>
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallWithShallowCopy
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
@@ -35,6 +36,13 @@ class IrCallImpl(
|
||||
override val origin: IrStatementOrigin? = null,
|
||||
override val superQualifier: ClassDescriptor? = null
|
||||
) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, type, descriptor.valueParameters.size, typeArguments), IrCallWithShallowCopy {
|
||||
constructor(
|
||||
startOffset: Int, endOffset: Int, descriptor: CallableDescriptor,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>? = null,
|
||||
origin: IrStatementOrigin? = null,
|
||||
superQualifier: ClassDescriptor? = null
|
||||
) : this(startOffset, endOffset, descriptor.returnType!!, descriptor, typeArguments, origin, superQualifier)
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitCall(this, data)
|
||||
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions.impl
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
@@ -26,8 +26,8 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
class IrDelegatingConstructorCallImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
override val descriptor: ConstructorDescriptor,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>?
|
||||
override val descriptor: ClassConstructorDescriptor,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>? = null
|
||||
) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, typeArguments),
|
||||
IrDelegatingConstructorCall {
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
|
||||
+2
-4
@@ -16,8 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions.impl
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
@@ -25,8 +24,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
class IrEnumConstructorCallImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
override val descriptor: ConstructorDescriptor,
|
||||
override val enumEntryDescriptor: ClassDescriptor? = null
|
||||
override val descriptor: ClassConstructorDescriptor
|
||||
) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, null),
|
||||
IrEnumConstructorCall {
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class IrReturnImpl(
|
||||
@@ -30,6 +31,9 @@ class IrReturnImpl(
|
||||
override val returnTarget: CallableDescriptor,
|
||||
override var value: IrExpression
|
||||
) : IrExpressionBase(startOffset, endOffset, type), IrReturn {
|
||||
constructor(startOffset: Int, endOffset: Int, returnTarget: CallableDescriptor, value: IrExpression) :
|
||||
this(startOffset, endOffset, returnTarget.builtIns.nothingType, returnTarget, value)
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitReturn(this, data)
|
||||
|
||||
|
||||
+3
@@ -34,4 +34,7 @@ class IrSyntheticBodyImpl(startOffset: Int, endOffset: Int, override val kind: I
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
// no children
|
||||
}
|
||||
|
||||
override fun toString(): String =
|
||||
"IrSyntheticBodyImpl($kind)"
|
||||
}
|
||||
@@ -38,7 +38,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() {
|
||||
protected open fun mapClassDeclaration(descriptor: ClassDescriptor) = descriptor
|
||||
protected open fun mapTypeAliasDeclaration(descriptor: TypeAliasDescriptor) = descriptor
|
||||
protected open fun mapFunctionDeclaration(descriptor: FunctionDescriptor) = descriptor
|
||||
protected open fun mapConstructorDeclaration(descriptor: ConstructorDescriptor) = descriptor
|
||||
protected open fun mapConstructorDeclaration(descriptor: ClassConstructorDescriptor) = descriptor
|
||||
protected open fun mapPropertyDeclaration(descriptor: PropertyDescriptor) = descriptor
|
||||
protected open fun mapLocalPropertyDeclaration(descriptor: VariableDescriptorWithAccessors) = descriptor
|
||||
protected open fun mapEnumEntryDeclaration(descriptor: ClassDescriptor) = descriptor
|
||||
@@ -52,9 +52,8 @@ open class DeepCopyIrTree : IrElementTransformerVoid() {
|
||||
protected open fun mapPropertyReference(descriptor: PropertyDescriptor) = descriptor
|
||||
protected open fun mapReceiverParameterReference(descriptor: ReceiverParameterDescriptor) = descriptor
|
||||
protected open fun mapCallee(descriptor: CallableDescriptor) = descriptor
|
||||
protected open fun mapDelegatedConstructorCallee(descriptor: ConstructorDescriptor) = descriptor
|
||||
protected open fun mapEnumConstructorCallee(descriptor: ConstructorDescriptor) = descriptor
|
||||
protected open fun mapEnumEntryInConstructor(descriptor: ClassDescriptor?) = descriptor
|
||||
protected open fun mapDelegatedConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor
|
||||
protected open fun mapEnumConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor
|
||||
protected open fun mapCallableReference(descriptor: CallableDescriptor) = descriptor
|
||||
protected open fun mapClassifierReference(descriptor: ClassifierDescriptor) = descriptor
|
||||
protected open fun mapReturnTarget(descriptor: CallableDescriptor) = mapCallee(descriptor)
|
||||
@@ -346,8 +345,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() {
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall =
|
||||
IrEnumConstructorCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
mapEnumConstructorCallee(expression.descriptor),
|
||||
mapEnumEntryInConstructor(expression.enumEntryDescriptor)
|
||||
mapEnumConstructorCallee(expression.descriptor)
|
||||
).transformValueArguments(expression)
|
||||
|
||||
override fun visitGetClass(expression: IrGetClass): IrGetClass =
|
||||
|
||||
@@ -119,11 +119,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
"DELEGATING_CONSTRUCTOR_CALL '${expression.descriptor.ref()}'"
|
||||
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): String =
|
||||
"ENUM_CONSTRUCTOR_CALL '${expression.descriptor.ref()}' " +
|
||||
expression.enumEntryDescriptor.let { enumEntryDescriptor ->
|
||||
if (enumEntryDescriptor == null) "super"
|
||||
else enumEntryDescriptor.ref()
|
||||
}
|
||||
"ENUM_CONSTRUCTOR_CALL '${expression.descriptor.ref()}'"
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: Nothing?): String =
|
||||
"INSTANCE_INITIALIZER_CALL classDescriptor='${expression.classDescriptor.ref()}'"
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.ir.util
|
||||
|
||||
inline fun <T> MutableList<T>.transform(transformation: (T) -> T) {
|
||||
forEachIndexed { i, item ->
|
||||
set(i, transformation(item))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a mutable list in place.
|
||||
* Each element `it` is replaced with a result of `transformation(it)`,
|
||||
* `null` means "keep existing element" (to avoid creating excessive singleton lists).
|
||||
*/
|
||||
inline fun <T> MutableList<T>.transformFlat(transformation: (T) -> List<T>?) {
|
||||
var i = 0
|
||||
while (i < size) {
|
||||
val item = get(i)
|
||||
|
||||
val transformed = transformation(item)
|
||||
|
||||
if (transformed == null) {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
addAll(i, transformed)
|
||||
i += transformed.size
|
||||
removeAt(i)
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
enum class Test { OK }
|
||||
|
||||
fun box() = Test.OK.toString()
|
||||
+1
-1
@@ -14,7 +14,7 @@ FILE /classes.kt
|
||||
CLASS ENUM_CLASS TestEnumClass
|
||||
CONSTRUCTOR private constructor TestEnumClass()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnumClass'
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<TestEnumClass>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
|
||||
+15
-15
@@ -2,12 +2,12 @@ FILE /enum.kt
|
||||
CLASS ENUM_CLASS TestEnum1
|
||||
CONSTRUCTOR private constructor TestEnum1()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum1'
|
||||
ENUM_ENTRY enum entry TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()'
|
||||
ENUM_ENTRY enum entry TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()'
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<TestEnum1>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): TestEnum1
|
||||
@@ -15,7 +15,7 @@ FILE /enum.kt
|
||||
CLASS ENUM_CLASS TestEnum2
|
||||
CONSTRUCTOR private constructor TestEnum2(x: kotlin.Int)
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum2'
|
||||
PROPERTY public final val x: kotlin.Int
|
||||
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
|
||||
@@ -27,13 +27,13 @@ FILE /enum.kt
|
||||
GET_FIELD 'x: Int' type=kotlin.Int origin=null
|
||||
receiver: THIS of 'TestEnum2' type=TestEnum2
|
||||
ENUM_ENTRY enum entry TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)'
|
||||
x: CONST Int type=kotlin.Int value='1'
|
||||
ENUM_ENTRY enum entry TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)'
|
||||
x: CONST Int type=kotlin.Int value='2'
|
||||
ENUM_ENTRY enum entry TEST3
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST3
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)'
|
||||
x: CONST Int type=kotlin.Int value='3'
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<TestEnum2>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
@@ -42,14 +42,14 @@ FILE /enum.kt
|
||||
CLASS ENUM_CLASS TestEnum3
|
||||
CONSTRUCTOR private constructor TestEnum3()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum3'
|
||||
ENUM_ENTRY enum entry TEST
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()' TEST
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()'
|
||||
class: CLASS ENUM_ENTRY TEST
|
||||
CONSTRUCTOR private constructor TEST()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum3()' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum3()'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TEST'
|
||||
FUN public open override fun foo(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
@@ -63,7 +63,7 @@ FILE /enum.kt
|
||||
CLASS ENUM_CLASS TestEnum4
|
||||
CONSTRUCTOR private constructor TestEnum4(x: kotlin.Int)
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum4'
|
||||
PROPERTY public final val x: kotlin.Int
|
||||
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
|
||||
@@ -75,11 +75,11 @@ FILE /enum.kt
|
||||
GET_FIELD 'x: Int' type=kotlin.Int origin=null
|
||||
receiver: THIS of 'TestEnum4' type=TestEnum4
|
||||
ENUM_ENTRY enum entry TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST1()' TEST1
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST1()'
|
||||
class: CLASS ENUM_ENTRY TEST1
|
||||
CONSTRUCTOR private constructor TEST1()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)'
|
||||
x: CONST Int type=kotlin.Int value='1'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TEST1'
|
||||
FUN public open override fun foo(): kotlin.Unit
|
||||
@@ -87,11 +87,11 @@ FILE /enum.kt
|
||||
CALL 'println(Any?): Unit' type=kotlin.Unit origin=null
|
||||
message: GET_ENUM 'TEST1' type=TestEnum4
|
||||
ENUM_ENTRY enum entry TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST2()' TEST2
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST2()'
|
||||
class: CLASS ENUM_ENTRY TEST2
|
||||
CONSTRUCTOR private constructor TEST2()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)'
|
||||
x: CONST Int type=kotlin.Int value='2'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='TEST2'
|
||||
PROPERTY public final val z: kotlin.Int
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
enum class Test1(val x: Int) {
|
||||
ZERO, ONE(1);
|
||||
constructor() : this(0)
|
||||
}
|
||||
|
||||
enum class Test2(val x: Int) {
|
||||
ZERO {
|
||||
override fun foo() {
|
||||
println("ZERO")
|
||||
}
|
||||
},
|
||||
ONE(1) {
|
||||
override fun foo() {
|
||||
println("ONE")
|
||||
}
|
||||
};
|
||||
constructor() : this(0)
|
||||
abstract fun foo()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
FILE /enumWithSecondaryCtor.kt
|
||||
CLASS ENUM_CLASS Test1
|
||||
CONSTRUCTOR private constructor Test1(x: kotlin.Int)
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='Test1'
|
||||
PROPERTY public final val x: kotlin.Int
|
||||
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
|
||||
EXPRESSION_BODY
|
||||
GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR public final fun <get-x>(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='<get-x>(): Int'
|
||||
GET_FIELD 'x: Int' type=kotlin.Int origin=null
|
||||
receiver: THIS of 'Test1' type=Test1
|
||||
ENUM_ENTRY enum entry ZERO
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor Test1(Int)'
|
||||
ENUM_ENTRY enum entry ONE
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor Test1(Int)'
|
||||
x: CONST Int type=kotlin.Int value='1'
|
||||
CONSTRUCTOR private constructor Test1()
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'constructor Test1(Int)'
|
||||
x: CONST Int type=kotlin.Int value='0'
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<Test1>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Test1
|
||||
SYNTHETIC_BODY kind=ENUM_VALUEOF
|
||||
CLASS ENUM_CLASS Test2
|
||||
CONSTRUCTOR private constructor Test2(x: kotlin.Int)
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='Test2'
|
||||
PROPERTY public final val x: kotlin.Int
|
||||
FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int
|
||||
EXPRESSION_BODY
|
||||
GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
FUN DEFAULT_PROPERTY_ACCESSOR public final fun <get-x>(): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='<get-x>(): Int'
|
||||
GET_FIELD 'x: Int' type=kotlin.Int origin=null
|
||||
receiver: THIS of 'Test2' type=Test2
|
||||
ENUM_ENTRY enum entry ZERO
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor ZERO()'
|
||||
class: CLASS ENUM_ENTRY ZERO
|
||||
CONSTRUCTOR private constructor ZERO()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Test2(Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='ZERO'
|
||||
FUN public open override fun foo(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
CALL 'println(Any?): Unit' type=kotlin.Unit origin=null
|
||||
message: CONST String type=kotlin.String value='ZERO'
|
||||
ENUM_ENTRY enum entry ONE
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor ONE()'
|
||||
class: CLASS ENUM_ENTRY ONE
|
||||
CONSTRUCTOR private constructor ONE()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Test2(Int)'
|
||||
x: CONST Int type=kotlin.Int value='1'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='ONE'
|
||||
FUN public open override fun foo(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
CALL 'println(Any?): Unit' type=kotlin.Unit origin=null
|
||||
message: CONST String type=kotlin.String value='ONE'
|
||||
CONSTRUCTOR private constructor Test2()
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'constructor Test2(Int)'
|
||||
x: CONST Int type=kotlin.Int value='0'
|
||||
FUN public abstract fun foo(): kotlin.Unit
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<Test2>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Test2
|
||||
SYNTHETIC_BODY kind=ENUM_VALUEOF
|
||||
+2
-2
@@ -2,10 +2,10 @@ FILE /values.kt
|
||||
CLASS ENUM_CLASS Enum
|
||||
CONSTRUCTOR private constructor Enum()
|
||||
BLOCK_BODY
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super
|
||||
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='Enum'
|
||||
ENUM_ENTRY enum entry A
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()' A
|
||||
init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()'
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array<Enum>
|
||||
SYNTHETIC_BODY kind=ENUM_VALUES
|
||||
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Enum
|
||||
|
||||
@@ -41,6 +41,12 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enumClass.kt")
|
||||
public void testEnumClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/enumClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fileClassInitializers.kt")
|
||||
public void testFileClassInitializers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/fileClassInitializers.kt");
|
||||
|
||||
@@ -97,6 +97,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enumWithSecondaryCtor.kt")
|
||||
public void testEnumWithSecondaryCtor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/enumWithSecondaryCtor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initBlock.kt")
|
||||
public void testInitBlock() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/initBlock.kt");
|
||||
|
||||
+10
@@ -55,6 +55,16 @@ public class ClassConstructorDescriptorImpl extends FunctionDescriptorImpl imple
|
||||
return new ClassConstructorDescriptorImpl(containingDeclaration, null, annotations, isPrimary, Kind.DECLARATION, source);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ClassConstructorDescriptorImpl createSynthesized(
|
||||
@NotNull ClassDescriptor containingDeclaration,
|
||||
@NotNull Annotations annotations,
|
||||
boolean isPrimary,
|
||||
@NotNull SourceElement source
|
||||
) {
|
||||
return new ClassConstructorDescriptorImpl(containingDeclaration, null, annotations, isPrimary, Kind.SYNTHESIZED, source);
|
||||
}
|
||||
|
||||
public ClassConstructorDescriptorImpl initialize(
|
||||
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
|
||||
@NotNull Visibility visibility,
|
||||
|
||||
Reference in New Issue
Block a user