diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt deleted file mode 100644 index eb3b14f172c..00000000000 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanDescriptorSerializer.kt +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license - * that can be found in the LICENSE file. - */ - -package org.jetbrains.kotlin.serialization - -import org.jetbrains.kotlin.backend.common.onlyIf -import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.backend.konan.descriptors.needsSerializedIr -import org.jetbrains.kotlin.backend.konan.serialization.IrAwareExtension -import org.jetbrains.kotlin.backend.konan.serialization.KonanStringTable -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.builtins.isSuspendFunctionType -import org.jetbrains.kotlin.builtins.transformSuspendFunctionToRuntimeFunctionType -import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.annotations.Annotated -import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor -import org.jetbrains.kotlin.metadata.ProtoBuf -import org.jetbrains.kotlin.metadata.deserialization.Flags -import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement -import org.jetbrains.kotlin.metadata.serialization.Interner -import org.jetbrains.kotlin.metadata.serialization.MutableTypeTable -import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable -import org.jetbrains.kotlin.metadata.serialization.StringTable -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.protobuf.MessageLite -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry -import org.jetbrains.kotlin.resolve.MemberComparator -import org.jetbrains.kotlin.resolve.RequireKotlinNames -import org.jetbrains.kotlin.resolve.checkers.KotlinVersionStringAnnotationValueChecker -import org.jetbrains.kotlin.resolve.constants.EnumValue -import org.jetbrains.kotlin.resolve.constants.IntValue -import org.jetbrains.kotlin.resolve.constants.NullValue -import org.jetbrains.kotlin.resolve.constants.StringValue -import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.contains -import org.jetbrains.kotlin.resolve.calls.components.isActualParameterWithAnyExpectedDefault -import java.io.ByteArrayOutputStream -import java.util.* - -class KonanDescriptorSerializer private constructor( - private val context: Context, - private val containingDeclaration: DeclarationDescriptor?, - private val typeParameters: Interner, - private val extension: SerializerExtension, - private val typeTable: MutableTypeTable, - private val versionRequirementTable: MutableVersionRequirementTable, - private val serializeTypeTableToFunction: Boolean -) { - private val contractSerializer = ContractSerializer() - - fun createChildSerializer(descriptor: DeclarationDescriptor): KonanDescriptorSerializer = - KonanDescriptorSerializer(context, descriptor, Interner(typeParameters), extension, typeTable, versionRequirementTable, - serializeTypeTableToFunction = false) - - val stringTable: DescriptorAwareStringTable - get() = extension.stringTable - - private fun useTypeTable(): Boolean = extension.shouldUseTypeTable() - - fun classProto(classDescriptor: ClassDescriptor): ProtoBuf.Class.Builder { - val builder = ProtoBuf.Class.newBuilder() - - val flags = Flags.getClassFlags( - hasAnnotations(classDescriptor), - ProtoEnumFlags.visibility(normalizeVisibility(classDescriptor)), - ProtoEnumFlags.modality(classDescriptor.modality), - ProtoEnumFlags.classKind(classDescriptor.kind, classDescriptor.isCompanionObject), - classDescriptor.isInner, classDescriptor.isData, classDescriptor.isExternal, classDescriptor.isExpect, classDescriptor.isInline - ) - if (flags != builder.flags) { - builder.flags = flags - } - - builder.fqName = getClassifierId(classDescriptor) - - for (typeParameterDescriptor in classDescriptor.declaredTypeParameters) { - builder.addTypeParameter(typeParameter(typeParameterDescriptor)) - } - - if (!KotlinBuiltIns.isSpecialClassWithNoSupertypes(classDescriptor)) { - // Special classes (Any, Nothing) have no supertypes - for (supertype in classDescriptor.typeConstructor.supertypes) { - if (useTypeTable()) { - builder.addSupertypeId(typeId(supertype)) - } - else { - builder.addSupertype(type(supertype)) - } - } - } - - for (descriptor in classDescriptor.constructors) { - builder.addConstructor(constructorProto(descriptor)) - } - - val callableMembers = - extension.customClassMembersProducer?.getCallableMembers(classDescriptor) - ?: sort( - DescriptorUtils.getAllDescriptors(classDescriptor.defaultType.memberScope) - .filterIsInstance() - ) - - for (descriptor in callableMembers) { - if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue - - when (descriptor) { - is PropertyDescriptor -> builder.addProperty(propertyProto(descriptor)) - is FunctionDescriptor -> builder.addFunction(functionProto(descriptor)) - } - } - - context.ir.classesDelegatedBackingFields[classDescriptor]?.forEach { - builder.addProperty(propertyProto(it)) - } - - val nestedClassifiers = sort(DescriptorUtils.getAllDescriptors(classDescriptor.unsubstitutedInnerClassesScope)) - for (descriptor in nestedClassifiers) { - if (descriptor is TypeAliasDescriptor) { - builder.addTypeAlias(typeAliasProto(descriptor)) - } - else { - val name = getSimpleNameIndex(descriptor.name) - if (isEnumEntry(descriptor)) { - builder.addEnumEntry(enumEntryProto(descriptor as ClassDescriptor)) - } - else { - builder.addNestedClassName(name) - } - } - } - - for (sealedSubclass in classDescriptor.sealedSubclasses) { - builder.addSealedSubclassFqName(getClassifierId(sealedSubclass)) - } - - val companionObjectDescriptor = classDescriptor.companionObjectDescriptor - if (companionObjectDescriptor != null) { - builder.companionObjectName = getSimpleNameIndex(companionObjectDescriptor.name) - } - - val typeTableProto = typeTable.serialize() - if (typeTableProto != null) { - builder.typeTable = typeTableProto - } - - builder.addAllVersionRequirement(serializeVersionRequirements(classDescriptor)) - - val versionRequirementTableProto = versionRequirementTable.serialize() - if (versionRequirementTableProto != null) { - builder.versionRequirementTable = versionRequirementTableProto - } - - extension.serializeClass(classDescriptor, builder, versionRequirementTable) - return builder - } - - fun propertyProto(descriptor: PropertyDescriptor): ProtoBuf.Property.Builder { - val builder = ProtoBuf.Property.newBuilder() - - val local = createChildSerializer(descriptor) - - var hasGetter = false - var hasSetter = false - - val compileTimeConstant = descriptor.compileTimeInitializer - val hasConstant = compileTimeConstant != null && compileTimeConstant !is NullValue - - val propertyFlags = Flags.getAccessorFlags( - hasAnnotations(descriptor), - ProtoEnumFlags.visibility(normalizeVisibility(descriptor)), - ProtoEnumFlags.modality(descriptor.modality), - false, false, false - ) - - val getter = descriptor.getter - if (getter != null) { - hasGetter = true - val accessorFlags = getAccessorFlags(getter) - if (accessorFlags != propertyFlags) { - builder.getterFlags = accessorFlags - } - } - - val setter = descriptor.setter - if (setter != null) { - hasSetter = true - val accessorFlags = getAccessorFlags(setter) - if (accessorFlags != propertyFlags) { - builder.setterFlags = accessorFlags - } - - if (!setter.isDefault) { - val setterLocal = local.createChildSerializer(setter) - for (valueParameterDescriptor in setter.valueParameters) { - builder.setSetterValueParameter(setterLocal.valueParameter(valueParameterDescriptor)) - } - } - } - - val flags = Flags.getPropertyFlags( - hasAnnotations(descriptor), - ProtoEnumFlags.visibility(normalizeVisibility(descriptor)), - ProtoEnumFlags.modality(descriptor.modality), - ProtoEnumFlags.memberKind(descriptor.kind), - descriptor.isVar, hasGetter, hasSetter, hasConstant, descriptor.isConst, descriptor.isLateInit, descriptor.isExternal, - @Suppress("DEPRECATION") descriptor.isDelegated, descriptor.isExpect - ) - if (flags != builder.flags) { - builder.flags = flags - } - - builder.name = getSimpleNameIndex(descriptor.name) - - if (useTypeTable()) { - builder.returnTypeId = local.typeId(descriptor.type) - } - else { - builder.setReturnType(local.type(descriptor.type)) - } - - for (typeParameterDescriptor in descriptor.typeParameters) { - builder.addTypeParameter(local.typeParameter(typeParameterDescriptor)) - } - - val receiverParameter = descriptor.extensionReceiverParameter - if (receiverParameter != null) { - if (useTypeTable()) { - builder.receiverTypeId = local.typeId(receiverParameter.type) - } - else { - builder.setReceiverType(local.type(receiverParameter.type)) - } - } - - builder.addAllVersionRequirement(serializeVersionRequirements(descriptor)) - - if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) - } - - extension.serializeProperty(descriptor, builder, versionRequirementTable) - - /* Konan specific chunk */ - if (extension is IrAwareExtension) { - descriptor.getter?.onlyIf({needsSerializedIr}) { - extension.addGetterIR(builder, - extension.serializeInlineBody(it, local)) - } - descriptor.setter?.onlyIf({needsSerializedIr}) { - extension.addSetterIR(builder, - extension.serializeInlineBody(it, local)) - } - } - - return builder - } - - private fun normalizeVisibility(descriptor: DeclarationDescriptorWithVisibility) = - // It can be necessary for Java classes serialization having package-private visibility - if (extension.shouldUseNormalizedVisibility()) - descriptor.visibility.normalize() - else - descriptor.visibility - - fun functionProto(descriptor: FunctionDescriptor): ProtoBuf.Function.Builder { - val builder = ProtoBuf.Function.newBuilder() - - val local = createChildSerializer(descriptor) - - val flags = Flags.getFunctionFlags( - hasAnnotations(descriptor), - ProtoEnumFlags.visibility(normalizeVisibility(descriptor)), - ProtoEnumFlags.modality(descriptor.modality), - ProtoEnumFlags.memberKind(descriptor.kind), - descriptor.isOperator, descriptor.isInfix, descriptor.isInline, descriptor.isTailrec, descriptor.isExternal, - descriptor.isSuspend, descriptor.isExpect - ) - if (flags != builder.flags) { - builder.flags = flags - } - - builder.name = getSimpleNameIndex(descriptor.name) - - if (useTypeTable()) { - builder.returnTypeId = local.typeId(descriptor.returnType!!) - } - else { - builder.setReturnType(local.type(descriptor.returnType!!)) - } - - for (typeParameterDescriptor in descriptor.typeParameters) { - builder.addTypeParameter(local.typeParameter(typeParameterDescriptor)) - } - - val receiverParameter = descriptor.extensionReceiverParameter - if (receiverParameter != null) { - if (useTypeTable()) { - builder.receiverTypeId = local.typeId(receiverParameter.type) - } - else { - builder.setReceiverType(local.type(receiverParameter.type)) - } - } - - for (valueParameterDescriptor in descriptor.valueParameters) { - builder.addValueParameter(local.valueParameter(valueParameterDescriptor)) - } - - if (serializeTypeTableToFunction) { - val typeTableProto = typeTable.serialize() - if (typeTableProto != null) { - builder.typeTable = typeTableProto - } - } - - builder.addAllVersionRequirement(serializeVersionRequirements(descriptor)) - - if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) - } - - val descriptorSerializer = DescriptorSerializer( - containingDeclaration = containingDeclaration, - typeParameters = typeParameters, - extension = extension, - typeTable = typeTable, - versionRequirementTable = versionRequirementTable, - serializeTypeTableToFunction = serializeTypeTableToFunction) - contractSerializer.serializeContractOfFunctionIfAny(descriptor, builder, descriptorSerializer) - - extension.serializeFunction(descriptor, builder) - - /* Konan specific chunk */ - if (extension is IrAwareExtension && descriptor.needsSerializedIr) { - extension.addFunctionIR(builder, - extension.serializeInlineBody(descriptor, local)) - } - - return builder - } - - fun constructorProto(descriptor: ConstructorDescriptor): ProtoBuf.Constructor.Builder { - val builder = ProtoBuf.Constructor.newBuilder() - - val local = createChildSerializer(descriptor) - - val flags = Flags.getConstructorFlags( - hasAnnotations(descriptor), ProtoEnumFlags.visibility(normalizeVisibility(descriptor)), !descriptor.isPrimary - ) - if (flags != builder.flags) { - builder.flags = flags - } - - for (valueParameterDescriptor in descriptor.valueParameters) { - builder.addValueParameter(local.valueParameter(valueParameterDescriptor)) - } - - builder.addAllVersionRequirement(serializeVersionRequirements(descriptor)) - - if (descriptor.isSuspendOrHasSuspendTypesInSignature()) { - builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) - } - - extension.serializeConstructor(descriptor, builder) - - /* Konan specific chunk */ - if (extension is IrAwareExtension && descriptor.needsSerializedIr) { - extension.addConstructorIR(builder, - extension.serializeInlineBody(descriptor, local)) - } - - return builder - } - - private fun CallableMemberDescriptor.isSuspendOrHasSuspendTypesInSignature(): Boolean { - if (this is FunctionDescriptor && isSuspend) return true - - return listOfNotNull( - extensionReceiverParameter?.type, - returnType, - *valueParameters.map(ValueParameterDescriptor::getType).toTypedArray() - ).any { type -> type.contains(UnwrappedType::isSuspendFunctionType) } - } - - fun typeAliasProto(descriptor: TypeAliasDescriptor): ProtoBuf.TypeAlias.Builder { - val builder = ProtoBuf.TypeAlias.newBuilder() - val local = createChildSerializer(descriptor) - - val flags = Flags.getTypeAliasFlags(hasAnnotations(descriptor), ProtoEnumFlags.visibility(normalizeVisibility(descriptor))) - if (flags != builder.flags) { - builder.flags = flags - } - - builder.name = getSimpleNameIndex(descriptor.name) - - for (typeParameterDescriptor in descriptor.declaredTypeParameters) { - builder.addTypeParameter(local.typeParameter(typeParameterDescriptor)) - } - - val underlyingType = descriptor.underlyingType - if (useTypeTable()) { - builder.underlyingTypeId = local.typeId(underlyingType) - } - else { - builder.setUnderlyingType(local.type(underlyingType)) - } - - val expandedType = descriptor.expandedType - if (useTypeTable()) { - builder.expandedTypeId = local.typeId(expandedType) - } - else { - builder.setExpandedType(local.type(expandedType)) - } - - builder.addVersionRequirement(writeVersionRequirementDependingOnCoroutinesVersion()) - - builder.addAllAnnotation(descriptor.annotations.map { extension.annotationSerializer.serializeAnnotation(it) }) - - return builder - } - - fun enumEntryProto(descriptor: ClassDescriptor): ProtoBuf.EnumEntry.Builder { - val builder = ProtoBuf.EnumEntry.newBuilder() - builder.name = getSimpleNameIndex(descriptor.name) - extension.serializeEnumEntry(descriptor, builder) - return builder - } - - private fun valueParameter(descriptor: ValueParameterDescriptor): ProtoBuf.ValueParameter.Builder { - val builder = ProtoBuf.ValueParameter.newBuilder() - - val declaresDefaultValue = descriptor.declaresDefaultValue() || descriptor.isActualParameterWithAnyExpectedDefault - - val flags = Flags.getValueParameterFlags( - hasAnnotations(descriptor), declaresDefaultValue, descriptor.isCrossinline, descriptor.isNoinline - ) - if (flags != builder.flags) { - builder.flags = flags - } - - builder.name = getSimpleNameIndex(descriptor.name) - - if (useTypeTable()) { - builder.typeId = typeId(descriptor.type) - } - else { - builder.setType(type(descriptor.type)) - } - - val varargElementType = descriptor.varargElementType - if (varargElementType != null) { - if (useTypeTable()) { - builder.varargElementTypeId = typeId(varargElementType) - } - else { - builder.setVarargElementType(type(varargElementType)) - } - } - - extension.serializeValueParameter(descriptor, builder) - - return builder - } - - private fun typeParameter(typeParameter: TypeParameterDescriptor): ProtoBuf.TypeParameter.Builder { - val builder = ProtoBuf.TypeParameter.newBuilder() - - builder.id = getTypeParameterId(typeParameter) - - builder.name = getSimpleNameIndex(typeParameter.name) - - if (typeParameter.isReified != builder.reified) { - builder.reified = typeParameter.isReified - } - - val variance = variance(typeParameter.variance) - if (variance != builder.variance) { - builder.variance = variance - } - extension.serializeTypeParameter(typeParameter, builder) - - val upperBounds = typeParameter.upperBounds - if (upperBounds.size == 1 && KotlinBuiltIns.isDefaultBound(upperBounds.single())) return builder - - for (upperBound in upperBounds) { - if (useTypeTable()) { - builder.addUpperBoundId(typeId(upperBound)) - } - else { - builder.addUpperBound(type(upperBound)) - } - } - - return builder - } - - /* Konan needs public modifier */ - fun typeId(type: KotlinType) = typeTable[type(type)] - - internal fun type(type: KotlinType): ProtoBuf.Type.Builder { - val builder = ProtoBuf.Type.newBuilder() - - if (type.isError) { - extension.serializeErrorType(type, builder) - return builder - } - - if (type.isFlexible()) { - val flexibleType = type.asFlexibleType() - - val lowerBound = type(flexibleType.lowerBound) - val upperBound = type(flexibleType.upperBound) - extension.serializeFlexibleType(flexibleType, lowerBound, upperBound) - if (useTypeTable()) { - lowerBound.flexibleUpperBoundId = typeTable[upperBound] - } - else { - lowerBound.setFlexibleUpperBound(upperBound) - } - return lowerBound - } - - if (type.isSuspendFunctionType) { - val functionType = type(transformSuspendFunctionToRuntimeFunctionType(type, extension.releaseCoroutines())) - functionType.flags = Flags.getTypeFlags(true) - return functionType - } - - val descriptor = type.constructor.declarationDescriptor - when (descriptor) { - is ClassDescriptor, is TypeAliasDescriptor -> { - val possiblyInnerType = type.buildPossiblyInnerType() ?: error("possiblyInnerType should not be null: $type") - fillFromPossiblyInnerType(builder, possiblyInnerType) - } - is TypeParameterDescriptor -> { - if (descriptor.containingDeclaration === containingDeclaration) { - builder.typeParameterName = getSimpleNameIndex(descriptor.name) - } - else { - builder.typeParameter = getTypeParameterId(descriptor) - } - - assert(type.arguments.isEmpty()) { "Found arguments for type constructor build on type parameter: $descriptor" } - } - } - - if (type.isMarkedNullable != builder.nullable) { - builder.nullable = type.isMarkedNullable - } - - val abbreviation = type.getAbbreviatedType()?.abbreviation - if (abbreviation != null) { - if (useTypeTable()) { - builder.abbreviatedTypeId = typeId(abbreviation) - } - else { - builder.setAbbreviatedType(type(abbreviation)) - } - } - - extension.serializeType(type, builder) - - return builder - } - - private fun fillFromPossiblyInnerType(builder: ProtoBuf.Type.Builder, type: PossiblyInnerType) { - val classifierDescriptor = type.classifierDescriptor - val classifierId = getClassifierId(classifierDescriptor) - when (classifierDescriptor) { - is ClassDescriptor -> builder.className = classifierId - is TypeAliasDescriptor -> builder.typeAliasName = classifierId - } - - for (projection in type.arguments) { - builder.addArgument(typeArgument(projection)) - } - - if (type.outerType != null) { - val outerBuilder = ProtoBuf.Type.newBuilder() - fillFromPossiblyInnerType(outerBuilder, type.outerType!!) - if (useTypeTable()) { - builder.outerTypeId = typeTable[outerBuilder] - } - else { - builder.setOuterType(outerBuilder) - } - } - } - - private fun typeArgument(typeProjection: TypeProjection): ProtoBuf.Type.Argument.Builder { - val builder = ProtoBuf.Type.Argument.newBuilder() - - if (typeProjection.isStarProjection) { - builder.projection = ProtoBuf.Type.Argument.Projection.STAR - } - else { - val projection = projection(typeProjection.projectionKind) - - if (projection != builder.projection) { - builder.projection = projection - } - - if (useTypeTable()) { - builder.typeId = typeId(typeProjection.type) - } - else { - builder.setType(type(typeProjection.type)) - } - } - - return builder - } - - fun packagePartProto(packageFqName: FqName, members: Collection): ProtoBuf.Package.Builder { - val builder = ProtoBuf.Package.newBuilder() - - for (declaration in members) { - when (declaration) { - is PropertyDescriptor -> builder.addProperty(propertyProto(declaration)) - is FunctionDescriptor -> builder.addFunction(functionProto(declaration)) - is TypeAliasDescriptor -> builder.addTypeAlias(typeAliasProto(declaration)) - } - } - - val typeTableProto = typeTable.serialize() - if (typeTableProto != null) { - builder.typeTable = typeTableProto - } - - val versionRequirementTableProto = versionRequirementTable.serialize() - if (versionRequirementTableProto != null) { - builder.versionRequirementTable = versionRequirementTableProto - } - - extension.serializePackage(packageFqName, builder) - - return builder - } - - private fun writeVersionRequirement(languageFeature: LanguageFeature): Int { - val languageVersion = languageFeature.sinceVersion!! - val requirement = ProtoBuf.VersionRequirement.newBuilder().apply { - VersionRequirement.Version(languageVersion.major, languageVersion.minor).encode( - writeVersion = { version = it }, - writeVersionFull = { versionFull = it } - ) - } - return versionRequirementTable[requirement] - } - - private fun getClassifierId(descriptor: ClassifierDescriptorWithTypeParameters): Int = - stringTable.getFqNameIndex(descriptor) - - private fun getSimpleNameIndex(name: Name): Int = - stringTable.getStringIndex(name.asString()) - - private fun getTypeParameterId(descriptor: TypeParameterDescriptor): Int = - typeParameters.intern(descriptor) - - private fun getAccessorFlags(accessor: PropertyAccessorDescriptor): Int = Flags.getAccessorFlags( - hasAnnotations(accessor), - ProtoEnumFlags.visibility(normalizeVisibility(accessor)), - ProtoEnumFlags.modality(accessor.modality), - !accessor.isDefault, - accessor.isExternal, - accessor.isInline - ) - private fun serializeVersionRequirements(descriptor: DeclarationDescriptor): List = - descriptor.annotations - .filter { it.fqName == RequireKotlinNames.FQ_NAME } - .mapNotNull(::serializeVersionRequirementFromRequireKotlin) - - private fun serializeVersionRequirementFromRequireKotlin(annotation: AnnotationDescriptor): Int? { - val args = annotation.allValueArguments - - val versionString = (args[RequireKotlinNames.VERSION] as? StringValue)?.value ?: return null - val matchResult = KotlinVersionStringAnnotationValueChecker.VERSION_REGEX.matchEntire(versionString) ?: return null - - val major = matchResult.groupValues.getOrNull(1)?.toIntOrNull() ?: return null - val minor = matchResult.groupValues.getOrNull(2)?.toIntOrNull() ?: 0 - val patch = matchResult.groupValues.getOrNull(4)?.toIntOrNull() ?: 0 - - val proto = ProtoBuf.VersionRequirement.newBuilder() - VersionRequirement.Version(major, minor, patch).encode( - writeVersion = { proto.version = it }, - writeVersionFull = { proto.versionFull = it } - ) - - val message = (args[RequireKotlinNames.MESSAGE] as? StringValue)?.value - if (message != null) { - proto.message = stringTable.getStringIndex(message) - } - - val level = (args[RequireKotlinNames.LEVEL] as? EnumValue)?.enumEntryName?.asString() - when (level) { - DeprecationLevel.ERROR.name -> { /* ERROR is the default level */ } - DeprecationLevel.WARNING.name -> proto.level = ProtoBuf.VersionRequirement.Level.WARNING - DeprecationLevel.HIDDEN.name -> proto.level = ProtoBuf.VersionRequirement.Level.HIDDEN - } - - val versionKind = (args[RequireKotlinNames.VERSION_KIND] as? EnumValue)?.enumEntryName?.asString() - when (versionKind) { - ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION.name -> { /* LANGUAGE_VERSION is the default kind */ } - ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION.name -> - proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION - ProtoBuf.VersionRequirement.VersionKind.API_VERSION.name -> - proto.versionKind = ProtoBuf.VersionRequirement.VersionKind.API_VERSION - } - - val errorCode = (args[RequireKotlinNames.ERROR_CODE] as? IntValue)?.value - if (errorCode != null && errorCode != -1) { - proto.errorCode = errorCode - } - - return versionRequirementTable[proto] - } - - private fun writeVersionRequirementDependingOnCoroutinesVersion(): Int = - writeVersionRequirement(if (this.extension.releaseCoroutines()) LanguageFeature.ReleaseCoroutines else LanguageFeature.Coroutines) - - companion object { - @JvmStatic - internal fun createTopLevel(context: Context, extension: SerializerExtension): KonanDescriptorSerializer { - return KonanDescriptorSerializer(context, null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), - serializeTypeTableToFunction = false) - } - - @JvmStatic - internal fun createForLambda(context: Context, extension: SerializerExtension): KonanDescriptorSerializer { - return KonanDescriptorSerializer(context, null, Interner(), extension, MutableTypeTable(), MutableVersionRequirementTable(), - serializeTypeTableToFunction = true) - } - - @JvmStatic - internal fun create(context: Context, descriptor: ClassDescriptor, extension: SerializerExtension): KonanDescriptorSerializer { - val container = descriptor.containingDeclaration - val parentSerializer = if (container is ClassDescriptor) - create(context, container, extension) - else - createTopLevel(context, extension) - - // Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always - // serializing outer classes before nested classes. - // Otherwise our interner can get wrong ids because we may serialize classes in any order. - val serializer = KonanDescriptorSerializer( - context, - descriptor, - Interner(parentSerializer.typeParameters), - parentSerializer.extension, - MutableTypeTable(), - MutableVersionRequirementTable(), - serializeTypeTableToFunction = false - ) - for (typeParameter in descriptor.declaredTypeParameters) { - serializer.typeParameters.intern(typeParameter) - } - return serializer - } - - @JvmStatic - fun serialize(message: MessageLite, stringTable: StringTable): ByteArray { - return ByteArrayOutputStream().apply { - (stringTable as KonanStringTable).serializeTo(this) - message.writeTo(this) - }.toByteArray() - } - - private fun variance(variance: Variance): ProtoBuf.TypeParameter.Variance = when (variance) { - Variance.INVARIANT -> ProtoBuf.TypeParameter.Variance.INV - Variance.IN_VARIANCE -> ProtoBuf.TypeParameter.Variance.IN - Variance.OUT_VARIANCE -> ProtoBuf.TypeParameter.Variance.OUT - } - - private fun projection(projectionKind: Variance): ProtoBuf.Type.Argument.Projection = when (projectionKind) { - Variance.INVARIANT -> ProtoBuf.Type.Argument.Projection.INV - Variance.IN_VARIANCE -> ProtoBuf.Type.Argument.Projection.IN - Variance.OUT_VARIANCE -> ProtoBuf.Type.Argument.Projection.OUT - } - - private fun hasAnnotations(descriptor: Annotated): Boolean = !descriptor.annotations.isEmpty() - - fun sort(descriptors: Collection): List = - ArrayList(descriptors).apply { - //NOTE: the exact comparator does matter here - Collections.sort(this, MemberComparator.INSTANCE) - } - } -} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 33ab5493f7f..09340383b5f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.CALLABLES import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.CLASSIFIERS import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered -import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer +import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.serialization.konan.SourceFileMap /* @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.serialization.konan.SourceFileMap * * It takes care of module and package fragment serializations. * The lower level (classes and members) serializations are delegated - * to the KonanDescriptorSerializer class. + * to the DescriptorSerializer class. * The lower level deserializations are performed by the frontend * with MemberDeserializer class. */ @@ -40,15 +40,15 @@ internal class KonanSerializationUtil(val context: Context, private val metadata data class SerializerContext( val serializerExtension: KonanSerializerExtension, - val topSerializer: KonanDescriptorSerializer, - var classSerializer: KonanDescriptorSerializer = topSerializer + val topSerializer: DescriptorSerializer, + var classSerializer: DescriptorSerializer = topSerializer ) private fun createNewContext(): SerializerContext { val extension = KonanSerializerExtension(context, metadataVersion, sourceFileMap) return SerializerContext( extension, - KonanDescriptorSerializer.createTopLevel(context, extension) + DescriptorSerializer.createTopLevel(extension) ) } @@ -65,7 +65,7 @@ internal class KonanSerializationUtil(val context: Context, private val metadata // TODO: this is to filter out object{}. Change me. if (classDescriptor.isExported()) - classSerializer = KonanDescriptorSerializer.create(context, classDescriptor, serializerExtension) + classSerializer = DescriptorSerializer.create(classDescriptor, serializerExtension, classSerializer) val classProto = classSerializer.classProto(classDescriptor).build() ?: error("Class not serialized: $classDescriptor") @@ -102,13 +102,13 @@ internal class KonanSerializationUtil(val context: Context, private val metadata val fragments = module.getPackage(fqName).fragments.filter { it.module == module } if (fragments.isEmpty()) return emptyList() - val classifierDescriptors = KonanDescriptorSerializer.sort( + val classifierDescriptors = DescriptorSerializer.sort( fragments.flatMap { it.getMemberScope().getDescriptorsFiltered(CLASSIFIERS) }.filter { !it.isExpectMember || it.isSerializableExpectClass } ) - val topLevelDescriptors = KonanDescriptorSerializer.sort( + val topLevelDescriptors = DescriptorSerializer.sort( fragments.flatMap { fragment -> fragment.getMemberScope().getDescriptorsFiltered(CALLABLES) }.filter { !it.isExpectMember } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index 5fcff1ff2e3..bcd014e55cd 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -5,7 +5,9 @@ package org.jetbrains.kotlin.backend.konan.serialization +import org.jetbrains.kotlin.backend.common.onlyIf import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.descriptors.needsSerializedIr import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.* @@ -13,7 +15,7 @@ import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable -import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer +import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol import org.jetbrains.kotlin.serialization.konan.SourceFileMap @@ -36,14 +38,6 @@ internal class KonanSerializerExtension(val context: Context, override val metad super.serializeType(type, proto) } - override fun serializeTypeParameter(typeParameter: TypeParameterDescriptor, proto: ProtoBuf.TypeParameter.Builder) { - super.serializeTypeParameter(typeParameter, proto) - } - - override fun serializeValueParameter(descriptor: ValueParameterDescriptor, proto: ProtoBuf.ValueParameter.Builder) { - super.serializeValueParameter(descriptor, proto) - } - override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) { // Serialization doesn't preserve enum entry order, so we need to serialize ordinal. val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(descriptor) @@ -51,22 +45,38 @@ internal class KonanSerializerExtension(val context: Context, override val metad super.serializeEnumEntry(descriptor, proto) } - override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder) { - - super.serializeConstructor(descriptor, proto) + override fun serializeConstructor(descriptor: ConstructorDescriptor, proto: ProtoBuf.Constructor.Builder, + childSerializer: DescriptorSerializer) { + super.serializeConstructor(descriptor, proto, childSerializer) + if (descriptor.needsSerializedIr) { + addConstructorIR(proto, serializeInlineBody(descriptor, childSerializer)) + } } - override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder, versionRequirementTable: MutableVersionRequirementTable) { - - super.serializeClass(descriptor, proto, versionRequirementTable) + override fun serializeClass(descriptor: ClassDescriptor, proto: ProtoBuf.Class.Builder, + versionRequirementTable: MutableVersionRequirementTable, + childSerializer: DescriptorSerializer) { + super.serializeClass(descriptor, proto, versionRequirementTable, childSerializer) + context.ir.classesDelegatedBackingFields[descriptor]?.forEach { + proto.addProperty(childSerializer.propertyProto(it)) + } + // Invocation of the propertyProto above can add more types + // to the type table that should also be serialized. + childSerializer.typeTable.serialize()?.let { proto.mergeTypeTable(it) } } - override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) { + override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder, + childSerializer: DescriptorSerializer) { proto.setExtension(KonanProtoBuf.functionFile, sourceFileMap.assign(descriptor.source.containingFile)) - super.serializeFunction(descriptor, proto) + super.serializeFunction(descriptor, proto, childSerializer) + if (descriptor.needsSerializedIr) { + addFunctionIR(proto, serializeInlineBody(descriptor, childSerializer)) + } } - override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder, versionRequirementTable: MutableVersionRequirementTable) { + override fun serializeProperty(descriptor: PropertyDescriptor, proto: ProtoBuf.Property.Builder, + versionRequirementTable: MutableVersionRequirementTable, + childSerializer: DescriptorSerializer) { val variable = originalVariables[descriptor] if (variable != null) { proto.setExtension(KonanProtoBuf.usedAsVariable, true) @@ -75,7 +85,15 @@ internal class KonanSerializerExtension(val context: Context, override val metad proto.setExtension(KonanProtoBuf.hasBackingField, context.ir.propertiesWithBackingFields.contains(descriptor)) - super.serializeProperty(descriptor, proto, versionRequirementTable) + super.serializeProperty(descriptor, proto, versionRequirementTable, childSerializer) + + /* Konan specific chunk */ + descriptor.getter?.onlyIf({ needsSerializedIr }) { + addGetterIR(proto, serializeInlineBody(it, childSerializer)) + } + descriptor.setter?.onlyIf({ needsSerializedIr }) { + addSetterIR(proto, serializeInlineBody(it, childSerializer)) + } } override fun addFunctionIR(proto: ProtoBuf.Function.Builder, serializedIR: String) @@ -90,7 +108,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad override fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String) = proto.setSetterIr(inlineBody(serializedIR)) - override fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String { + override fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: DescriptorSerializer): String { return IrSerializer( context, inlineDescriptorTable, stringTable, serializer, descriptor).serializeInlineBody() @@ -102,7 +120,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad internal interface IrAwareExtension { - fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: KonanDescriptorSerializer): String + fun serializeInlineBody(descriptor: FunctionDescriptor, serializer: DescriptorSerializer): String fun addFunctionIR(proto: ProtoBuf.Function.Builder, serializedIR: String): ProtoBuf.Function.Builder @@ -111,5 +129,4 @@ internal interface IrAwareExtension { fun addSetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String): ProtoBuf.Property.Builder fun addGetterIR(proto: ProtoBuf.Property.Builder, serializedIR: String): ProtoBuf.Property.Builder -} - +} \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt index 90d41d547fb..fe0c478b089 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/LocalDeclarationSerializer.kt @@ -18,12 +18,12 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations.Companion.EMPTY import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor -import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.metadata.KonanIr +import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.types.KotlinType /* - * This class knows how to create KonanDescriptorSerializer + * This class knows how to create DescriptorSerializer * invocations to serialize function local declaration descriptors. * Those descriptors are not part of the public descriptor tree. * @@ -32,9 +32,9 @@ import org.jetbrains.kotlin.types.KotlinType * And class serialization is context specific. */ -internal class LocalDeclarationSerializer(val context: Context, val rootFunctionSerializer: KonanDescriptorSerializer) { +internal class LocalDeclarationSerializer(val context: Context, val rootFunctionSerializer: DescriptorSerializer) { - private val contextStack = mutableListOf(rootFunctionSerializer) + private val contextStack = mutableListOf(rootFunctionSerializer) fun pushContext(descriptor: DeclarationDescriptor) { val previousContext = contextStack.peek()!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt index 5aaabd146ba..0d8a2b72d1b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/SerializeIr.kt @@ -30,7 +30,6 @@ import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.metadata.KonanIr import org.jetbrains.kotlin.metadata.KonanIr.IrConst.ValueCase.* import org.jetbrains.kotlin.metadata.KonanIr.IrOperation.OperationCase.* @@ -38,6 +37,7 @@ import org.jetbrains.kotlin.metadata.KonanIr.IrVarargElement.VarargElementCase.* import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.parents +import org.jetbrains.kotlin.serialization.DescriptorSerializer import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassConstructorDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor @@ -50,7 +50,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor internal class IrSerializer(val context: Context, descriptorTable: DescriptorTable, stringTable: KonanStringTable, - rootFunctionSerializer: KonanDescriptorSerializer, + rootFunctionSerializer: DescriptorSerializer, private var rootFunction: FunctionDescriptor) { private val loopIndex = mutableMapOf() diff --git a/gradle.properties b/gradle.properties index f002ee6a23f..ee3e02e42ec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,10 +18,9 @@ buildKotlinVersion=1.3.0-rc-116 buildKotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_130_CompilerAllPlugins),number:1.3.0-rc-116,tag:kotlin-native,pinned:true/artifacts/content/maven remoteRoot=konan_tests -testDataVersion=1226829:id -kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_CompilerAllPlugins),number:1.3.20-dev-1845,tag:kotlin-native,pinned:true/artifacts/content/maven -kotlinVersion=1.3.20-dev-1845 -testKotlinVersion=1.3.20-dev-1845 +kotlinCompilerRepo=https://teamcity.jetbrains.com/guestAuth/app/rest/builds/buildType:(id:Kotlin_dev_CompilerAllPlugins),number:1.3.20-dev-2050,tag:kotlin-native,pinned:true/artifacts/content/maven +kotlinVersion=1.3.20-dev-2050 +testKotlinVersion=1.3.20-dev-2050 konanVersion=1.1.0 org.gradle.jvmargs='-Dfile.encoding=UTF-8' org.gradle.workers.max=4 diff --git a/runtime/src/main/kotlin/kotlin/text/Strings.kt b/runtime/src/main/kotlin/kotlin/text/Strings.kt index d172a8e9917..906d05d5977 100644 --- a/runtime/src/main/kotlin/kotlin/text/Strings.kt +++ b/runtime/src/main/kotlin/kotlin/text/Strings.kt @@ -115,19 +115,19 @@ public actual inline fun String.substring(startIndex: Int): String = /** * Returns `true` if this string starts with the specified prefix. */ -public fun String.startsWith(prefix: String, ignoreCase: Boolean = false): Boolean = +public actual fun String.startsWith(prefix: String, ignoreCase: Boolean): Boolean = regionMatches(0, prefix, 0, prefix.length, ignoreCase) /** * Returns `true` if a substring of this string starting at the specified offset [startIndex] starts with the specified prefix. */ -public fun String.startsWith(prefix: String, startIndex: Int, ignoreCase: Boolean = false): Boolean = +public actual fun String.startsWith(prefix: String, startIndex: Int, ignoreCase: Boolean): Boolean = regionMatches(startIndex, prefix, 0, prefix.length, ignoreCase) /** * Returns `true` if this string ends with the specified suffix. */ -public fun String.endsWith(suffix: String, ignoreCase: Boolean = false): Boolean = +public actual fun String.endsWith(suffix: String, ignoreCase: Boolean): Boolean = regionMatches(length - suffix.length, suffix, 0, suffix.length, ignoreCase) /**