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:
committed by
alexander-gorshenev
parent
6a6424f462
commit
35668cc7e1
@@ -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()
|
||||
|
||||
+30
-11
@@ -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");
|
||||
}
|
||||
}
|
||||
+125
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+73
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+100
@@ -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
-1
@@ -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
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -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 {
|
||||
+46
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
+76
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+84
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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
|
||||
+1
-1
@@ -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
|
||||
+3
-3
@@ -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
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
+1
@@ -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
|
||||
|
||||
-43
@@ -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>()
|
||||
}
|
||||
+43
-2
@@ -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>()
|
||||
}
|
||||
|
||||
+59
-35
@@ -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");
|
||||
|
||||
+2
-1
@@ -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)!!
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -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
|
||||
}
|
||||
|
||||
+5
-5
@@ -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 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+1
@@ -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.
|
||||
|
||||
+2
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user