Added phase control flags.

-print_descriptors
-print_ir
-print_bitcode

-verify_descriptors
-verify_ir
-verify_bitcode

-list

-enable <phase name>
-disable <phase name>
-verbose <phase name>
This commit is contained in:
Alexander Gorshenev
2016-12-09 02:35:56 +03:00
committed by alexander-gorshenev
parent 6a6424f462
commit 35668cc7e1
28 changed files with 734 additions and 192 deletions
@@ -1,16 +1,16 @@
package org.jetbrains.kotlin.cli.bc
import org.jetbrains.kotlin.backend.konan.*
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.config.addKotlinSourceRoots
@@ -21,70 +21,65 @@ import org.jetbrains.kotlin.psi.KtFile
import java.lang.System.out
import java.util.*
class NativeAnalyzer(
val environment: KotlinCoreEnvironment,
val sources: Collection<KtFile>,
val config: KonanConfig) : AnalyzerWithCompilerReport.Analyzer {
override fun analyze(): AnalysisResult {
return TopDownAnalyzerFacadeForKonan.analyzeFiles(sources, config);
}
override fun reportEnvironmentErrors() {
}
}
class K2Native : CLICompiler<K2NativeCompilerArguments>() {
val defaultModuleName = "main";
override fun doExecute(arguments : K2NativeCompilerArguments,
override fun doExecute(arguments : K2NativeCompilerArguments,
configuration : CompilerConfiguration,
rootDisposable: Disposable
): ExitCode {
configuration.put(CommonConfigurationKeys.MODULE_NAME, defaultModuleName)
configuration.addKotlinSourceRoots(arguments.freeArgs)
val libraries = arguments.libraries?.asList<String>() ?: listOf<String>()
configuration.put(KonanConfigurationKeys.LIBRARY_FILES, libraries)
libraries.forEach{println(it)}
configuration.get(KonanConfigKeys.LIBRARY_FILES)?.forEach{ println(it) }
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)
val konanConfig = 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)
runTopLevelPhases(konanConfig, environment)
return ExitCode.OK
}
fun Array<String>?.toNonNullList(): List<String> {
return this?.asList<String>() ?: listOf<String>()
}
// It is executed before doExecute().
override fun setupPlatformSpecificArgumentsAndServices(
configuration: CompilerConfiguration,
arguments : K2NativeCompilerArguments,
services : Services) {}
services : Services) {
configuration.addKotlinSourceRoots(arguments.freeArgs)
configuration.put(CommonConfigurationKeys.MODULE_NAME, "main")
val libraries = arguments.libraries.toNonNullList()
configuration.put(KonanConfigKeys.LIBRARY_FILES,
arguments.libraries.toNonNullList())
configuration.put(KonanConfigKeys.RUNTIME_FILE, arguments.runtimeFile)
configuration.put(KonanConfigKeys.OUTPUT_FILE, arguments.outputFile)
configuration.put(KonanConfigKeys.PRINT_IR, arguments.printIr)
configuration.put(KonanConfigKeys.PRINT_DESCRIPTORS, arguments.printDescriptors)
configuration.put(KonanConfigKeys.PRINT_BITCODE, arguments.printBitCode)
configuration.put(KonanConfigKeys.VERIFY_IR, arguments.verifyIr)
configuration.put(KonanConfigKeys.VERIFY_DESCRIPTORS, arguments.verifyDescriptors)
configuration.put(KonanConfigKeys.VERIFY_BITCODE, arguments.verifyBitCode)
configuration.put(KonanConfigKeys.ENABLED_PHASES,
arguments.enablePhases.toNonNullList())
configuration.put(KonanConfigKeys.DISABLED_PHASES,
arguments.disablePhases.toNonNullList())
configuration.put(KonanConfigKeys.VERBOSE_PHASES,
arguments.verbosePhases.toNonNullList())
configuration.put(KonanConfigKeys.LIST_PHASES, arguments.listPhases)
}
override fun createArguments(): K2NativeCompilerArguments {
return K2NativeCompilerArguments()
@@ -4,7 +4,6 @@ import com.sampullara.cli.Argument;
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments;
import org.jetbrains.kotlin.cli.common.arguments.ValueDescription;
public class K2NativeCompilerArguments extends CommonCompilerArguments {
@Argument(value = "output", description = "Output file path")
@ValueDescription("<path>")
@@ -18,17 +17,37 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments {
@ValueDescription("<path>")
public String[] libraries;
@Argument(value = "print_ir", description = "Print IR")
public boolean printIr;
public K2NativeCompilerArguments() {
}
@Argument(value = "print_descriptors", description = "Print descriptor tree")
public boolean printDescriptors;
public K2NativeCompilerArguments(K2NativeCompilerArguments arguments) {
this.outputFile = arguments.outputFile;
this.runtimeFile = arguments.runtimeFile;
this.libraries = arguments.libraries;
}
@Argument(value = "print_bitcode", description = "Print llvm bitcode")
public boolean printBitCode;
public CommonCompilerArguments copy() {
return new K2NativeCompilerArguments(this);
}
@Argument(value = "verify_ir", description = "Verify IR")
public boolean verifyIr;
@Argument(value = "verify_descriptors", description = "Verify descriptor tree")
public boolean verifyDescriptors;
@Argument(value = "verify_bitcode", description = "Verify llvm bitcode")
public boolean verifyBitCode;
@Argument(value = "enable", description = "Enable backend phase")
@ValueDescription("<Phase>")
public String[] enablePhases;
@Argument(value = "disable", description = "Disable backend phase")
@ValueDescription("<Phase>")
public String[] disablePhases;
@Argument(value = "verbose", description = "Trace phase execution")
@ValueDescription("<Phase>")
public String[] verbosePhases;
@Argument(value = "list", description = "List all backend phases")
public boolean listPhases;
}
@@ -1,77 +0,0 @@
package org.jetbrains.kotlin.cli.bc
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatform
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 libraries = configuration.getList(KonanConfigurationKeys.LIBRARY_FILES)
private val metadata = KotlinKonanMetadataUtils.loadLibMetadata(libraries)
val moduleId: String
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
val moduleKind: ModuleKind
get() = configuration.get(KonanConfigurationKeys.MODULE_KIND)!!
// We reuse JsModuleDescriptor for serialization for now, as we haven't got one for Konan yet.
internal val moduleDescriptors: MutableList<JsModuleDescriptor<ModuleDescriptorImpl>> by lazy {
val jsDescriptors = mutableListOf<JsModuleDescriptor<ModuleDescriptorImpl>>()
val descriptors = mutableListOf<ModuleDescriptorImpl>()
for (metadataEntry in metadata) {
val descriptor = createModuleDescriptor(metadataEntry)
jsDescriptors.add(descriptor)
descriptors.add(descriptor.data)
}
for (module in jsDescriptors) {
setDependencies(module.data, descriptors)
}
jsDescriptors
}
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))
}
}
}
@@ -1,17 +0,0 @@
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");
}
}
@@ -1,75 +0,0 @@
/*
* 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.backend.konan.llvm.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatform
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.moduleDescriptors.map { it.data } +
listOf(compilerBuiltInsModule)
)
return analyzeFilesWithGivenTrace(files, BindingTraceContext(), context, config)
}
fun analyzeFilesWithGivenTrace(
files: Collection<KtFile>,
trace: BindingTrace,
moduleContext: ModuleContext,
config: KonanConfig
): AnalysisResult {
// we print out each file we compile for now
files.forEach{println(it)}
val analyzerForKonan = createTopDownAnalyzerForKonan(
moduleContext, trace,
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
config.configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
)
analyzerForKonan.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
return AnalysisResult.success(trace.bindingContext, moduleContext.module)
}
fun checkForErrors(files: Collection<KtFile>, bindingContext: BindingContext) {
AnalyzingUtils.throwExceptionOnErrors(bindingContext)
for (file in files) {
AnalyzingUtils.checkForSyntacticErrors(file)
}
}
}
@@ -1,58 +0,0 @@
/*
* 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.backend.konan.llvm.KonanPlatform
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>()
}