Don't emit fields for interop static const vals

This commit is contained in:
Svyatoslav Scherbina
2018-08-27 15:02:56 +03:00
committed by SvyatoslavScherbina
parent 037960558a
commit 5eaaa5bbb9
5 changed files with 47 additions and 7 deletions
@@ -65,7 +65,7 @@ internal fun produceOutput(context: Context, phaser: PhaseManager) {
val abiVersion = context.config.currentAbiVersion
val target = context.config.target
val nopack = config.getBoolean(KonanConfigKeys.NOPACK)
val manifest = config.get(KonanConfigKeys.MANIFEST_FILE)
val manifestProperties = context.config.manifestProperties
val library = buildLibrary(
context.config.nativeLibraries,
@@ -78,7 +78,7 @@ internal fun produceOutput(context: Context, phaser: PhaseManager) {
libraryName,
llvmModule,
nopack,
manifest,
manifestProperties,
context.dataFlowGraph)
context.library = library
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.KonanLibrary
import org.jetbrains.kotlin.konan.library.defaultResolver
import org.jetbrains.kotlin.konan.library.libraryResolver
import org.jetbrains.kotlin.konan.properties.loadProperties
import org.jetbrains.kotlin.konan.target.*
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
@@ -103,6 +104,12 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
internal val friendModuleFiles: Set<File> =
configuration.get(KonanConfigKeys.FRIEND_MODULES)?.map { File(it) }?.toSet() ?: emptySet()
internal val manifestProperties = configuration.get(KonanConfigKeys.MANIFEST_FILE)?.let {
File(it).loadProperties()
}
internal val isInteropStubs: Boolean get() = manifestProperties?.getProperty("interop") == "true"
}
fun CompilerConfiguration.report(priority: CompilerMessageSeverity, message: String)
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.library
import llvm.LLVMModuleRef
import org.jetbrains.kotlin.konan.library.KonanLibrary
import java.util.*
const val KLIB_CURRENT_ABI_VERSION = 1
@@ -16,7 +17,7 @@ interface KonanLibraryWriter {
fun addIncludedBinary(library: String)
fun addKotlinBitcode(llvmModule: LLVMModuleRef)
fun addLinkDependencies(libraries: List<KonanLibrary>)
fun addManifestAddend(path: String)
fun addManifestAddend(properties: Properties)
fun addDataFlowGraph(dataFlowGraph: ByteArray)
val mainBitcodeFileName: String
fun commit()
@@ -88,8 +88,7 @@ class LibraryWriterImpl(
}
}
override fun addManifestAddend(path: String) {
val properties = File(path).loadProperties()
override fun addManifestAddend(properties: Properties) {
manifestProperties.putAll(properties)
}
@@ -117,7 +116,7 @@ internal fun buildLibrary(
moduleName: String,
llvmModule: LLVMModuleRef,
nopack: Boolean,
manifest: String?,
manifestProperties: Properties?,
dataFlowGraph: ByteArray?): KonanLibraryWriter {
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
@@ -130,7 +129,7 @@ internal fun buildLibrary(
included.forEach {
library.addIncludedBinary(it)
}
manifest ?.let { library.addManifestAddend(it) }
manifestProperties?.let { library.addManifestAddend(it) }
library.addLinkDependencies(linkDependencies)
dataFlowGraph?.let { library.addDataFlowGraph(it) }
@@ -674,6 +674,39 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
}
}
override fun visitProperty(declaration: IrProperty): IrStatement {
val backingField = declaration.backingField
return if (declaration.isConst && backingField?.isStatic == true && context.config.isInteropStubs) {
// Transform top-level `const val x = 42` to `val x get() = 42`.
// Generally this transformation is just an optimization to ensure that interop constants
// don't require any storage and/or initialization at program startup.
// Also it is useful due to uncertain design of top-level stored properties in Kotlin/Native.
val initializer = backingField.initializer!!.expression
declaration.backingField = null
val getter = declaration.getter!!
val getterBody = getter.body!! as IrBlockBody
getterBody.statements.clear()
getterBody.statements += IrReturnImpl(
declaration.startOffset,
declaration.endOffset,
context.irBuiltIns.nothingType,
getter.symbol,
initializer
)
// Note: in interop stubs const val initializer is either `IrConst` or quite simple expression,
// so it is ok to compute it every time.
assert(declaration.setter == null)
assert(!declaration.isVar)
declaration.transformChildrenVoid()
declaration
} else {
super.visitProperty(declaration)
}
}
private fun IrBuilderWithScope.callAllocAndInit(
classPtr: IrExpression,
initMethodInfo: ObjCMethodInfo,