[StubIr] Refactor origins

1. Get rid of useless origin for FunctionParameterStub.
2. Add origins for enum entries and struct members.
3. Put all synthetic origins under single sealed class.
4. Add mangling for enum entries.
This commit is contained in:
Sergey Bogolepov
2020-01-27 13:05:00 +07:00
committed by Sergey Bogolepov
parent 3a4620cd33
commit bb34a0f22b
6 changed files with 60 additions and 27 deletions
@@ -37,6 +37,7 @@ sealed class ManglingContext {
interface InteropMangler { interface InteropMangler {
val StructDecl.uniqueSymbolName: String val StructDecl.uniqueSymbolName: String
val EnumDef.uniqueSymbolName: String val EnumDef.uniqueSymbolName: String
val EnumConstant.uniqSymbolName: String
val ObjCClass.uniqueSymbolName: String val ObjCClass.uniqueSymbolName: String
val ObjCClass.metaClassUniqueSymbolName: String val ObjCClass.metaClassUniqueSymbolName: String
val ObjCProtocol.uniqueSymbolName: String val ObjCProtocol.uniqueSymbolName: String
@@ -63,6 +64,9 @@ class KotlinLikeInteropMangler(context: ManglingContext = ManglingContext.Empty)
override val EnumDef.uniqueSymbolName: String override val EnumDef.uniqueSymbolName: String
get() = "enumdef:$prefix$spelling" get() = "enumdef:$prefix$spelling"
override val EnumConstant.uniqSymbolName: String
get() = "enumconstant:$prefix$name"
override val ObjCClass.uniqueSymbolName: String override val ObjCClass.uniqueSymbolName: String
get() = "objcclass:$prefix$name" get() = "objcclass:$prefix$name"
@@ -435,7 +435,7 @@ internal abstract class ObjCContainerStubBuilder(
ConstructorStub( ConstructorStub(
isPrimary = false, isPrimary = false,
visibility = VisibilityModifier.PROTECTED, visibility = VisibilityModifier.PROTECTED,
origin = StubOrigin.SyntheticDefaultConstructor) origin = StubOrigin.Synthetic.DefaultConstructor)
} else null } else null
return Pair( return Pair(
@@ -91,13 +91,29 @@ sealed class StubOrigin {
/** /**
* Special case when element of IR was generated. * Special case when element of IR was generated.
*/ */
// TODO: All "synthetic" cases should be handled separately. sealed class Synthetic : StubOrigin() {
object Synthetic : StubOrigin() object CompanionObject : Synthetic()
/** /**
* Denotes default constructor that was generated and has no real origin. * Denotes default constructor that was generated and has no real origin.
*/ */
object SyntheticDefaultConstructor : StubOrigin() object DefaultConstructor : Synthetic()
/**
* CEnum.Companion.byValue.
*/
class EnumByValue(val enum: EnumDef) : Synthetic()
/**
* CEnum.value.
*/
class EnumValueField(val enum: EnumDef) : Synthetic()
/**
* E.CEnumVar.value.
*/
class EnumVarValueField(val enum: EnumDef) : Synthetic()
}
class ObjCCategoryInitMethod( class ObjCCategoryInitMethod(
val method: org.jetbrains.kotlin.native.interop.indexer.ObjCMethod val method: org.jetbrains.kotlin.native.interop.indexer.ObjCMethod
@@ -125,13 +141,16 @@ sealed class StubOrigin {
class Enum(val enum: EnumDef) : StubOrigin() class Enum(val enum: EnumDef) : StubOrigin()
class EnumEntry(val constant: EnumConstant) : StubOrigin()
class Function(val function: FunctionDecl) : StubOrigin() class Function(val function: FunctionDecl) : StubOrigin()
// TODO: Unused, remove.
class FunctionParameter(val parameter: Parameter) : StubOrigin()
class Struct(val struct: StructDecl) : StubOrigin() class Struct(val struct: StructDecl) : StubOrigin()
class StructMember(
val member: org.jetbrains.kotlin.native.interop.indexer.StructMember
) : StubOrigin()
class Constant(val constantDef: ConstantDef): StubOrigin() class Constant(val constantDef: ConstantDef): StubOrigin()
class Global(val global: GlobalDecl) : StubOrigin() class Global(val global: GlobalDecl) : StubOrigin()
@@ -283,7 +302,7 @@ sealed class ClassStub : StubContainer(), StubElementWithOrigin, AnnotationHolde
override val superClassInit: SuperClassInit? = null, override val superClassInit: SuperClassInit? = null,
override val interfaces: List<StubType> = emptyList(), override val interfaces: List<StubType> = emptyList(),
override val properties: List<PropertyStub> = emptyList(), override val properties: List<PropertyStub> = emptyList(),
override val origin: StubOrigin = StubOrigin.Synthetic, override val origin: StubOrigin = StubOrigin.Synthetic.CompanionObject,
override val annotations: List<AnnotationStub> = emptyList(), override val annotations: List<AnnotationStub> = emptyList(),
override val childrenClasses: List<ClassStub> = emptyList(), override val childrenClasses: List<ClassStub> = emptyList(),
override val simpleContainers: List<SimpleStubContainer> = emptyList() override val simpleContainers: List<SimpleStubContainer> = emptyList()
@@ -328,8 +347,7 @@ class FunctionParameterStub(
val name: String, val name: String,
val type: StubType, val type: StubType,
override val annotations: List<AnnotationStub> = emptyList(), override val annotations: List<AnnotationStub> = emptyList(),
val isVararg: Boolean = false, val isVararg: Boolean = false
val origin: StubOrigin = StubOrigin.Synthetic
) : AnnotationHolder ) : AnnotationHolder
enum class MemberStubModality { enum class MemberStubModality {
@@ -454,7 +472,8 @@ class ConstructorStub(
class EnumEntryStub( class EnumEntryStub(
val name: String, val name: String,
val constant: IntegralConstantStub, val constant: IntegralConstantStub,
val aliases: List<Alias> val aliases: List<Alias>,
val origin: StubOrigin.EnumEntry
) { ) {
class Alias(val name: String) class Alias(val name: String)
} }
@@ -73,7 +73,7 @@ internal class StructStubBuilder(
val offset = field.offset / 8 val offset = field.offset / 8
val fieldRefType = context.mirror(field.type) val fieldRefType = context.mirror(field.type)
val unwrappedFieldType = field.type.unwrapTypedefs() val unwrappedFieldType = field.type.unwrapTypedefs()
val origin = StubOrigin.Synthetic val origin = StubOrigin.StructMember(field)
if (unwrappedFieldType is ArrayType) { if (unwrappedFieldType is ArrayType) {
val type = (fieldRefType as TypeMirror.ByValue).valueType val type = (fieldRefType as TypeMirror.ByValue).valueType
val annotations = if (platform == KotlinPlatform.JVM) { val annotations = if (platform == KotlinPlatform.JVM) {
@@ -115,7 +115,7 @@ internal class StructStubBuilder(
context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo) context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo)
context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo) context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo)
val kind = PropertyStub.Kind.Var(readBits, writeBits) val kind = PropertyStub.Kind.Var(readBits, writeBits)
PropertyStub(field.name, kotlinType.toStubIrType(), kind, origin = StubOrigin.Synthetic) PropertyStub(field.name, kotlinType.toStubIrType(), kind, origin = StubOrigin.StructMember(field))
} }
val superClass = context.platform.getRuntimeType("CStructVar") val superClass = context.platform.getRuntimeType("CStructVar")
@@ -215,7 +215,7 @@ internal class EnumStubBuilder(
type = baseType, type = baseType,
kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetConstructorParameter(constructorParameter)), kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.GetConstructorParameter(constructorParameter)),
modality = MemberStubModality.OPEN, modality = MemberStubModality.OPEN,
origin = StubOrigin.Synthetic, origin = StubOrigin.Synthetic.EnumValueField(enumDef),
isOverride = true) isOverride = true)
val canonicalsByValue = enumDef.constants val canonicalsByValue = enumDef.constants
@@ -233,7 +233,7 @@ internal class EnumStubBuilder(
val literal = context.tryCreateIntegralStub(enumDef.baseType, constant.value) val literal = context.tryCreateIntegralStub(enumDef.baseType, constant.value)
?: error("Cannot create enum value ${constant.value} of type ${enumDef.baseType}") ?: error("Cannot create enum value ${constant.value} of type ${enumDef.baseType}")
val aliases = aliasConstants.filter { it.value == constant.value }.map { EnumEntryStub.Alias(it.name) } val aliases = aliasConstants.filter { it.value == constant.value }.map { EnumEntryStub.Alias(it.name) }
EnumEntryStub(constant.name, literal, aliases) EnumEntryStub(constant.name, literal, aliases, StubOrigin.EnumEntry(constant))
} }
val origin = StubOrigin.Enum(enumDef) val origin = StubOrigin.Enum(enumDef)
val primaryConstructor = ConstructorStub(listOf(constructorParameter), emptyList(), isPrimary = true, origin = origin) val primaryConstructor = ConstructorStub(listOf(constructorParameter), emptyList(), isPrimary = true, origin = origin)
@@ -303,7 +303,7 @@ internal class EnumStubBuilder(
kind, kind,
MemberStubModality.FINAL, MemberStubModality.FINAL,
null, null,
origin = StubOrigin.Synthetic origin = StubOrigin.EnumEntry(constant)
) )
} }
val container = SimpleStubContainer( val container = SimpleStubContainer(
@@ -333,7 +333,6 @@ internal class FunctionStubBuilder(
} }
val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type) val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type)
val origin = StubOrigin.FunctionParameter(parameter)
parameters += when { parameters += when {
representCFunctionParameterAsString(func, parameter.type) -> { representCFunctionParameterAsString(func, parameter.type) -> {
val annotations = when (platform) { val annotations = when (platform) {
@@ -341,7 +340,7 @@ internal class FunctionStubBuilder(
KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.CString) KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.CString)
} }
val type = KotlinTypes.string.makeNullable().toStubIrType() val type = KotlinTypes.string.makeNullable().toStubIrType()
val functionParameterStub = FunctionParameterStub(parameterName, type, annotations, origin = origin) val functionParameterStub = FunctionParameterStub(parameterName, type, annotations)
context.bridgeComponentsBuilder.cStringParameters += functionParameterStub context.bridgeComponentsBuilder.cStringParameters += functionParameterStub
functionParameterStub functionParameterStub
} }
@@ -351,17 +350,17 @@ internal class FunctionStubBuilder(
KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.WCString) KotlinPlatform.NATIVE -> listOf(AnnotationStub.CCall.WCString)
} }
val type = KotlinTypes.string.makeNullable().toStubIrType() val type = KotlinTypes.string.makeNullable().toStubIrType()
val functionParameterStub = FunctionParameterStub(parameterName, type, annotations, origin = origin) val functionParameterStub = FunctionParameterStub(parameterName, type, annotations)
context.bridgeComponentsBuilder.wCStringParameters += functionParameterStub context.bridgeComponentsBuilder.wCStringParameters += functionParameterStub
functionParameterStub functionParameterStub
} }
representAsValuesRef != null -> { representAsValuesRef != null -> {
FunctionParameterStub(parameterName, representAsValuesRef.toStubIrType(), origin = origin) FunctionParameterStub(parameterName, representAsValuesRef.toStubIrType())
} }
else -> { else -> {
val mirror = context.mirror(parameter.type) val mirror = context.mirror(parameter.type)
val type = mirror.argType.toStubIrType() val type = mirror.argType.toStubIrType()
FunctionParameterStub(parameterName, type, origin = origin) FunctionParameterStub(parameterName, type)
} }
} }
} }
@@ -83,7 +83,7 @@ internal class ModuleMetadataEmitter(
typeParametersInterner = Interner(data.typeParametersInterner) typeParametersInterner = Interner(data.typeParametersInterner)
) )
val children = element.children + if (element is ClassStub.Companion) { val children = element.children + if (element is ClassStub.Companion) {
listOf(ConstructorStub(isPrimary = true, visibility = VisibilityModifier.PRIVATE, origin = StubOrigin.SyntheticDefaultConstructor)) listOf(ConstructorStub(isPrimary = true, visibility = VisibilityModifier.PRIVATE, origin = StubOrigin.Synthetic.DefaultConstructor))
} else emptyList() } else emptyList()
val elements = KmElements(children.map { it.accept(this, classVisitingContext) }) val elements = KmElements(children.map { it.accept(this, classVisitingContext) })
val kmClass = with (MappingExtensions(data.typeParametersInterner)) { val kmClass = with (MappingExtensions(data.typeParametersInterner)) {
@@ -21,6 +21,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) {
is StubOrigin.Function -> function.origin.function.uniqueSymbolName is StubOrigin.Function -> function.origin.function.uniqueSymbolName
is StubOrigin.ObjCMethod -> function.origin.method.uniqueSymbolName is StubOrigin.ObjCMethod -> function.origin.method.uniqueSymbolName
is StubOrigin.ObjCCategoryInitMethod -> "${function.origin.method.uniqueSymbolName}#Create" is StubOrigin.ObjCCategoryInitMethod -> "${function.origin.method.uniqueSymbolName}#Create"
is StubOrigin.Synthetic.EnumByValue -> "${function.origin.enum.uniqueSymbolName}#ByValue"
else -> error("Unexpected origin ${function.origin} for function ${function.name}.") else -> error("Unexpected origin ${function.origin} for function ${function.name}.")
}.toUniqId() }.toUniqId()
} }
@@ -30,7 +31,12 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) {
is StubOrigin.ObjCProperty -> property.origin.property.uniqueSymbolName is StubOrigin.ObjCProperty -> property.origin.property.uniqueSymbolName
is StubOrigin.Constant -> property.origin.constantDef.uniqueSymbolName is StubOrigin.Constant -> property.origin.constantDef.uniqueSymbolName
is StubOrigin.Global -> property.origin.global.uniqueSymbolName is StubOrigin.Global -> property.origin.global.uniqueSymbolName
// TODO: What to do with origin for enum entries and struct fields? // TODO: Is it correct for entries that are emitted as top-level constants?
// Should we emit the same uniq id for constants and enum entries?
is StubOrigin.EnumEntry -> property.origin.constant.uniqSymbolName
is StubOrigin.Synthetic.EnumValueField -> "${property.origin.enum.uniqueSymbolName}#Value"
is StubOrigin.StructMember -> property.origin.member.name
is StubOrigin.Synthetic.EnumVarValueField -> "${property.origin.enum.uniqueSymbolName}#Var"
else -> error("Unexpected origin ${property.origin} for property ${property.name}.") else -> error("Unexpected origin ${property.origin} for property ${property.name}.")
}.toUniqId() }.toUniqId()
} }
@@ -60,6 +66,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) {
} }
is StubOrigin.Struct -> origin.struct.uniqueSymbolName is StubOrigin.Struct -> origin.struct.uniqueSymbolName
is StubOrigin.Enum -> origin.enum.uniqueSymbolName is StubOrigin.Enum -> origin.enum.uniqueSymbolName
is StubOrigin.VarOf -> "${uniqSymbolNameForClass(origin.typeOrigin)}#Var"
else -> null else -> null
} }
@@ -72,7 +79,7 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) {
}.toUniqId() }.toUniqId()
private fun InteropMangler.uniqSymbolNameForConstructor(origin: StubOrigin): String? = when (origin) { private fun InteropMangler.uniqSymbolNameForConstructor(origin: StubOrigin): String? = when (origin) {
is StubOrigin.SyntheticDefaultConstructor -> "${context.prefix}#Constructor" is StubOrigin.Synthetic.DefaultConstructor -> "${context.prefix}#Constructor"
is StubOrigin.Enum -> "${origin.enum.uniqueSymbolName}#Constructor" is StubOrigin.Enum -> "${origin.enum.uniqueSymbolName}#Constructor"
is StubOrigin.Struct -> "${origin.struct.uniqueSymbolName}#Constructor" is StubOrigin.Struct -> "${origin.struct.uniqueSymbolName}#Constructor"
is StubOrigin.ObjCMethod -> "${origin.method.uniqueSymbolName}#Constructor" is StubOrigin.ObjCMethod -> "${origin.method.uniqueSymbolName}#Constructor"
@@ -84,6 +91,10 @@ internal class StubIrUniqIdProvider(private val context: ManglingContext) {
?: error("Unexpected origin ${constructorStub.origin} for constructor.") ?: error("Unexpected origin ${constructorStub.origin} for constructor.")
}.toUniqId() }.toUniqId()
fun uniqIdForEnumEntry(enumEntry: EnumEntryStub, enum: ClassStub.Enum): UniqId = with (mangler) {
"${uniqSymbolNameForClass(enum.origin)}#${enumEntry.origin.constant.name}"
}.toUniqId()
/** /**
* MSB should be set to 1 for public declarations. * MSB should be set to 1 for public declarations.
* @see org.jetbrains.kotlin.ir.util.UniqId * @see org.jetbrains.kotlin.ir.util.UniqId