From e0117fd2976896d3e4a8719b086ac2a365eaeefc Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Thu, 30 Jan 2020 18:52:44 +0700 Subject: [PATCH] [StubIr] Support for structs --- .../kotlin/native/interop/gen/StubIr.kt | 11 +++- .../interop/gen/StubIrElementBuilders.kt | 53 ++++++++++++++----- .../interop/gen/StubIrMetadataEmitter.kt | 11 ++++ .../native/interop/gen/StubIrTextEmitter.kt | 5 +- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt index a2641da4080..0fe2b915250 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIr.kt @@ -199,8 +199,13 @@ sealed class AnnotationStub(val classifier: Classifier) { class Symbol(val symbolName: String) : CCall(cCallClassifier) } - class CStruct(val struct: String) : - AnnotationStub(Classifier.topLevel(cinteropInternalPackage, "CStruct")) + class CStruct(val struct: String) : AnnotationStub(cStructClassifier) { + class MemberAt(val offset: Long) : AnnotationStub(cStructClassifier.nested("MemberAt")) + + class BitField(val offset: Long, val size: Int) : AnnotationStub(cStructClassifier.nested("BitField")) + + class VarType(val size: Long, val align: Int) : AnnotationStub(cStructClassifier.nested("VarType")) + } class CNaturalStruct(val members: List) : AnnotationStub(Classifier.topLevel(cinteropPackage, "CNaturalStruct")) @@ -220,6 +225,8 @@ sealed class AnnotationStub(val classifier: Classifier) { private companion object { val cCallClassifier = Classifier.topLevel(cinteropInternalPackage, "CCall") + + val cStructClassifier = Classifier.topLevel(cinteropInternalPackage, "CStruct") } } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt index 668f05fd564..a45fddfcba3 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrElementBuilders.kt @@ -84,20 +84,37 @@ internal class StructStubBuilder( } else { emptyList() } - val kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.ArrayMemberAt(offset)) + val getter = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> PropertyAccessor.Getter.ArrayMemberAt(offset) + GenerationMode.METADATA -> PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + } + val kind = PropertyStub.Kind.Val(getter) // TODO: Should receiver be added? PropertyStub(field.name, type.toStubIrType(), kind, annotations = annotations, origin = origin) } else { val pointedType = fieldRefType.pointedType.toStubIrType() val pointedTypeArgument = TypeArgumentStub(pointedType) if (fieldRefType is TypeMirror.ByValue) { - val kind = PropertyStub.Kind.Var( - PropertyAccessor.Getter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument), hasValueAccessor = true), - PropertyAccessor.Setter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument)) - ) + val getter: PropertyAccessor.Getter + val setter: PropertyAccessor.Setter + when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + getter = PropertyAccessor.Getter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument), hasValueAccessor = true) + setter = PropertyAccessor.Setter.MemberAt(offset, typeArguments = listOf(pointedTypeArgument)) + } + GenerationMode.METADATA -> { + getter = PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + setter = PropertyAccessor.Setter.ExternalSetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + } + } + val kind = PropertyStub.Kind.Var(getter, setter) PropertyStub(field.name, fieldRefType.argType.toStubIrType(), kind, origin = origin) } else { - val kind = PropertyStub.Kind.Val(PropertyAccessor.Getter.MemberAt(offset, hasValueAccessor = false)) + val accessor = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> PropertyAccessor.Getter.MemberAt(offset, hasValueAccessor = false) + GenerationMode.METADATA -> PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.MemberAt(offset))) + } + val kind = PropertyStub.Kind.Val(accessor) PropertyStub(field.name, pointedType, kind, origin = origin) } } @@ -111,11 +128,20 @@ internal class StructStubBuilder( val typeInfo = typeMirror.info val kotlinType = typeMirror.argType val signed = field.type.isIntegerTypeSigned() - val readBits = PropertyAccessor.Getter.ReadBits(field.offset, field.size, signed) - val writeBits = PropertyAccessor.Setter.WriteBits(field.offset, field.size) - context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo) - context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo) - val kind = PropertyStub.Kind.Var(readBits, writeBits) + val kind = when (context.generationMode) { + GenerationMode.SOURCE_CODE -> { + val readBits = PropertyAccessor.Getter.ReadBits(field.offset, field.size, signed) + val writeBits = PropertyAccessor.Setter.WriteBits(field.offset, field.size) + context.bridgeComponentsBuilder.getterToBridgeInfo[readBits] = BridgeGenerationInfo("", typeInfo) + context.bridgeComponentsBuilder.setterToBridgeInfo[writeBits] = BridgeGenerationInfo("", typeInfo) + PropertyStub.Kind.Var(readBits, writeBits) + } + GenerationMode.METADATA -> { + val readBits = PropertyAccessor.Getter.ExternalGetter(listOf(AnnotationStub.CStruct.BitField(field.offset, field.size))) + val writeBits = PropertyAccessor.Setter.ExternalSetter(listOf(AnnotationStub.CStruct.BitField(field.offset, field.size))) + PropertyStub.Kind.Var(readBits, writeBits) + } + } PropertyStub(field.name, kotlinType.toStubIrType(), kind, origin = StubOrigin.StructMember(field)) } @@ -135,7 +161,10 @@ internal class StructStubBuilder( val typeSize = listOf(IntegralConstantStub(def.size, 4, true), IntegralConstantStub(def.align.toLong(), 4, true)) val companionSuperInit = SuperClassInit(companionSuper, typeSize) val companionClassifier = classifier.nested("Companion") - val companion = ClassStub.Companion(companionClassifier, emptyList(), companionSuperInit) + val annotation = AnnotationStub.CStruct.VarType(def.size, def.align).takeIf { + context.generationMode == GenerationMode.METADATA + } + val companion = ClassStub.Companion(companionClassifier, superClassInit = companionSuperInit, annotations = listOfNotNull(annotation)) return listOf(ClassStub.Simple( classifier, diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt index 6d317d42154..2316ebf6fcc 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrMetadataEmitter.kt @@ -390,6 +390,17 @@ private class MappingExtensions( is AnnotationStub.CEnumVarTypeSize -> mapOfNotNull( ("size" to KmAnnotationArgument.IntValue(size)) ) + is AnnotationStub.CStruct.MemberAt -> mapOfNotNull( + ("offset" to KmAnnotationArgument.LongValue(offset)) + ) + is AnnotationStub.CStruct.BitField -> mapOfNotNull( + ("offset" to KmAnnotationArgument.LongValue(offset)), + ("size" to KmAnnotationArgument.IntValue(size)) + ) + is AnnotationStub.CStruct.VarType -> mapOfNotNull( + ("size" to KmAnnotationArgument.LongValue(size)), + ("align" to KmAnnotationArgument.IntValue(align)) + ) } return KmAnnotation(classifier.fqNameSerialized, args) } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt index 5c612fe3605..88ee2bea9d2 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/StubIrTextEmitter.kt @@ -497,7 +497,10 @@ class StubIrTextEmitter( "ReplaceWith(${annotationStub.replaceWith.quoteAsKotlinLiteral()}), " + "DeprecationLevel.ERROR)" is AnnotationStub.CEnumEntryAlias, - is AnnotationStub.CEnumVarTypeSize -> + is AnnotationStub.CEnumVarTypeSize, + is AnnotationStub.CStruct.MemberAt, + is AnnotationStub.CStruct.BitField, + is AnnotationStub.CStruct.VarType -> error("${annotationStub.classifier.fqName} annotation is unsupported in textual mode") }