Introduced KonanPlatform, KonanConfig, TopDownAnalyzerFacadeForKonan
and several other supporting facilities
This commit is contained in:
committed by
alexander-gorshenev
parent
cae9094705
commit
8321c14e36
@@ -12,77 +12,85 @@ import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
|||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys.ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES
|
|
||||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys.CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES
|
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NativeAnalyzer(val environment: KotlinCoreEnvironment) :
|
class NativeAnalyzer(
|
||||||
AnalyzerWithCompilerReport.Analyzer {
|
val environment: KotlinCoreEnvironment,
|
||||||
override fun analyze(): AnalysisResult {
|
val sources: Collection<KtFile>,
|
||||||
val sharedTrace =
|
val config: KonanConfig) : AnalyzerWithCompilerReport.Analyzer {
|
||||||
CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
|
||||||
|
|
||||||
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
override fun analyze(): AnalysisResult {
|
||||||
environment.project,
|
return TopDownAnalyzerFacadeForKonan.analyzeFiles(sources, config);
|
||||||
environment.getSourceFiles(),
|
}
|
||||||
sharedTrace,
|
|
||||||
environment.configuration.apply {
|
|
||||||
put(ADD_BUILT_INS_FROM_COMPILER_TO_DEPENDENCIES, true)
|
|
||||||
put(CREATE_BUILT_INS_FROM_MODULE_DEPENDENCIES, true)
|
|
||||||
},
|
|
||||||
{ scope -> JvmPackagePartProvider(environment, scope) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun reportEnvironmentErrors() {
|
override fun reportEnvironmentErrors() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||||
override fun doExecute(arguments : K2NativeCompilerArguments,
|
|
||||||
configuration : CompilerConfiguration,
|
|
||||||
rootDisposable: Disposable): ExitCode {
|
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME,
|
|
||||||
JvmAbi.DEFAULT_MODULE_NAME)
|
|
||||||
configuration.addKotlinSourceRoots(arguments.freeArgs)
|
|
||||||
// TODO: add to source set, once we know how to not compile them.
|
|
||||||
configuration.addKotlinSourceRoots(arguments.headers.asList())
|
|
||||||
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
|
||||||
configuration, Arrays.asList<String>("extensions/common.xml"))
|
|
||||||
|
|
||||||
val collector = configuration.getNotNull(
|
val defaultModuleName = "main";
|
||||||
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
|
||||||
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
override fun doExecute(arguments : K2NativeCompilerArguments,
|
||||||
|
configuration : CompilerConfiguration,
|
||||||
|
rootDisposable: Disposable
|
||||||
|
): ExitCode {
|
||||||
|
|
||||||
// Build AST and binding info.
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, defaultModuleName )
|
||||||
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
|
|
||||||
NativeAnalyzer(environment))
|
|
||||||
|
|
||||||
// Translate AST to high level IR.
|
configuration.addKotlinSourceRoots(arguments.freeArgs)
|
||||||
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
|
||||||
val module = translator.generateModule(
|
|
||||||
analyzerWithCompilerReport.analysisResult.moduleDescriptor,
|
|
||||||
environment.getSourceFiles(),
|
|
||||||
analyzerWithCompilerReport.analysisResult.bindingContext)
|
|
||||||
|
|
||||||
// Emit LLVM code.
|
|
||||||
module.accept(DumpIrTreeVisitor(out), "")
|
// TODO: remove, once linker is available.
|
||||||
emitLLVM(module, arguments.runtimeFile, arguments.outputFile)
|
if (arguments.headers != null) {
|
||||||
return ExitCode.OK
|
configuration.addKotlinSourceRoots(arguments.headers.asList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As of now we don't have any library mechnanism
|
||||||
|
var libraryFiles = listOf<String>()
|
||||||
|
configuration.put(KonanConfigurationKeys.LIBRARY_FILES, libraryFiles)
|
||||||
|
|
||||||
|
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
||||||
|
configuration, Arrays.asList<String>("extensions/common.xml"))
|
||||||
|
|
||||||
|
val collector = configuration.getNotNull(
|
||||||
|
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
|
|
||||||
|
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
||||||
|
|
||||||
|
val project = environment.project
|
||||||
|
val config = KonanConfig(project, configuration)
|
||||||
|
|
||||||
|
|
||||||
|
// Build AST and binding info.
|
||||||
|
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
|
||||||
|
NativeAnalyzer(environment, environment.getSourceFiles(), config))
|
||||||
|
|
||||||
|
// Translate AST to high level IR.
|
||||||
|
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
||||||
|
val module = translator.generateModule(
|
||||||
|
analyzerWithCompilerReport.analysisResult.moduleDescriptor,
|
||||||
|
environment.getSourceFiles(),
|
||||||
|
analyzerWithCompilerReport.analysisResult.bindingContext)
|
||||||
|
|
||||||
|
// Emit LLVM code.
|
||||||
|
module.accept(DumpIrTreeVisitor(out), "")
|
||||||
|
emitLLVM(module, arguments.runtimeFile, arguments.outputFile)
|
||||||
|
|
||||||
|
return ExitCode.OK
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupPlatformSpecificArgumentsAndServices(
|
override fun setupPlatformSpecificArgumentsAndServices(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
arguments : K2NativeCompilerArguments,
|
arguments : K2NativeCompilerArguments,
|
||||||
services : Services) {}
|
services : Services) {}
|
||||||
|
|
||||||
override fun createArguments(): K2NativeCompilerArguments {
|
override fun createArguments(): K2NativeCompilerArguments {
|
||||||
return K2NativeCompilerArguments()
|
return K2NativeCompilerArguments()
|
||||||
@@ -95,3 +103,4 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun main(args: Array<String>) = K2Native.main(args)
|
fun main(args: Array<String>) = K2Native.main(args)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
|
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadata
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadataUtils
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class representing a configuration of translator.
|
||||||
|
*/
|
||||||
|
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||||
|
private val storageManager = LockBasedStorageManager()
|
||||||
|
|
||||||
|
private val sourceFilesFromLibraries = listOf<KtFile>()
|
||||||
|
private var metadata = listOf<KotlinKonanMetadata>()
|
||||||
|
internal var moduleDescriptors: MutableList<JsModuleDescriptor<ModuleDescriptorImpl>>? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
val libraries = configuration.getList(KonanConfigurationKeys.LIBRARY_FILES)
|
||||||
|
metadata = KotlinKonanMetadataUtils.loadLibMetadata(libraries)
|
||||||
|
}
|
||||||
|
|
||||||
|
val moduleId: String
|
||||||
|
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||||
|
|
||||||
|
val moduleKind: ModuleKind
|
||||||
|
get() = configuration.get(KonanConfigurationKeys.MODULE_KIND)!!
|
||||||
|
|
||||||
|
fun getModuleDescriptors(): MutableList<JsModuleDescriptor<ModuleDescriptorImpl>> {
|
||||||
|
if (moduleDescriptors != null) return moduleDescriptors!!
|
||||||
|
|
||||||
|
moduleDescriptors = mutableListOf<JsModuleDescriptor<ModuleDescriptorImpl>>()
|
||||||
|
val kotlinModuleDescriptors = mutableListOf<ModuleDescriptorImpl>()
|
||||||
|
for (metadataEntry in metadata) {
|
||||||
|
val descriptor = createModuleDescriptor(metadataEntry)
|
||||||
|
moduleDescriptors!!.add(descriptor)
|
||||||
|
kotlinModuleDescriptors.add(descriptor.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (module in moduleDescriptors!!) {
|
||||||
|
setDependencies(module.data, kotlinModuleDescriptors)
|
||||||
|
}
|
||||||
|
|
||||||
|
return moduleDescriptors!!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We reuse JsModuleDescriptor for serialization for now, as we haven't got one for Konan yet.
|
||||||
|
private fun createModuleDescriptor(metadata: KotlinKonanMetadata): JsModuleDescriptor<ModuleDescriptorImpl> {
|
||||||
|
|
||||||
|
val moduleDescriptor = ModuleDescriptorImpl(
|
||||||
|
Name.special("<" + metadata.moduleName + ">"), storageManager, KonanPlatform.builtIns)
|
||||||
|
|
||||||
|
val rawDescriptor = KotlinJavascriptSerializationUtil.readModule(
|
||||||
|
metadata.body, storageManager, moduleDescriptor, CompilerDeserializationConfiguration(
|
||||||
|
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)))
|
||||||
|
|
||||||
|
val provider = rawDescriptor.data
|
||||||
|
moduleDescriptor.initialize(provider ?: PackageFragmentProvider.Empty)
|
||||||
|
|
||||||
|
return rawDescriptor.copy(moduleDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun setDependencies(module: ModuleDescriptorImpl, modules: List<ModuleDescriptorImpl>) {
|
||||||
|
module.setDependencies(modules.plus(KonanPlatform.builtIns.builtInsModule))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withJsLibAdded(files: Collection<KtFile>, config: KonanConfig): Collection<KtFile> {
|
||||||
|
val allFiles = mutableListOf<KtFile>()
|
||||||
|
allFiles.addAll(files)
|
||||||
|
// We don't store source files in the bitcode for Konan, dont't we?
|
||||||
|
//allFiles.addAll(config.getSourceFilesFromLibraries());
|
||||||
|
return allFiles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.jetbrains.kotlin.cli.bc;
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfigurationKey;
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ModuleKind;
|
||||||
|
|
||||||
|
class KonanConfigurationKeys {
|
||||||
|
companion object {
|
||||||
|
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
|
||||||
|
= CompilerConfigurationKey.create("library file paths");
|
||||||
|
val SOURCE_MAP: CompilerConfigurationKey<List<String>>
|
||||||
|
= CompilerConfigurationKey.create("generate source map");
|
||||||
|
val META_INFO: CompilerConfigurationKey<List<String>>
|
||||||
|
= CompilerConfigurationKey.create("generate metadata");
|
||||||
|
val MODULE_KIND: CompilerConfigurationKey<ModuleKind>
|
||||||
|
= CompilerConfigurationKey.create("module kind");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.resolve.ImportPath
|
||||||
|
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||||
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
|
import org.jetbrains.kotlin.storage.StorageManager
|
||||||
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
|
|
||||||
|
class KonanBuiltIns: KotlinBuiltIns {
|
||||||
|
constructor(storageManager: StorageManager) : super(storageManager)
|
||||||
|
|
||||||
|
constructor(storageManager: StorageManager, withModule: Boolean) : this(storageManager) {
|
||||||
|
if (withModule) createBuiltInsModule()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object KonanPlatform : TargetPlatform("Konan") {
|
||||||
|
override val defaultImports: List<ImportPath> = Default.defaultImports + listOf(
|
||||||
|
ImportPath("kotlin.*"),
|
||||||
|
ImportPath("kotlin.io.*")
|
||||||
|
)
|
||||||
|
|
||||||
|
override val platformConfigurator: PlatformConfigurator = KonanPlatformConfigurator
|
||||||
|
|
||||||
|
val builtIns: KonanBuiltIns = KonanBuiltIns(LockBasedStorageManager.NO_LOCKS, false)
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Adapted from JS compiler, but everyhing has been switched off for now.
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||||
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
|
import org.jetbrains.kotlin.container.useInstance
|
||||||
|
import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap
|
||||||
|
import org.jetbrains.kotlin.resolve.IdentifierChecker
|
||||||
|
import org.jetbrains.kotlin.resolve.OverloadFilter
|
||||||
|
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.SyntheticConstructorsProvider
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||||
|
import org.jetbrains.kotlin.types.DynamicTypesAllowed
|
||||||
|
|
||||||
|
|
||||||
|
object KonanPlatformConfigurator : PlatformConfigurator(
|
||||||
|
DynamicTypesAllowed(),
|
||||||
|
additionalDeclarationCheckers = listOf(),
|
||||||
|
additionalCallCheckers = listOf(),
|
||||||
|
additionalTypeCheckers = listOf(),
|
||||||
|
additionalClassifierUsageCheckers = listOf(),
|
||||||
|
additionalAnnotationCheckers = listOf(),
|
||||||
|
identifierChecker = IdentifierChecker.DEFAULT,
|
||||||
|
overloadFilter = OverloadFilter.DEFAULT,
|
||||||
|
platformToKotlinClassMap = PlatformToKotlinClassMap.EMPTY
|
||||||
|
) {
|
||||||
|
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||||
|
container.useInstance(SyntheticScopes.Empty)
|
||||||
|
container.useInstance(SyntheticConstructorsProvider.Empty)
|
||||||
|
container.useInstance(TypeSpecificityComparator.NONE)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+75
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
|
import org.jetbrains.kotlin.context.ContextForNewModule
|
||||||
|
import org.jetbrains.kotlin.context.ModuleContext
|
||||||
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.*
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||||
|
|
||||||
|
object TopDownAnalyzerFacadeForKonan {
|
||||||
|
fun analyzeFiles(files: Collection<KtFile>, config: KonanConfig): AnalysisResult {
|
||||||
|
val context = ContextForNewModule(ProjectContext(config.project), Name.special("<${config.moduleId}>"), KonanPlatform.builtIns)
|
||||||
|
|
||||||
|
val builtinsForCompilerModule = KonanBuiltIns(context.storageManager, true)
|
||||||
|
val compilerBuiltInsModule = builtinsForCompilerModule.builtInsModule
|
||||||
|
KonanPlatform.builtIns.builtInsModule = context.module
|
||||||
|
|
||||||
|
// Make sure the compiler produced BuiltIns module comes in last
|
||||||
|
context.setDependencies(
|
||||||
|
listOf(context.module) +
|
||||||
|
config.getModuleDescriptors().map { it.data } +
|
||||||
|
listOf(compilerBuiltInsModule)
|
||||||
|
)
|
||||||
|
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun analyzeFilesWithGivenTrace(
|
||||||
|
files: Collection<KtFile>,
|
||||||
|
trace: BindingTrace,
|
||||||
|
moduleContext: ModuleContext,
|
||||||
|
config: KonanConfig
|
||||||
|
): AnalysisResult {
|
||||||
|
|
||||||
|
val allFiles = KonanConfig.withJsLibAdded(files, config)
|
||||||
|
|
||||||
|
// we print out each file we compile for now
|
||||||
|
allFiles.forEach{println(it)}
|
||||||
|
|
||||||
|
val analyzerForKonan = createTopDownAnalyzerForKonan(
|
||||||
|
moduleContext, trace,
|
||||||
|
FileBasedDeclarationProviderFactory(moduleContext.storageManager, allFiles),
|
||||||
|
config.configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
|
||||||
|
)
|
||||||
|
|
||||||
|
analyzerForKonan.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||||
|
return AnalysisResult.success(trace.bindingContext, moduleContext.module)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkForErrors(allFiles: Collection<KtFile>, bindingContext: BindingContext) {
|
||||||
|
AnalyzingUtils.throwExceptionOnErrors(bindingContext)
|
||||||
|
for (file in allFiles) {
|
||||||
|
AnalyzingUtils.checkForSyntacticErrors(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.container.get
|
||||||
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
|
import org.jetbrains.kotlin.container.useInstance
|
||||||
|
import org.jetbrains.kotlin.context.ModuleContext
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.frontend.di.configureModule
|
||||||
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
|
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||||
|
import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
|
||||||
|
import org.jetbrains.kotlin.resolve.createContainer
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.FileScopeProviderImpl
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||||
|
|
||||||
|
fun createTopDownAnalyzerForKonan(
|
||||||
|
moduleContext: ModuleContext,
|
||||||
|
bindingTrace: BindingTrace,
|
||||||
|
declarationProviderFactory: DeclarationProviderFactory,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
|
): LazyTopDownAnalyzer {
|
||||||
|
val storageComponentContainer = createContainer("TopDownAnalyzerForKonan", KonanPlatform) {
|
||||||
|
configureModule(moduleContext, KonanPlatform, bindingTrace)
|
||||||
|
|
||||||
|
useInstance(declarationProviderFactory)
|
||||||
|
useImpl<FileScopeProviderImpl>()
|
||||||
|
|
||||||
|
CompilerEnvironment.configure(this)
|
||||||
|
|
||||||
|
useInstance(LookupTracker.DO_NOTHING)
|
||||||
|
useInstance(languageVersionSettings)
|
||||||
|
useImpl<ResolveSession>()
|
||||||
|
useImpl<LazyTopDownAnalyzer>()
|
||||||
|
}.apply {
|
||||||
|
get<ModuleDescriptorImpl>().initialize(get<KotlinCodeAnalyzer>().packageFragmentProvider)
|
||||||
|
}
|
||||||
|
return storageComponentContainer.get<LazyTopDownAnalyzer>()
|
||||||
|
}
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2015 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// this file has been adapted from the corresponding piece of Javascript compiler
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||||
|
import java.io.File
|
||||||
|
import javax.xml.bind.DatatypeConverter.parseBase64Binary
|
||||||
|
import javax.xml.bind.DatatypeConverter.printBase64Binary
|
||||||
|
|
||||||
|
|
||||||
|
class KotlinKonanMetadata(val abiVersion: Int, val moduleName: String, val body: ByteArray) {
|
||||||
|
val isAbiVersionCompatible: Boolean = KotlinKonanMetadataUtils.isAbiVersionCompatible(abiVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsBinaryVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
|
||||||
|
override fun isCompatible() = this.isCompatibleTo(INSTANCE)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val INSTANCE = JsBinaryVersion(0, 5, 0)
|
||||||
|
|
||||||
|
val INVALID_VERSION = JsBinaryVersion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object KotlinKonanMetadataUtils {
|
||||||
|
private val KOTLIN_JAVASCRIPT_METHOD_NAME = "kotlin_module_metadata"
|
||||||
|
private val KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN = "\\.kotlin_module_metadata\\(".toPattern()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches string like <name>.kotlin_module_metadata(<abi version>, <module name>, <base64 data>)
|
||||||
|
*/
|
||||||
|
private val METADATA_PATTERN = "(?m)\\w+\\.$KOTLIN_JAVASCRIPT_METHOD_NAME\\((\\d+),\\s*(['\"])([^'\"]*)\\2,\\s*(['\"])([^'\"]*)\\4\\)".toPattern()
|
||||||
|
|
||||||
|
val ABI_VERSION: Int = JsBinaryVersion.INSTANCE.minor
|
||||||
|
|
||||||
|
fun isAbiVersionCompatible(abiVersion: Int): Boolean = abiVersion == ABI_VERSION
|
||||||
|
|
||||||
|
fun hasMetadata(text: String): Boolean =
|
||||||
|
KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN.matcher(text).find() && METADATA_PATTERN.matcher(text).find()
|
||||||
|
|
||||||
|
fun formatMetadataAsString(moduleName: String, content: ByteArray): String =
|
||||||
|
"// Kotlin.$KOTLIN_JAVASCRIPT_METHOD_NAME($ABI_VERSION, \"$moduleName\", \"${printBase64Binary(content)}\");\n"
|
||||||
|
|
||||||
|
fun loadMetadata(file: File): List<KotlinKonanMetadata> {
|
||||||
|
assert(file.exists()) { "Library $file not found" }
|
||||||
|
val metadataList = arrayListOf<KotlinKonanMetadata>()
|
||||||
|
|
||||||
|
// For the time being we don't have a reader, so just produce nothing
|
||||||
|
//val content = readModuleMetadata(file)
|
||||||
|
//parseMetadata(content, metadataList)
|
||||||
|
|
||||||
|
return metadataList
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadMetadata(path: String): List<KotlinKonanMetadata> = loadMetadata(File(path))
|
||||||
|
|
||||||
|
fun parseMetadata(text: String, metadataList: MutableList<KotlinKonanMetadata>) {
|
||||||
|
// Check for literal pattern first in order to reduce time for large files without metadata
|
||||||
|
if (!KOTLIN_JAVASCRIPT_METHOD_NAME_PATTERN.matcher(text).find()) return
|
||||||
|
|
||||||
|
val matcher = METADATA_PATTERN.matcher(text)
|
||||||
|
while (matcher.find()) {
|
||||||
|
val abiVersion = matcher.group(1).toInt()
|
||||||
|
val moduleName = matcher.group(3)
|
||||||
|
val data = matcher.group(5)
|
||||||
|
metadataList.add(KotlinKonanMetadata(abiVersion, moduleName, parseBase64Binary(data)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadLibMetadata(libraries: List<String>): List<KotlinKonanMetadata> {
|
||||||
|
|
||||||
|
val allMetadata = mutableListOf<KotlinKonanMetadata>()
|
||||||
|
|
||||||
|
for (path in libraries) {
|
||||||
|
val filePath = File(path)
|
||||||
|
if (!filePath.exists()) {
|
||||||
|
// TODO: should we throw here?
|
||||||
|
println("Path '" + path + "' does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
val metadataList = loadMetadata(filePath);
|
||||||
|
|
||||||
|
if (metadataList.isEmpty()) {
|
||||||
|
// TODO: should we throw here?
|
||||||
|
println("'" + path + "' is not a valid Kotlin Native library");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (metadata in metadataList) {
|
||||||
|
if (!metadata.isAbiVersionCompatible) {
|
||||||
|
// TODO: should we throw here?
|
||||||
|
println("File '" + path + "' was compiled with an incompatible version of Kotlin. " +
|
||||||
|
"Its ABI version is " + metadata.abiVersion +
|
||||||
|
", expected version is " + ABI_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allMetadata.addAll(metadataList);
|
||||||
|
}
|
||||||
|
return allMetadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user