translator: refactoring, add a skeleton for LLVMBuilder, reformat expression generation

This commit is contained in:
Alexey Stepanov
2016-07-08 18:02:51 +03:00
parent 349055959f
commit 86e50516a3
7 changed files with 63 additions and 165 deletions
@@ -2,22 +2,15 @@ package org.kotlinnative.translator
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlin.native.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
import org.kotlinnative.translator.llvm.LLVMMapStandardType
import org.kotlinnative.translator.llvm.LLVMBuilder
class FileTranslator(val state: TranslationState, val file: KtFile) {
private var codeBuilder = LLVMBuilder()
private var compiled = false;
fun generateCode(): String {
if (!compiled) {
generateFileBody()
}
compiled = true
codeBuilder.clean()
generateFileBody()
return codeBuilder.toString()
}
@@ -10,21 +10,19 @@ import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlin.native.translator.llvm.LLVMBuilder
import org.kotlin.native.translator.llvm.LLVMVariable
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
import org.kotlinnative.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.llvm.LLVMVariable
import org.kotlinnative.translator.llvm.LLVMDescriptorGenerate
import org.kotlinnative.translator.llvm.LLVMMapStandardType
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
private var variableCount = 0
fun generate() {
generateDeclaration(function)
codeBuilder.addLlvmCode("{")
codeBuilder.addStartExpression()
expressionWalker(function.bodyExpression)
codeBuilder.addLlvmCode("}")
codeBuilder.addEndExpression()
}
private fun generateDeclaration(function: KtNamedFunction) {
@@ -34,8 +32,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
val returnType = LLVMMapStandardType(descriptor?.returnType.toString())
codeBuilder.addLlvmCode(LLVMDescriptorGenearte(function.fqName.toString(), args, returnType))
codeBuilder.addLLVMCode(LLVMDescriptorGenerate(function.fqName.toString(), args, returnType))
}
private fun expressionWalker(expr: Any?) {
@@ -48,17 +45,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
private fun evaluateBlockExpression(expr: KtBlockExpression) {
var element = expr
expressionWalker(element.firstChild)
expressionWalker(element.getNextSiblingIgnoringWhitespaceAndComments())
expressionWalker(expr.firstChild)
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments())
}
private fun evaluatePsiExpression(expr: PsiElement) {
var element = expr
evaluateExpression(element.firstChild)
evaluatePsiExpression(element.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
evaluateExpression(expr.firstChild)
evaluatePsiExpression(expr.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
}
private fun evaluateExpression(expr: Any?): LLVMVariable? {
@@ -73,21 +66,11 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
}
private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMVariable {
val left = evaluateExpression(expr.firstChild)
val right = evaluateExpression(expr.lastChild)
val left = evaluateExpression(expr.firstChild) ?: throw UnsupportedOperationException("Wrong binary exception")
val right = evaluateExpression(expr.lastChild) ?: throw UnsupportedOperationException("Wrong binary exception")
val operator = expr.operationToken
val llvmOperator = when (operator) {
KtTokens.PLUS -> "add nsw i32"
KtTokens.MINUS -> "sub nsw i32"
KtTokens.MUL -> "mul nsw i32"
else -> throw UnsupportedOperationException("Unkbown binary operator")
}
variableCount++
codeBuilder.addLlvmCode("%var$variableCount = $llvmOperator ${left?.label}, ${right?.label}")
return LLVMVariable("%var$variableCount")
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
@@ -109,14 +92,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
else -> LLVMVariable("")
}
}
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
val retVar = evaluateExpression(next)
codeBuilder.addLlvmCode("ret i32 ${retVar?.label}")
codeBuilder.addLLVMCode("ret i32 ${retVar?.label}")
return null
}
}
@@ -1,117 +0,0 @@
package hello
import com.intellij.openapi.util.Disposer
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.getModuleName
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.addKotlinSourceRoot
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.TopDownAnalysisContext
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.*
import java.util.logging.Logger
class KotlinScriptParser {
companion object {
private val LOG = Logger.getLogger(KotlinScriptParser.javaClass.name)
private val messageCollector = object : MessageCollector {
override fun hasErrors(): Boolean {
throw UnsupportedOperationException()
}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
val path = location.path
val position = if (path == null) "" else "$path: (${location.line}, ${location.column}) "
val text = position + message
if (CompilerMessageSeverity.VERBOSE.contains(severity)) {
LOG.finest(text)
} else if (CompilerMessageSeverity.ERRORS.contains(severity)) {
LOG.severe(text)
} else if (severity == CompilerMessageSeverity.INFO) {
LOG.info(text)
} else {
LOG.warning(text)
}
}
}
private val classPath: ArrayList<File> by lazy {
val classpath = arrayListOf<File>()
classpath += PathUtil.getResourcePathForClass(AnnotationTarget.CLASS.javaClass)
classpath
}
}
fun parse(vararg files: String): TopDownAnalysisContext {
// The Kotlin compiler configuration
val configuration = CompilerConfiguration()
val groupingCollector = GroupingMessageCollector(messageCollector)
//val severityCollector = MessageSeverityCollector(groupingCollector)
//configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, severityCollector)
configuration.addJvmClasspathRoots(PathUtil.getJdkClassesRoots())
// The path to .kt files sources
files.forEach { configuration.addKotlinSourceRoot(it) }
// Configuring Kotlin class path
configuration.addJvmClasspathRoots(classPath)
configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME)
//configuration.put<List<AnalyzerScriptParameter>>(JVMConfigurationKeys.SCRIPT_PARAMETERS, CommandLineScriptUtils.scriptParameters())
val rootDisposable = Disposer.newDisposable()
try {
val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
val ktFiles = environment.getSourceFiles()
//printFile(ktFiles.first())
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project,
environment.getModuleName())
val project = moduleContext.project
val allFiles = JvmAnalyzerFacade.getAllFilesToAnalyze(project, null, ktFiles)
val providerFactory = FileBasedDeclarationProviderFactory(moduleContext.storageManager, allFiles)
val lookupTracker = LookupTracker.DO_NOTHING
val packagePartProvider = JvmPackagePartProvider(environment)
val container = createContainerForTopDownAnalyzerForJvm(
moduleContext,
sharedTrace,
providerFactory,
GlobalSearchScope.allScope(project),
lookupTracker,
packagePartProvider, LanguageVersion.LATEST)
val additionalProviders = ArrayList<PackageFragmentProvider>()
additionalProviders.add(container.javaDescriptorResolver.packageFragmentProvider)
return container.lazyTopDownAnalyzerForTopLevel.analyzeFiles(TopDownAnalysisMode.LocalDeclarations, allFiles, additionalProviders)
} finally {
rootDisposable.dispose()
//if (severityCollector.anyReported(CompilerMessageSeverity.ERROR)) {
// throw RuntimeException("Compilation error")
//}
}
}
}
@@ -1,4 +1,5 @@
package org.kotlinnative.translator
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -1,12 +1,47 @@
package org.kotlin.native.translator.llvm
package org.kotlinnative.translator.llvm
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.lexer.KtTokens
class LLVMBuilder {
private val llvmCode: StringBuilder = StringBuilder()
private var llvmCode: StringBuilder = StringBuilder()
private var variableCount = 0
fun addLlvmCode(code: String) {
private fun getNewVariable(): LLVMVariable {
variableCount++
return LLVMVariable("%var$variableCount")
}
fun addLLVMCode(code: String) {
llvmCode.appendln(code)
}
fun addStartExpression() {
llvmCode.appendln("{")
}
fun addEndExpression() {
llvmCode.appendln("}")
}
fun addPrimitiveBinaryOperation(operation: IElementType, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMVariable {
val newVar = getNewVariable()
val llvmOperator = when (operation) {
KtTokens.PLUS -> "add nsw i32"
KtTokens.MINUS -> "sub nsw i32"
KtTokens.MUL -> "mul nsw i32"
else -> throw UnsupportedOperationException("Unkbown binary operator")
}
llvmCode.appendln("$newVar = $llvmOperator $firstOp, $secondOp")
return newVar
}
fun clean() {
llvmCode = StringBuilder()
}
override fun toString(): String {
return llvmCode.toString()
}
@@ -1,3 +1,7 @@
package org.kotlin.native.translator.llvm
package org.kotlinnative.translator.llvm
data class LLVMVariable(val label: String)
data class LLVMVariable(val label: String){
override fun toString(): String {
return label
}
}
@@ -1,6 +1,6 @@
package org.kotlinnative.translator.llvm
fun LLVMDescriptorGenearte(name: String, argTypes: List<Pair<String, String>>?, returnType: String) =
fun LLVMDescriptorGenerate(name: String, argTypes: List<Pair<String, String>>?, returnType: String) =
"define $returnType @$name(${argTypes?.mapIndexed { i: Int, s: Pair<String, String> -> "${s.second} %${s.first}" }?.joinToString() ?: "" })"
fun LLVMMapStandardType(type: String) = when(type) {