diff --git a/backend.native/build.gradle b/backend.native/build.gradle index f6dbf70c3bc..feb5d046afd 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -200,7 +200,7 @@ targetList.each { target -> "-Dkonan.home=${project.parent.file('dist')}", "-Djava.library.path=${project.buildDir}/nativelibs" args('-output', project(':runtime').file("build/${target}/stdlib.kt.bc"), - '-nolink', '-nostdlib', + '-nolink', '-nostdlib', '-compile_as_stdlib', '-target', target, '-runtime', project(':runtime').file("build/${target}/runtime.bc"), '-properties', project(':backend.native').file('konan.properties'), diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt index 0ae870af545..0f468046d81 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2Native.kt @@ -55,6 +55,7 @@ class K2Native : CLICompiler() { with (KonanConfigKeys) { with (configuration) { put(NOSTDLIB, arguments.nostdlib) + put(COMPILE_AS_STDLIB, arguments.compileAsStdlib) put(NOLINK, arguments.nolink) put(LIBRARY_FILES, arguments.libraries.toNonNullList()) diff --git a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java index 3f5b742207f..4ce17a87df0 100644 --- a/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java +++ b/backend.native/cli.bc/src/org/jetbrains/kotlin/cli/bc/K2NativeCompilerArguments.java @@ -31,6 +31,9 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments { @Argument(value = "nostdlib", description = "Don't link with stdlib") public boolean nostdlib; + @Argument(value = "compile_as_stdlib", description = "Compile the module as stdlib") + public boolean compileAsStdlib; + @Argument(value = "opt", description = "Enable optimizations during compilation") public boolean optimization; diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt index 61dfa408d34..a3ecc00751a 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfig.kt @@ -18,7 +18,9 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration internal val distribution = Distribution(configuration) - internal val libraries: List + internal val compileAsStdlib = configuration.get(KonanConfigKeys.COMPILE_AS_STDLIB) ?: false + + internal val libraries: List get() { val fromCommandLine = configuration.getList(KonanConfigKeys.LIBRARY_FILES) if (configuration.get(KonanConfigKeys.NOSTDLIB) ?: false) { @@ -29,6 +31,13 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration private val loadedDescriptors = loadLibMetadata(libraries) + init { + if (!compileAsStdlib) { + val stdlib = loadedDescriptors.single { it.isStdlib() } + KonanPlatform.builtIns.createBuiltInsModule(stdlib) + } + } + internal val librariesToLink: List get() = libraries + configuration.getList(KonanConfigKeys.NATIVE_LIBRARY_FILES) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt index 0f8d7982470..69702c6fc83 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanConfigurationKeys.kt @@ -23,6 +23,8 @@ class KonanConfigKeys { = CompilerConfigurationKey.create("optimized compilation") val NOSTDLIB: CompilerConfigurationKey = CompilerConfigurationKey.create("don't link with stdlib") + val COMPILE_AS_STDLIB: CompilerConfigurationKey + = CompilerConfigurationKey.create("compile the module as stdlib") val NOLINK: CompilerConfigurationKey = CompilerConfigurationKey.create("don't link, only produce a bitcode file ") val TARGET: CompilerConfigurationKey diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt index 8aab7562070..491be3747a4 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanPlatform.kt @@ -17,21 +17,44 @@ package org.jetbrains.kotlin.backend.konan import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.backend.konan.KonanPlatformConfigurator -import org.jetbrains.kotlin.builtins.PrimitiveType +import org.jetbrains.kotlin.builtins.createBuiltInPackageFragmentProvider import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.MultiTargetPlatform import org.jetbrains.kotlin.resolve.PlatformConfigurator import org.jetbrains.kotlin.resolve.TargetPlatform -import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.storage.StorageManager -class KonanBuiltIns: KotlinBuiltIns { - constructor(storageManager: StorageManager) : super(storageManager) +val STDLIB_MODULE_NAME = Name.special("") - constructor(storageManager: StorageManager, withModule: Boolean) : this(storageManager) { - if (withModule) createBuiltInsModule() +fun ModuleDescriptor.isStdlib(): Boolean { + return name == STDLIB_MODULE_NAME +} + +class KonanBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManager) { + override fun createBuiltInsModule() = throw Error("should not be called") + + fun createBuiltInsModule(stdlib: ModuleDescriptorImpl) { + builtInsModule = ModuleDescriptorImpl(BUILTINS_MODULE_NAME, storageManager, this, null) + val packageFragmentProvider = createBuiltInPackageFragmentProvider( + storageManager, builtInsModule, BUILT_INS_PACKAGE_FQ_NAMES, + classDescriptorFactories, + platformDependentDeclarationFilter, + additionalClassPartsProvider + ) { path -> + val classLoader = KotlinBuiltIns::class.java.classLoader + if (classLoader != null) classLoader.getResourceAsStream(path) else ClassLoader.getSystemResourceAsStream(path) + } + + builtInsModule.initialize(packageFragmentProvider) + // The code above is copy-pasted from super.createBuiltInsModule(); TODO: refactor. + + // stdlib comes first to override declarations from builtIns (even when they are requested from builtIns). + builtInsModule.setDependencies(stdlib, builtInsModule) } } @@ -47,5 +70,5 @@ object KonanPlatform : TargetPlatform("Konan") { override val platformConfigurator: PlatformConfigurator = KonanPlatformConfigurator - val builtIns: KonanBuiltIns = KonanBuiltIns(LockBasedStorageManager.NO_LOCKS, false) + val builtIns: KonanBuiltIns = KonanBuiltIns(LockBasedStorageManager.NO_LOCKS) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt index af7f8770fed..bab4990fe4e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/TopDownAnalyzerFacadeForKonan.kt @@ -31,19 +31,29 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProvid object TopDownAnalyzerFacadeForKonan { fun analyzeFiles(files: Collection, config: KonanConfig): AnalysisResult { - val context = ContextForNewModule(ProjectContext(config.project), Name.special("<${config.moduleId}>"), - KonanPlatform.builtIns, null) + val moduleName = if (config.compileAsStdlib) { + STDLIB_MODULE_NAME + } else { + Name.special("<${config.moduleId}>") + } - val builtinsForCompilerModule = KonanBuiltIns(context.storageManager, true) - val compilerBuiltInsModule = builtinsForCompilerModule.builtInsModule - KonanPlatform.builtIns.builtInsModule = context.module + val context = ContextForNewModule(ProjectContext(config.project), moduleName, KonanPlatform.builtIns, null) + + val module = context.module + assert (module.isStdlib() == config.compileAsStdlib) + + if (!module.isStdlib()) { + context.setDependencies(listOf(module) + config.moduleDescriptors + KonanPlatform.builtIns.builtInsModule) + } else { + KonanPlatform.builtIns.createBuiltInsModule(module) + assert (config.moduleDescriptors.isEmpty()) + context.setDependencies(module) + + // TODO: stdlib should probably also depend on builtInsModule. + // However this would lead to mutual dependency between stdlib and builtInsModule, + // and the compiler can't handle it. + } - // Make sure the compiler produced BuiltIns module comes in last - context.setDependencies( - listOf(context.module) + - config.moduleDescriptors + - listOf(compilerBuiltInsModule) - ) return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config) }