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.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||||
import org.kotlin.native.translator.llvm.LLVMBuilder
|
|
||||||
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
|
|
||||||
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
|
||||||
|
|
||||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||||
|
|
||||||
private var codeBuilder = LLVMBuilder()
|
private var codeBuilder = LLVMBuilder()
|
||||||
private var compiled = false;
|
|
||||||
|
|
||||||
fun generateCode(): String {
|
fun generateCode(): String {
|
||||||
if (!compiled) {
|
codeBuilder.clean()
|
||||||
generateFileBody()
|
generateFileBody()
|
||||||
}
|
|
||||||
|
|
||||||
compiled = true
|
|
||||||
return codeBuilder.toString()
|
return codeBuilder.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,21 +10,19 @@ import org.jetbrains.kotlin.psi.KtConstantExpression
|
|||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.kotlin.native.translator.llvm.LLVMBuilder
|
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||||
import org.kotlin.native.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
|
import org.kotlinnative.translator.llvm.LLVMDescriptorGenerate
|
||||||
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
||||||
|
|
||||||
|
|
||||||
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
||||||
|
|
||||||
private var variableCount = 0
|
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
generateDeclaration(function)
|
generateDeclaration(function)
|
||||||
codeBuilder.addLlvmCode("{")
|
codeBuilder.addStartExpression()
|
||||||
expressionWalker(function.bodyExpression)
|
expressionWalker(function.bodyExpression)
|
||||||
codeBuilder.addLlvmCode("}")
|
codeBuilder.addEndExpression()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDeclaration(function: KtNamedFunction) {
|
private fun generateDeclaration(function: KtNamedFunction) {
|
||||||
@@ -34,8 +32,7 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
}
|
}
|
||||||
val returnType = LLVMMapStandardType(descriptor?.returnType.toString())
|
val returnType = LLVMMapStandardType(descriptor?.returnType.toString())
|
||||||
|
|
||||||
|
codeBuilder.addLLVMCode(LLVMDescriptorGenerate(function.fqName.toString(), args, returnType))
|
||||||
codeBuilder.addLlvmCode(LLVMDescriptorGenearte(function.fqName.toString(), args, returnType))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expressionWalker(expr: Any?) {
|
private fun expressionWalker(expr: Any?) {
|
||||||
@@ -48,17 +45,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBlockExpression(expr: KtBlockExpression) {
|
private fun evaluateBlockExpression(expr: KtBlockExpression) {
|
||||||
var element = expr
|
expressionWalker(expr.firstChild)
|
||||||
expressionWalker(element.firstChild)
|
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments())
|
||||||
|
|
||||||
expressionWalker(element.getNextSiblingIgnoringWhitespaceAndComments())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluatePsiExpression(expr: PsiElement) {
|
private fun evaluatePsiExpression(expr: PsiElement) {
|
||||||
var element = expr
|
evaluateExpression(expr.firstChild)
|
||||||
evaluateExpression(element.firstChild)
|
evaluatePsiExpression(expr.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
|
||||||
|
|
||||||
evaluatePsiExpression(element.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateExpression(expr: Any?): LLVMVariable? {
|
private fun evaluateExpression(expr: Any?): LLVMVariable? {
|
||||||
@@ -73,21 +66,11 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMVariable {
|
private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMVariable {
|
||||||
val left = evaluateExpression(expr.firstChild)
|
val left = evaluateExpression(expr.firstChild) ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||||
val right = evaluateExpression(expr.lastChild)
|
val right = evaluateExpression(expr.lastChild) ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||||
val operator = expr.operationToken
|
val operator = expr.operationToken
|
||||||
|
|
||||||
|
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
|
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
|
||||||
@@ -109,14 +92,13 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
|
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
|
||||||
else -> LLVMVariable("")
|
else -> LLVMVariable("")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
|
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
|
||||||
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
|
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
|
||||||
val retVar = evaluateExpression(next)
|
val retVar = evaluateExpression(next)
|
||||||
|
|
||||||
codeBuilder.addLlvmCode("ret i32 ${retVar?.label}")
|
codeBuilder.addLLVMCode("ret i32 ${retVar?.label}")
|
||||||
return null
|
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
|
package org.kotlinnative.translator
|
||||||
|
|
||||||
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.cli.common.CLIConfigurationKeys
|
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 {
|
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)
|
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 {
|
override fun toString(): String {
|
||||||
return llvmCode.toString()
|
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
|
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() ?: "" })"
|
"define $returnType @$name(${argTypes?.mapIndexed { i: Int, s: Pair<String, String> -> "${s.second} %${s.first}" }?.joinToString() ?: "" })"
|
||||||
|
|
||||||
fun LLVMMapStandardType(type: String) = when(type) {
|
fun LLVMMapStandardType(type: String) = when(type) {
|
||||||
|
|||||||
Reference in New Issue
Block a user