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
|
package org.jetbrains.kotlin.cli.bc
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import com.intellij.openapi.Disposable
|
import com.intellij.openapi.Disposable
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
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.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.messages.AnalyzerWithCompilerReport
|
||||||
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||||
@@ -21,70 +21,65 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import java.lang.System.out
|
import java.lang.System.out
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NativeAnalyzer(
|
|
||||||
val environment: KotlinCoreEnvironment,
|
|
||||||
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>() {
|
class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||||
|
|
||||||
val defaultModuleName = "main";
|
|
||||||
|
|
||||||
override fun doExecute(arguments : K2NativeCompilerArguments,
|
override fun doExecute(arguments : K2NativeCompilerArguments,
|
||||||
configuration : CompilerConfiguration,
|
configuration : CompilerConfiguration,
|
||||||
rootDisposable: Disposable
|
rootDisposable: Disposable
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
|
|
||||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, defaultModuleName)
|
|
||||||
|
|
||||||
configuration.addKotlinSourceRoots(arguments.freeArgs)
|
configuration.get(KonanConfigKeys.LIBRARY_FILES)?.forEach{ println(it) }
|
||||||
|
|
||||||
val libraries = arguments.libraries?.asList<String>() ?: listOf<String>()
|
|
||||||
configuration.put(KonanConfigurationKeys.LIBRARY_FILES, libraries)
|
|
||||||
libraries.forEach{println(it)}
|
|
||||||
|
|
||||||
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable,
|
||||||
configuration, Arrays.asList<String>("extensions/common.xml"))
|
configuration, Arrays.asList<String>("extensions/common.xml"))
|
||||||
|
|
||||||
val collector = configuration.getNotNull(
|
|
||||||
CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
|
||||||
|
|
||||||
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
|
||||||
|
|
||||||
val project = environment.project
|
val project = environment.project
|
||||||
val config = KonanConfig(project, configuration)
|
val konanConfig = KonanConfig(project, configuration)
|
||||||
|
|
||||||
|
runTopLevelPhases(konanConfig, environment)
|
||||||
// Build AST and binding info.
|
|
||||||
analyzerWithCompilerReport.analyzeAndReport(environment.getSourceFiles(),
|
|
||||||
NativeAnalyzer(environment, environment.getSourceFiles(), config))
|
|
||||||
|
|
||||||
// Translate AST to high level IR.
|
|
||||||
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
|
||||||
val module = translator.generateModule(
|
|
||||||
analyzerWithCompilerReport.analysisResult.moduleDescriptor,
|
|
||||||
environment.getSourceFiles(),
|
|
||||||
analyzerWithCompilerReport.analysisResult.bindingContext)
|
|
||||||
|
|
||||||
// Emit LLVM code.
|
|
||||||
module.accept(DumpIrTreeVisitor(out), "")
|
|
||||||
emitLLVM(module, arguments.runtimeFile, arguments.outputFile)
|
|
||||||
|
|
||||||
return ExitCode.OK
|
return ExitCode.OK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Array<String>?.toNonNullList(): List<String> {
|
||||||
|
return this?.asList<String>() ?: listOf<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// It is executed before doExecute().
|
||||||
override fun setupPlatformSpecificArgumentsAndServices(
|
override fun setupPlatformSpecificArgumentsAndServices(
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
arguments : K2NativeCompilerArguments,
|
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 {
|
override fun createArguments(): K2NativeCompilerArguments {
|
||||||
return 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.CommonCompilerArguments;
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.ValueDescription;
|
import org.jetbrains.kotlin.cli.common.arguments.ValueDescription;
|
||||||
|
|
||||||
|
|
||||||
public class K2NativeCompilerArguments extends CommonCompilerArguments {
|
public class K2NativeCompilerArguments extends CommonCompilerArguments {
|
||||||
@Argument(value = "output", description = "Output file path")
|
@Argument(value = "output", description = "Output file path")
|
||||||
@ValueDescription("<path>")
|
@ValueDescription("<path>")
|
||||||
@@ -18,17 +17,37 @@ public class K2NativeCompilerArguments extends CommonCompilerArguments {
|
|||||||
@ValueDescription("<path>")
|
@ValueDescription("<path>")
|
||||||
public String[] libraries;
|
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) {
|
@Argument(value = "print_bitcode", description = "Print llvm bitcode")
|
||||||
this.outputFile = arguments.outputFile;
|
public boolean printBitCode;
|
||||||
this.runtimeFile = arguments.runtimeFile;
|
|
||||||
this.libraries = arguments.libraries;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommonCompilerArguments copy() {
|
@Argument(value = "verify_ir", description = "Verify IR")
|
||||||
return new K2NativeCompilerArguments(this);
|
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
|
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.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
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.common.BackendContext
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager
|
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 {
|
open internal class KonanBackendContext : BackendContext {
|
||||||
override val builtIns = KonanPlatform.builtIns
|
override val builtIns = KonanPlatform.builtIns
|
||||||
@@ -12,4 +12,4 @@ open internal class KonanBackendContext : BackendContext {
|
|||||||
// TODO: investigate this.
|
// TODO: investigate this.
|
||||||
KonanSharedVariablesManager(builtIns)
|
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 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.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
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.KotlinKonanMetadata
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadataUtils
|
import org.jetbrains.kotlin.backend.konan.llvm.KotlinKonanMetadataUtils
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class representing a configuration of translator.
|
|
||||||
*/
|
|
||||||
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
class KonanConfig(val project: Project, val configuration: CompilerConfiguration) {
|
||||||
|
|
||||||
private val storageManager = LockBasedStorageManager()
|
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)
|
private val metadata = KotlinKonanMetadataUtils.loadLibMetadata(libraries)
|
||||||
|
|
||||||
@@ -32,7 +30,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
|||||||
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
get() = configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)
|
||||||
|
|
||||||
val moduleKind: ModuleKind
|
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.
|
// We reuse JsModuleDescriptor for serialization for now, as we haven't got one for Konan yet.
|
||||||
internal val moduleDescriptors: MutableList<JsModuleDescriptor<ModuleDescriptorImpl>> by lazy {
|
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
|
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.LocalFunctionsLowering
|
||||||
import org.jetbrains.kotlin.backend.common.lower.SharedVariablesLowering
|
import org.jetbrains.kotlin.backend.common.lower.SharedVariablesLowering
|
||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
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.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
|
||||||
internal class KonanLower(val context: KonanBackendContext) {
|
internal class KonanLower(val context: Context) {
|
||||||
|
|
||||||
fun lower(module: IrModuleFragment) {
|
fun lower(module: IrModuleFragment) {
|
||||||
module.files.forEach {
|
module.files.forEach {
|
||||||
@@ -16,8 +18,16 @@ internal class KonanLower(val context: KonanBackendContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun lower(irFile: IrFile) {
|
fun lower(irFile: IrFile) {
|
||||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
val phaser = PhaseManager(context)
|
||||||
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
|
|
||||||
CallableReferenceLowering(context).runOnFilePostfix(irFile)
|
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.
|
* 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.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.ImportPath
|
||||||
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
import org.jetbrains.kotlin.resolve.PlatformConfigurator
|
||||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
// Adapted from JS compiler, but everyhing has been switched off for now.
|
// 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.StorageComponentContainer
|
||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
+3
-3
@@ -14,11 +14,11 @@
|
|||||||
* limitations under the License.
|
* 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.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.KonanBuiltIns
|
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
||||||
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.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
import org.jetbrains.kotlin.context.ContextForNewModule
|
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.common.descriptors.SharedVariablesManager
|
||||||
import org.jetbrains.kotlin.backend.konan.getKonanInternalClass
|
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.ClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
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
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
+1
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
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 kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.hash.GlobalHash
|
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.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
@@ -22,7 +24,7 @@ internal interface ContextUtils {
|
|||||||
val context: Context
|
val context: Context
|
||||||
|
|
||||||
val runtime: Runtime
|
val runtime: Runtime
|
||||||
get() = context.runtime
|
get() = context.llvm.runtime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes the target platform.
|
* Describes the target platform.
|
||||||
@@ -33,7 +35,7 @@ internal interface ContextUtils {
|
|||||||
get() = runtime.targetData
|
get() = runtime.targetData
|
||||||
|
|
||||||
val staticData: StaticData
|
val staticData: StaticData
|
||||||
get() = context.staticData
|
get() = context.llvm.staticData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All fields of the class instance.
|
* All fields of the class instance.
|
||||||
@@ -161,3 +163,42 @@ internal interface ContextUtils {
|
|||||||
val FqName.localHash: LocalHash
|
val FqName.localHash: LocalHash
|
||||||
get() = this.toString().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.isNothing
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
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?
|
internal fun emitLLVM(context: Context) {
|
||||||
val context = Context(
|
|
||||||
module, runtime, llvmModule, BindingContext.EMPTY) // TODO: dispose
|
|
||||||
|
|
||||||
KonanLower(context).lower(module)
|
val irModule = context.irModule!!
|
||||||
|
val llvmModule = LLVMModuleCreateWithName("out")!! // TODO: dispose
|
||||||
|
context.llvmModule = llvmModule
|
||||||
|
|
||||||
module.acceptVoid(RTTIGeneratorVisitor(context))
|
val phaser = PhaseManager(context)
|
||||||
println("\n--- Generate bitcode ------------------------------------------------------\n")
|
|
||||||
module.acceptVoid(CodeGeneratorVisitor(context))
|
phaser.phase("RTTI") {
|
||||||
verifyModule(llvmModule)
|
irModule.acceptVoid(RTTIGeneratorVisitor(context))
|
||||||
LLVMWriteBitcodeToFile(llvmModule, outFile)
|
}
|
||||||
|
|
||||||
|
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 {
|
memScoped {
|
||||||
val errorRef = allocPointerTo<CInt8Var>()
|
val errorRef = allocPointerTo<CInt8Var>()
|
||||||
// TODO: use LLVMDisposeMessage() on errorRef, once possible in interop.
|
// 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 {
|
internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid {
|
||||||
|
|
||||||
val codegen = CodeGenerator(context)
|
val codegen = CodeGenerator(context)
|
||||||
val logger = Logger(codegen, context)
|
val logger = if (context.phase!!.verbose) {
|
||||||
val metadator = MetadataGenerator(context)
|
Logger(codegen, context)
|
||||||
|
} else {
|
||||||
|
DummyLogger(codegen, context)
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
@@ -191,9 +217,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
logger.log("visitModule : ${ir2string(module)}")
|
logger.log("visitModule : ${ir2string(module)}")
|
||||||
module.acceptChildrenVoid(this)
|
module.acceptChildrenVoid(this)
|
||||||
|
|
||||||
appendLlvmUsed(context.usedFunctions)
|
appendLlvmUsed(context.llvm.usedFunctions)
|
||||||
|
|
||||||
metadator.endModule(module)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -459,7 +483,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
override fun genThrow(exception: LLVMValueRef) {
|
override fun genThrow(exception: LLVMValueRef) {
|
||||||
val objHeaderPtr = codegen.bitcast(codegen.kObjHeaderPtr, exception, codegen.newVar())
|
val objHeaderPtr = codegen.bitcast(codegen.kObjHeaderPtr, exception, codegen.newVar())
|
||||||
val args = listOf(objHeaderPtr)
|
val args = listOf(objHeaderPtr)
|
||||||
codegen.call(context.throwExceptionFunction, args, "")
|
codegen.call(context.llvm.throwExceptionFunction, args, "")
|
||||||
codegen.unreachable()
|
codegen.unreachable()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,14 +509,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
return
|
return
|
||||||
|
|
||||||
codegen.prologue(declaration)
|
codegen.prologue(declaration)
|
||||||
metadator.function(declaration)
|
|
||||||
|
|
||||||
using(FunctionScope(declaration)) {
|
using(FunctionScope(declaration)) {
|
||||||
declaration.acceptChildrenVoid(this)
|
declaration.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen.epilogue(declaration)
|
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 ctor = codegen.llvmFunction(initFunction)
|
||||||
val args = listOf(objectPtr, typeInfo, allocHint, ctor)
|
val args = listOf(objectPtr, typeInfo, allocHint, ctor)
|
||||||
val newValue = currentCodeContext.genCall(
|
val newValue = currentCodeContext.genCall(
|
||||||
context.initInstanceFunction, args, codegen.newVar())
|
context.llvm.initInstanceFunction, args, codegen.newVar())
|
||||||
codegen.br(bbExit)
|
codegen.br(bbExit)
|
||||||
|
|
||||||
codegen.positionAtEnd(bbExit)
|
codegen.positionAtEnd(bbExit)
|
||||||
@@ -763,14 +787,14 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
val typeInfo = codegen.typeInfoValue(value.type)!!
|
val typeInfo = codegen.typeInfoValue(value.type)!!
|
||||||
val arrayCreationArgs = listOf(typeInfo, kImmInt32One, finalLength!!)
|
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) ->
|
elements.fold(kImmZero) { sum, (exp, size, isArray) ->
|
||||||
if (!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())
|
return@fold codegen.plus(sum, kImmOne, codegen.newVar())
|
||||||
} else {
|
} 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())
|
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 srcArg = evaluateExpression(codegen.newVar(), value.argument)!! // Evaluate src expression.
|
||||||
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
|
val srcObjInfoPtr = codegen.bitcast(codegen.kObjHeaderPtr, srcArg, codegen.newVar()) // Cast src to ObjInfoPtr.
|
||||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
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
|
return srcArg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1293,7 +1317,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
val args = listOf(srcObjInfoPtr, dstTypeInfo) // Create arg list.
|
||||||
|
|
||||||
val result = currentCodeContext.genCall( // Check if dst is subclass of src.
|
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
|
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.Int -> return LLVMConstInt(LLVMInt32Type(), (value.value as Int).toLong(), 1)
|
||||||
IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1)
|
IrConstKind.Long -> return LLVMConstInt(LLVMInt64Type(), value.value as Long, 1)
|
||||||
IrConstKind.String ->
|
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.Float -> return LLVMConstRealOfString(LLVMFloatType(), (value.value as Float).toString())
|
||||||
IrConstKind.Double -> return LLVMConstRealOfString(LLVMDoubleType(), (value.value as Double).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>`,
|
// however `vararg` is immutable, and in current implementation it has type `Array<E>`,
|
||||||
// so let's ignore this mismatch currently for simplicity.
|
// 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) {
|
val thisValue = if (containingClass.isArray) {
|
||||||
assert(args.size == 1 && args[0].type == int32Type)
|
assert(args.size == 1 && args[0].type == int32Type)
|
||||||
val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0])
|
val allocArrayInstanceArgs = listOf(typeInfo, allocHint, args[0])
|
||||||
currentCodeContext.genCall(context.allocArrayFunction, allocArrayInstanceArgs, variableName)
|
currentCodeContext.genCall(context.llvm.allocArrayFunction, allocArrayInstanceArgs, variableName)
|
||||||
} else {
|
} else {
|
||||||
currentCodeContext.genCall(context.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
|
currentCodeContext.genCall(context.llvm.allocInstanceFunction, listOf(typeInfo, allocHint), variableName)
|
||||||
}
|
}
|
||||||
val constructorParams: MutableList<LLVMValueRef> = mutableListOf()
|
val constructorParams: MutableList<LLVMValueRef> = mutableListOf()
|
||||||
constructorParams += thisValue
|
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 methodHash = codegen.functionHash(descriptor) // Calculate hash of the method to be invoked
|
||||||
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
|
val lookupArgs = listOf(typeInfoPtr, methodHash) // Prepare args for lookup
|
||||||
val llvmMethod = currentCodeContext.genCall(
|
val llvmMethod = currentCodeContext.genCall(
|
||||||
context.lookupOpenMethodFunction,
|
context.llvm.lookupOpenMethodFunction,
|
||||||
lookupArgs,
|
lookupArgs,
|
||||||
codegen.newVar()) // Get method ptr to be invoked
|
codegen.newVar()) // Get method ptr to be invoked
|
||||||
|
|
||||||
@@ -1897,7 +1921,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val arrayLength = args.size
|
val arrayLength = args.size
|
||||||
val argsCasted = args.map { it -> constPointer(it).bitcast(int8TypePtr) }
|
val argsCasted = args.map { it -> constPointer(it).bitcast(int8TypePtr) }
|
||||||
val llvmUsedGlobal =
|
val llvmUsedGlobal =
|
||||||
context.staticData.placeGlobalArray("llvm.used", int8TypePtr, argsCasted)
|
context.llvm.staticData.placeGlobalArray("llvm.used", int8TypePtr, argsCasted)
|
||||||
|
|
||||||
LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage);
|
LLVMSetLinkage(llvmUsedGlobal.llvmGlobal, LLVMLinkage.LLVMAppendingLinkage);
|
||||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata");
|
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata");
|
||||||
|
|||||||
+2
-1
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.allValueParameters
|
import org.jetbrains.kotlin.backend.konan.allValueParameters
|
||||||
|
import org.jetbrains.kotlin.backend.konan.KonanPlatform
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
|
||||||
internal val LLVMValueRef.type: LLVMTypeRef
|
internal val LLVMValueRef.type: LLVMTypeRef
|
||||||
@@ -184,4 +185,4 @@ internal fun functionType(returnType: LLVMTypeRef, isVarArg: Boolean = false, va
|
|||||||
memScoped {
|
memScoped {
|
||||||
val paramTypesPtr = allocArrayOf(*paramTypes)[0].ptr
|
val paramTypesPtr = allocArrayOf(*paramTypes)[0].ptr
|
||||||
LLVMFunctionType(returnType, paramTypesPtr, paramTypes.size, if (isVarArg) 1 else 0)!!
|
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 kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||||
import java.io.StringWriter
|
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
|
private var logcounter: Int = LLVMPrintModuleToString(context.llvmModule)!!.asCString().toString().lines().size
|
||||||
|
|
||||||
//---------------------------------------------------------------------------//
|
//---------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun log(msg: String) {
|
open fun log(msg: String) {
|
||||||
// logIr()
|
|
||||||
println(msg)
|
println(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------//
|
//---------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun logIr() {
|
open fun logIr() {
|
||||||
val function = generator.currentFunction ?: return
|
val function = generator.currentFunction ?: return
|
||||||
|
|
||||||
val irFunctionDeclaration = LLVMPrintValueToString(function.llvmFunction)!!.asCString().toString()
|
val irFunctionDeclaration = LLVMPrintValueToString(function.llvmFunction)!!.asCString().toString()
|
||||||
@@ -48,3 +48,10 @@ fun llvm2string(value: LLVMValueRef?): String {
|
|||||||
return LLVMPrintValueToString(value)!!.asCString().toString()
|
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
|
package org.jetbrains.kotlin.backend.konan.llvm
|
||||||
|
|
||||||
|
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
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.backend.konan.llvm.BinaryLinkdata.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
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 args = listOf(fn, metadataString(info));
|
||||||
val md = metadataNode(args)
|
val md = metadataNode(args)
|
||||||
return md
|
return md
|
||||||
@@ -146,11 +146,12 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
|
|||||||
// Convert it to ProtoBuf's TextFormat representation.
|
// Convert it to ProtoBuf's TextFormat representation.
|
||||||
// Use TextFormat.merge(str, builder) to parse it back
|
// Use TextFormat.merge(str, builder) to parse it back
|
||||||
val str = proto.toString()
|
val str = proto.toString()
|
||||||
|
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun function(declaration: IrFunction) {
|
internal fun function(declaration: IrFunction) {
|
||||||
val fn = declaration.descriptor.llvmFunction
|
val fn = declaration.descriptor.llvmFunction!!
|
||||||
|
|
||||||
val proto = serializeFunSignature(declaration)
|
val proto = serializeFunSignature(declaration)
|
||||||
|
|
||||||
@@ -173,6 +174,7 @@ internal class MetadataGenerator(override val context: Context): ContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun serializeModule(moduleDescriptor: ModuleDescriptor): String {
|
private fun serializeModule(moduleDescriptor: ModuleDescriptor): String {
|
||||||
|
|
||||||
val description = JsModuleDescriptor(
|
val description = JsModuleDescriptor(
|
||||||
name = "foo",
|
name = "foo",
|
||||||
kind = ModuleKind.PLAIN,
|
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 kotlinx.cinterop.*
|
||||||
import llvm.*
|
import llvm.*
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.implementation
|
import org.jetbrains.kotlin.backend.konan.implementation
|
||||||
import org.jetbrains.kotlin.backend.konan.implementedInterfaces
|
import org.jetbrains.kotlin.backend.konan.implementedInterfaces
|
||||||
import org.jetbrains.kotlin.backend.konan.isInterface
|
import org.jetbrains.kotlin.backend.konan.isInterface
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan.llvm
|
|||||||
|
|
||||||
import llvm.*
|
import llvm.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides utilities to create static data.
|
* 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 {
|
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 pkg = module.getPackage(FqName.fromSegments(listOf("kotlin", "collections")))
|
||||||
val classifier = pkg.memberScope.getContributedClassifier(Name.identifier("ArrayList"),
|
val classifier = pkg.memberScope.getContributedClassifier(Name.identifier("ArrayList"),
|
||||||
NoLookupLocation.FROM_BACKEND)
|
NoLookupLocation.FROM_BACKEND)
|
||||||
@@ -138,4 +138,4 @@ internal fun StaticData.createArrayList(elementType: TypeProjection, array: Cons
|
|||||||
)
|
)
|
||||||
|
|
||||||
return createKotlinObject(type, body)
|
return createKotlinObject(type, body)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user