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,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");
}
}
@@ -0,0 +1,125 @@
package org.jetbrains.kotlin.backend.konan
import llvm.*
import org.jetbrains.kotlin.backend.konan.llvm.Runtime
import org.jetbrains.kotlin.backend.konan.llvm.getFunctionType
import org.jetbrains.kotlin.backend.konan.llvm.StaticData
import org.jetbrains.kotlin.backend.konan.llvm.Llvm
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.KonanPhase
import org.jetbrains.kotlin.backend.konan.ModuleIndex
import org.jetbrains.kotlin.backend.konan.KonanConfig
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.backend.konan.DeepPrintVisitor
import org.jetbrains.kotlin.backend.konan.PrintVisitor
import org.jetbrains.kotlin.backend.konan.llvm.verifyModule
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import java.lang.System.out
internal final class Context(val config: KonanConfig,
// TODO: Need to eliminate when deserialization is fixed.
val bindingContext: BindingContext,
val moduleDescriptor: ModuleDescriptor
) : KonanBackendContext() {
var irModule: IrModuleFragment? = null
set(module: IrModuleFragment?) {
if (field != null) {
throw Error("Another IrModule in the context.")
}
field = module!!
moduleIndex = ModuleIndex(irModule!!)
}
lateinit var moduleIndex: ModuleIndex
var llvmModule: LLVMModuleRef? = null
set(module: LLVMModuleRef?) {
if (field != null) {
throw Error("Another LLVMModule in the context.")
}
field = module!!
llvm = Llvm(this, module)
}
lateinit var llvm: Llvm
var phase: KonanPhase? = null
protected fun separator(title: String) {
println("\n\n--- ${title} ----------------------\n")
}
fun verifyDescriptors() {
// TODO: Nothing here for now.
}
fun printDescriptors() {
separator("Descriptors after: ${phase?.description}")
moduleDescriptor!!.accept(DeepPrintVisitor(PrintVisitor()), 0)
}
fun verifyIr() {
if (irModule == null) return
// TODO: We don't have it yet.
}
fun printIr() {
if (irModule == null) return
separator("IR after: ${phase?.description}")
irModule!!.accept(DumpIrTreeVisitor(out), "")
}
fun verifyBitCode() {
if (llvmModule == null) return
verifyModule(llvmModule!!)
}
fun printBitCode() {
if (llvmModule == null) return
separator("BitCode after: ${phase?.description}")
LLVMDumpModule(llvmModule!!)
}
fun verify() {
verifyDescriptors()
verifyIr()
verifyBitCode()
}
fun print() {
printDescriptors()
printIr()
printBitCode()
}
fun shouldVerifyDescriptors(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.VERIFY_DESCRIPTORS)
}
fun shouldVerifyIr(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.VERIFY_IR)
}
fun shouldVerifyBitCode(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.VERIFY_BITCODE)
}
fun shouldPrintDescriptors(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.PRINT_DESCRIPTORS)
}
fun shouldPrintIr(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.PRINT_IR)
}
fun shouldPrintBitCode(): Boolean {
return config.configuration.getBoolean(KonanConfigKeys.PRINT_BITCODE)
}
}
@@ -0,0 +1,73 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.renderer.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
public class DeepPrintVisitor(worker: DeclarationDescriptorVisitor<Boolean, Int>): DeepVisitor< Int>(worker) {
override public fun visitChildren(descriptor: DeclarationDescriptor?, data: Int): Boolean {
return super.visitChildren(descriptor, data+1)
}
override public fun visitChildren(descriptors: Collection<DeclarationDescriptor>, data: Int): Boolean {
return super.visitChildren(descriptors, data+1)
}
}
public class PrintVisitor: DeclarationDescriptorVisitor<Boolean, Int> {
fun printDescriptor(descriptor: DeclarationDescriptor, amount: Int): Boolean {
println(String.format("%1$-${(amount+1)*4}s", "") + descriptor.toString())
return true;
}
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitScriptDescriptor(descriptor: ScriptDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: Int): Boolean
= printDescriptor(descriptor, data)
}
@@ -0,0 +1,100 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
open class DeepVisitor<D>(val worker: DeclarationDescriptorVisitor<Boolean, D>) : DeclarationDescriptorVisitor<Boolean, D> {
open fun visitChildren(descriptors: Collection<DeclarationDescriptor>, data: D): Boolean {
for (descriptor in descriptors) {
if (!descriptor.accept(this, data)) return false
}
return true
}
open fun visitChildren(descriptor: DeclarationDescriptor?, data: D): Boolean {
if (descriptor == null) return true
return descriptor!!.accept(this, data)
}
fun applyWorker(descriptor: DeclarationDescriptor, data: D): Boolean {
return descriptor.accept(worker, data)
}
fun processCallable(descriptor: CallableDescriptor, data: D): Boolean {
return applyWorker(descriptor, data)
&& visitChildren(descriptor.getTypeParameters(), data)
&& visitChildren(descriptor.getExtensionReceiverParameter(), data)
&& visitChildren(descriptor.getValueParameters(), data)
}
override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data) && visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getMemberScope()), data)
}
override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data) && visitChildren(DescriptorUtils.getAllDescriptors(descriptor.memberScope), data)
}
override fun visitVariableDescriptor(descriptor: VariableDescriptor, data: D): Boolean? {
return processCallable(descriptor, data)
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: D): Boolean? {
return processCallable(descriptor, data)
&& visitChildren(descriptor.getter, data)
&& visitChildren(descriptor.setter, data)
}
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: D): Boolean? {
return processCallable(descriptor, data)
}
override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data)
}
override fun visitClassDescriptor(descriptor: ClassDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data)
&& visitChildren(descriptor.getThisAsReceiverParameter(), data)
&& visitChildren(descriptor.getConstructors(), data)
&& visitChildren(descriptor.getTypeConstructor().getParameters(), data)
&& visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().memberScope), data)
}
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data) && visitChildren(descriptor.getDeclaredTypeParameters(), data)
}
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data) && visitChildren(descriptor.getPackage(FqName.ROOT), data)
}
override fun visitConstructorDescriptor(constructorDescriptor: ConstructorDescriptor, data: D): Boolean? {
return visitFunctionDescriptor(constructorDescriptor, data)
}
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, data: D): Boolean? {
return visitClassDescriptor(scriptDescriptor, data)
}
override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor, data: D): Boolean? {
return visitVariableDescriptor(descriptor, data)
}
override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor, data: D): Boolean? {
return visitFunctionDescriptor(descriptor, data)
}
override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor, data: D): Boolean? {
return visitFunctionDescriptor(descriptor, data)
}
override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor, data: D): Boolean? {
return applyWorker(descriptor, data)
}
}
@@ -1,6 +1,6 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.llvm.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
@@ -2,7 +2,7 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatform
import org.jetbrains.kotlin.backend.konan.KonanPlatform
open internal class KonanBackendContext : BackendContext {
override val builtIns = KonanPlatform.builtIns
@@ -12,4 +12,4 @@ open internal class KonanBackendContext : BackendContext {
// TODO: investigate this.
KonanSharedVariablesManager(builtIns)
}
}
}
@@ -1,7 +1,7 @@
package org.jetbrains.kotlin.cli.bc
package org.jetbrains.kotlin.backend.konan
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatform
import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
@@ -18,13 +18,11 @@ 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 libraries = configuration.getList(KonanConfigKeys.LIBRARY_FILES)
private val metadata = KotlinKonanMetadataUtils.loadLibMetadata(libraries)
@@ -32,7 +30,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
val moduleKind: ModuleKind
get() = configuration.get(KonanConfigurationKeys.MODULE_KIND)!!
get() = configuration.get(KonanConfigKeys.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 {
@@ -0,0 +1,46 @@
package org.jetbrains.kotlin.backend.konan;
import org.jetbrains.kotlin.config.CompilerConfigurationKey;
import org.jetbrains.kotlin.serialization.js.ModuleKind;
class KonanConfigKeys {
companion object {
val LIBRARY_FILES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("library file paths");
val RUNTIME_FILE: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("runtime file path");
val OUTPUT_FILE: CompilerConfigurationKey<String>
= CompilerConfigurationKey.create("output file path");
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");
val VERIFY_IR: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify ir");
val VERIFY_DESCRIPTORS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify descriptors");
val VERIFY_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("verify bitcode");
val PRINT_IR: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print ir");
val PRINT_DESCRIPTORS: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print descriptors");
val PRINT_BITCODE: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("print bitcode");
val ENABLED_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("enable backend phases");
val DISABLED_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("disable backend phases");
val VERBOSE_PHASES: CompilerConfigurationKey<List<String>>
= CompilerConfigurationKey.create("verbose backend phases");
val LIST_PHASES: CompilerConfigurationKey<Boolean>
= CompilerConfigurationKey.create("list backend phases");
}
}
@@ -0,0 +1,76 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
class NativeAnalyzer(
val environment: KotlinCoreEnvironment,
val sources: Collection<KtFile>,
val konanConfig: KonanConfig) : AnalyzerWithCompilerReport.Analyzer {
override fun analyze(): AnalysisResult {
return TopDownAnalyzerFacadeForKonan.analyzeFiles(sources, konanConfig);
}
override fun reportEnvironmentErrors() {
}
}
public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEnvironment) {
val config = konanConfig.configuration
KonanPhases.config(konanConfig)
if (config.get(KonanConfigKeys.LIST_PHASES) ?: false) {
KonanPhases.list()
}
val collector = config.getNotNull(
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
// Build AST and binding info.
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
NativeAnalyzer(environment, environment.getSourceFiles(), konanConfig))
val bindingContext = analyzerWithCompilerReport.analysisResult.bindingContext
val moduleDescriptor = analyzerWithCompilerReport.analysisResult.moduleDescriptor
val context = Context(konanConfig, bindingContext, moduleDescriptor)
// Translate AST to high level IR.
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
val module = translator.generateModule( moduleDescriptor,
environment.getSourceFiles(), bindingContext)
context.irModule = module
val phaser = PhaseManager(context)
phaser.phase("Optimizer") {
KonanLower(context).lower(module)
}
phaser.phase("Bitcode") {
emitLLVM(context)
}
phaser.phase("Linker") {
//TODO: We don't have it yet.
// invokeLinker()
}
}
@@ -1,5 +1,7 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.PhaseManager
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.common.lower.LocalFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.SharedVariablesLowering
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
@@ -7,7 +9,7 @@ import org.jetbrains.kotlin.backend.konan.lower.CallableReferenceLowering
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
internal class KonanLower(val context: KonanBackendContext) {
internal class KonanLower(val context: Context) {
fun lower(module: IrModuleFragment) {
module.files.forEach {
@@ -16,8 +18,16 @@ internal class KonanLower(val context: KonanBackendContext) {
}
fun lower(irFile: IrFile) {
SharedVariablesLowering(context).runOnFilePostfix(irFile)
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
CallableReferenceLowering(context).runOnFilePostfix(irFile)
val phaser = PhaseManager(context)
phaser.phase("Lower_shared_variables") {
SharedVariablesLowering(context).runOnFilePostfix(irFile)
}
phaser.phase("Lower_local_functions") {
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
}
phaser.phase("Lower_callables") {
CallableReferenceLowering(context).runOnFilePostfix(irFile)
}
}
}
}
@@ -0,0 +1,84 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.Context
class KonanPhase (val description: String,
var enabled: Boolean = true, var verbose: Boolean = false) {
}
object KonanPhases {
val phases = mapOf<String, KonanPhase> (
"Backend" to KonanPhase("All backend"),
"Optimizer" to KonanPhase("IR Optimizer"),
"Lower_shared_variables" to KonanPhase("Shared Variable Lowering"),
"Lower_local_functions" to KonanPhase("Local Function Lowering"),
"Lower_callables" to KonanPhase("Callable references Lowering"),
"Lower" to KonanPhase("IR Lowering"),
"Bitcode" to KonanPhase("LLVM BitCode Generation"),
"RTTI" to KonanPhase("RTTI Generation"),
"Codegen" to KonanPhase("Code Generation"),
"Metadator" to KonanPhase("Metadata Generation"),
"Linker" to KonanPhase("Link Stage")
)
fun config(config: KonanConfig) {
val disabled = config.configuration.get(KonanConfigKeys.DISABLED_PHASES)
disabled?.forEach { phases[it]!!.enabled = false }
val enabled = config.configuration.get(KonanConfigKeys.ENABLED_PHASES)
enabled?.forEach { phases[it]!!.enabled = true }
val verbose = config.configuration.get(KonanConfigKeys.VERBOSE_PHASES)
verbose?.forEach { phases[it]!!.verbose = true }
}
fun list() {
phases.forEach { key, phase ->
val enabled = if (phase.enabled) "(Enabled)" else ""
val verbose = if (phase.verbose) "(Verbose)" else ""
println(String.format("%1$-30s%2$-30s%3$-10s", "${key}:", phase.description, "$enabled $verbose"))
}
}
}
internal class PhaseManager(val context: Context) {
internal fun phase(shortName: String, body: () -> Unit) {
val phase = KonanPhases.phases[shortName]
if (phase == null) throw Error("Unknown backend phase: $shortName")
if (!phase .enabled) return
val savePhase = context.phase
context.phase = phase
body()
with (context) {
if (shouldVerifyDescriptors()) {
verifyDescriptors()
}
if (shouldVerifyIr()) {
verifyIr()
}
if (shouldVerifyBitCode()) {
verifyBitCode()
}
if (shouldPrintDescriptors()) {
printDescriptors()
}
if (shouldPrintIr()) {
printIr()
}
if (shouldPrintBitCode()) {
printBitCode()
}
}
context.phase = savePhase
}
}
@@ -14,10 +14,10 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.konan.llvm
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatformConfigurator
import org.jetbrains.kotlin.backend.konan.KonanPlatformConfigurator
import org.jetbrains.kotlin.resolve.ImportPath
import org.jetbrains.kotlin.resolve.PlatformConfigurator
import org.jetbrains.kotlin.resolve.TargetPlatform
@@ -16,7 +16,7 @@
// Adapted from JS compiler, but everyhing has been switched off for now.
package org.jetbrains.kotlin.backend.konan.llvm
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
@@ -14,11 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.bc
package org.jetbrains.kotlin.backend.konan
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.backend.konan.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.ContextForNewModule
@@ -3,7 +3,7 @@ package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.backend.konan.getKonanInternalClass
import org.jetbrains.kotlin.backend.konan.llvm.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
@@ -103,4 +103,4 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared
}
}
}
}
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.cli.bc
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.konan.llvm.KonanPlatform
import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.get
import org.jetbrains.kotlin.container.useImpl
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -1,43 +0,0 @@
package org.jetbrains.kotlin.backend.konan.llvm
import llvm.*
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.backend.konan.ModuleIndex
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.resolve.BindingContext
// TODO: module-independent part should probably be extracted
internal class Context(val irModule: IrModuleFragment,
val runtime: Runtime,
val llvmModule: LLVMModuleRef,
val bindingContext: BindingContext) : KonanBackendContext() {
val moduleIndex = ModuleIndex(irModule)
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
if (LLVMGetNamedFunction(llvmModule, name) != null) {
throw IllegalArgumentException("function $name already exists")
}
val externalFunction = LLVMGetNamedFunction(otherModule, name)!!
val functionType = getFunctionType(externalFunction)
return LLVMAddFunction(llvmModule, name, functionType)!!
}
val staticData = StaticData(this)
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
val allocInstanceFunction = importRtFunction("AllocInstance")
val initInstanceFunction = importRtFunction("InitInstance")
val allocArrayFunction = importRtFunction("AllocArrayInstance")
val setArrayFunction = importRtFunction("Kotlin_Array_set")
val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl")
val lookupFieldOffset = importRtFunction("LookupFieldOffset")
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
val isInstanceFunction = importRtFunction("IsInstance")
val checkInstanceFunction = importRtFunction("CheckInstance")
val throwExceptionFunction = importRtFunction("ThrowException")
val usedFunctions = mutableListOf<LLVMValueRef>()
}
@@ -2,7 +2,9 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -22,7 +24,7 @@ internal interface ContextUtils {
val context: Context
val runtime: Runtime
get() = context.runtime
get() = context.llvm.runtime
/**
* Describes the target platform.
@@ -33,7 +35,7 @@ internal interface ContextUtils {
get() = runtime.targetData
val staticData: StaticData
get() = context.staticData
get() = context.llvm.staticData
/**
* All fields of the class instance.
@@ -161,3 +163,42 @@ internal interface ContextUtils {
val FqName.localHash: LocalHash
get() = this.toString().localHash
}
internal class Llvm(val context: Context, val llvmModule: LLVMModuleRef) {
private fun importFunction(name: String, otherModule: LLVMModuleRef): LLVMValueRef {
if (LLVMGetNamedFunction(llvmModule, name) != null) {
throw IllegalArgumentException("function $name already exists")
}
val externalFunction = LLVMGetNamedFunction(otherModule, name)!!
val functionType = getFunctionType(externalFunction)
return LLVMAddFunction(llvmModule, name, functionType)!!
}
val staticData = StaticData(context)
val runtimeFile = context.config.configuration.get(KonanConfigKeys.RUNTIME_FILE)!!
val runtime = Runtime(runtimeFile) // TODO: dispose
init {
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
LLVMSetTarget(llvmModule, runtime.target)
}
private fun importRtFunction(name: String) = importFunction(name, runtime.llvmModule)
val allocInstanceFunction = importRtFunction("AllocInstance")
val initInstanceFunction = importRtFunction("InitInstance")
val allocArrayFunction = importRtFunction("AllocArrayInstance")
val setArrayFunction = importRtFunction("Kotlin_Array_set")
val copyImplArrayFunction = importRtFunction("Kotlin_Array_copyImpl")
val lookupFieldOffset = importRtFunction("LookupFieldOffset")
val lookupOpenMethodFunction = importRtFunction("LookupOpenMethod")
val isInstanceFunction = importRtFunction("IsInstance")
val checkInstanceFunction = importRtFunction("CheckInstance")
val throwExceptionFunction = importRtFunction("ThrowException")
val usedFunctions = mutableListOf<LLVMValueRef>()
}
@@ -26,26 +26,32 @@ import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
fun emitLLVM(module: IrModuleFragment, runtimeFile: String, outFile: String) {
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
val runtime = Runtime(runtimeFile) // TODO: dispose
LLVMSetDataLayout(llvmModule, runtime.dataLayout)
LLVMSetTarget(llvmModule, runtime.target)
// TODO: shall we provide better binding context?
val context = Context(
module, runtime, llvmModule, BindingContext.EMPTY) // TODO: dispose
internal fun emitLLVM(context: Context) {
KonanLower(context).lower(module)
val irModule = context.irModule!!
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
context.llvmModule = llvmModule
module.acceptVoid(RTTIGeneratorVisitor(context))
println("\n--- Generate bitcode ------------------------------------------------------\n")
module.acceptVoid(CodeGeneratorVisitor(context))
verifyModule(llvmModule)
LLVMWriteBitcodeToFile(llvmModule, outFile)
val phaser = PhaseManager(context)
phaser.phase("RTTI") {
irModule.acceptVoid(RTTIGeneratorVisitor(context))
}
phaser.phase("Codegen") {
irModule.acceptVoid(CodeGeneratorVisitor(context))
}
phaser.phase("Metadator") {
irModule.acceptVoid(MetadatorVisitor(context))
}
val outFile = context.config.configuration.get(KonanConfigKeys.OUTPUT_FILE)!!
LLVMWriteBitcodeToFile(llvmModule, outFile)
}
private fun verifyModule(llvmModule: LLVMModuleRef) {
internal fun verifyModule(llvmModule: LLVMModuleRef) {
memScoped {
val errorRef = allocPointerTo<CInt8Var>()
// TODO: use LLVMDisposeMessage() on errorRef, once possible in interop.
@@ -82,13 +88,33 @@ internal class RTTIGeneratorVisitor(context: Context) : IrElementVisitorVoid {
}
//-------------------------------------------------------------------------//
internal class MetadatorVisitor(val context: Context) : IrElementVisitorVoid {
val metadator = MetadataGenerator(context)
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitModuleFragment(module: IrModuleFragment) {
module.acceptChildrenVoid(this)
metadator.endModule(module)
}
}
//-------------------------------------------------------------------------//
internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid {
val codegen = CodeGenerator(context)
val logger = Logger(codegen, context)
val metadator = MetadataGenerator(context)
val logger = if (context.phase!!.verbose) {
Logger(codegen, context)
} else {
DummyLogger(codegen, context)
}
//-------------------------------------------------------------------------//
@@ -191,9 +217,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("visitModule : ${ir2string(module)}")
module.acceptChildrenVoid(this)
appendLlvmUsed(context.usedFunctions)
metadator.endModule(module)
appendLlvmUsed(context.llvm.usedFunctions)
}
//-------------------------------------------------------------------------//
@@ -459,7 +483,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun genThrow(exception: LLVMValueRef) {
val objHeaderPtr = codegen.bitcast(codegen.kObjHeaderPtr, exception, codegen.newVar())
val args = listOf(objHeaderPtr)
codegen.call(context.throwExceptionFunction, args, "")
codegen.call(context.llvm.throwExceptionFunction, args, "")
codegen.unreachable()
}
}
@@ -485,14 +509,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
return
codegen.prologue(declaration)
metadator.function(declaration)
using(FunctionScope(declaration)) {
declaration.acceptChildrenVoid(this)
}
codegen.epilogue(declaration)
verifyModule(context.llvmModule)
verifyModule(context.llvmModule!!)
}
//-------------------------------------------------------------------------//
@@ -641,7 +665,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val ctor = codegen.llvmFunction(initFunction)
val args = listOf(objectPtr, typeInfo, allocHint, ctor)
val newValue = currentCodeContext.genCall(
context.initInstanceFunction, args, codegen.newVar())
context.llvm.initInstanceFunction, args, codegen.newVar())
codegen.br(bbExit)
codegen.positionAtEnd(bbExit)
@@ -763,14 +787,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val typeInfo = codegen.typeInfoValue(value.type)!!
val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength!!)
val array = currentCodeContext.genCall(context.allocArrayFunction, arrayCreationArgs, tmpVariableName)
val array = currentCodeContext.genCall(context.llvm.allocArrayFunction, arrayCreationArgs, tmpVariableName)
elements.fold(kImmZero) { sum, (exp, size, isArray) ->
if (!isArray) {
currentCodeContext.genCall(context.setArrayFunction, listOf(array, sum, exp), "")
currentCodeContext.genCall(context.llvm.setArrayFunction, listOf(array, sum, exp), "")
return@fold codegen.plus(sum, kImmOne, codegen.newVar())
} else {
currentCodeContext.genCall(context.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!), "")
currentCodeContext.genCall(context.llvm.copyImplArrayFunction, listOf(exp, kImmZero, array, sum, size!!), "")
return@fold codegen.plus(sum, size, codegen.newVar())
}
}
@@ -1251,7 +1275,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val srcArg = evaluateExpression(codegen.newVar(), value.argument)!! // Evaluate src expression.
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
currentCodeContext.genCall(context.checkInstanceFunction, args, "") // Check if dst is subclass of src.
currentCodeContext.genCall(context.llvm.checkInstanceFunction, args, "") // Check if dst is subclass of src.
return srcArg
}
@@ -1293,7 +1317,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
val result = currentCodeContext.genCall( // Check if dst is subclass of src.
context.isInstanceFunction, args, codegen.newVar())
context.llvm.isInstanceFunction, args, codegen.newVar())
return LLVMBuildTrunc(codegen.builder, result, kInt1, tmpVariableName)!! // Truncate result to boolean
}
@@ -1422,7 +1446,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
IrConstKind.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1)
IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1)
IrConstKind.String ->
return context.staticData.kotlinStringLiteral(value as IrConst<String>).llvm
return context.llvm.staticData.kotlinStringLiteral(value as IrConst<String>).llvm
IrConstKind.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString())
IrConstKind.Double -> return LLVMConstRealOfString(LLVMDoubleType(), (value.value as Double).toString())
}
@@ -1507,7 +1531,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
// however `vararg` is immutable, and in current implementation it has type `Array<E>`,
// so let's ignore this mismatch currently for simplicity.
return context.staticData.createArrayList(elementType, array, length).llvm
return context.llvm.staticData.createArrayList(elementType, array, length).llvm
}
}
@@ -1641,9 +1665,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val thisValue = if (containingClass.isArray) {
assert(args.size == 1 && args[0].type == int32Type)
val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0])
currentCodeContext.genCall(context.allocArrayFunction, allocArrayInstanceArgs, variableName)
currentCodeContext.genCall(context.llvm.allocArrayFunction, allocArrayInstanceArgs, variableName)
} else {
currentCodeContext.genCall(context.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
currentCodeContext.genCall(context.llvm.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
}
val constructorParams: MutableList<LLVMValueRef> = mutableListOf()
constructorParams += thisValue
@@ -1833,7 +1857,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
val llvmMethod = currentCodeContext.genCall(
context.lookupOpenMethodFunction,
context.llvm.lookupOpenMethodFunction,
lookupArgs,
codegen.newVar()) // Get method ptr to be invoked
@@ -1897,7 +1921,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
val arrayLength = args.size
val argsCasted = args.map { it -> constPointer(it).bitcast(int8TypePtr) }
val llvmUsedGlobal =
context.staticData.placeGlobalArray("llvm.used", int8TypePtr, argsCasted)
context.llvm.staticData.placeGlobalArray("llvm.used", int8TypePtr, argsCasted)
LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage);
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata");
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.allValueParameters
import org.jetbrains.kotlin.backend.konan.KonanPlatform
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
internal val LLVMValueRef.type: LLVMTypeRef
@@ -184,4 +185,4 @@ internal fun functionType(returnType: LLVMTypeRef, isVarArg: Boolean = false, va
memScoped {
val paramTypesPtr = allocArrayOf(*paramTypes)[0].ptr
LLVMFunctionType(returnType, paramTypesPtr, paramTypes.size, if (isVarArg) 1 else 0)!!
}
}
@@ -2,23 +2,23 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import java.io.StringWriter
internal class Logger(val generator: CodeGenerator, override val context: Context) : ContextUtils {
internal open class Logger(val generator: CodeGenerator, override val context: Context) : ContextUtils {
private var logcounter: Int = LLVMPrintModuleToString(context.llvmModule)!!.asCString().toString().lines().size
//---------------------------------------------------------------------------//
fun log(msg: String) {
// logIr()
open fun log(msg: String) {
println(msg)
}
//---------------------------------------------------------------------------//
fun logIr() {
open fun logIr() {
val function = generator.currentFunction ?: return
val irFunctionDeclaration = LLVMPrintValueToString(function.llvmFunction)!!.asCString().toString()
@@ -48,3 +48,10 @@ fun llvm2string(value: LLVMValueRef?): String {
return LLVMPrintValueToString(value)!!.asCString().toString()
}
//-----------------------------------------------------------------------------//
internal class DummyLogger(generator: CodeGenerator, context: Context) : Logger(generator, context) {
override fun log(msg: String) = Unit
override fun logIr() = Unit
}
@@ -1,10 +1,10 @@
package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.llvm.BinaryLinkdata.*
import org.jetbrains.kotlin.types.KotlinType
@@ -104,7 +104,7 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
}
}
private fun metadataFun(fn: LLVMValueRef?, info: String): LLVMValueRef {
private fun metadataFun(fn: LLVMValueRef, info: String): LLVMValueRef {
val args = listOf(fn, metadataString(info));
val md = metadataNode(args)
return md
@@ -146,11 +146,12 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
// Convert it to ProtoBuf's TextFormat representation.
// Use TextFormat.merge(str, builder) to parse it back
val str = proto.toString()
return str
}
internal fun function(declaration: IrFunction) {
val fn = declaration.descriptor.llvmFunction
val fn = declaration.descriptor.llvmFunction!!
val proto = serializeFunSignature(declaration)
@@ -173,6 +174,7 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
}
private fun serializeModule(moduleDescriptor: ModuleDescriptor): String {
val description = JsModuleDescriptor(
name = "foo",
kind = ModuleKind.PLAIN,
@@ -197,5 +199,3 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import kotlinx.cinterop.*
import llvm.*
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.implementation
import org.jetbrains.kotlin.backend.konan.implementedInterfaces
import org.jetbrains.kotlin.backend.konan.isInterface
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
import llvm.*
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.backend.konan.Context
/**
* Provides utilities to create static data.
@@ -108,7 +108,7 @@ internal fun StaticData.createKotlinObject(type: KotlinType, body: ConstValue):
}
private fun StaticData.getArrayListClass(): ClassDescriptor {
val module = context.irModule.descriptor
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)
@@ -138,4 +138,4 @@ internal fun StaticData.createArrayList(elementType: TypeProjection, array: Cons
)
return createKotlinObject(type, body)
}
}