translator: refactoring, add a skeleton for LLVMBuilder, reformat expression generation
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user