original copy of student's translator
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.kotlinnative.translator.codegens.ClassCodegen
|
||||
import org.kotlinnative.translator.codegens.FunctionCodegen
|
||||
import org.kotlinnative.translator.codegens.ObjectCodegen
|
||||
import org.kotlinnative.translator.codegens.PropertyCodegen
|
||||
|
||||
class ProjectTranslator(val files: List<KtFile>,
|
||||
val state: TranslationState) {
|
||||
private var codeBuilder = state.codeBuilder
|
||||
|
||||
fun generateCode(): String {
|
||||
with(files) {
|
||||
map { addClassDeclarations(it) }
|
||||
map { addObjectDeclarations(it) }
|
||||
map { addFunctionDeclarations(it) }
|
||||
map { addPropertyDeclarations(it) }
|
||||
}
|
||||
generateProjectBody()
|
||||
return codeBuilder.toString()
|
||||
}
|
||||
|
||||
fun addFunctionDeclarations(file: KtFile) {
|
||||
val variableManager = VariableManager(state.globalVariableCollection)
|
||||
for (declaration in file.declarations.filterIsInstance<KtNamedFunction>()) {
|
||||
val function = FunctionCodegen(state, variableManager, declaration, codeBuilder)
|
||||
if (function.external) {
|
||||
state.externalFunctions.put(function.fullName, function)
|
||||
} else {
|
||||
state.functions.put(function.fullName, function)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addClassDeclarations(file: KtFile) {
|
||||
val variableManager = VariableManager(state.globalVariableCollection)
|
||||
for (declaration in file.declarations.filterIsInstance<KtClass>()) {
|
||||
val codegen = ClassCodegen(state, variableManager, declaration, codeBuilder)
|
||||
state.classes.put(codegen.structName, codegen)
|
||||
}
|
||||
}
|
||||
|
||||
fun addPropertyDeclarations(file: KtFile) {
|
||||
val variableManager = VariableManager(state.globalVariableCollection)
|
||||
for (declaration in file.declarations.filterIsInstance<KtProperty>()) {
|
||||
val property = PropertyCodegen(state, variableManager, declaration, codeBuilder)
|
||||
state.properties.put(declaration.name!!, property)
|
||||
}
|
||||
}
|
||||
|
||||
fun addObjectDeclarations(file: KtFile) {
|
||||
val variableManager = VariableManager(state.globalVariableCollection)
|
||||
for (declaration in file.declarations.filterIsInstance<KtObjectDeclaration>()) {
|
||||
val codegen = ObjectCodegen(state, variableManager, declaration, codeBuilder)
|
||||
state.objects.put(codegen.structName, codegen)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateProjectBody() {
|
||||
with(state) {
|
||||
properties.values.map { it.generate() }
|
||||
objects.values.map { it.prepareForGenerate() }
|
||||
classes.values.map { it.prepareForGenerate() }
|
||||
objects.values.map { it.generate() }
|
||||
classes.values.map { it.generate() }
|
||||
externalFunctions.values.map { it.generate() }
|
||||
functions.values.filter { it.isExtensionDeclaration }.map { it.generate() }
|
||||
functions.values.filter { !it.isExtensionDeclaration }.map { it.generate() }
|
||||
}
|
||||
|
||||
if (state.mainFunction != "main") {
|
||||
codeBuilder.declareEntryPoint(state.mainFunction)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
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.getModuleName
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import org.kotlinnative.translator.codegens.ClassCodegen
|
||||
import org.kotlinnative.translator.codegens.FunctionCodegen
|
||||
import org.kotlinnative.translator.codegens.ObjectCodegen
|
||||
import org.kotlinnative.translator.codegens.PropertyCodegen
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import java.util.*
|
||||
|
||||
|
||||
class TranslationState
|
||||
private constructor
|
||||
(
|
||||
val environment: KotlinCoreEnvironment,
|
||||
val bindingContext: BindingContext,
|
||||
val mainFunction: String, arm: Boolean
|
||||
) {
|
||||
var externalFunctions = HashMap<String, FunctionCodegen>()
|
||||
var functions = HashMap<String, FunctionCodegen>()
|
||||
var classes = HashMap<String, ClassCodegen>()
|
||||
var objects = HashMap<String, ObjectCodegen>()
|
||||
var properties = HashMap<String, PropertyCodegen>()
|
||||
val codeBuilder = LLVMBuilder(arm)
|
||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||
val globalVariableCollection = HashMap<String, LLVMVariable>()
|
||||
|
||||
init {
|
||||
POINTER_ALIGN = if (arm) 4 else 8
|
||||
POINTER_SIZE = if (arm) 4 else 8
|
||||
}
|
||||
|
||||
companion object {
|
||||
var POINTER_ALIGN = 4
|
||||
var POINTER_SIZE = 4
|
||||
|
||||
fun createTranslationState(sources1: List<String>, disposer: Disposable, mainFunction: String, arm: Boolean = false): TranslationState {
|
||||
|
||||
val configuration = CompilerConfiguration()
|
||||
val messageCollector = object : MessageCollector {
|
||||
private var hasError = false
|
||||
|
||||
override fun hasErrors(): Boolean = hasError
|
||||
|
||||
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
|
||||
if (severity.isError) {
|
||||
System.err.println("[${severity.toString()}]${location.path} ${location.line}:${location.column} $message")
|
||||
hasError = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
|
||||
configuration.put(CommonConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME)
|
||||
|
||||
configuration.addKotlinSourceRoots(sources)
|
||||
|
||||
val environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
|
||||
val bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException("Can't initialize binding context for project")
|
||||
|
||||
return TranslationState(environment, bindingContext, mainFunction, arm)
|
||||
}
|
||||
|
||||
private fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
|
||||
val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
|
||||
val analyzer = AnalyzerWithCompilerReport(collector)
|
||||
analyzer.analyzeAndReport(environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer {
|
||||
override fun analyze(): AnalysisResult {
|
||||
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
||||
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.getModuleName())
|
||||
|
||||
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
||||
moduleContext,
|
||||
environment.getSourceFiles(),
|
||||
sharedTrace,
|
||||
environment.configuration.get(JVMConfigurationKeys.MODULES),
|
||||
environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
|
||||
JvmPackagePartProvider(environment))
|
||||
}
|
||||
|
||||
override fun reportEnvironmentErrors() {
|
||||
val files = environment.configuration.jvmClasspathRoots
|
||||
val runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() }
|
||||
collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION)
|
||||
System.err.println(runtimes.joinToString { it.toString() })
|
||||
}
|
||||
})
|
||||
|
||||
return if (analyzer.hasErrors()) null else analyzer.analysisResult
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMScope
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
import java.util.*
|
||||
|
||||
class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable>) {
|
||||
|
||||
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>()
|
||||
|
||||
private companion object UniqueGenerator {
|
||||
private var unique = 0
|
||||
fun generateUniqueString() =
|
||||
".unique." + unique++
|
||||
}
|
||||
|
||||
operator fun get(variableName: String): LLVMVariable? {
|
||||
return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName]
|
||||
}
|
||||
|
||||
operator fun contains(variableName: String): Boolean {
|
||||
return (fileVariableCollectionTree.contains(variableName) && !fileVariableCollectionTree[variableName]!!.empty()) || globalVariableCollection.containsKey(variableName)
|
||||
}
|
||||
|
||||
fun pullOneUpwardLevelVariable(variableName: String) {
|
||||
fileVariableCollectionTree[variableName]?.pop()
|
||||
}
|
||||
|
||||
fun pullUpwardsLevel(level: Int) {
|
||||
fileVariableCollectionTree.forEach { s, stack -> while (!stack.empty() && stack.peek().second >= level) stack.pop() }
|
||||
}
|
||||
|
||||
fun addVariable(name: String, variable: LLVMVariable, level: Int) {
|
||||
val stack = fileVariableCollectionTree.getOrDefault(name, Stack<Pair<LLVMVariable, Int>>())
|
||||
stack.push(Pair(variable, level))
|
||||
fileVariableCollectionTree.put(name, stack)
|
||||
}
|
||||
|
||||
fun addGlobalVariable(name: String, variable: LLVMVariable) {
|
||||
globalVariableCollection.put(name, variable)
|
||||
}
|
||||
|
||||
fun receiveVariable(name: String, type: LLVMType, scope: LLVMScope, pointer: Int): LLVMVariable {
|
||||
return LLVMVariable("managed${generateUniqueString()}.$name", type, name, scope, pointer)
|
||||
}
|
||||
|
||||
}
|
||||
+1121
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
package org.kotlinnative.translator.codegens
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.VariableManager
|
||||
import org.kotlinnative.translator.exceptions.TranslationException
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class ClassCodegen(state: TranslationState,
|
||||
variableManager: VariableManager,
|
||||
val clazz: KtClass,
|
||||
codeBuilder: LLVMBuilder,
|
||||
parentCodegen: StructCodegen? = null) :
|
||||
StructCodegen(state, variableManager, clazz, codeBuilder, parentCodegen) {
|
||||
|
||||
val annotation: Boolean
|
||||
val enum: Boolean
|
||||
var companionObjectCodegen: ObjectCodegen? = null
|
||||
val descriptor: ClassDescriptor
|
||||
|
||||
override var size: Int = 0
|
||||
override val structName: String = clazz.fqName?.asString()!!
|
||||
override val type: LLVMReferenceType
|
||||
|
||||
init {
|
||||
type = LLVMReferenceType(structName, "class", align = TranslationState.POINTER_ALIGN, size = TranslationState.POINTER_SIZE, byRef = true)
|
||||
descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name)
|
||||
|
||||
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
|
||||
enum = descriptor.kind == ClassKind.ENUM_CLASS
|
||||
|
||||
type.align = TranslationState.POINTER_ALIGN
|
||||
}
|
||||
|
||||
override fun prepareForGenerate() {
|
||||
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
||||
indexFields(parameterList)
|
||||
generateInnerFields(clazz.declarations)
|
||||
|
||||
type.size = calculateTypeSize()
|
||||
|
||||
if (annotation) {
|
||||
return
|
||||
}
|
||||
|
||||
super.prepareForGenerate()
|
||||
nestedClasses.forEach { x, classCodegen -> classCodegen.prepareForGenerate() }
|
||||
|
||||
if (descriptor.companionObjectDescriptor != null) {
|
||||
val companionObject = clazz.getCompanionObjects().first()
|
||||
companionObjectCodegen = ObjectCodegen(state, variableManager, companionObject, codeBuilder, this)
|
||||
companionObjectCodegen!!.prepareForGenerate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun generate() {
|
||||
if (annotation) {
|
||||
return
|
||||
}
|
||||
|
||||
super.generate()
|
||||
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
||||
companionObjectCodegen?.generate()
|
||||
}
|
||||
|
||||
private fun indexFields(parameters: MutableList<KtParameter>) {
|
||||
if (annotation) {
|
||||
return
|
||||
}
|
||||
|
||||
val currentConstructorFields = parameters.mapIndexed { i, it -> resolveType(it, state.bindingContext.get(BindingContext.TYPE, it.typeReference)!!, fields.size + i) }
|
||||
fields.addAll(currentConstructorFields)
|
||||
fieldsIndex.putAll(currentConstructorFields.map { Pair(it.label, it) })
|
||||
primaryConstructorIndex = LLVMType.mangleFunctionArguments(currentConstructorFields)
|
||||
constructorFields.put(primaryConstructorIndex!!, currentConstructorFields)
|
||||
}
|
||||
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package org.kotlinnative.translator.codegens
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.VariableManager
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMFunctionType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||
import java.util.*
|
||||
|
||||
|
||||
class FunctionCodegen(state: TranslationState,
|
||||
variableManager: VariableManager,
|
||||
val function: KtNamedFunction,
|
||||
codeBuilder: LLVMBuilder) :
|
||||
BlockCodegen(state, variableManager, codeBuilder) {
|
||||
|
||||
var name: String
|
||||
var args = LinkedList<LLVMVariable>()
|
||||
val isExtensionDeclaration = function.isExtensionDeclaration()
|
||||
var functionNamePrefix = ""
|
||||
val external: Boolean
|
||||
val defaultValues: List<KtExpression?>
|
||||
val fullName: String
|
||||
get() = functionNamePrefix + name
|
||||
|
||||
init {
|
||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
||||
args.addAll(descriptor.valueParameters.map {
|
||||
LLVMInstanceOfStandardType(it?.fqNameSafe?.asString() ?: it.name.toString(), it.type, state = state)
|
||||
})
|
||||
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!, state = state)
|
||||
if (returnType!!.type is LLVMReferenceType) {
|
||||
returnType!!.pointer = 2
|
||||
}
|
||||
external = descriptor.isExternal
|
||||
name = if (external) function.name!! else function.fqName!!.convertToNativeName() + LLVMType.mangleFunctionArguments(args)
|
||||
|
||||
if (isExtensionDeclaration) {
|
||||
name = "${function.name}${if (!external) LLVMType.mangleFunctionArguments(args) else ""}"
|
||||
val receiverType = descriptor.extensionReceiverParameter!!.type
|
||||
val translatorType = LLVMMapStandardType(receiverType, state)
|
||||
val packageName = (function.containingFile as KtFile).packageFqName.asString()
|
||||
functionNamePrefix = packageName.addAfterIfNotEmpty(".") + translatorType.mangle + "."
|
||||
|
||||
val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType.toString(), HashMap())
|
||||
extensionFunctionsOfThisType.put(fullName, this)
|
||||
state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType)
|
||||
}
|
||||
|
||||
defaultValues = descriptor.valueParameters.indices.map {
|
||||
val parameterDescriptor = descriptor.valueParameters[it]
|
||||
if (parameterDescriptor.declaresDefaultValue()) {
|
||||
val initializer = (parameterDescriptor.source as KotlinSourceElement).psi as KtParameter
|
||||
initializer.defaultValue
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generate(this_type: LLVMVariable? = null) {
|
||||
generateDeclaration(this_type)
|
||||
|
||||
if (external) {
|
||||
return
|
||||
}
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments()
|
||||
evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevelScopeDepth, isBlock = function.hasBlockBody())
|
||||
|
||||
if (returnType?.type is LLVMVoidType){
|
||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||
}
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateDeclaration(this_type: LLVMVariable? = null) {
|
||||
var actualReturnType: LLVMType = returnType!!.type
|
||||
val actualArgs = ArrayList<LLVMVariable>()
|
||||
|
||||
if (returnType!!.pointer > 0) {
|
||||
actualReturnType = LLVMVoidType()
|
||||
actualArgs.add(returnType!!)
|
||||
}
|
||||
|
||||
if (isExtensionDeclaration) {
|
||||
val receiverParameter = state.bindingContext.get(BindingContext.FUNCTION, function)!!.extensionReceiverParameter!!
|
||||
val receiverType = receiverParameter.type
|
||||
val translatorType = LLVMMapStandardType(receiverType, state)
|
||||
|
||||
val classVal = when (translatorType) {
|
||||
is LLVMReferenceType -> LLVMVariable("classvariable.this", translatorType, pointer = 1)
|
||||
else -> LLVMVariable("type", translatorType, pointer = 0)
|
||||
}
|
||||
|
||||
variableManager.addVariable("this", classVal, level = 0)
|
||||
actualArgs.add(classVal)
|
||||
}
|
||||
|
||||
if (this_type != null) {
|
||||
actualArgs.add(this_type)
|
||||
}
|
||||
|
||||
actualArgs.addAll(args)
|
||||
|
||||
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(fullName, actualArgs, actualReturnType, external))
|
||||
}
|
||||
|
||||
private fun generateLoadArguments() {
|
||||
args.forEach(fun(it: LLVMVariable) {
|
||||
if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && it.type.byRef)) {
|
||||
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevelScopeDepth)
|
||||
return
|
||||
}
|
||||
|
||||
if (it.type !is LLVMReferenceType || it.type.byRef) {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer)
|
||||
val allocVar = codeBuilder.loadArgument(loadVariable)
|
||||
variableManager.addVariable(it.label, allocVar, topLevelScopeDepth)
|
||||
} else {
|
||||
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 0), topLevelScopeDepth)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.kotlinnative.translator.codegens
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.VariableManager
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class ObjectCodegen(state: TranslationState,
|
||||
variableManager: VariableManager,
|
||||
val objectDeclaration: KtObjectDeclaration,
|
||||
codeBuilder: LLVMBuilder,
|
||||
parentCodegen: StructCodegen? = null) :
|
||||
StructCodegen(state, variableManager, objectDeclaration, codeBuilder, parentCodegen) {
|
||||
|
||||
override var size: Int = 0
|
||||
override val structName: String = objectDeclaration.fqName?.asString()!!
|
||||
override val type = LLVMReferenceType(structName, "class")
|
||||
|
||||
init {
|
||||
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
||||
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
||||
}
|
||||
|
||||
override fun prepareForGenerate() {
|
||||
generateInnerFields(objectDeclaration.declarations)
|
||||
type.size = calculateTypeSize()
|
||||
|
||||
super.prepareForGenerate()
|
||||
|
||||
val classInstance = LLVMVariable("object.instance.$structName", type, objectDeclaration.name, LLVMVariableScope(), pointer = 1)
|
||||
codeBuilder.addGlobalInitialize(classInstance, fields, initializedFields.map {
|
||||
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, it.value)!!.type!!
|
||||
Pair(it.key, state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, it.value)!!.getValue(type).toString())
|
||||
}.toMap(), type)
|
||||
variableManager.addGlobalVariable(structName, classInstance)
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package org.kotlinnative.translator.codegens
|
||||
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.VariableManager
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMInstanceOfStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||
|
||||
|
||||
class PropertyCodegen(val state: TranslationState,
|
||||
val variableManager: VariableManager,
|
||||
val property: KtProperty,
|
||||
val codeBuilder: LLVMBuilder) {
|
||||
|
||||
fun generate() {
|
||||
val varInfo = state.bindingContext.get(BindingContext.VARIABLE, property)?.compileTimeInitializer ?: return
|
||||
|
||||
val kotlinType = varInfo.type
|
||||
val value = varInfo.value
|
||||
if (kotlinType.nameIfStandardType != null) {
|
||||
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType, state = state).type
|
||||
val variable = LLVMVariable(property.name.toString(), variableType, property.name.toString(), LLVMVariableScope())
|
||||
variableManager.addGlobalVariable(property.name.toString(), variable)
|
||||
codeBuilder.defineGlobalVariable(variable, variableType.parseArg(value.toString()))
|
||||
variable.pointer++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
package org.kotlinnative.translator.codegens
|
||||
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.VariableManager
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMCharType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
||||
import java.util.*
|
||||
|
||||
/*
|
||||
* TODO make high level description of code generation process
|
||||
* and structure of generated code.
|
||||
*/
|
||||
abstract class StructCodegen(val state: TranslationState,
|
||||
val variableManager: VariableManager,
|
||||
val classOrObject: KtClassOrObject,
|
||||
val codeBuilder: LLVMBuilder,
|
||||
val parentCodegen: StructCodegen? = null) {
|
||||
|
||||
val fields = ArrayList<LLVMClassVariable>()
|
||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||
val enumFields = HashMap<String, LLVMVariable>()
|
||||
val constructorFields = HashMap<String, List<LLVMVariable>>()
|
||||
var primaryConstructorIndex: String? = null
|
||||
val initializedFields = HashMap<LLVMVariable, KtExpression>()
|
||||
var methods = HashMap<String, FunctionCodegen>()
|
||||
|
||||
abstract val type: LLVMReferenceType
|
||||
abstract var size: Int
|
||||
abstract val structName: String
|
||||
|
||||
open fun prepareForGenerate() {
|
||||
generateStruct()
|
||||
classOrObject.declarations.filterIsInstance<KtNamedFunction>().map {
|
||||
val function = FunctionCodegen(state, variableManager, it, codeBuilder)
|
||||
methods.put(function.name, function)
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateTypeSize(): Int {
|
||||
val classAlignment = fields.map { it.type.align }.max()?.toInt() ?: 0
|
||||
var alignmentRemainder = 0
|
||||
size = 0
|
||||
|
||||
for (item in fields) {
|
||||
val currentFieldSize = if (item.pointer > 0) TranslationState.POINTER_ALIGN else item.type.align
|
||||
alignmentRemainder -= (alignmentRemainder % currentFieldSize)
|
||||
if (alignmentRemainder < currentFieldSize) {
|
||||
size += classAlignment
|
||||
alignmentRemainder = classAlignment - currentFieldSize
|
||||
} else {
|
||||
alignmentRemainder -= currentFieldSize
|
||||
}
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
open fun generate() {
|
||||
generateEnumFields()
|
||||
generatePrimaryConstructor()
|
||||
classOrObject.getSecondaryConstructors().map { generateSecondaryConstructor(it) }
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = if (type.isPrimitive) 0 else 1)
|
||||
variableManager.addVariable("this", classVal, level = 0)
|
||||
|
||||
methods.values.map { it.generate(classVal) }
|
||||
}
|
||||
|
||||
fun generateInnerFields(declarations: List<KtDeclaration>) {
|
||||
for (declaration in declarations) {
|
||||
when (declaration) {
|
||||
is KtProperty -> {
|
||||
val ktType = state.bindingContext.get(BindingContext.TYPE, declaration.typeReference)
|
||||
?: state.bindingContext.get(BindingContext.VARIABLE, declaration)!!.type
|
||||
val field = resolveType(declaration, ktType, fields.size)
|
||||
|
||||
if (declaration.initializer != null) {
|
||||
initializedFields.put(field, declaration.initializer!!)
|
||||
}
|
||||
|
||||
fields.add(field)
|
||||
fieldsIndex[field.label] = field
|
||||
}
|
||||
is KtEnumEntry -> {
|
||||
val name = declaration.name!!
|
||||
val field = LLVMVariable("class.$structName.$name", type, scope = LLVMVariableScope(), pointer = 2)
|
||||
enumFields.put(name, field)
|
||||
}
|
||||
is KtClass ->
|
||||
nestedClasses.put(declaration.fqName!!.asString(),
|
||||
ClassCodegen(state,
|
||||
VariableManager(state.globalVariableCollection),
|
||||
declaration, codeBuilder, this))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateEnumFields() {
|
||||
val enumEntries = classOrObject.declarations.filterIsInstance<KtEnumEntry>()
|
||||
|
||||
for (declaration in enumEntries) {
|
||||
val name = declaration.name!!
|
||||
val initializer = declaration.initializerList!!.initializers[0]
|
||||
val arguments = (initializer as KtSuperTypeCallEntry).valueArguments.map { it.getArgumentExpression()!!.text }
|
||||
|
||||
val field = codeBuilder.getNewVariable(type, scope = LLVMVariableScope())
|
||||
val enumField = enumFields[name]!!
|
||||
|
||||
codeBuilder.defineGlobalVariable(field, codeBuilder.makeStructInitializer(constructorFields[primaryConstructorIndex]!!, arguments))
|
||||
codeBuilder.defineGlobalVariable(LLVMVariable(enumField.label, enumField.type, enumField.kotlinName, enumField.scope, enumField.pointer - 1), field.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateStruct() =
|
||||
codeBuilder.createClass(structName, fields)
|
||||
|
||||
private fun generateSecondaryConstructor(secondaryConstructor: KtSecondaryConstructor) {
|
||||
val thisCall = secondaryConstructor.getDelegationCall().calleeExpression
|
||||
val descriptor = state.bindingContext.get(BindingContext.CONSTRUCTOR, secondaryConstructor)
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||
variableManager.addVariable("this", classVal, level = 0)
|
||||
|
||||
val secondaryConstructorArguments = descriptor!!.valueParameters.map {
|
||||
LLVMInstanceOfStandardType(it.fqNameSafe.convertToNativeName(), it.type, state = state)
|
||||
}
|
||||
|
||||
val argFields = mutableListOf(classVal)
|
||||
argFields.addAll(secondaryConstructorArguments)
|
||||
val currentConstructorIndex = LLVMType.mangleFunctionArguments(secondaryConstructorArguments)
|
||||
constructorFields.put(currentConstructorIndex, argFields)
|
||||
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(structName + currentConstructorIndex, argFields, LLVMVoidType()))
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
|
||||
secondaryConstructorArguments.map { variableManager.addVariable(it.label, it, level = 2) }
|
||||
|
||||
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
||||
val mainConstructorThis = blockCodegen.evaluateConstructorDelegationReferenceExpression(thisCall!!, this, secondaryConstructorArguments, 1) as LLVMVariable
|
||||
variableManager.addVariable("this", mainConstructorThis, level = 0)
|
||||
|
||||
blockCodegen.evaluateCodeBlock(secondaryConstructor.bodyExpression, scopeDepth = 1)
|
||||
generateReturn(codeBuilder.receivePointedArgument(variableManager["this"]!!, requirePointer = 1) as LLVMVariable)
|
||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generatePrimaryConstructor() {
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||
variableManager.addVariable("this", classVal, level = 0)
|
||||
|
||||
val argFields = mutableListOf(classVal)
|
||||
argFields.addAll(constructorFields[primaryConstructorIndex]!!)
|
||||
|
||||
codeBuilder.addLLVMCodeToLocalPlace(LLVMFunctionDescriptor(structName + primaryConstructorIndex, argFields, LLVMVoidType()))
|
||||
|
||||
codeBuilder.addStartExpression()
|
||||
generateLoadArguments(classVal)
|
||||
generateAssignments()
|
||||
generateReturn(LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1))
|
||||
genClassInitializers()
|
||||
codeBuilder.addAnyReturn(LLVMVoidType())
|
||||
codeBuilder.addEndExpression()
|
||||
}
|
||||
|
||||
private fun generateLoadArguments(thisField: LLVMVariable) {
|
||||
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
|
||||
codeBuilder.loadArgument(thisVariable, false)
|
||||
|
||||
constructorFields[primaryConstructorIndex]!!.filter { it.type !is LLVMReferenceType }.forEach {
|
||||
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
|
||||
codeBuilder.loadArgument(loadVariable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateAssignments() {
|
||||
constructorFields[primaryConstructorIndex]!!.forEach {
|
||||
when (it.type) {
|
||||
is LLVMReferenceType -> {
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = it.pointer + 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, it)
|
||||
}
|
||||
else -> {
|
||||
val argument = codeBuilder.loadAndGetVariable(LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
|
||||
val classField = codeBuilder.getNewVariable(it.type, pointer = 1)
|
||||
codeBuilder.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
|
||||
codeBuilder.storeVariable(classField, argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val blockCodegen = object : BlockCodegen(state, variableManager, codeBuilder) {}
|
||||
val receiverThis = LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
variableManager.addVariable("this", receiverThis, level = 2)
|
||||
|
||||
for ((variable, initializer) in initializedFields) {
|
||||
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevelScopeDepth, call = null)!!
|
||||
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevelScopeDepth)!!
|
||||
blockCodegen.addPrimitiveBinaryOperation(KtTokens.EQ, left, right)
|
||||
}
|
||||
|
||||
variableManager.pullOneUpwardLevelVariable("this")
|
||||
}
|
||||
|
||||
private fun generateReturn(src: LLVMVariable) {
|
||||
val dst = LLVMVariable("classvariable.this", type, scope = LLVMRegisterScope(), pointer = 1)
|
||||
|
||||
val castedDst = codeBuilder.bitcast(dst, LLVMCharType(), pointer = 1)
|
||||
val castedSrc = codeBuilder.bitcast(src, LLVMCharType(), pointer = 1)
|
||||
|
||||
codeBuilder.memcpy(castedDst, castedSrc, size)
|
||||
}
|
||||
|
||||
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType, offset: Int): LLVMClassVariable {
|
||||
val annotations = parseFieldAnnotations(field)
|
||||
val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName()
|
||||
?: field.fqName?.asString()
|
||||
?: field.name!!
|
||||
|
||||
val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state)
|
||||
|
||||
if (state.classes.containsKey(field.name!!)) {
|
||||
return LLVMClassVariable(result.label, state.classes[fieldName]!!.type, result.pointer)
|
||||
}
|
||||
|
||||
if (annotations.contains("Plain")) {
|
||||
result.pointer = 0
|
||||
}
|
||||
|
||||
return LLVMClassVariable(result.label, result.type, result.pointer, offset)
|
||||
}
|
||||
|
||||
private fun parseFieldAnnotations(field: KtNamedDeclaration): Set<String> =
|
||||
field.annotationEntries.map { state.bindingContext.get(BindingContext.ANNOTATION, it)?.type.toString() }.toHashSet()
|
||||
|
||||
protected fun genClassInitializers() =
|
||||
classOrObject.getAnonymousInitializers().map {
|
||||
object : BlockCodegen(state, variableManager, codeBuilder) {
|
||||
fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevelScopeDepth)
|
||||
}
|
||||
}.map { it.generate() }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.kotlinnative.translator.debug
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
fun debugPrintNode(node: Any?, indent: Int = 0): Unit {
|
||||
if (node == null) {
|
||||
return
|
||||
}
|
||||
|
||||
for (i in 0..indent) {
|
||||
print(" ")
|
||||
}
|
||||
|
||||
println(node.toString())
|
||||
|
||||
when (node) {
|
||||
is CompositeElement -> {
|
||||
debugPrintNode(node.firstChildNode, indent + 2)
|
||||
debugPrintNode(node.treeNext, indent)
|
||||
}
|
||||
is PsiElement -> {
|
||||
debugPrintNode(node.firstChild, indent + 2)
|
||||
debugPrintNode(node.nextSibling, indent)
|
||||
}
|
||||
is PsiWhiteSpace -> {
|
||||
debugPrintNode(node.firstChild, indent + 2)
|
||||
debugPrintNode(node.nextSibling, indent)
|
||||
}
|
||||
else -> {
|
||||
print(" not supported: " + node.javaClass.canonicalName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun printFunction(function: KtNamedFunction) {
|
||||
debugPrintNode(function.node)
|
||||
}
|
||||
|
||||
fun printClass(function: KtClass) {
|
||||
debugPrintNode(function.node)
|
||||
}
|
||||
|
||||
fun printFile(file: KtFile) {
|
||||
|
||||
for (declaration in file.declarations) {
|
||||
|
||||
when (declaration) {
|
||||
is KtNamedFunction -> printFunction(declaration)
|
||||
is KtClass -> printClass(declaration)
|
||||
else -> println(declaration.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.kotlinnative.translator.exceptions
|
||||
|
||||
import java.lang.Exception
|
||||
|
||||
class TranslationException(message: String) : Exception(message)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package org.kotlinnative.translator.exceptions
|
||||
|
||||
import java.lang.Exception
|
||||
|
||||
class UnimplementedException() : Exception()
|
||||
@@ -0,0 +1,252 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import java.rmi.UnexpectedException
|
||||
import java.util.*
|
||||
|
||||
class LLVMBuilder(arm: Boolean = false) {
|
||||
|
||||
private val localCode: StringBuilder = StringBuilder()
|
||||
private val globalCode: StringBuilder = StringBuilder()
|
||||
private var variableCount = 0
|
||||
private var labelCount = 0
|
||||
private val exceptions = mapOf(
|
||||
Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException")))
|
||||
|
||||
|
||||
init {
|
||||
val declares = arrayOf(
|
||||
"declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)",
|
||||
"declare i8* @malloc_heap(i32)",
|
||||
"declare i32 @printf(i8*, ...)",
|
||||
"declare void @abort()",
|
||||
"%class.Nothing = type { }")
|
||||
|
||||
declares.forEach { addLLVMCodeToGlobalPlace(it) }
|
||||
|
||||
if (arm) {
|
||||
val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
|
||||
addLLVMCodeToGlobalPlace(functionAttributes)
|
||||
}
|
||||
}
|
||||
|
||||
fun addLLVMCodeToLocalPlace(code: String) =
|
||||
localCode.appendln(code)
|
||||
|
||||
fun addLLVMCodeToGlobalPlace(code: String) =
|
||||
globalCode.appendln(code)
|
||||
|
||||
fun addComment(comment: String) =
|
||||
addLLVMCodeToLocalPlace("; " + comment)
|
||||
|
||||
fun addStartExpression() =
|
||||
addLLVMCodeToLocalPlace("{")
|
||||
|
||||
fun addEndExpression() =
|
||||
addLLVMCodeToLocalPlace("unreachable\n}")
|
||||
|
||||
fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) =
|
||||
addLLVMCodeToLocalPlace("$lhs = $rhs")
|
||||
|
||||
fun addReturnOperator(llvmVariable: LLVMSingleValue) =
|
||||
addLLVMCodeToLocalPlace("ret ${llvmVariable.type} $llvmVariable")
|
||||
|
||||
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue, pointer: Int = 0) =
|
||||
addLLVMCodeToLocalPlace("ret $type${"*".repeat(pointer)} $value")
|
||||
|
||||
fun addStringConstant(variable: LLVMVariable, value: String) =
|
||||
addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
|
||||
|
||||
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) =
|
||||
addLLVMCodeToLocalPlace("br ${condition.pointedType} $condition, label $thenLabel, label $elseLabel")
|
||||
|
||||
fun addUnconditionalJump(label: LLVMLabel) =
|
||||
addLLVMCodeToLocalPlace("br label $label")
|
||||
|
||||
fun addExceptionCall(exceptionName: String) {
|
||||
val exception = exceptions[exceptionName]
|
||||
val printResult = getNewVariable(LLVMIntType(), pointer = 0)
|
||||
addLLVMCodeToLocalPlace("$printResult = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds (${(exception!!.type as LLVMStringType).fullArrayType}* $exception, i32 0, i32 0))")
|
||||
addFunctionCall(LLVMVariable("abort", LLVMVoidType(), scope = LLVMVariableScope()), emptyList())
|
||||
}
|
||||
|
||||
fun addFunctionCall(functionName: LLVMVariable, arguments: List<LLVMVariable>) =
|
||||
addLLVMCodeToLocalPlace("call ${functionName.type} $functionName(${arguments.joinToString { it -> "${it.type} $it" }})")
|
||||
|
||||
fun allocStackVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
|
||||
val type = if (asValue) target.type.toString() else target.pointedType
|
||||
addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}")
|
||||
}
|
||||
|
||||
fun allocStaticVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
|
||||
val allocated = getNewVariable(LLVMCharType(), pointer = 1)
|
||||
val size = if ((target.pointer >= 2) || (target.pointer >= 1 && !pointer)) TranslationState.POINTER_SIZE else target.type.size
|
||||
|
||||
addLLVMCodeToLocalPlace("$allocated = call i8* @malloc_heap(i32 $size)")
|
||||
addLLVMCodeToLocalPlace("$target = bitcast ${allocated.pointedType} $allocated to ${if (asValue) target.type.toString() else target.pointedType}" + if (pointer) "" else "*")
|
||||
}
|
||||
|
||||
fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMClassVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) {
|
||||
val code = "$target = internal global $classType { ${
|
||||
fields.map { it.pointedType + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString()
|
||||
} }, align ${classType.align}"
|
||||
addLLVMCodeToGlobalPlace(code)
|
||||
}
|
||||
|
||||
fun bitcast(src: LLVMVariable, llvmType: LLVMType, pointer: Int): LLVMVariable {
|
||||
val empty = getNewVariable(llvmType, pointer = pointer)
|
||||
addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.toString() + "*".repeat(pointer)}")
|
||||
return empty
|
||||
}
|
||||
|
||||
fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue {
|
||||
var resultVariable = variable
|
||||
if (variable.type != targetType) {
|
||||
val convertedExpression = targetType.convertFrom(variable)
|
||||
resultVariable = saveExpression(convertedExpression)
|
||||
}
|
||||
return resultVariable
|
||||
}
|
||||
|
||||
fun copyVariable(from: LLVMVariable, to: LLVMVariable) =
|
||||
when {
|
||||
from.type is LLVMStringType && !from.type.isLoaded -> storeString(to, from, 0)
|
||||
else -> copyVariableValue(to, from)
|
||||
}
|
||||
|
||||
fun createClass(name: String, fields: List<LLVMVariable>) =
|
||||
addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }")
|
||||
|
||||
fun declareEntryPoint(name: String) {
|
||||
addLLVMCodeToLocalPlace("define weak void @main()")
|
||||
addStartExpression()
|
||||
addFunctionCall(LLVMVariable(name, LLVMVoidType(), scope = LLVMVariableScope()), listOf())
|
||||
addAnyReturn(LLVMVoidType())
|
||||
addEndExpression()
|
||||
}
|
||||
|
||||
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) =
|
||||
addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}")
|
||||
|
||||
fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null, scope: LLVMScope = LLVMRegisterScope(), prefix: String = "var"): LLVMVariable {
|
||||
variableCount++
|
||||
return LLVMVariable("$prefix$variableCount", type, kotlinName, scope, pointer)
|
||||
}
|
||||
|
||||
fun getNewLabel(scope: LLVMScope = LLVMRegisterScope(), prefix: String): LLVMLabel {
|
||||
labelCount++
|
||||
return LLVMLabel("label.$prefix.$labelCount", scope)
|
||||
}
|
||||
|
||||
fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
|
||||
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
|
||||
return receivePointedArgument(value, args[i].pointer)
|
||||
}).toList()
|
||||
|
||||
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
|
||||
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1)
|
||||
allocStackVar(allocVar, asValue = false, pointer = true)
|
||||
if (store) {
|
||||
storeVariable(allocVar, llvmVariable)
|
||||
}
|
||||
return allocVar
|
||||
}
|
||||
|
||||
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) =
|
||||
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.pointedType} $source, i32 0, i32 $offset")
|
||||
|
||||
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) =
|
||||
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}")
|
||||
|
||||
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
|
||||
assert(source.pointer > 0)
|
||||
val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName)
|
||||
addLLVMCodeToLocalPlace("$target = load ${source.pointedType} $source, align ${target.type.align}")
|
||||
return target
|
||||
}
|
||||
|
||||
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
|
||||
= "{ ${args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString()} }"
|
||||
|
||||
fun markWithLabel(label: LLVMLabel?) {
|
||||
if (label != null)
|
||||
addLLVMCodeToLocalPlace("${label.label}:")
|
||||
}
|
||||
|
||||
fun memcpy(castedDst: LLVMVariable, castedSrc: LLVMVariable, size: Int, align: Int = 4, volatile: Boolean = false) =
|
||||
addLLVMCodeToLocalPlace("call void @llvm.memcpy.p0i8.p0i8.i64(i8* $castedDst, i8* $castedSrc, i64 $size, i32 $align, i1 $volatile)")
|
||||
|
||||
fun nullCheck(variable: LLVMVariable): LLVMVariable {
|
||||
val result = getNewVariable(LLVMBooleanType(), pointer = 0)
|
||||
val loaded = loadAndGetVariable(variable)
|
||||
addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded")
|
||||
return result
|
||||
}
|
||||
|
||||
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue =
|
||||
when {
|
||||
firstOp is LLVMConstant || firstOp.pointer == 0 -> firstOp
|
||||
firstOp is LLVMVariable -> loadAndGetVariable(firstOp)
|
||||
else -> throw UnexpectedException("Unknown inheritor of LLVMSingleValue")
|
||||
}
|
||||
|
||||
fun receivePointedArgument(value: LLVMSingleValue, requirePointer: Int): LLVMSingleValue {
|
||||
var result = value
|
||||
|
||||
while (result.pointer > requirePointer) {
|
||||
result = receiveNativeValue(result)
|
||||
}
|
||||
|
||||
if ((value.type is LLVMStringType) && !(value.type.isLoaded)) {
|
||||
val newVariable = getNewVariable(value.type, pointer = result.pointer + 1)
|
||||
allocStackVar(newVariable, asValue = true)
|
||||
copyVariable(result as LLVMVariable, newVariable)
|
||||
result = loadAndGetVariable(newVariable)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
|
||||
val code = "store ${target.type} getelementptr inbounds (" +
|
||||
"${(source.type as LLVMStringType).fullArrayType}* $source, i32 0, i32 $offset), ${target.pointedType} $target, align ${source.type.align}"
|
||||
(target.type as LLVMStringType).isLoaded = true
|
||||
addLLVMCodeToLocalPlace(code)
|
||||
}
|
||||
|
||||
fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) {
|
||||
if ((source.type is LLVMStringType) && !(source.type.isLoaded)) {
|
||||
storeString(target as LLVMVariable, source as LLVMVariable, 0)
|
||||
} else {
|
||||
addLLVMCodeToLocalPlace("store ${source.pointedType} $source, ${target.pointedType} $target, align ${source.type.align}")
|
||||
}
|
||||
}
|
||||
|
||||
fun saveExpression(expression: LLVMSingleValue): LLVMVariable {
|
||||
val resultOp = getNewVariable(expression.type, pointer = expression.pointer)
|
||||
addAssignment(resultOp, expression)
|
||||
return resultOp
|
||||
}
|
||||
|
||||
fun storeNull(result: LLVMVariable) =
|
||||
addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.POINTER_ALIGN}")
|
||||
|
||||
override fun toString() = globalCode.toString() + localCode.toString()
|
||||
|
||||
private fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) {
|
||||
var from = source
|
||||
if (source.pointer > 0) {
|
||||
from = getNewVariable(source.type, source.pointer)
|
||||
addLLVMCodeToLocalPlace("$from = load ${source.pointedType} $source, align ${from.type.align}")
|
||||
}
|
||||
addLLVMCodeToLocalPlace("store ${target.type} $from, ${target.pointedType} $target, align ${from.type.align}")
|
||||
}
|
||||
|
||||
private fun initializeExceptionString(string: String): LLVMVariable {
|
||||
val result = getNewVariable(LLVMStringType(string.length), pointer = 0, scope = LLVMVariableScope(), prefix = "exceptions.str.")
|
||||
addStringConstant(result, string)
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class LLVMCall(val returnType: LLVMType,
|
||||
val name: String,
|
||||
val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) {
|
||||
|
||||
override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class LLVMClassVariable(label: String,
|
||||
type: LLVMType,
|
||||
pointer: Int = 0,
|
||||
var offset: Int = 0) : LLVMVariable(label, type, pointer = pointer)
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
open class LLVMConstant(value: String,
|
||||
type: LLVMType,
|
||||
pointer: Int = 0) : LLVMSingleValue(type, pointer) {
|
||||
|
||||
val value = type.parseArg(value)
|
||||
|
||||
override fun toString() = value
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
class LLVMExpression(type: LLVMType, val llvmCode: String, pointer: Int = 0) : LLVMSingleValue(type, pointer) {
|
||||
|
||||
override fun toString() = llvmCode
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
class LLVMLabel(val label: String, val scope: LLVMScope) : LLVMNode() {
|
||||
|
||||
override fun toString() = "$scope$label"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
abstract class LLVMNode
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
abstract class LLVMScope
|
||||
|
||||
class LLVMVariableScope : LLVMScope() {
|
||||
override fun toString() = "@"
|
||||
}
|
||||
|
||||
class LLVMRegisterScope : LLVMScope() {
|
||||
override fun toString() = "%"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
open class LLVMSingleValue(val type: LLVMType, var pointer: Int = 0) : LLVMNode() {
|
||||
|
||||
open val pointedType: String
|
||||
get() = type.toString() + "*".repeat(pointer)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
||||
|
||||
open class LLVMVariable(val label: String,
|
||||
type: LLVMType,
|
||||
var kotlinName: String? = null,
|
||||
val scope: LLVMScope = LLVMRegisterScope(),
|
||||
pointer: Int = 0) : LLVMSingleValue(type, pointer) {
|
||||
|
||||
override fun toString() = "$scope$label"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
|
||||
|
||||
fun LLVMFunctionDescriptor(name: String,
|
||||
argTypes: List<LLVMVariable>?,
|
||||
returnType: LLVMType,
|
||||
declare: Boolean = false) =
|
||||
"${if (declare) "declare" else "define weak"} $returnType @$name(${
|
||||
argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
|
||||
"${s.pointedType} ${if (s.type is LLVMReferenceType && !s.type.byRef) "byval" else ""} %${s.label}"
|
||||
}?.joinToString()}) #0"
|
||||
|
||||
fun LLVMInstanceOfStandardType(name: String,
|
||||
type: KotlinType,
|
||||
scope: LLVMScope = LLVMRegisterScope(),
|
||||
state: TranslationState): LLVMVariable {
|
||||
val typeName = type.toString().dropLastWhile { it == '?' }
|
||||
val pointerMark = if (type.isMarkedNullable) 1 else 0
|
||||
return when {
|
||||
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
|
||||
typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark)
|
||||
typeName == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope, pointerMark)
|
||||
typeName == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope, pointerMark)
|
||||
typeName == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope, pointerMark)
|
||||
typeName == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope, pointerMark)
|
||||
typeName == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope, pointerMark)
|
||||
typeName == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope, pointerMark)
|
||||
typeName == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope, pointerMark)
|
||||
typeName == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope, pointerMark)
|
||||
type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope)
|
||||
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
|
||||
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(typeName, prefix = "class"), name, scope, pointer = pointerMark)
|
||||
else -> {
|
||||
val declarationDescriptor = type.constructor.declarationDescriptor!!
|
||||
val refName = declarationDescriptor.fqNameSafe.asString()
|
||||
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.POINTER_ALIGN, prefix = "class")
|
||||
|
||||
LLVMVariable(name, refType, name, scope, pointer = 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun LLVMMapStandardType(type: KotlinType,
|
||||
state: TranslationState) =
|
||||
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
|
||||
|
||||
fun String.addBeforeIfNotEmpty(add: String): String =
|
||||
if (this.length > 0) add + this else this
|
||||
|
||||
fun String.addAfterIfNotEmpty(add: String): String =
|
||||
if (this.length > 0) this + add else this
|
||||
|
||||
fun FqName.convertToNativeName(): String =
|
||||
this.asString().replace(".<init>", "")
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
interface LLVMArray {
|
||||
|
||||
val arrayElementType: LLVMType
|
||||
val fullArrayType: String
|
||||
val length: Int
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
|
||||
class LLVMBooleanType() : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 1
|
||||
override val defaultValue = "0"
|
||||
override val mangle = "Boolean"
|
||||
override val isPrimitive = true
|
||||
override val typename = "i1"
|
||||
|
||||
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "sub nsw i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "mul nsw i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "add nsw i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "sdiv i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i1" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i1" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorOr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "or i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorAnd(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "and i1 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorXor(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "xor i1 $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMBooleanType
|
||||
|
||||
override fun parseArg(inputArg: String) =
|
||||
when (inputArg.toLowerCase()) {
|
||||
"true" -> "1"
|
||||
"false" -> "0"
|
||||
else -> throw IllegalArgumentException("Failed to parse boolean type")
|
||||
}
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
class LLVMByteType() : LLVMType() {
|
||||
|
||||
override val align = 1
|
||||
override var size: Int = 1
|
||||
override val mangle = "Byte"
|
||||
override val typename = "i8"
|
||||
override val defaultValue = "0"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i8" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i8" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMByteType(), "srem i8 $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMByteType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
class LLVMCharType() : LLVMType() {
|
||||
|
||||
override val align = 1
|
||||
override var size: Int = 1
|
||||
override val mangle = "Char"
|
||||
override val typename = "i8"
|
||||
override val defaultValue = "0"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun parseArg(inputArg: String) = inputArg.first().toInt().toString()
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i8 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i8" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i8" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMCharType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
|
||||
class LLVMDoubleType() : LLVMType() {
|
||||
|
||||
override val align = 8
|
||||
override var size: Int = 8
|
||||
override val mangle = "Double"
|
||||
override val typename = "double"
|
||||
override val defaultValue = "0.0"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fsub double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fmul double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorInc(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fadd double $firstOp, 1.0")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fdiv double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDec(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fsub double $firstOp, 1.0")
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp olt double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp ogt double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp ole double i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp oge double i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp oeq double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp one double $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "frem double $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMDoubleType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
|
||||
class LLVMFloatType() : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 4
|
||||
override val mangle = "Float"
|
||||
override val typename = "float"
|
||||
override val defaultValue = "0.0"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMFloatType(), "fsub float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMFloatType(), "fmul float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMFloatType(), "fadd float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMFloatType(), "fdiv float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorInc(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fadd float $firstOp, 1.0")
|
||||
|
||||
override fun operatorDec(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMDoubleType(), "fsub float $firstOp, 1.0")
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp olt float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp ogt float $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp ole float i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp oge float i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp oeq float" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "fcmp one float" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMFloatType(), "frem float $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMFloatType
|
||||
|
||||
override fun hashCode() =
|
||||
typename.hashCode()
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.LLVMInstanceOfStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
|
||||
class LLVMFunctionType(type: KotlinType, state: TranslationState) : LLVMType() {
|
||||
|
||||
override val defaultValue = ""
|
||||
override val align: Int = 4
|
||||
override var size: Int = 4
|
||||
override val mangle: String
|
||||
override val typename = "FunctionType"
|
||||
|
||||
val arguments: List<LLVMVariable>
|
||||
val returnType: LLVMVariable
|
||||
|
||||
init {
|
||||
val types = type.arguments.map { LLVMInstanceOfStandardType("", it.type, state = state) }.toList()
|
||||
returnType = types.last()
|
||||
arguments = types.dropLast(1)
|
||||
mangle = "F.${LLVMType.mangleFunctionArguments(arguments)}.EF"
|
||||
}
|
||||
|
||||
fun mangleArgs() = LLVMType.mangleFunctionArguments(arguments)
|
||||
|
||||
override fun toString() =
|
||||
"${returnType.type} (${arguments.map { it.pointedType }.joinToString()})"
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
(other is LLVMFunctionType) && (mangle == other.mangle)
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.exceptions.UnimplementedException
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
|
||||
class LLVMIntType() : LLVMType() {
|
||||
|
||||
override val align = 4
|
||||
override var size: Int = 4
|
||||
override val defaultValue = "0"
|
||||
override val mangle = "Int"
|
||||
override val typename = "i32"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun convertFrom(source: LLVMSingleValue) =
|
||||
when (source.type) {
|
||||
is LLVMBooleanType,
|
||||
is LLVMByteType,
|
||||
is LLVMCharType,
|
||||
is LLVMShortType -> LLVMExpression(LLVMIntType(), " sext ${source.type} $source to i32")
|
||||
else -> throw UnimplementedException()
|
||||
}
|
||||
|
||||
override fun operatorOr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "or i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorAnd(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "and i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorXor(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "xor i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorShl(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "shl i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorShr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "ashr i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorUshr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "lshr i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "mul nsw i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "sdiv i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorInc(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "add nsw i32 $firstOp, 1")
|
||||
|
||||
override fun operatorDec(firstOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "sub nsw i32 $firstOp, 1")
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i32 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i32" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i32" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMIntType(), "srem i32 $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMIntType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.exceptions.UnimplementedException
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
|
||||
class LLVMLongType() : LLVMType() {
|
||||
|
||||
override val align = 8
|
||||
override var size = 8
|
||||
override val defaultValue = "0"
|
||||
override val typename = "i64"
|
||||
override val mangle = "Long"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun convertFrom(source: LLVMSingleValue) =
|
||||
when (source.type) {
|
||||
is LLVMBooleanType,
|
||||
is LLVMByteType,
|
||||
is LLVMCharType,
|
||||
is LLVMShortType,
|
||||
is LLVMIntType -> LLVMExpression(LLVMLongType(), " sext ${source.type} $source to i64")
|
||||
else -> throw UnimplementedException()
|
||||
}
|
||||
|
||||
override fun operatorOr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "or i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorAnd(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "and i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorXor(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "xor i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorShl(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "shl i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorShr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "ashr i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorUshr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "lshr i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "sub nsw i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "mul nsw i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "add nsw i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "sdiv i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i64 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i64" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i64" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMLongType(), "srem i64 $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMLongType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMNullType(var baseType: LLVMType? = null) : LLVMType() {
|
||||
|
||||
override val align = 1
|
||||
override var size = 0
|
||||
override val defaultValue = "null"
|
||||
override val mangle = ""
|
||||
override val typename = baseType?.typename.orEmpty()
|
||||
|
||||
override fun parseArg(inputArg: String) = "null"
|
||||
override fun toString() = baseType?.toString().orEmpty()
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMNullType
|
||||
|
||||
override fun hashCode() =
|
||||
"null".hashCode()
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.TranslationState
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
import org.kotlinnative.translator.llvm.addAfterIfNotEmpty
|
||||
|
||||
|
||||
class LLVMReferenceType(val type: String,
|
||||
var prefix: String = "",
|
||||
override var align: Int = TranslationState.POINTER_ALIGN,
|
||||
override var size: Int = TranslationState.POINTER_SIZE,
|
||||
var byRef: Boolean = true) : LLVMType() {
|
||||
|
||||
override val defaultValue: String = "null"
|
||||
override val mangle = "Ref_$type"
|
||||
override val typename = prefix.addAfterIfNotEmpty(".") + type
|
||||
|
||||
override fun toString() = "%$typename"
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.pointedType} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne ${firstOp.pointedType} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
(other is LLVMReferenceType) and (typename.equals((other as LLVMReferenceType).typename))
|
||||
|
||||
override fun hashCode() =
|
||||
typename.hashCode()
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
class LLVMShortType() : LLVMType() {
|
||||
|
||||
override val align = 2
|
||||
override var size: Int = 2
|
||||
override val defaultValue = "0"
|
||||
override val typename = "i16"
|
||||
override val mangle = "Short"
|
||||
override val isPrimitive = true
|
||||
|
||||
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp slt i16 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sgt i16 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sle i16 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp sge i16 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp eq i16" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMBooleanType(), "icmp ne i16" + (if ((firstOp.pointer > 0) || (secondOp.pointer > 0)) "*" else "") + " $firstOp, $secondOp")
|
||||
|
||||
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMShortType(), "srem i16 $firstOp, $secondOp")
|
||||
|
||||
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||
LLVMExpression(LLVMShortType(), "sdiv i16 $firstOp, $secondOp")
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMShortType
|
||||
|
||||
override fun hashCode() =
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMStringType(override val length: Int, var isLoaded: Boolean = true) : LLVMArray, LLVMType() {
|
||||
|
||||
override val align = 8
|
||||
override var size: Int = 1
|
||||
override val defaultValue = ""
|
||||
override val typename = "i8*"
|
||||
override val mangle = "String"
|
||||
override val arrayElementType = LLVMCharType()
|
||||
override val fullArrayType = "[${length + 1} x i8]"
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
when (other) {
|
||||
is LLVMStringType -> this.length == other.length
|
||||
else -> false
|
||||
}
|
||||
|
||||
override fun hashCode() =
|
||||
length * 31 + if (isLoaded) 1 else 0 +
|
||||
mangle.hashCode()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.kotlinnative.translator.exceptions.UnimplementedException
|
||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||
import org.kotlinnative.translator.llvm.LLVMSingleValue
|
||||
|
||||
abstract class LLVMType() {
|
||||
|
||||
companion object {
|
||||
fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
|
||||
mangleFunctionTypes(names.map { it.type })
|
||||
|
||||
fun mangleFunctionTypes(names: List<LLVMType>) =
|
||||
if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.mangle })}" else ""
|
||||
|
||||
fun nullOrVoidType(type: LLVMType): Boolean =
|
||||
(type is LLVMNullType) or (type is LLVMVoidType)
|
||||
|
||||
fun isReferredType(type: LLVMType?): Boolean =
|
||||
(type is LLVMNullType) or (type is LLVMReferenceType)
|
||||
|
||||
}
|
||||
|
||||
abstract val align: Int
|
||||
abstract val typename: String
|
||||
abstract var size: Int
|
||||
abstract val defaultValue: String
|
||||
abstract val mangle: String
|
||||
open val isPrimitive: Boolean = false
|
||||
|
||||
open fun parseArg(inputArg: String) = inputArg
|
||||
open fun convertFrom(source: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
override fun toString() = typename
|
||||
|
||||
open fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorOr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorAnd(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorXor(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorShl(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorShr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorUshr(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
open fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression = throw UnimplementedException()
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
class LLVMVoidType() : LLVMType() {
|
||||
|
||||
override val align = 0
|
||||
override var size = 0
|
||||
override val defaultValue = ""
|
||||
override val typename = "void"
|
||||
override val mangle = ""
|
||||
|
||||
override fun equals(other: Any?) =
|
||||
other is LLVMVoidType
|
||||
|
||||
override fun hashCode() =
|
||||
typename.hashCode()
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user