translator: add ability specify entry point, optimize external function detector
This commit is contained in:
@@ -21,9 +21,17 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") {
|
|||||||
shortNames = listOf('o')
|
shortNames = listOf('o')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val mainClass = optionalParameter(
|
||||||
|
name = "main class",
|
||||||
|
aliasNames = listOf("main"),
|
||||||
|
default = "main",
|
||||||
|
shortNames = listOf('M')
|
||||||
|
)
|
||||||
|
|
||||||
val sources = positionalArguments(
|
val sources = positionalArguments(
|
||||||
name = "sources",
|
name = "sources",
|
||||||
description = "source files",
|
description = "source files",
|
||||||
minCount = 1
|
minCount = 1
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ fun main(args: Array<String>) {
|
|||||||
|
|
||||||
analyzedFiles.addAll(arguments.sources)
|
analyzedFiles.addAll(arguments.sources)
|
||||||
|
|
||||||
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.arm ?: false)
|
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm ?: false)
|
||||||
val files = state.environment.getSourceFiles()
|
val files = state.environment.getSourceFiles()
|
||||||
val code = ProjectTranslator(files, state).generateCode()
|
val code = ProjectTranslator(files, state).generateCode()
|
||||||
|
|
||||||
|
|||||||
@@ -44,23 +44,18 @@ class FunctionCodegen(state: TranslationState,
|
|||||||
if (returnType!!.type is LLVMReferenceType) {
|
if (returnType!!.type is LLVMReferenceType) {
|
||||||
returnType!!.pointer = 2
|
returnType!!.pointer = 2
|
||||||
}
|
}
|
||||||
external = isExternal()
|
external = descriptor.isExternal
|
||||||
name = "${function.fqName}${if (args.size > 0 && !external) LLVMType.mangleFunctionArguments(args) else ""}"
|
name = "${function.fqName}${if (!external) LLVMType.mangleFunctionArguments(args) else ""}"
|
||||||
val pureName = name.substringAfterLast('.')
|
|
||||||
if (pureName == "main") {
|
|
||||||
state.mainFunctions.add(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isExtensionDeclaration) {
|
if (isExtensionDeclaration) {
|
||||||
name = "${function.name}${if (args.size > 0 && !external) LLVMType.mangleFunctionArguments(args) else ""}"
|
name = "${function.name}${if (args.size > 0 && !external) LLVMType.mangleFunctionArguments(args) else ""}"
|
||||||
val receiverType = descriptor.extensionReceiverParameter!!.type
|
val receiverType = descriptor.extensionReceiverParameter!!.type
|
||||||
val translatorType = LLVMMapStandardType(receiverType, state)
|
val translatorType = LLVMMapStandardType(receiverType, state)
|
||||||
val packageName = (function.containingFile as KtFile).packageFqName.asString()
|
val packageName = (function.containingFile as KtFile).packageFqName.asString()
|
||||||
functionNamePrefix += if (packageName.length > 0) "$packageName." else ""
|
functionNamePrefix = packageName.addAfterIfNotEmpty(".") + translatorType.mangle() + "."
|
||||||
functionNamePrefix += translatorType.mangle() + "."
|
|
||||||
|
|
||||||
val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType.toString(), HashMap())
|
val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType.toString(), HashMap())
|
||||||
extensionFunctionsOfThisType.put(functionNamePrefix + name, this)
|
extensionFunctionsOfThisType.put(fullName, this)
|
||||||
state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType)
|
state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +145,7 @@ class FunctionCodegen(state: TranslationState,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).byRef) {
|
if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).byRef) {
|
||||||
val loadVariable = LLVMVariable("${it.label}", it.type, it.label, LLVMRegisterScope(), pointer = it.pointer)
|
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer)
|
||||||
val allocVar = codeBuilder.loadArgument(loadVariable)
|
val allocVar = codeBuilder.loadArgument(loadVariable)
|
||||||
variableManager.addVariable(it.label, allocVar, topLevel)
|
variableManager.addVariable(it.label, allocVar, topLevel)
|
||||||
} else {
|
} else {
|
||||||
@@ -159,16 +154,4 @@ class FunctionCodegen(state: TranslationState,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isExternal(): Boolean {
|
|
||||||
var keyword = function.firstChild
|
|
||||||
while (keyword != null) {
|
|
||||||
if (keyword.text == "external") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
keyword = keyword.getNextSiblingIgnoringWhitespaceAndComments()
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -63,8 +63,8 @@ class ProjectTranslator(val files: List<KtFile>, val state: TranslationState) {
|
|||||||
functions.values.filter { !it.isExtensionDeclaration }.map { it.generate() }
|
functions.values.filter { !it.isExtensionDeclaration }.map { it.generate() }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.mainFunctions.contains("main") && state.mainFunctions.isNotEmpty()) {
|
if (state.mainFunction != "main") {
|
||||||
codeBuilder.declareEntryPoint(state.mainFunctions.first())
|
codeBuilder.declareEntryPoint(state.mainFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,13 +39,9 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
open fun prepareForGenerate() {
|
open fun prepareForGenerate() {
|
||||||
generateStruct()
|
generateStruct()
|
||||||
|
|
||||||
for (declaration in classOrObject.declarations) {
|
for (declaration in classOrObject.declarations.filter { it is KtNamedFunction }) {
|
||||||
when (declaration) {
|
val function = FunctionCodegen(state, variableManager, declaration as KtNamedFunction, codeBuilder, packageName, this)
|
||||||
is KtNamedFunction -> {
|
methods.put(function.name, function)
|
||||||
val function = FunctionCodegen(state, variableManager, declaration, codeBuilder, packageName, this)
|
|
||||||
methods.put(function.name, function)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,20 +218,15 @@ abstract class StructCodegen(val state: TranslationState,
|
|||||||
|
|
||||||
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
||||||
val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||||
codeBuilder.addComment("field initializers starts")
|
|
||||||
variableManager.addVariable("this", receiverThis, 2)
|
variableManager.addVariable("this", receiverThis, 2)
|
||||||
|
|
||||||
for ((variable, initializer) in initializedFields) {
|
for ((variable, initializer) in initializedFields) {
|
||||||
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!!
|
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!!
|
||||||
codeBuilder.addComment("left expression")
|
|
||||||
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!!
|
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!!
|
||||||
codeBuilder.addComment("right expression")
|
|
||||||
blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right)
|
blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right)
|
||||||
codeBuilder.addComment("next initializer")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variableManager.pullOneUpwardLevelVariable("this")
|
variableManager.pullOneUpwardLevelVariable("this")
|
||||||
codeBuilder.addComment("field initializers ends")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateReturn(src: LLVMVariable) {
|
private fun generateReturn(src: LLVMVariable) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import org.kotlinnative.translator.llvm.LLVMBuilder
|
|||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, arm: Boolean) {
|
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) {
|
||||||
companion object {
|
companion object {
|
||||||
var pointerAlign = 4
|
var pointerAlign = 4
|
||||||
var pointerSize = 4
|
var pointerSize = 4
|
||||||
@@ -43,12 +43,11 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
|||||||
var objects = HashMap<String, ObjectCodegen>()
|
var objects = HashMap<String, ObjectCodegen>()
|
||||||
var properties = HashMap<String, PropertyCodegen>()
|
var properties = HashMap<String, PropertyCodegen>()
|
||||||
val codeBuilder = LLVMBuilder(arm)
|
val codeBuilder = LLVMBuilder(arm)
|
||||||
val mainFunctions = ArrayList<String>()
|
|
||||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseAndAnalyze(sources: List<String>, disposer: Disposable, arm: Boolean = false): TranslationState {
|
fun parseAndAnalyze(sources: List<String>, disposer: Disposable, mainFunction: String, arm: Boolean = false): TranslationState {
|
||||||
|
|
||||||
val configuration = CompilerConfiguration()
|
val configuration = CompilerConfiguration()
|
||||||
val messageCollector = object : MessageCollector {
|
val messageCollector = object : MessageCollector {
|
||||||
@@ -72,7 +71,7 @@ fun parseAndAnalyze(sources: List<String>, disposer: Disposable, arm: Boolean =
|
|||||||
val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||||
val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project")
|
val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project")
|
||||||
|
|
||||||
return TranslationState(environment, bindingContext, arm)
|
return TranslationState(environment, bindingContext, mainFunction, arm)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
||||||
|
|||||||
Reference in New Issue
Block a user