[backend] friend module support

This commit is contained in:
Vasily Levchenko
2018-07-05 18:53:35 +03:00
parent 856392a6e1
commit f376d9da37
7 changed files with 35 additions and 7 deletions
@@ -20,18 +20,19 @@ import com.intellij.openapi.Disposable
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.konan.util.profile
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.WARNING
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.util.profile
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.KotlinPaths
@@ -172,6 +173,8 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
} else {
arguments.checkDependencies
})
if (arguments.friendModules != null)
put(FRIEND_MODULES, arguments.friendModules!!.split(File.pathSeparator).filterNot(String::isEmpty))
}
}
}
@@ -141,5 +141,11 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
@Argument(value = "--verify_ir", description = "Verify IR")
var verifyIr: Boolean = false
@Argument(
value = "-friend-modules",
valueDescription = "<path>",
description = "Paths to friend modules"
)
var friendModules: String? = null
}
@@ -108,6 +108,8 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
private val loadedDescriptors = loadLibMetadata()
internal lateinit var friends:Set<ModuleDescriptorImpl>
internal val defaultNativeLibraries =
if (produce == CompilerOutputKind.PROGRAM)
File(distribution.defaultNatives(target)).listFiles.map { it.absolutePath }
@@ -125,13 +127,20 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
val specifics = configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!
val libraries = immediateLibraries.withResolvedDependencies()
val friendLibsSet = configuration.get(KonanConfigKeys.FRIEND_MODULES)?.map{File(it)}?.toSet()
val friends = mutableListOf<ModuleDescriptorImpl>()
for (klib in libraries) {
profile("Loading ${klib.libraryName}") {
// MutableModuleContext needs ModuleDescriptorImpl, rather than ModuleDescriptor.
val moduleDescriptor = klib.moduleDescriptor(specifics)
allMetadata.add(moduleDescriptor)
friendLibsSet?.apply {
if (contains(klib.libraryFile))
friends.add(moduleDescriptor)
}
}
}
this.friends = friends.toSet()
return allMetadata
}
@@ -105,6 +105,8 @@ class KonanConfigKeys {
= CompilerConfigurationKey.create("verify ir")
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("verbose backend phases")
val FRIEND_MODULES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create<List<String>>("friend module paths")
}
}
@@ -39,8 +39,9 @@ object TopDownAnalyzerFacadeForKonan {
val context = MutableModuleContextImpl(module, projectContext)
if (!module.isStdlib()) {
context.setDependencies(listOf(module) + config.moduleDescriptors +
config.getOrCreateForwardDeclarationsModule(module.builtIns, projectContext.storageManager))
val dependencies = listOf(module) + config.moduleDescriptors +
config.getOrCreateForwardDeclarationsModule(module.builtIns, projectContext.storageManager)
module.setDependencies(dependencies, config.friends)
} else {
assert (config.moduleDescriptors.isEmpty())
context.setDependencies(module)
@@ -99,6 +99,9 @@ internal tailrec fun DeclarationDescriptor.isExported(): Boolean {
else -> null
}
/**
* note: about INTERNAL - with support of friend modules we let frontend to deal with internal declarations.
*/
if (visibility != null && !visibility.isPublicAPI && visibility != Visibilities.INTERNAL) {
// If the declaration is explicitly marked as non-public,
// then it must not be accessible from other modules.
@@ -16,23 +16,27 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.cValuesOf
import kotlinx.cinterop.get
import kotlinx.cinterop.memScoped
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.CurrentKonanModule
import org.jetbrains.kotlin.backend.konan.descriptors.DeserializedKonanModule
import org.jetbrains.kotlin.backend.konan.descriptors.LlvmSymbolOrigin
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
import org.jetbrains.kotlin.backend.konan.isNativeBinary
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
import org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl
import org.jetbrains.kotlin.backend.konan.library.withResolvedDependencies
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import kotlin.properties.ReadOnlyProperty