translator: add ability specify entry point, optimize external function detector

This commit is contained in:
Alexey Stepanov
2016-08-29 13:50:01 +03:00
parent ffbb69e051
commit 4ab79533b1
6 changed files with 23 additions and 42 deletions
@@ -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
) )
}
}
+1 -1
View File
@@ -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? {