Implemented code generation of combined IR of all libraries
This commit is contained in:
@@ -153,7 +153,6 @@ classes.dependsOn 'compilerClasses', 'cli_bcClasses', 'bc_frontendClasses'
|
||||
|
||||
// These are just a couple of aliases
|
||||
task stdlib(dependsOn: "${hostName}Stdlib")
|
||||
task start(dependsOn: "${hostName}Start")
|
||||
|
||||
def commonSrc = file('build/stdlib')
|
||||
|
||||
@@ -180,7 +179,8 @@ final List<File> stdLibSrc = [
|
||||
project(':Interop:Runtime').file('src/main/kotlin'),
|
||||
project(':Interop:Runtime').file('src/native/kotlin'),
|
||||
project(':Interop:JsRuntime').file('src/main/kotlin'),
|
||||
project(':runtime').file('src/main/kotlin')
|
||||
project(':runtime').file('src/main/kotlin'),
|
||||
project(':runtime').file('src/launcher/kotlin')
|
||||
]
|
||||
|
||||
task zipStdLibSources(type: Zip, dependsOn: unzipStdlibSources) {
|
||||
@@ -244,21 +244,6 @@ targetList.each { target ->
|
||||
dependsOn ":runtime:${target}Runtime"
|
||||
dependsOn ":distCompiler"
|
||||
}
|
||||
|
||||
task("${target}Start", type: JavaExec) {
|
||||
main = 'org.jetbrains.kotlin.cli.bc.K2NativeKt'
|
||||
classpath = project.configurations.cli_bc
|
||||
jvmArgs = konanJvmArgs
|
||||
args = [*konanArgs, '-produce', 'bitcode',
|
||||
'-output', project(':runtime').file("build/${target}Start"),
|
||||
'-library', project(':runtime').file("build/${target}Stdlib"),
|
||||
project(':runtime').file('src/launcher/kotlin')]
|
||||
|
||||
inputs.dir(project(':runtime').file('src/launcher/kotlin'))
|
||||
outputs.file(project(':runtime').file("build/${target}Start.bc"))
|
||||
|
||||
dependsOn ":runtime:${target}Runtime", "${target}Stdlib"
|
||||
}
|
||||
}
|
||||
|
||||
task run {
|
||||
|
||||
+6
-8
@@ -29,7 +29,6 @@ internal fun produceCStubs(context: Context) {
|
||||
|
||||
internal fun produceOutput(context: Context) {
|
||||
|
||||
val llvmModule = context.llvmModule!!
|
||||
val config = context.config.configuration
|
||||
val tempFiles = context.config.tempFiles
|
||||
val produce = config.get(KonanConfigKeys.PRODUCE)
|
||||
@@ -42,7 +41,7 @@ internal fun produceOutput(context: Context) {
|
||||
val output = tempFiles.nativeBinaryFileName
|
||||
context.bitcodeFileName = output
|
||||
|
||||
val generatedBitcodeFiles =
|
||||
val generatedBitcodeFiles =
|
||||
if (produce == CompilerOutputKind.DYNAMIC || produce == CompilerOutputKind.STATIC) {
|
||||
produceCAdapterBitcode(
|
||||
context.config.clang,
|
||||
@@ -57,16 +56,15 @@ internal fun produceOutput(context: Context) {
|
||||
generatedBitcodeFiles
|
||||
|
||||
for (library in nativeLibraries) {
|
||||
parseAndLinkBitcodeFile(llvmModule, library)
|
||||
parseAndLinkBitcodeFile(context.llvmModule!!, library)
|
||||
}
|
||||
|
||||
LLVMWriteBitcodeToFile(llvmModule, output)
|
||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||
}
|
||||
CompilerOutputKind.LIBRARY -> {
|
||||
val output = context.config.outputFiles.outputName
|
||||
val libraryName = context.config.moduleId
|
||||
val neededLibraries
|
||||
= context.llvm.librariesForLibraryManifest
|
||||
val neededLibraries = context.librariesWithDependencies
|
||||
val abiVersion = KonanAbiVersion.CURRENT
|
||||
val compilerVersion = KonanVersion.CURRENT
|
||||
val libraryVersion = config.get(KonanConfigKeys.LIBRARY_VERSION)
|
||||
@@ -85,7 +83,7 @@ internal fun produceOutput(context: Context) {
|
||||
target,
|
||||
output,
|
||||
libraryName,
|
||||
llvmModule,
|
||||
null,
|
||||
nopack,
|
||||
manifestProperties,
|
||||
context.dataFlowGraph)
|
||||
@@ -96,7 +94,7 @@ internal fun produceOutput(context: Context) {
|
||||
CompilerOutputKind.BITCODE -> {
|
||||
val output = context.config.outputFile
|
||||
context.bitcodeFileName = output
|
||||
LLVMWriteBitcodeToFile(llvmModule, output)
|
||||
LLVMWriteBitcodeToFile(context.llvmModule!!, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-20
@@ -99,7 +99,9 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
|
||||
descriptor,
|
||||
outerClass.defaultType
|
||||
)
|
||||
).apply {
|
||||
parent = innerClass
|
||||
}
|
||||
}
|
||||
|
||||
fun getLoweredEnum(enumClass: IrClass): LoweredEnum {
|
||||
@@ -109,25 +111,8 @@ internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun assignOrdinalsToEnumEntries(classDescriptor: ClassDescriptor): Map<ClassDescriptor, Int> {
|
||||
val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>()
|
||||
classDescriptor.enumEntries.forEachIndexed { index, entry ->
|
||||
enumEntryOrdinals[entry] = index
|
||||
}
|
||||
return enumEntryOrdinals
|
||||
}
|
||||
|
||||
fun getEnumEntryOrdinal(entryDescriptor: ClassDescriptor): Int {
|
||||
val enumClassDescriptor = entryDescriptor.containingDeclaration as ClassDescriptor
|
||||
// If enum came from another module then we need to get serialized ordinal number.
|
||||
// We serialize ordinal because current serialization cannot preserve enum entry order.
|
||||
if (enumClassDescriptor is DeserializedClassDescriptor) {
|
||||
return enumClassDescriptor.classProto.enumEntryList
|
||||
.first { entryDescriptor.name == enumClassDescriptor.c.nameResolver.getName(it.name) }
|
||||
.getExtension(KonanProtoBuf.enumEntryOrdinal)
|
||||
}
|
||||
return ordinals.getOrPut(enumClassDescriptor) { assignOrdinalsToEnumEntries(enumClassDescriptor) }[entryDescriptor]!!
|
||||
}
|
||||
fun getEnumEntryOrdinal(enumEntry: IrEnumEntry) =
|
||||
enumEntry.parentAsClass.declarations.filterIsInstance<IrEnumEntry>().indexOf(enumEntry)
|
||||
|
||||
fun getBridge(overriddenFunction: OverriddenFunctionInfo): IrSimpleFunction {
|
||||
val irFunction = overriddenFunction.function
|
||||
@@ -295,6 +280,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
return true
|
||||
}
|
||||
|
||||
lateinit var irModules: Map<String, IrModuleFragment>
|
||||
|
||||
// TODO: make lateinit?
|
||||
var irModule: IrModuleFragment? = null
|
||||
set(module) {
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.konan.properties.loadProperties
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
import org.jetbrains.kotlin.konan.KonanAbiVersion
|
||||
import org.jetbrains.kotlin.konan.KonanVersion
|
||||
import org.jetbrains.kotlin.konan.library.resolver.TopologicalLibraryOrder
|
||||
import org.jetbrains.kotlin.konan.library.toUnresolvedLibraries
|
||||
import org.jetbrains.kotlin.konan.parseKonanVersion
|
||||
|
||||
@@ -105,7 +106,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
fun librariesWithDependencies(moduleDescriptor: ModuleDescriptor?): List<KonanLibrary> {
|
||||
if (moduleDescriptor == null) error("purgeUnneeded() only works correctly after resolve is over, and we have successfully marked package files as needed or not needed.")
|
||||
|
||||
return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList()
|
||||
return resolvedLibraries.filterRoots { (!it.isDefault && !this.purgeUserLibs) || it.isNeededForLink }.getFullList(TopologicalLibraryOrder)
|
||||
}
|
||||
|
||||
internal val defaultNativeLibraries: List<String> = mutableListOf<String>().apply {
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ internal val innerClassPhase = makeKonanFileLoweringPhase(
|
||||
::InnerClassLowering,
|
||||
name = "InnerClasses",
|
||||
description = "Inner classes lowering",
|
||||
prerequisite = setOf(defaultParameterExtentPhase, genSyntheticFieldsPhase )
|
||||
prerequisite = setOf(defaultParameterExtentPhase)
|
||||
)
|
||||
|
||||
internal val forLoopsPhase = makeKonanFileLoweringPhase(
|
||||
|
||||
+2
@@ -5,5 +5,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
object RuntimeNames {
|
||||
val symbolName = FqName("kotlin.native.SymbolName")
|
||||
val exportForCppRuntime = FqName("kotlin.native.internal.ExportForCppRuntime")
|
||||
val exportForCompilerAnnotation = FqName("kotlin.native.internal.ExportForCompiler")
|
||||
val exportTypeInfoAnnotation = FqName("kotlin.native.internal.ExportTypeInfo")
|
||||
val cCall = FqName("kotlinx.cinterop.internal.CCall")
|
||||
}
|
||||
|
||||
+134
-78
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.serialization.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
@@ -65,22 +66,39 @@ internal val psiToIrPhase = konanUnitPhase(
|
||||
forwardDeclarationsModuleDescriptor
|
||||
)
|
||||
|
||||
val irModules = moduleDescriptor.allDependencyModules.map {
|
||||
val library = it.konanLibrary
|
||||
if (library == null) {
|
||||
return@map null
|
||||
val modules = mutableMapOf<String, IrModuleFragment>()
|
||||
|
||||
var dependenciesCount = 0
|
||||
while (true) {
|
||||
// context.config.librariesWithDependencies could change at each iteration.
|
||||
val dependencies = moduleDescriptor.allDependencyModules.filter {
|
||||
config.librariesWithDependencies(moduleDescriptor).contains(it.konanLibrary)
|
||||
}
|
||||
library.irHeader?.let { header -> deserializer.deserializeIrModule(it, header) }
|
||||
}.filterNotNull()
|
||||
for (dependency in dependencies) {
|
||||
val konanLibrary = dependency.konanLibrary!!
|
||||
if (modules.containsKey(konanLibrary.libraryName)) continue
|
||||
konanLibrary.irHeader?.let { header ->
|
||||
val deserializationStrategy = when {
|
||||
config.produce.isNativeBinary -> DeserializationStrategy.EXPLICITLY_EXPORTED
|
||||
else -> DeserializationStrategy.ONLY_REFERENCED
|
||||
}
|
||||
modules[konanLibrary.libraryName] = deserializer.deserializeIrModuleHeader(dependency, header, deserializationStrategy)
|
||||
}
|
||||
}
|
||||
if (dependencies.size == dependenciesCount) break
|
||||
dependenciesCount = dependencies.size
|
||||
}
|
||||
|
||||
|
||||
val symbols = KonanSymbols(this, generatorContext.symbolTable, generatorContext.symbolTable.lazyWrapper)
|
||||
val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles(), deserializer)
|
||||
|
||||
irModules.forEach {
|
||||
modules.values.forEach {
|
||||
it.patchDeclarationParents()
|
||||
}
|
||||
|
||||
irModule = module
|
||||
irModules = modules
|
||||
ir.symbols = symbols
|
||||
|
||||
// validateIrModule(this, module)
|
||||
@@ -102,12 +120,6 @@ internal val irGeneratorPluginsPhase = konanUnitPhase(
|
||||
description = "Plugged-in ir generators"
|
||||
)
|
||||
|
||||
internal val genSyntheticFieldsPhase = konanUnitPhase(
|
||||
op = { markBackingFields(this) },
|
||||
name = "GenSyntheticFields",
|
||||
description = "Generate synthetic fields"
|
||||
)
|
||||
|
||||
// TODO: We copy default value expressions from expects to actuals before IR serialization,
|
||||
// because the current infrastructure doesn't allow us to get them at deserialization stage.
|
||||
// That requires some design and implementation work.
|
||||
@@ -128,15 +140,13 @@ internal val patchDeclarationParents0Phase = konanUnitPhase(
|
||||
internal val serializerPhase = konanUnitPhase(
|
||||
op = {
|
||||
val declarationTable = DeclarationTable(irModule!!.irBuiltins, DescriptorTable())
|
||||
val serializedIr = IrModuleSerializer(
|
||||
this, declarationTable, bodiesOnlyForInlines = config.isInteropStubs).serializedIrModule(irModule!!)
|
||||
val serializedIr = IrModuleSerializer(this, declarationTable).serializedIrModule(irModule!!)
|
||||
val serializer = KonanSerializationUtil(this, config.configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
|
||||
serializedLinkData =
|
||||
serializer.serializeModule(moduleDescriptor, /*if (!config.isInteropStubs) serializedIr else null*/ serializedIr)
|
||||
},
|
||||
name = "Serializer",
|
||||
description = "Serialize descriptor tree and inline IR bodies",
|
||||
prerequisite = setOf(genSyntheticFieldsPhase)
|
||||
description = "Serialize descriptor tree and inline IR bodies"
|
||||
)
|
||||
|
||||
internal val setUpLinkStagePhase = konanUnitPhase(
|
||||
@@ -165,13 +175,108 @@ internal val linkPhase = namedUnitPhase(
|
||||
linkerPhase
|
||||
)
|
||||
|
||||
internal val allLoweringsPhase = namedIrModulePhase(
|
||||
name = "IrLowering",
|
||||
description = "IR Lowering",
|
||||
lower = removeExpectDeclarationsPhase then
|
||||
lowerBeforeInlinePhase then
|
||||
inlinePhase then
|
||||
lowerAfterInlinePhase then
|
||||
interopPart1Phase then
|
||||
patchDeclarationParents1Phase then
|
||||
performByIrFile(
|
||||
name = "IrLowerByFile",
|
||||
description = "IR Lowering by file",
|
||||
lower = lateinitPhase then
|
||||
stringConcatenationPhase then
|
||||
enumConstructorsPhase then
|
||||
initializersPhase then
|
||||
sharedVariablesPhase then
|
||||
localFunctionsPhase then
|
||||
tailrecPhase then
|
||||
defaultParameterExtentPhase then
|
||||
innerClassPhase then
|
||||
forLoopsPhase then
|
||||
dataClassesPhase then
|
||||
builtinOperatorPhase then
|
||||
finallyBlocksPhase then
|
||||
testProcessorPhase then
|
||||
enumClassPhase then
|
||||
delegationPhase then
|
||||
callableReferencePhase then
|
||||
interopPart2Phase then
|
||||
varargPhase then
|
||||
compileTimeEvaluatePhase then
|
||||
coroutinesPhase then
|
||||
typeOperatorPhase then
|
||||
bridgesPhase then
|
||||
autoboxPhase then
|
||||
returnsInsertionPhase
|
||||
) then
|
||||
checkDeclarationParentsPhase
|
||||
// validateIrModulePhase // Temporarily disabled until moving to new IR finished.
|
||||
)
|
||||
|
||||
internal val dependenciesLowerPhase = SameTypeNamedPhaseWrapper(
|
||||
name = "LowerLibIR",
|
||||
description = "Lower library's IR",
|
||||
prerequisite = emptySet(),
|
||||
dumperVerifier = EmptyDumperVerifier(),
|
||||
lower = object : CompilerPhase<Context, IrModuleFragment, IrModuleFragment> {
|
||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState, context: Context, irModule: IrModuleFragment): IrModuleFragment {
|
||||
|
||||
val files = mutableListOf<IrFile>()
|
||||
files += irModule.files
|
||||
irModule.files.clear()
|
||||
|
||||
// TODO: KonanLibraryResolver.TopologicalLibraryOrder actually returns libraries in the reverse topological order.
|
||||
context.librariesWithDependencies
|
||||
.reversed()
|
||||
.forEach {
|
||||
val libModule = context.irModules[it.libraryName]
|
||||
?: return@forEach
|
||||
|
||||
irModule.files += libModule.files
|
||||
allLoweringsPhase.invoke(phaseConfig, phaserState, context, irModule)
|
||||
|
||||
irModule.files.clear()
|
||||
}
|
||||
|
||||
// Save all files for codegen in reverse topological order.
|
||||
// This guarantees that libraries initializers are emitted in correct order.
|
||||
context.librariesWithDependencies
|
||||
.forEach {
|
||||
val libModule = context.irModules[it.libraryName]
|
||||
?: return@forEach
|
||||
irModule.files += libModule.files
|
||||
}
|
||||
irModule.files += files
|
||||
|
||||
return irModule
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
internal val bitcodePhase = namedIrModulePhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
lower = contextLLVMSetupPhase then
|
||||
RTTIPhase then
|
||||
generateDebugInfoHeaderPhase then
|
||||
deserializeDFGPhase then
|
||||
devirtualizationPhase then
|
||||
escapeAnalysisPhase then
|
||||
codegenPhase then
|
||||
finalizeDebugInfoPhase then
|
||||
cStubsPhase
|
||||
)
|
||||
|
||||
internal val toplevelPhase = namedUnitPhase(
|
||||
name = "Compiler",
|
||||
description = "The whole compilation process",
|
||||
lower = frontendPhase then
|
||||
psiToIrPhase then
|
||||
irGeneratorPluginsPhase then
|
||||
genSyntheticFieldsPhase then
|
||||
copyDefaultValuesToActualPhase then
|
||||
patchDeclarationParents0Phase then
|
||||
serializerPhase then
|
||||
@@ -179,67 +284,16 @@ internal val toplevelPhase = namedUnitPhase(
|
||||
name = "Backend",
|
||||
description = "All backend",
|
||||
lower = takeFromContext<Context, Unit, IrModuleFragment> { it.irModule!! } then
|
||||
namedIrModulePhase(
|
||||
name = "IrLowering",
|
||||
description = "IR Lowering",
|
||||
lower = removeExpectDeclarationsPhase then
|
||||
lowerBeforeInlinePhase then
|
||||
inlinePhase then
|
||||
lowerAfterInlinePhase then
|
||||
interopPart1Phase then
|
||||
patchDeclarationParents1Phase then
|
||||
performByIrFile(
|
||||
name = "IrLowerByFile",
|
||||
description = "IR Lowering by file",
|
||||
lower = lateinitPhase then
|
||||
stringConcatenationPhase then
|
||||
enumConstructorsPhase then
|
||||
initializersPhase then
|
||||
sharedVariablesPhase then
|
||||
localFunctionsPhase then
|
||||
tailrecPhase then
|
||||
defaultParameterExtentPhase then
|
||||
innerClassPhase then
|
||||
forLoopsPhase then
|
||||
dataClassesPhase then
|
||||
builtinOperatorPhase then
|
||||
finallyBlocksPhase then
|
||||
testProcessorPhase then
|
||||
enumClassPhase then
|
||||
delegationPhase then
|
||||
callableReferencePhase then
|
||||
interopPart2Phase then
|
||||
varargPhase then
|
||||
compileTimeEvaluatePhase then
|
||||
coroutinesPhase then
|
||||
typeOperatorPhase then
|
||||
bridgesPhase then
|
||||
autoboxPhase then
|
||||
returnsInsertionPhase
|
||||
) then
|
||||
checkDeclarationParentsPhase then
|
||||
// validateIrModulePhase then // Temporarily disabled until moving to new IR finished.
|
||||
moduleIndexForCodegenPhase
|
||||
) then
|
||||
namedIrModulePhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
lower = contextLLVMSetupPhase then
|
||||
RTTIPhase then
|
||||
generateDebugInfoHeaderPhase then
|
||||
buildDFGPhase then
|
||||
deserializeDFGPhase then
|
||||
devirtualizationPhase then
|
||||
escapeAnalysisPhase then
|
||||
serializeDFGPhase then
|
||||
codegenPhase then
|
||||
finalizeDebugInfoPhase then
|
||||
cStubsPhase then
|
||||
bitcodeLinkerPhase
|
||||
) then
|
||||
allLoweringsPhase then // Lower current module first.
|
||||
dependenciesLowerPhase then // Then lower all libraries in topological order.
|
||||
// With that we guarantee that inline functions are unlowered while being inlined.
|
||||
moduleIndexForCodegenPhase then
|
||||
buildDFGPhase then
|
||||
serializeDFGPhase then
|
||||
bitcodePhase then
|
||||
produceOutputPhase then
|
||||
verifyBitcodePhase then
|
||||
printBitcodePhase
|
||||
then
|
||||
printBitcodePhase then
|
||||
unitSink()
|
||||
) then
|
||||
linkPhase
|
||||
@@ -256,6 +310,8 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
||||
|
||||
// Don't serialize anything to a final executable.
|
||||
switch(serializerPhase, config.produce == CompilerOutputKind.LIBRARY)
|
||||
switch(dependenciesLowerPhase, config.produce != CompilerOutputKind.LIBRARY)
|
||||
switch(bitcodePhase, config.produce != CompilerOutputKind.LIBRARY)
|
||||
switch(linkPhase, config.produce.isNativeBinary)
|
||||
switch(testProcessorPhase, getNotNull(KonanConfigKeys.GENERATE_TEST_RUNNER) != TestRunnerKind.NONE)
|
||||
}
|
||||
|
||||
-1
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
|
||||
+6
-25
@@ -7,25 +7,22 @@ package org.jetbrains.kotlin.backend.konan.irasdescriptors
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanBackingField
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.ir.util.isFunction
|
||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
|
||||
val IrConstructor.constructedClass get() = this.parent as IrClass
|
||||
|
||||
@@ -95,23 +92,7 @@ fun IrClass.getSuperInterfaces() = this.superClasses.map { it.owner }.filter { i
|
||||
val IrProperty.konanBackingField: IrField?
|
||||
get() {
|
||||
assert(this.isReal)
|
||||
this.backingField?.let { return it }
|
||||
|
||||
(this.descriptor as? DeserializedPropertyDescriptor)?.konanBackingField?.let { backingFieldDescriptor ->
|
||||
val result = IrFieldImpl(
|
||||
this.startOffset,
|
||||
this.endOffset,
|
||||
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||
backingFieldDescriptor,
|
||||
this.getter!!.returnType
|
||||
).also {
|
||||
it.parent = this.parent
|
||||
}
|
||||
this.backingField = result
|
||||
return result
|
||||
}
|
||||
|
||||
return null
|
||||
return this.backingField
|
||||
}
|
||||
|
||||
val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
|
||||
+2
-2
@@ -121,14 +121,14 @@ internal fun buildLibrary(
|
||||
target: KonanTarget,
|
||||
output: String,
|
||||
moduleName: String,
|
||||
llvmModule: LLVMModuleRef,
|
||||
llvmModule: LLVMModuleRef?,
|
||||
nopack: Boolean,
|
||||
manifestProperties: Properties?,
|
||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||
|
||||
val library = LibraryWriterImpl(File(output), moduleName, versions, target, nopack)
|
||||
|
||||
library.addKotlinBitcode(llvmModule)
|
||||
llvmModule?.let { library.addKotlinBitcode(it) }
|
||||
library.addLinkData(linkData)
|
||||
natives.forEach {
|
||||
library.addNativeBitcode(it)
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ private val cnameAnnotation = FqName("kotlin.native.CName")
|
||||
|
||||
private val exportForCppRuntimeAnnotation = RuntimeNames.exportForCppRuntime
|
||||
|
||||
private val exportForCompilerAnnotation = FqName("kotlin.native.internal.ExportForCompiler")
|
||||
private val exportForCompilerAnnotation = RuntimeNames.exportForCompilerAnnotation
|
||||
|
||||
private val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||
|
||||
|
||||
+3
-3
@@ -151,9 +151,9 @@ internal val cStubsPhase = makeKonanModuleOpPhase(
|
||||
op = { context, _ -> produceCStubs(context) }
|
||||
)
|
||||
|
||||
internal val bitcodeLinkerPhase = makeKonanModuleOpPhase(
|
||||
name = "BitcodeLinker",
|
||||
description = "Bitcode linking",
|
||||
internal val produceOutputPhase = makeKonanModuleOpPhase(
|
||||
name = "ProduceOutput",
|
||||
description = "Produce output",
|
||||
op = { context, _ -> produceOutput(context) }
|
||||
)
|
||||
|
||||
|
||||
+1
-19
@@ -142,12 +142,7 @@ internal interface ContextUtils : RuntimeAware {
|
||||
get() = context.llvm.staticData
|
||||
|
||||
fun isExternal(declaration: IrDeclaration): Boolean {
|
||||
val pkg = declaration.findPackage()
|
||||
return when (pkg) {
|
||||
is IrFile -> pkg.packageFragmentDescriptor.containingDeclaration != context.moduleDescriptor
|
||||
is IrExternalPackageFragment -> true
|
||||
else -> error(pkg)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -367,19 +362,6 @@ internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
|
||||
.getFullList(TopologicalLibraryOrder)
|
||||
}
|
||||
|
||||
val librariesForLibraryManifest: List<KonanLibrary>
|
||||
get() {
|
||||
// Note: library manifest should contain the list of all user libraries and frontend-used default libraries.
|
||||
// However this would result into linking too many default libraries into the application which uses current
|
||||
// library. This problem should probably be fixed by adding different kind of dependencies to library
|
||||
// manifest.
|
||||
// Currently the problem is workarounded like this:
|
||||
return this.librariesToLink
|
||||
// This list contains all user libraries and the default libraries required for link (not frontend).
|
||||
// That's why the workaround doesn't work only in very special cases, e.g. when `-nodefaultlibs` is enabled
|
||||
// when compiling the application, while the library API uses types from default libs.
|
||||
}
|
||||
|
||||
val staticData = StaticData(context)
|
||||
|
||||
private val target = context.config.target
|
||||
|
||||
+2
-3
@@ -40,10 +40,9 @@ internal fun findMainEntryPoint(context: Context): FunctionDescriptor? {
|
||||
candidates.singleOrNull { it.hasSingleArrayOfStringParameter } ?:
|
||||
candidates.singleOrNull { it.hasNoParameters } ?:
|
||||
context.reportCompilationError("Could not find '$entryName' in '$packageName' package.")
|
||||
|
||||
if (main.isSuspend) {
|
||||
|
||||
if (main.isSuspend)
|
||||
context.reportCompilationError("Entry point can not be a suspend function.")
|
||||
}
|
||||
|
||||
return main
|
||||
}
|
||||
|
||||
+8
@@ -58,6 +58,7 @@ internal enum class IntrinsicType {
|
||||
IDENTITY,
|
||||
IMMUTABLE_BLOB,
|
||||
INIT_INSTANCE,
|
||||
SELECT_ENTRY_POINT,
|
||||
// Coroutines
|
||||
GET_CONTINUATION,
|
||||
RETURN_IF_SUSPEND,
|
||||
@@ -218,6 +219,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
IntrinsicType.IDENTITY -> emitIdentity(args)
|
||||
IntrinsicType.GET_CONTINUATION -> emitGetContinuation()
|
||||
IntrinsicType.INTEROP_MEMORY_COPY -> emitMemoryCopy(callSite, args)
|
||||
IntrinsicType.SELECT_ENTRY_POINT -> emitEntryPointSelection(args)
|
||||
IntrinsicType.RETURN_IF_SUSPEND,
|
||||
IntrinsicType.INTEROP_BITS_TO_FLOAT,
|
||||
IntrinsicType.INTEROP_BITS_TO_DOUBLE,
|
||||
@@ -246,6 +248,12 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
|
||||
private fun FunctionGenerationContext.emitIdentity(args: List<LLVMValueRef>): LLVMValueRef =
|
||||
args.single()
|
||||
|
||||
private fun FunctionGenerationContext.emitEntryPointSelection(args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val entryPoint = context.ir.symbols.entryPoint?.owner ?: return unreachable()!! // TODO: Don't put start.kt in source set unless produce=PROGRAM.
|
||||
return call(codegen.llvmFunction(entryPoint), args.take(entryPoint.valueParameters.size),
|
||||
Lifetime.IRRELEVANT, environment.exceptionHandler)
|
||||
}
|
||||
|
||||
private fun FunctionGenerationContext.emitListOfInternal(callSite: IrCall, args: List<LLVMValueRef>): LLVMValueRef {
|
||||
val varargExpression = callSite.getValueArgument(0) as IrVararg
|
||||
val vararg = args.single()
|
||||
|
||||
-9
@@ -324,7 +324,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
appendStaticInitializers()
|
||||
appendEntryPointSelector(context.ir.symbols.entryPoint?.owner)
|
||||
if (context.isNativeLibrary) {
|
||||
appendCAdapters()
|
||||
}
|
||||
@@ -2336,14 +2335,6 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
appendingTo(bbNeedInit) {
|
||||
LLVMBuildStore(builder, kImmOne, initGuard)
|
||||
|
||||
if (context.config.produce.isNativeBinary) {
|
||||
context.llvm.librariesToLink.forEach {
|
||||
val dependencyCtorFunction = context.llvm.externalFunction(
|
||||
it.moduleConstructorName, kVoidFuncType, CurrentKonanModuleOrigin)
|
||||
call(dependencyCtorFunction, emptyList(), Lifetime.IRRELEVANT,
|
||||
exceptionHandler = ExceptionHandler.Caller, verbatim = true)
|
||||
}
|
||||
}
|
||||
// TODO: shall we put that into the try block?
|
||||
context.llvm.staticInitializers.forEach {
|
||||
call(it, emptyList(), Lifetime.IRRELEVANT,
|
||||
|
||||
+1
-1
@@ -212,7 +212,7 @@ internal fun ContextUtils.importGlobal(name: String, type: LLVMTypeRef, origin:
|
||||
val found = LLVMGetNamedGlobal(context.llvmModule, name)
|
||||
if (found != null) {
|
||||
assert (getGlobalType(found) == type)
|
||||
assert (LLVMGetInitializer(found) == null)
|
||||
assert (LLVMGetInitializer(found) == null) { "$name is already declared in the current module" }
|
||||
if (threadLocal)
|
||||
assert(LLVMGetThreadLocalMode(found) == context.llvm.tlsMode)
|
||||
return found
|
||||
|
||||
-9
@@ -86,15 +86,6 @@ internal fun StaticData.createConstKotlinObject(type: IrClass, vararg fields: Co
|
||||
internal fun StaticData.createInitializer(type: IrClass, vararg fields: ConstValue): ConstValue =
|
||||
Struct(objHeader(type.typeInfoPtr), *fields)
|
||||
|
||||
private fun StaticData.getArrayListClass(): ClassDescriptor {
|
||||
val module = context.irModule!!.descriptor
|
||||
val pkg = module.getPackage(FqName.fromSegments(listOf("kotlin", "collections")))
|
||||
val classifier = pkg.memberScope.getContributedClassifier(Name.identifier("ArrayList"),
|
||||
NoLookupLocation.FROM_BACKEND)
|
||||
|
||||
return classifier as ClassDescriptor
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates static instance of `kotlin.collections.ArrayList<elementType>` with given values of fields.
|
||||
*
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
// TODO: inlining a function returning an object
|
||||
// we get PropertyDescriptors from whithin that object here.
|
||||
// we get PropertyDescriptors from within that object here.
|
||||
// That is a bug, most probably.
|
||||
// We workaround the issue with question marks here.
|
||||
(declaration.descriptor as? WrappedFieldDescriptor)?.bind(declaration)
|
||||
|
||||
+1
-1
@@ -136,10 +136,10 @@ internal class EnumUsageLowering(val context: Context)
|
||||
internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
fun run(irFile: IrFile) {
|
||||
runOnFilePostfix(irFile)
|
||||
// EnumWhenLowering should be performed before EnumUsageLowering because
|
||||
// the latter performs lowering of IrGetEnumValue
|
||||
EnumWhenLowering(context).lower(irFile)
|
||||
runOnFilePostfix(irFile)
|
||||
EnumUsageLowering(context).lower(irFile)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -238,7 +238,7 @@ internal class EnumConstructorsLowering(val context: Context) : ClassLoweringPas
|
||||
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val name = enumEntry.name.asString()
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry.descriptor)
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(enumEntry)
|
||||
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ internal class EnumWhenLowering(private val context: Context) : IrElementTransfo
|
||||
if (lhs is IrValueAccessExpression && lhs.symbol.owner == topmostSubject && rhs is IrGetEnumValue &&
|
||||
// Both entries should belong to the same class:
|
||||
topmostSubject.type.classifierOrNull?.owner == rhs.symbol.owner.parent) {
|
||||
val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.descriptor)
|
||||
val entryOrdinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(rhs.symbol.owner)
|
||||
val subjectOrdinal = topmostOrdinalProvider.value
|
||||
return IrCallImpl(call.startOffset, call.endOffset, areEqualByValue.owner.returnType, areEqualByValue).apply {
|
||||
putValueArgument(0,
|
||||
|
||||
+26
-2
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.file
|
||||
import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -24,6 +28,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
@@ -169,6 +175,24 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
else -> error("Unknown ReturnTarget: $this")
|
||||
}
|
||||
|
||||
private fun createSyntheticFunctionDescriptor(name: String): SimpleFunctionDescriptor {
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
descriptor.bind(IrFunctionImpl(
|
||||
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||
IrDeclarationOrigin.DEFINED,
|
||||
IrSimpleFunctionSymbolImpl(descriptor),
|
||||
Name.identifier(name),
|
||||
Visibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
context.irBuiltIns.unitType,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false)
|
||||
)
|
||||
return descriptor
|
||||
}
|
||||
|
||||
private fun performHighLevelJump(tryScopes: List<TryScope>,
|
||||
index: Int,
|
||||
jump: HighLevelJump,
|
||||
@@ -181,7 +205,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
val currentTryScope = tryScopes[index]
|
||||
currentTryScope.jumps.getOrPut(jump) {
|
||||
val type = (jump as? Return)?.target?.owner?.returnType ?: value.type
|
||||
val symbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
|
||||
val symbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Finally$index"))
|
||||
with(currentTryScope) {
|
||||
irBuilder.run {
|
||||
val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression)
|
||||
@@ -252,7 +276,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
)
|
||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||
val fallThroughType = aTry.type
|
||||
val fallThroughSymbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
|
||||
val fallThroughSymbol = IrReturnableBlockSymbolImpl(createSyntheticFunctionDescriptor("\$Fallthrough"))
|
||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||
for (aCatch in aTry.catches) {
|
||||
|
||||
+3
@@ -131,6 +131,9 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
|
||||
if (descriptor.isInlineConstructor) {
|
||||
// Copier sets parent to be the current function but
|
||||
// constructor's parent cannot be a function.
|
||||
copiedCallee.parent = callee.parent
|
||||
val delegatingConstructorCall = statements[0] as IrDelegatingConstructorCall
|
||||
irBuilder.run {
|
||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||
|
||||
+1
@@ -44,6 +44,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private fun createOuterThisField() {
|
||||
irClass.declarations += context.specialDeclarationsFactory.getOuterThisField(irClass)
|
||||
outerThisFieldSymbol = context.specialDeclarationsFactory.getOuterThisField(irClass).symbol
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -628,7 +628,7 @@ internal class InteropLoweringPart1(val context: Context) : IrBuildingTransforme
|
||||
|
||||
descriptor.getExternalObjCMethodInfo()?.let { methodInfo ->
|
||||
val isInteropStubsFile =
|
||||
currentFile.fileAnnotations.any { it.fqName == FqName("kotlinx.cinterop.InteropStubs") }
|
||||
currentFile.annotations.hasAnnotation(FqName("kotlinx.cinterop.InteropStubs"))
|
||||
|
||||
// Special case: bridge from Objective-C method implementation template to Kotlin method;
|
||||
// handled in CodeGeneratorVisitor.callVirtual.
|
||||
|
||||
-54
@@ -1,54 +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.backend.konan.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.addChild
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
|
||||
internal class BackingFieldVisitor(val context: Context) : IrElementVisitorVoid {
|
||||
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitProperty(declaration: IrProperty) {
|
||||
super.visitProperty(declaration)
|
||||
|
||||
if (declaration.isDelegated) {
|
||||
val irClass = declaration.parent as? IrClass
|
||||
val list = irClass?.let { context.ir.classesDelegatedBackingFields.getOrPut(irClass.descriptor) { mutableListOf() } }
|
||||
list?.add(declaration.backingField!!.descriptor)
|
||||
}
|
||||
if (declaration.backingField == null || declaration.isDelegated) return
|
||||
assert(declaration.backingField!!.descriptor == declaration.descriptor) {
|
||||
"backing field descriptor mismatch: ${declaration.backingField!!.descriptor} != ${declaration.descriptor}"
|
||||
}
|
||||
|
||||
context.ir.propertiesWithBackingFields.add(declaration.descriptor)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
if (declaration.isInner)
|
||||
declaration.declarations += context.specialDeclarationsFactory.getOuterThisField(declaration)
|
||||
|
||||
// Mark all dangling fields (they are created when class is inherited via delegation).
|
||||
declaration.declarations.filterIsInstance<IrField>().forEach {
|
||||
val list = context.ir.classesDelegatedBackingFields.getOrPut(declaration.descriptor) { mutableListOf() }
|
||||
list.add(it.descriptor)
|
||||
}
|
||||
|
||||
super.visitClass(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun markBackingFields(context: Context) {
|
||||
context.irModule!!.accept(BackingFieldVisitor(context), null)
|
||||
}
|
||||
|
||||
+26
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.konan.serialization
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.RuntimeNames
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDeclaration
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass
|
||||
@@ -39,6 +40,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrUnaryPrimitiveImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.konan.library.impl.CombinedIrFileWriter
|
||||
import org.jetbrains.kotlin.konan.library.impl.DeclarationId
|
||||
import org.jetbrains.kotlin.metadata.KonanIr
|
||||
@@ -1058,6 +1063,7 @@ internal class IrModuleSerializer(
|
||||
val proto = KonanIr.IrFile.newBuilder()
|
||||
.setFileEntry(serializeFileEntry(file.fileEntry))
|
||||
.setFqName(serializeString(file.fqName.toString()))
|
||||
.setAnnotations(serializeAnnotations(file.annotations))
|
||||
|
||||
file.declarations.forEach {
|
||||
if (it is IrTypeAlias || (it.descriptor.isExpectMember && !it.descriptor.isSerializableExpectClass)) {
|
||||
@@ -1070,6 +1076,26 @@ internal class IrModuleSerializer(
|
||||
writer.addDeclaration(DeclarationId(uniqId.index, uniqId.isLocal), byteArray)
|
||||
proto.addDeclarationId(protoUniqId(uniqId))
|
||||
}
|
||||
|
||||
file.acceptVoid(object: IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCppRuntime)
|
||||
|| declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportForCompilerAnnotation))
|
||||
proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol))
|
||||
super.visitDeclaration(declaration)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
if (declaration.descriptor.annotations.hasAnnotation(RuntimeNames.exportTypeInfoAnnotation))
|
||||
proto.addExplicitlyExportedToCompiler(serializeIrSymbol(declaration.symbol))
|
||||
super.visitDeclaration(declaration)
|
||||
}
|
||||
})
|
||||
|
||||
return proto.build()
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -89,6 +89,8 @@ message IrFile {
|
||||
repeated UniqId declaration_id = 1;
|
||||
required FileEntry file_entry = 2;
|
||||
required String fq_name = 3;
|
||||
required Annotations annotations = 4;
|
||||
repeated IrSymbol explicitly_exported_to_compiler = 5; // Symbols referenced by C runtime. TODO: Make an extension?
|
||||
}
|
||||
|
||||
message IrModule {
|
||||
|
||||
+19
-6
@@ -309,7 +309,7 @@ class KonanIrModuleDeserializer(
|
||||
}
|
||||
}
|
||||
|
||||
fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrFile {
|
||||
fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deseralizationStrategy: DeserializationStrategy): IrFile {
|
||||
val fileEntry = NaiveSourceBasedFileEntryImpl(
|
||||
deserializeString(fileProto.fileEntry.name),
|
||||
fileProto.fileEntry.lineStartOffsetsList.toIntArray()
|
||||
@@ -327,15 +327,22 @@ class KonanIrModuleDeserializer(
|
||||
val uniqIdKey = it.uniqIdKey(moduleDescriptor)
|
||||
reversedFileIndex.put(uniqIdKey, file)
|
||||
|
||||
if (deserializeAllDeclarations) {
|
||||
if (deseralizationStrategy == DeserializationStrategy.ALL) {
|
||||
file.declarations.add(deserializeTopLevelDeclaration(uniqIdKey))
|
||||
}
|
||||
}
|
||||
|
||||
val annotations = deserializeAnnotations(fileProto.annotations)
|
||||
file.annotations.addAll(annotations)
|
||||
|
||||
|
||||
if (deseralizationStrategy == DeserializationStrategy.EXPLICITLY_EXPORTED)
|
||||
fileProto.explicitlyExportedToCompilerList.forEach { deserializeIrSymbol(it) }
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
fun deserializeIrModule(proto: KonanIr.IrModule, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrModuleFragment {
|
||||
fun deserializeIrModuleHeader(proto: KonanIr.IrModule, moduleDescriptor: ModuleDescriptor, deserializationStrategy: DeserializationStrategy): IrModuleFragment {
|
||||
|
||||
deserializedModuleDescriptor = moduleDescriptor
|
||||
deserializedModuleProtoSymbolTables.put(moduleDescriptor, proto.symbolTable)
|
||||
@@ -343,7 +350,7 @@ class KonanIrModuleDeserializer(
|
||||
deserializedModuleProtoTypeTables.put(moduleDescriptor, proto.typeTable)
|
||||
|
||||
val files = proto.fileList.map {
|
||||
deserializeIrFile(it, moduleDescriptor, deserializeAllDeclarations)
|
||||
deserializeIrFile(it, moduleDescriptor, deserializationStrategy)
|
||||
|
||||
}
|
||||
val module = IrModuleFragmentImpl(moduleDescriptor, builtIns, files)
|
||||
@@ -351,8 +358,14 @@ class KonanIrModuleDeserializer(
|
||||
return module
|
||||
}
|
||||
|
||||
fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializeAllDeclarations: Boolean = false): IrModuleFragment {
|
||||
fun deserializeIrModuleHeader(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializationStrategy: DeserializationStrategy = DeserializationStrategy.ONLY_REFERENCED): IrModuleFragment {
|
||||
val proto = KonanIr.IrModule.parseFrom(byteArray.codedInputStream, KonanSerializerProtocol.extensionRegistry)
|
||||
return deserializeIrModule(proto, moduleDescriptor, deserializeAllDeclarations)
|
||||
return deserializeIrModuleHeader(proto, moduleDescriptor, deserializationStrategy)
|
||||
}
|
||||
}
|
||||
|
||||
enum class DeserializationStrategy {
|
||||
ONLY_REFERENCED,
|
||||
ALL,
|
||||
EXPLICITLY_EXPORTED
|
||||
}
|
||||
-2
@@ -53,8 +53,6 @@ internal class KonanSerializerExtension(val context: Context, override val metad
|
||||
override fun serializeEnumEntry(descriptor: ClassDescriptor, proto: ProtoBuf.EnumEntry.Builder) {
|
||||
uniqId(descriptor) ?.let { proto.setExtension(KonanProtoBuf.enumEntryUniqId, it) }
|
||||
// Serialization doesn't preserve enum entry order, so we need to serialize ordinal.
|
||||
val ordinal = context.specialDeclarationsFactory.getEnumEntryOrdinal(descriptor)
|
||||
proto.setExtension(KonanProtoBuf.enumEntryOrdinal, ordinal)
|
||||
super.serializeEnumEntry(descriptor, proto)
|
||||
}
|
||||
|
||||
|
||||
@@ -340,7 +340,6 @@ targetList.each { target ->
|
||||
task("${target}CrossDistRuntime", type: Copy) {
|
||||
dependsOn ":runtime:${target}Runtime"
|
||||
dependsOn ":backend.native:${target}Stdlib"
|
||||
dependsOn ":backend.native:${target}Start"
|
||||
|
||||
destinationDir distDir
|
||||
|
||||
@@ -357,10 +356,6 @@ targetList.each { target ->
|
||||
include('**')
|
||||
into(stdlib)
|
||||
}
|
||||
from(project(':runtime').file("build/${target}Start.bc")) {
|
||||
rename("${target}Start.bc", 'start.bc')
|
||||
into("konan/targets/$target/native")
|
||||
}
|
||||
if (target == 'wasm32') {
|
||||
into("$stdlib/targets/wasm32/included") {
|
||||
from(project(':runtime').file('src/main/js'))
|
||||
|
||||
@@ -4,16 +4,18 @@
|
||||
*/
|
||||
|
||||
import kotlin.native.internal.ExportForCppRuntime
|
||||
import kotlin.native.internal.TypedIntrinsic
|
||||
import kotlin.native.internal.IntrinsicType
|
||||
|
||||
// This function is produced by the code generator given
|
||||
// the '-entry foo.bar.main' flag.
|
||||
// It calls the requested entry point.
|
||||
// The default is main(Array<String>):Unit in the root package.
|
||||
@SymbolName("EntryPointSelector")
|
||||
external fun EntryPointSelector(args: Array<String>)
|
||||
@TypedIntrinsic(IntrinsicType.SELECT_ENTRY_POINT)
|
||||
private external fun EntryPointSelector(args: Array<String>)
|
||||
|
||||
@SymbolName("OnUnhandledException")
|
||||
external private fun OnUnhandledException(throwable: Throwable)
|
||||
private external fun OnUnhandledException(throwable: Throwable)
|
||||
|
||||
@ExportForCppRuntime
|
||||
private fun Konan_start(args: Array<String>): Int {
|
||||
|
||||
@@ -59,7 +59,7 @@ class AutoFree {
|
||||
}
|
||||
};
|
||||
|
||||
// RuntimeUtiks.kt
|
||||
// RuntimeUtils.kt
|
||||
extern "C" void ReportUnhandledException(KRef throwable);
|
||||
extern "C" void ExceptionReporterLaunchpad(KRef reporter, KRef throwable);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ class IntrinsicType {
|
||||
const val IDENTITY = "IDENTITY"
|
||||
const val IMMUTABLE_BLOB = "IMMUTABLE_BLOB"
|
||||
const val INIT_INSTANCE = "INIT_INSTANCE"
|
||||
const val SELECT_ENTRY_POINT = "SELECT_ENTRY_POINT"
|
||||
|
||||
const val GET_CONTINUATION = "GET_CONTINUATION"
|
||||
const val RETURN_IF_SUSPEND = "RETURN_IF_SUSPEND"
|
||||
|
||||
@@ -81,7 +81,7 @@ class Distribution(
|
||||
|
||||
fun runtime(target: KonanTarget) = runtimeFileOverride ?: "$stdlib/targets/${target.visibleName}/native/runtime.bc"
|
||||
|
||||
val launcherFiles = listOf("start.bc", "launcher.bc")
|
||||
val launcherFiles = listOf("launcher.bc")
|
||||
|
||||
val dependenciesDir = DependencyProcessor.defaultDependenciesRoot.absolutePath
|
||||
|
||||
|
||||
Reference in New Issue
Block a user