diff --git a/Interop/StubGenerator/build.gradle b/Interop/StubGenerator/build.gradle index c03109ffe79..b73417847a8 100644 --- a/Interop/StubGenerator/build.gradle +++ b/Interop/StubGenerator/build.gradle @@ -36,3 +36,9 @@ dependencies { compile project(':Interop:Indexer') compile "org.jetbrains.kotlin:kotlin-native-shared:$konanVersion" } + +compileKotlin { + kotlinOptions { + freeCompilerArgs = ['-Xuse-experimental=kotlin.ExperimentalUnsignedTypes'] + } +} diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt index 6316d0ad63e..07d2649dad3 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/StubGenerator.kt @@ -732,32 +732,31 @@ class StubGenerator( } private fun integerLiteral(size: Int, isSigned: Boolean, value: Long): String? { - if (!isSigned) { - val signedLiteral = integerLiteral(size, true, value) - val converter = when (size) { - 1 -> "toUByte" - 2 -> "toUShort" - 4 -> "toUInt" - 8 -> "toULong" + return if (isSigned) { + if (value == Long.MIN_VALUE) { + return "${value + 1} - 1" // Workaround for "The value is out of range" compile error. + } + + val narrowedValue: Number = when (size) { + 1 -> value.toByte() + 2 -> value.toShort() + 4 -> value.toInt() + 8 -> value else -> return null } - return "($signedLiteral).$converter()" - } + narrowedValue.toString() + } else { + val narrowedValue: Any = when (size) { + 1 -> value.toUByte() + 2 -> value.toUShort() + 4 -> value.toUInt() + 8 -> value.toULong() + else -> return null + } - if (value == Long.MIN_VALUE) { - return "${value + 1} - 1" // Workaround for "The value is out of range" compile error. + "${narrowedValue}u" } - - val narrowedValue: Number = when (size) { - 1 -> value.toByte() - 2 -> value.toShort() - 4 -> value.toInt() - 8 -> value - else -> return null - } - - return narrowedValue.toString() } private fun floatingLiteral(type: Type, value: Double): String? { @@ -777,37 +776,41 @@ class StubGenerator( } } + private fun topLevelValWithGetter(name: String, type: KotlinType, expressionBody: String): String = + "val ${name.asSimpleName()}: ${type.render(kotlinFile)} get() = $expressionBody" + + private fun topLevelConstVal(name: String, type: KotlinType, initializer: String): String = + "const val ${name.asSimpleName()}: ${type.render(kotlinFile)} = $initializer" + private fun generateConstant(constant: ConstantDef) { - val literal = when (constant) { - is IntegerConstantDef -> integerLiteral(constant.type, constant.value) ?: return - is FloatingConstantDef -> floatingLiteral(constant.type, constant.value) ?: return - is StringConstantDef -> constant.value.quoteAsKotlinLiteral() - else -> { - // Not supported yet, ignore: - return + val kotlinName = constant.name + val declaration = when (constant) { + is IntegerConstantDef -> { + val literal = integerLiteral(constant.type, constant.value) ?: return + val kotlinType = mirror(constant.type).argType + when (platform) { + KotlinPlatform.NATIVE -> topLevelConstVal(kotlinName, kotlinType, literal) + // No reason to make it const val with backing field on Kotlin/JVM yet: + KotlinPlatform.JVM -> topLevelValWithGetter(kotlinName, kotlinType, literal) + } } + is FloatingConstantDef -> { + val literal = floatingLiteral(constant.type, constant.value) ?: return + val kotlinType = mirror(constant.type).argType + topLevelValWithGetter(kotlinName, kotlinType, literal) + } + is StringConstantDef -> { + val literal = constant.value.quoteAsKotlinLiteral() + val kotlinType = KotlinTypes.string + topLevelValWithGetter(kotlinName, kotlinType, literal) + } + else -> return } - val kotlinType = when (constant) { - is IntegerConstantDef, - is FloatingConstantDef -> mirror(constant.type).argType + out(declaration) - is StringConstantDef -> KotlinTypes.string - - else -> { - // Not supported yet, ignore: - return - } - }.render(kotlinFile) - - // TODO: improve value rendering. - - // TODO: consider using `const` modifier. - // It is not currently possible for floating literals. - // Also it provokes constant propagation which can reduce binary compatibility - // when replacing interop stubs without recompiling the application. - - out("val ${constant.name.asSimpleName()}: $kotlinType get() = $literal") + // TODO: consider using `const` modifier in all cases. + // Note: It is not currently possible for floating literals. } private fun generateStubs(): List { diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/KonanModuleOrigin.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/KonanModuleOrigin.kt index 8288183842f..85b6c3b6ee0 100644 --- a/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/KonanModuleOrigin.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/KonanModuleOrigin.kt @@ -2,6 +2,7 @@ package org.jetbrains.kotlin.descriptors.konan import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.isInterop sealed class KonanModuleOrigin { @@ -18,4 +19,9 @@ object CurrentKonanModuleOrigin: CompiledKonanModuleOrigin() object SyntheticModulesOrigin : KonanModuleOrigin() +internal fun KonanModuleOrigin.isInteropLibrary(): Boolean = when (this) { + is DeserializedKonanModuleOrigin -> this.library.isInterop + CurrentKonanModuleOrigin, SyntheticModulesOrigin -> false +} + val ModuleDescriptor.konanModuleOrigin get() = this.getCapability(KonanModuleOrigin.CAPABILITY)!! diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/impl/KonanModuleDescriptorFactoryImpl.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/impl/KonanModuleDescriptorFactoryImpl.kt index 75c6d3a5532..b62b3236751 100644 --- a/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/impl/KonanModuleDescriptorFactoryImpl.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/descriptors/konan/impl/KonanModuleDescriptorFactoryImpl.kt @@ -6,7 +6,9 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.konan.KonanModuleDescriptorFactory import org.jetbrains.kotlin.descriptors.konan.KonanModuleOrigin +import org.jetbrains.kotlin.descriptors.konan.isInteropLibrary import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.ImplicitIntegerCoercion import org.jetbrains.kotlin.storage.StorageManager internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory { @@ -21,7 +23,10 @@ internal object KonanModuleDescriptorFactoryImpl: KonanModuleDescriptorFactory { name, storageManager, builtIns, - capabilities = customCapabilities + mapOf(KonanModuleOrigin.CAPABILITY to origin)) + capabilities = customCapabilities + mapOf( + KonanModuleOrigin.CAPABILITY to origin, + ImplicitIntegerCoercion.MODULE_CAPABILITY to origin.isInteropLibrary() + )) override fun createDescriptorAndNewBuiltIns( name: Name,