translator: complex refactoring, merge functions in LLVMBuilder, delete unused parts of code

This commit is contained in:
Alexey Stepanov
2016-08-31 18:06:16 +03:00
parent 728cb18834
commit baddaa0755
24 changed files with 257 additions and 382 deletions
@@ -12,7 +12,8 @@ class DefaultArguments(raw: RawArguments) : Arguments(raw, name = "default") {
val arm = optionalFlag(
name = "arm",
description = "enable arm build",
aliasNames = listOf("arm")
aliasNames = listOf("arm"),
default = false
)
val output = optionalParameter(
+4 -10
View File
@@ -3,24 +3,18 @@ import com.jshmrsn.karg.parseArguments
import org.kotlinnative.translator.ProjectTranslator
import org.kotlinnative.translator.parseAndAnalyze
import java.io.*
import java.util.*
fun main(args: Array<String>) {
val arguments = parseArguments(args, ::DefaultArguments)
val disposer = Disposer.newDisposable()
val analyzedFiles = ArrayList<String>()
val stdlib = mutableListOf<String>()
val analyzedFiles = arguments.sources.toMutableList()
if (arguments.includeDir != null) {
val libraryFile = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath }
stdlib.addAll(libraryFile)
analyzedFiles.addAll(stdlib)
val libraryFiles = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath }
analyzedFiles.addAll(libraryFiles)
}
analyzedFiles.addAll(arguments.sources)
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm ?: false)
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm)
val files = state.environment.getSourceFiles()
val code = ProjectTranslator(files, state).generateCode()
@@ -26,7 +26,7 @@ import kotlin.comparisons.compareBy
abstract class BlockCodegen(val state: TranslationState, val variableManager: VariableManager, val codeBuilder: LLVMBuilder) {
val topLevel = 2
val topLevelScopeDepth = 2
var returnType: LLVMVariable? = null
var wasReturnOnTopLevel = false
@@ -38,12 +38,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text)
when (result) {
is LLVMVariable -> {
if (result.pointer == 1 && result.type !is LLVMReferenceType) {
result = codeBuilder.loadAndGetVariable(result)
}
if (result.type is LLVMReferenceType) {
generateReferenceReturn(result)
} else {
result = codeBuilder.receivePointedArgument(result, 0)
codeBuilder.addReturnOperator(result)
}
}
@@ -105,9 +103,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
is KtThisExpression -> evaluateThisExpression()
is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth)
is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth)
null,
is PsiWhiteSpace -> null
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
null -> null
else -> throw UnsupportedOperationException()
}
}
@@ -123,10 +121,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
variableManager["this"]
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)
val type = (receiveValue as TypedCompileTimeConstant).type
val value = receiveValue.getValue(type) ?: return null
val variable = variableManager.receiveVariable(".str" + LLVMBuilder.UniqueGenerator.generateUniqueString(), LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0)
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) as TypedCompileTimeConstant
val value = receiveValue.getValue(receiveValue.type) ?: return null
val variable = variableManager.receiveVariable(".str", LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0)
codeBuilder.addStringConstant(variable, value.toString())
return variable
@@ -134,7 +131,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
val result = LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope(), state)
val result = LLVMInstanceOfStandardType(expr.callableReference.text, kotlinType, LLVMVariableScope(), state)
return LLVMVariable("${result.label}${(result.type as LLVMFunctionType).mangleArgs()}", result.type, result.kotlinName, result.scope, result.pointer)
}
@@ -146,27 +143,22 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val loadedLeft = codeBuilder.receiveNativeValue(left)
val expectedType = LLVMMapStandardType(state.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)!!, state) as LLVMReferenceType
if (state.classes.containsKey(expectedType.type)) {
expectedType.prefix = "class"
}
val result = codeBuilder.getNewVariable(expectedType, pointer = 2)
codeBuilder.allocStaticVar(result, pointer = true)
val condition = left.type.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType()))
val thenLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val elseLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val nullLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val notNullLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val endLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val conditionResult = codeBuilder.getNewVariable(condition.variableType)
codeBuilder.addAssignment(conditionResult, condition)
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
val conditionResult = codeBuilder.storeExpression(condition)
codeBuilder.addCondition(conditionResult, nullLabel, notNullLabel)
codeBuilder.markWithLabel(thenLabel)
codeBuilder.markWithLabel(nullLabel)
codeBuilder.storeNull(result)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel)
codeBuilder.markWithLabel(notNullLabel)
val right = evaluateDotBody(receiver, selector!!, scopeDepth) as LLVMVariable
val rightLoaded = codeBuilder.loadAndGetVariable(right)
codeBuilder.storeVariable(result, rightLoaded)
@@ -201,7 +193,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
when (referenceContext) {
is PropertyDescriptorImpl -> {
val receiverThis = variableManager["this"]!!
evaluateMemberMethodOrField(receiverThis, receiverName, topLevel, call = null)!! as LLVMVariable
evaluateMemberMethodOrField(receiverThis, receiverName, topLevelScopeDepth, call = null)!! as LLVMVariable
}
else -> variableManager[receiverName]
}
@@ -237,21 +229,21 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
private fun evaluateExtensionExpression(receiver: KtExpression, receiverExpressionArgument: LLVMVariable?, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
val standardType = LLVMMapStandardType(receiverType!!.type!!, state)
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)!!.type!!
val receiverType = LLVMMapStandardType(kotlinType, state)
val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression)
val candidateDescriptor = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)!!.candidateDescriptor
val targetFunctionName = candidateDescriptor.fqNameSafe.convertToNativeName()
val nameWithoutMangling = candidateDescriptor.name.asString().replace(Regex("""(.?)<init>"""), "")
val packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.convertToNativeName() ?: ""
val packageNameFirst = targetFunction?.calleeExpression?.getContainingKtFile()?.packageFqName?.convertToNativeName().orEmpty()
val packageNameSecond = candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName()
val names = parseArgList(selector, scopeDepth)
val type = LLVMType.mangleFunctionArguments(names)
val constructedFunctionName = standardType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type
val targetExtension = state.extensionFunctions[standardType.toString()]
val constructedFunctionName = receiverType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type
val targetExtension = state.extensionFunctions[receiverType.toString()]
val extensionCodegen = targetExtension?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?:
targetExtension?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?:
@@ -259,9 +251,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
?: throw UnexpectedException(constructedFunctionName)
val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!!
val typeThisArgument = LLVMVariable("type", standardType, pointer = if (standardType is LLVMReferenceType) 1 else 0)
val args = mutableListOf(codeBuilder.loadOneArgumentIfRequired(receiverExpression, typeThisArgument))
val args = mutableListOf(codeBuilder.receivePointedArgument(receiverExpression, if (receiverType is LLVMReferenceType) 1 else 0))
args.addAll(codeBuilder.loadArgsIfRequired(names, extensionCodegen.args))
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
}
@@ -281,7 +271,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if (field != null) {
return evaluateClassField(receiver, field)
} else {
return evaluateMemberMethod(receiver, selectorName, clazz, scopeDepth, call)
return evaluateMemberMethod(receiver, clazz, scopeDepth, call as? KtCallExpression ?: throw UnexpectedException("$receiver:$selectorName"))
}
}
@@ -291,9 +281,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return result
}
fun evaluateMemberMethod(receiver: LLVMVariable, selectorName: String, clazz: StructCodegen, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? {
(call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName")
val resolvedCall = (call as KtCallExpression).getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? {
val resolvedCall = call.getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
val functionDescriptor = resolvedCall.candidateDescriptor
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
val methodName = functionDescriptor.fqNameSafe.asString() + LLVMType.mangleFunctionTypes(functionArguments)
@@ -302,8 +291,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val returnType = method.returnType!!.type
val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values
val names = parseNamedValueArguments(arguments, method.defaultValues, scopeDepth)
val loadedArgs = codeBuilder.loadArgsIfRequired(names, method.args)
val substitutionArguments = parseArgumentsWithDefaultValues(arguments, method.defaultValues, scopeDepth)
val loadedArgs = codeBuilder.loadArgsIfRequired(substitutionArguments, method.args)
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
callArgs.addAll(loadedArgs)
@@ -351,14 +340,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get"
val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver
val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable
val pureReceiver = codeBuilder.downLoadArgument(receiver, 1)
val pureReceiver = codeBuilder.receivePointedArgument(receiver, 1)
val targetClassName = (receiver.type as LLVMReferenceType).type
val names = parseValueArguments(callMaker.valueArguments, scope)
val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}"
val type = receiver.type
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
val clazz = resolveClassOrObjectLocation(receiver.type) ?: throw UnexpectedException(receiver.type.toString())
val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text)
val returnType = clazz.methods[methodName]!!.returnType!!.type
@@ -388,21 +376,19 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return when {
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope)
(targetName != null) && (variableManager[targetName] != null) -> variableManager[targetName]
((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!)
(targetName != null) && variableManager.contains(targetName) -> variableManager[targetName]
((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(targetName!!, classScope.parentCodegen!! as ClassCodegen)
else -> {
val clazz = classScope ?: resolveCodegen(expr)
val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"]
targetName ?: throw RuntimeException(expr.firstChild.text)
evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevel)
targetName ?: throw UnexpectedException("Can't find target in reference expression " + expr.firstChild.text)
evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevelScopeDepth)
}
}
}
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): LLVMSingleValue? {
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text)
private fun evaluateNameReferenceExpression(fieldName: String, classScope: ClassCodegen): LLVMSingleValue? {
val companionObject = classScope.companionObjectCodegen!!
val field = companionObject.fieldsIndex[fieldName] ?: return null
val receiver = variableManager[companionObject.structName]!!
val result = codeBuilder.getNewVariable(field.type, pointer = 1)
@@ -419,7 +405,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun resolveCodegen(expr: KtExpression): StructCodegen? {
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type
?: expr.getType(state.bindingContext)
?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext)
val name = type?.constructor?.declarationDescriptor?.fqNameSafe?.asString() ?: throw UnexpectedException(expr.text)
@@ -430,7 +415,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun resolveCodegenByName(name: String): StructCodegen? =
resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class"))
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
var names = parseArgList(expr, scopeDepth)
val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression)
@@ -439,51 +423,34 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
resolvedCall = resolvedCall.variableCall
}
val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName()
val functionDescriptor = expr.getFunctionResolvedCallWithAssert(state.bindingContext).candidateDescriptor
val functionDescriptor = resolvedCall!!.candidateDescriptor
val targetFunctionName = functionDescriptor.fqNameSafe.convertToNativeName()
val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values
val external = state.externalFunctions.containsKey(targetFunctionName)
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
val function = "$targetFunctionName${if (!external) LLVMType.mangleFunctionTypes(functionArguments) else ""}"
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) {
val descriptor = state.functions[function] ?: state.externalFunctions[function] ?: return null
names = parseNamedValueArguments(arguments, descriptor.defaultValues, scopeDepth)
if (function in state.functions || function in state.externalFunctions) {
val descriptor = state.functions[function] ?: state.externalFunctions[function]!!
names = parseArgumentsWithDefaultValues(arguments, descriptor.defaultValues, scopeDepth)
val args = codeBuilder.loadArgsIfRequired(names, descriptor.args)
return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), args)
}
if (state.classes.containsKey(targetFunctionName) || classScope?.structName == targetFunctionName) {
if (targetFunctionName in state.classes || classScope?.structName == targetFunctionName) {
val descriptor = state.classes[targetFunctionName] ?: classScope ?: return null
val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments)
val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
return evaluateConstructorCallExpression(LLVMVariable(descriptor.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
}
val localFunction = variableManager[targetFunctionName]
if (localFunction != null) {
val type = localFunction.type as LLVMFunctionType
if (targetFunctionName in variableManager) {
val type = variableManager[targetFunctionName]!!.type as LLVMFunctionType
val args = codeBuilder.loadArgsIfRequired(names, type.arguments)
return evaluateFunctionCallExpression(LLVMVariable(targetFunctionName, type.returnType.type, scope = LLVMRegisterScope()), args)
}
if (classScope != null) {
if (classScope.methods.containsKey(function)) {
val descriptor = classScope.methods[function]!!
val parentDescriptor = descriptor.parentCodegen!!
val receiver = variableManager[parentDescriptor.structName] ?: throw UnexpectedException(parentDescriptor.structName)
val methodFullName = descriptor.name
val returnType = descriptor.returnType!!.type
val loadedArgs = codeBuilder.loadArgsIfRequired(names, descriptor.args)
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
callArgs.addAll(loadedArgs)
return evaluateFunctionCallExpression(LLVMVariable(methodFullName, returnType, scope = LLVMVariableScope()), callArgs)
}
}
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
if (nestedConstructor != null) {
val args = codeBuilder.loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!)
@@ -496,7 +463,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if (caller != null) {
args.add(caller)
} else if (variableManager[containingClass.structName] != null) {
} else if (containingClass.structName in variableManager) {
args.add(variableManager[containingClass.structName]!!)
} else {
args.add(variableManager["this"]!!)
@@ -517,6 +484,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
when (returnType) {
is LLVMVoidType -> {
codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
return null
}
is LLVMReferenceType -> {
val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2)
@@ -542,8 +510,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return resultPtr
}
}
return null
}
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? {
@@ -575,7 +541,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
fun parseOneValueArgument(arg: ValueArgument, scopeDepth: Int): LLVMSingleValue =
evaluateExpression(arg.getArgumentExpression(), scopeDepth) as LLVMSingleValue
private fun parseNamedValueArguments(args: MutableCollection<ResolvedValueArgument>, defaultValues: List<KtExpression?>, scopeDepth: Int): List<LLVMSingleValue> =
private fun parseArgumentsWithDefaultValues(args: MutableCollection<ResolvedValueArgument>, defaultValues: List<KtExpression?>, scopeDepth: Int): List<LLVMSingleValue> =
args.mapIndexed(fun(i: Int, value: ResolvedValueArgument): LLVMSingleValue {
return when (value) {
is DefaultValueArgument -> evaluateExpression(defaultValues[i], scopeDepth)!!
@@ -604,108 +570,92 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val right = evaluateExpression(expr.right, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}")
return executeBinaryExpression(operator, expr.operationReference, left, right)
return addPrimitiveBinaryOperation(operator, left, right, expr.operationReference)
}
private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? {
val operator = expr.operationToken
val left = evaluateExpression(expr.baseExpression, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}")
return executePostfixExpression(operator, left as LLVMVariable)
return addPrimitivePostfixOperation(operator, left as LLVMVariable)
}
private fun evaluatePrefixExpression(expr: KtPrefixExpression, scopeDepth: Int): LLVMSingleValue? {
val operator = expr.operationToken
val left = evaluateExpression(expr.baseExpression, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression")
return executePrefixExpression(operator, expr.operationReference, left)
return addPrimitivePrefixOperation(operator, left)
}
private fun executePostfixExpression(operator: IElementType?, left: LLVMVariable): LLVMSingleValue?
= addPrimitivePostfixOperation(operator, left)
private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? =
when (operator) {
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer)
codeBuilder.allocStackVar(oldValue, asValue = true)
codeBuilder.copyVariable(firstOp, oldValue)
private fun executePrefixExpression(operator: IElementType?, operationReference: KtSimpleNameExpression, left: LLVMSingleValue): LLVMSingleValue?
= addPrimitivePrefixOperation(operator, operationReference, left)
val llvmExpression = when (operator) {
KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp)
KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp)
else -> throw IllegalAccessError()
}
private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
when (operator) {
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> {
val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer)
codeBuilder.allocStackVar(oldValue, asValue = true)
codeBuilder.copyVariable(firstOp, oldValue)
val resultOp = codeBuilder.storeExpression(llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
val llvmExpression = when (operator) {
KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp)
KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp)
else -> throw IllegalAccessError()
oldValue
}
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
codeBuilder.storeVariable(firstOp, resultOp)
return oldValue
}
KtTokens.EXCLEXCL -> {
var result = firstOp
val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val nullCheck = codeBuilder.nullCheck(firstOp)
codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel)
codeBuilder.markWithLabel(nullLabel)
codeBuilder.addExceptionCall("KotlinNullPointerException")
codeBuilder.addUnconditionalJump(notNullLabel)
codeBuilder.markWithLabel(notNullLabel)
if (firstOp.type.isPrimitive) {
result = codeBuilder.downLoadArgument(firstOp, 0) as LLVMVariable
KtTokens.EXCLEXCL -> {
var result = firstOp
val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val nullCheck = codeBuilder.nullCheck(firstOp)
codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel)
codeBuilder.markWithLabel(nullLabel)
codeBuilder.addExceptionCall("KotlinNullPointerException")
codeBuilder.addUnconditionalJump(notNullLabel)
codeBuilder.markWithLabel(notNullLabel)
if (firstOp.type.isPrimitive) {
result = codeBuilder.receivePointedArgument(firstOp, 0) as LLVMVariable
}
result
}
return result
else -> throw UnsupportedOperationException()
}
else -> throw UnsupportedOperationException()
}
}
private fun addPrimitivePrefixOperation(operator: IElementType?, operationReference: KtSimpleNameExpression, firstOp: LLVMSingleValue): LLVMSingleValue? {
private fun addPrimitivePrefixOperation(operator: IElementType?, firstOp: LLVMSingleValue): LLVMSingleValue? {
when (operator) {
KtTokens.MINUS,
KtTokens.PLUS -> {
return addPrimitiveBinaryOperation(operator!!, operationReference, LLVMConstant("0", firstOp.type), firstOp)
return addPrimitiveBinaryOperation(operator!!, LLVMConstant("0", firstOp.type), firstOp)
}
KtTokens.EXCL -> {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val llvmExpression = addPrimitiveReferenceOperationByName("xor", LLVMConstant("true", LLVMBooleanType()), firstNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType)
codeBuilder.addAssignment(resultOp, llvmExpression)
return resultOp
return codeBuilder.storeExpression(llvmExpression)
}
else -> throw UnsupportedOperationException()
}
}
fun executeBinaryExpression(operator: IElementType, referenceName: KtSimpleNameExpression?, left: LLVMSingleValue, right: LLVMSingleValue)
= addPrimitiveBinaryOperation(operator, referenceName, left, right)
private fun evaluateElvisOperator(expr: KtBinaryExpression, scopeDepth: Int): LLVMVariable {
val left = evaluateExpression(expr.firstChild, scopeDepth)
val left = evaluateExpression(expr.left, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression")
val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable)
val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType()))
val conditionResult = codeBuilder.getNewVariable(condition.variableType)
codeBuilder.addAssignment(conditionResult, condition)
val conditionResult = codeBuilder.storeExpression(condition)
val thenLabel = codeBuilder.getNewLabel(prefix = "elvis")
val elseLabel = codeBuilder.getNewLabel(prefix = "elvis")
val notNull = codeBuilder.getNewLabel(prefix = "elvis")
val endLabel = codeBuilder.getNewLabel(prefix = "elvis")
codeBuilder.addCondition(conditionResult, elseLabel, thenLabel)
codeBuilder.markWithLabel(thenLabel)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.addCondition(conditionResult, notNull, endLabel)
codeBuilder.markWithLabel(elseLabel)
var right = evaluateExpression(expr.lastChild, scopeDepth + 1)
codeBuilder.markWithLabel(notNull)
var right = evaluateExpression(expr.right, scopeDepth + 1)
if (right != null) {
right = codeBuilder.loadAndGetVariable(right as LLVMVariable)
codeBuilder.storeVariable(left, right)
@@ -717,9 +667,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return left
}
fun addPrimitiveReferenceOperation(referenceName: KtSimpleNameExpression, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression
= addPrimitiveReferenceOperationByName(referenceName.getReferencedName(), firstOp, secondNativeOp)
fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
@@ -734,23 +681,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
"shr" -> firstNativeOp.type.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"ushr" -> firstNativeOp.type.operatorUshr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"+=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorPlus(firstNativeOp, secondNativeOp))
val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorPlus(firstNativeOp, secondNativeOp))
codeBuilder.storeVariable(firstOp, resultOp)
return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
}
"-=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMinus(firstNativeOp, secondNativeOp))
val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorMinus(firstNativeOp, secondNativeOp))
codeBuilder.storeVariable(firstOp, resultOp)
return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
}
"*=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorTimes(firstNativeOp, secondNativeOp))
val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorTimes(firstNativeOp, secondNativeOp))
codeBuilder.storeVariable(firstOp, resultOp)
return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
}
"%=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp))
val resultOp = codeBuilder.storeExpression(firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp))
codeBuilder.storeVariable(firstOp, resultOp)
return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
}
".." -> {
val descriptor = state.classes["kotlin.ranges.IntRange"]
val descriptor = state.classes["kotlin.ranges.${firstOp.type.mangle}Range"]
val arguments = listOf(firstOp, secondNativeOp)
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type })
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments)
@@ -760,7 +711,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
}
private fun addPrimitiveBinaryOperation(operator: IElementType, referenceName: KtSimpleNameExpression?, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMVariable {
fun addPrimitiveBinaryOperation(operator: IElementType, firstOp: LLVMSingleValue, secondOp: LLVMSingleValue, referenceName: KtSimpleNameExpression? = null): LLVMVariable {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
@@ -817,18 +768,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.storeVariable(result, sourceArgument)
return result
}
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp)
else -> addPrimitiveReferenceOperationByName(referenceName!!.getReferencedName(), firstOp, secondNativeOp)
}
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType, pointer = llvmExpression.pointer)
codeBuilder.addAssignment(resultOp, llvmExpression)
return resultOp
return codeBuilder.storeExpression(llvmExpression)
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType)
val type = LLVMMapStandardType(expressionKotlinType, state)
return LLVMConstant(expressionValue?.toString() ?: "", type, pointer = 0)
return LLVMConstant(expressionValue?.toString().orEmpty(), type, pointer = 0)
}
private fun evaluatePsiElement(element: PsiElement, scopeDepth: Int): LLVMSingleValue? {
@@ -864,11 +813,11 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.next"] ?: throw UnexpectedException("$returnTypeName.nextInt")
val conditionIterator = evaluateFunctionCallExpression(LLVMVariable("$rangeTypeName.iterator", returnType, scope = LLVMVariableScope()), listOf(range))!!
val iteratorThisArgument = codeBuilder.loadOneArgumentIfRequired(conditionIterator, LLVMVariable("type", descriptor.type, pointer = 1))
val iteratorThisArgument = codeBuilder.receivePointedArgument(conditionIterator, 1)
codeBuilder.addUnconditionalJump(conditionLabel)
codeBuilder.markWithLabel(conditionLabel)
var conditionResult = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.hasNext", LLVMBooleanType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!!
conditionResult = codeBuilder.downLoadArgument(conditionResult, 0)
conditionResult = codeBuilder.receivePointedArgument(conditionResult, 0)
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
codeBuilder.addUnconditionalJump(bodyLabel)
@@ -881,7 +830,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
variableManager.addVariable(loopParameterDescriptor, allocVar, scopeDepth + 1)
codeBuilder.allocStackVar(allocVar, pointer = true)
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, loopParameter)
addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, loopParameter, null)
evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1)
codeBuilder.markWithLabel(exitLabel)
@@ -899,8 +848,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.markWithLabel(nextLabel)
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
val currentConditionExpression = evaluateExpression(condition.firstChild, scopeDepth + 1)!!
val conditionResult = executeBinaryExpression(KtTokens.EQEQ, null, target, currentConditionExpression)
val currentConditionExpression = evaluateExpression((condition as KtWhenConditionWithExpression).expression, scopeDepth + 1)!!
val conditionResult = addPrimitiveBinaryOperation(KtTokens.EQEQ, target, currentConditionExpression)
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
}
@@ -910,11 +859,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.markWithLabel(successConditionsLabel)
var successExpression = evaluateExpression(item.expression, scopeDepth + 1)
while (successExpression is LLVMVariable && successExpression.pointer > 0) {
successExpression = codeBuilder.loadAndGetVariable(successExpression)
}
if (successExpression != null && !LLVMType.nullOrVoidType(resultVariable.type)) {
successExpression = codeBuilder.receivePointedArgument(successExpression, 0)
codeBuilder.storeVariable(resultVariable, successExpression)
}
@@ -964,9 +911,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.addUnconditionalJump(if (checkConditionBeforeExecute) conditionLabel else bodyLabel)
codeBuilder.markWithLabel(conditionLabel)
var conditionResult = evaluateExpression(condition, scopeDepth + 1)!!
while (conditionResult.pointer > 0) {
conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable)
}
conditionResult = codeBuilder.receivePointedArgument(conditionResult, 0)
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, exitLabel, scopeDepth + 1)
@@ -977,7 +922,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? {
val conditionResult = evaluateExpression(element.condition, scopeDepth)!!
val conditionNativeResult = codeBuilder.downLoadArgument(conditionResult, 0)
val conditionNativeResult = codeBuilder.receivePointedArgument(conditionResult, 0)
return if (isExpression)
executeIfExpression(conditionNativeResult, element.then!!, element.`else`, element, scopeDepth + 1)
@@ -1037,7 +982,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth)
val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state)
val primitivePointer = !LLVMType.isReferredType(LLVMMapStandardType(variable.type, state))
val primitivePointer = LLVMMapStandardType(variable.type, state).isPrimitive
val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer + 1)
codeBuilder.allocStackVar(allocVar, pointer = true)
@@ -1047,7 +992,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) {
throw UnexpectedException(element.text)
}
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, assignExpression)
addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, assignExpression, null)
}
return null
@@ -1068,15 +1013,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
generateReferenceReturn(retVar)
}
is LLVMVoidType -> {
codeBuilder.addAnyReturn(LLVMVoidType())
}
is LLVMVoidType -> codeBuilder.addAnyReturn(LLVMVoidType())
else -> {
val retNativeValue = codeBuilder.receiveNativeValue(retVar!!)
codeBuilder.addReturnOperator(retNativeValue)
}
}
if (scopeDepth == topLevel + 2) {
if (scopeDepth == topLevelScopeDepth + 2) {
wasReturnOnTopLevel = true
}
return null
@@ -27,13 +27,13 @@ class ClassCodegen(state: TranslationState,
override val type: LLVMReferenceType
init {
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
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.pointerAlign
type.align = TranslationState.POINTER_ALIGN
}
private fun indexFields(parameters: MutableList<KtParameter>) {
@@ -53,8 +53,7 @@ class ClassCodegen(state: TranslationState,
indexFields(parameterList)
generateInnerFields(clazz.declarations)
calculateTypeSize()
type.size = size
type.size = calculateTypeSize()
if (annotation) {
return
@@ -19,18 +19,17 @@ import java.util.*
class FunctionCodegen(state: TranslationState,
variableManager: VariableManager,
val function: KtNamedFunction,
codeBuilder: LLVMBuilder,
val parentCodegen: StructCodegen? = null) :
codeBuilder: LLVMBuilder) :
BlockCodegen(state, variableManager, codeBuilder) {
var name: String
var args = LinkedList<LLVMVariable>()
val isExtensionDeclaration = function.isExtensionDeclaration()
var functionNamePrefix = ""
val fullName: String
get() = functionNamePrefix + name
val external: Boolean
val defaultValues: List<KtExpression?>
val fullName: String
get() = functionNamePrefix + name
init {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
@@ -58,9 +57,8 @@ class FunctionCodegen(state: TranslationState,
}
defaultValues = mutableListOf()
val valueParameters = descriptor.valueParameters
for (index in valueParameters.indices) {
val parameterDescriptor = valueParameters[index]
for (index in descriptor.valueParameters.indices) {
val parameterDescriptor = descriptor.valueParameters[index]
if (parameterDescriptor.declaresDefaultValue()) {
val initializer = (parameterDescriptor.source as KotlinSourceElement).psi
val defaultValue = (initializer as KtParameter).defaultValue
@@ -69,21 +67,6 @@ class FunctionCodegen(state: TranslationState,
defaultValues.add(null)
}
}
val retType = returnType!!.type
when (retType) {
is LLVMReferenceType -> {
if (state.classes.containsKey(retType.type)) {
retType.prefix = "class"
returnType!!.pointer = 2
}
retType.byRef = true
}
}
if (retType is LLVMReferenceType && state.classes.containsKey(retType.type)) {
retType.prefix = "class"
}
}
fun generate(this_type: LLVMVariable? = null) {
@@ -95,7 +78,7 @@ class FunctionCodegen(state: TranslationState,
codeBuilder.addStartExpression()
generateLoadArguments()
evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevel, isBlock = function.hasBlockBody())
evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevelScopeDepth, isBlock = function.hasBlockBody())
if (!wasReturnOnTopLevel)
codeBuilder.addAnyReturn(returnType!!.type)
@@ -138,16 +121,16 @@ class FunctionCodegen(state: TranslationState,
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), topLevel)
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, topLevel)
variableManager.addVariable(it.label, allocVar, topLevelScopeDepth)
} else {
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 0), topLevel)
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 0), topLevelScopeDepth)
}
})
}
@@ -20,16 +20,15 @@ class ObjectCodegen(state: TranslationState,
override val type: LLVMReferenceType
init {
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
type = LLVMReferenceType(structName, "class", align = TranslationState.POINTER_ALIGN, size = TranslationState.POINTER_SIZE, byRef = true)
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
}
override fun prepareForGenerate() {
generateInnerFields(objectDeclaration.declarations)
calculateTypeSize()
type.size = size
type.align = TranslationState.pointerAlign
type.size = calculateTypeSize()
type.align = TranslationState.POINTER_ALIGN
super.prepareForGenerate()
@@ -7,10 +7,12 @@ class ProjectTranslator(val files: List<KtFile>, val state: TranslationState) {
fun generateCode(): String {
codeBuilder.clean()
files.map { addClassDeclarations(it) }
files.map { addObjectDeclarations(it) }
files.map { addFunctionDeclarations(it) }
files.map { addPropertyDeclarations(it) }
with(files) {
map { addClassDeclarations(it) }
map { addObjectDeclarations(it) }
map { addFunctionDeclarations(it) }
map { addPropertyDeclarations(it) }
}
generateProjectBody()
return codeBuilder.toString()
}
@@ -33,20 +33,19 @@ abstract class StructCodegen(val state: TranslationState,
open fun prepareForGenerate() {
generateStruct()
for (declaration in classOrObject.declarations.filter { it is KtNamedFunction }) {
val function = FunctionCodegen(state, variableManager, declaration as KtNamedFunction, codeBuilder, this)
classOrObject.declarations.filter { it is KtNamedFunction }.map {
val function = FunctionCodegen(state, variableManager, it as KtNamedFunction, codeBuilder)
methods.put(function.name, function)
}
}
fun calculateTypeSize() {
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.pointerAlign else item.type.align
val currentFieldSize = if (item.pointer > 0) TranslationState.POINTER_ALIGN else item.type.align
alignmentRemainder -= (alignmentRemainder % currentFieldSize)
if (alignmentRemainder < currentFieldSize) {
size += classAlignment
@@ -55,6 +54,7 @@ abstract class StructCodegen(val state: TranslationState,
alignmentRemainder -= currentFieldSize
}
}
return size
}
open fun generate() {
@@ -143,7 +143,7 @@ abstract class StructCodegen(val state: TranslationState,
variableManager.addVariable("this", mainConstructorThis, 0)
blockCodegen.evaluateCodeBlock(secondaryConstructor.bodyExpression, scopeDepth = 1)
generateReturn(codeBuilder.downLoadArgument(variableManager["this"]!!, 1) as LLVMVariable)
generateReturn(codeBuilder.receivePointedArgument(variableManager["this"]!!, 1) as LLVMVariable)
codeBuilder.addAnyReturn(LLVMVoidType())
codeBuilder.addEndExpression()
}
@@ -170,11 +170,9 @@ abstract class StructCodegen(val state: TranslationState,
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
codeBuilder.loadArgument(thisVariable, false)
constructorFields[primaryConstructorIndex]!!.forEach {
if (it.type !is LLVMReferenceType) {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
codeBuilder.loadArgument(loadVariable)
}
constructorFields[primaryConstructorIndex]!!.filter { it.type !is LLVMReferenceType }.forEach {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
codeBuilder.loadArgument(loadVariable)
}
}
@@ -187,7 +185,7 @@ abstract class StructCodegen(val state: TranslationState,
codeBuilder.storeVariable(classField, it)
}
else -> {
val argument = codeBuilder.loadVariable(LLVMVariable("${it.label}.addr", it.type, scope = LLVMRegisterScope(), pointer = it.pointer + 1))
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)
@@ -200,9 +198,9 @@ abstract class StructCodegen(val state: TranslationState,
variableManager.addVariable("this", receiverThis, 2)
for ((variable, initializer) in initializedFields) {
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!!
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!!
blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right)
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")
@@ -220,15 +218,11 @@ abstract class StructCodegen(val state: TranslationState,
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!!
?: field.fqName?.asString()
?: field.name!!
val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state)
if (result.type is LLVMReferenceType) {
result.type.prefix = "class"
result.type.byRef = true
}
if (state.classes.containsKey(field.name!!)) {
return LLVMClassVariable(result.label, state.classes[fieldName]!!.type, result.pointer)
}
@@ -246,7 +240,7 @@ abstract class StructCodegen(val state: TranslationState,
protected fun genClassInitializers() =
classOrObject.getAnonymousInitializers().map {
object : BlockCodegen(state, variableManager, codeBuilder) {
fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevel)
fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevelScopeDepth)
}
}.map { it.generate() }
@@ -27,13 +27,13 @@ import java.util.*
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) {
companion object {
var pointerAlign = 4
var pointerSize = 4
var POINTER_ALIGN = 4
var POINTER_SIZE = 4
}
init {
pointerAlign = if (arm) 4 else 8
pointerSize = if (arm) 4 else 8
POINTER_ALIGN = if (arm) 4 else 8
POINTER_SIZE = if (arm) 4 else 8
}
var externalFunctions = HashMap<String, FunctionCodegen>()
@@ -8,12 +8,21 @@ import java.util.*
class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable>) {
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>()
private var variableVersion = HashMap<String, 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()
}
@@ -33,9 +42,7 @@ class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable
}
fun receiveVariable(name: String, type: LLVMType, scope: LLVMScope, pointer: Int): LLVMVariable {
val ourVersion = variableVersion.getOrDefault(name, 0) + 1
variableVersion.put(name, ourVersion)
return LLVMVariable("managed.$name.$ourVersion", type, name, scope, pointer)
return LLVMVariable("managed${generateUniqueString()}.$name", type, name, scope, pointer)
}
}
@@ -2,6 +2,7 @@ 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(val arm: Boolean = false) {
@@ -12,35 +13,11 @@ class LLVMBuilder(val arm: Boolean = false) {
private var labelCount = 0
var exceptions: Map<String, LLVMVariable> = mapOf()
object UniqueGenerator {
private var unique = 0
fun generateUniqueString() =
".unique." + unique++
}
init {
initBuilder()
}
private fun initBuilder() {
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*, ...)",
"%class.Nothing = type { }",
"declare void @abort()")
declares.forEach { addLLVMCodeToGlobalPlace(it) }
exceptions = mapOf(
Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException")))
if (arm) {
val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
addLLVMCodeToGlobalPlace(functionAttributes)
}
}
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)
@@ -54,58 +31,44 @@ class LLVMBuilder(val arm: Boolean = false) {
fun addLLVMCodeToLocalPlace(code: String) =
localCode.appendln(code)
fun addLLVMCodeToGlobalPlace(code: String) =
globalCode.appendln(code)
fun addStartExpression() =
addLLVMCodeToLocalPlace("{")
fun addEndExpression() =
addLLVMCodeToLocalPlace("}")
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue =
when (firstOp) {
is LLVMConstant -> firstOp
is LLVMVariable -> if (firstOp.pointer == 0) firstOp else loadAndGetVariable(firstOp)
else -> throw UnsupportedOperationException()
when {
firstOp is LLVMConstant || firstOp.pointer == 0 -> firstOp
firstOp is LLVMVariable -> loadAndGetVariable(firstOp)
else -> throw UnexpectedException("Unknown inheritor of LLVMSingleValue")
}
fun receivePointedArgument(variable: LLVMSingleValue, pointer: Int): LLVMSingleValue {
var currentVariable = variable
while (currentVariable.pointer > pointer) {
currentVariable = receiveNativeValue(currentVariable)
}
return currentVariable
}
fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
return loadOneArgumentIfRequired(value, args[i])
return receivePointedArgument(value, args[i].pointer)
}).toList()
fun loadOneArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
fun receivePointedArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue {
var result = value
while (argument.pointer < result.pointer) {
result = loadVariable(result as LLVMVariable)
while (result.pointer > pointer) {
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 = loadVariable(newVariable)
result = loadAndGetVariable(newVariable)
}
return result
}
fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
loadOneArgumentIfRequired(value, LLVMVariable("", value.type, pointer = pointer))
fun clean() {
localCode = StringBuilder()
globalCode = StringBuilder()
@@ -115,31 +78,20 @@ class LLVMBuilder(val arm: Boolean = false) {
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")
private fun initializeExceptionString(string: String): LLVMVariable {
val result = getNewVariable(LLVMStringType(string.length), pointer = 0, scope = LLVMVariableScope(), prefix = "exceptions.str.")
addStringConstant(result, string)
return result
}
fun addStringConstant(variable: LLVMVariable, value: String) =
addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
fun convertVariableToType(variable: LLVMSingleValue, tarpointedType: LLVMType): LLVMSingleValue {
fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue {
var resultVariable = variable
if (variable.type != tarpointedType) {
val convertedExpression = tarpointedType.convertFrom(variable)
resultVariable = getNewVariable(convertedExpression.variableType)
addAssignment(resultVariable, convertedExpression)
if (variable.type != targetType) {
val convertedExpression = targetType.convertFrom(variable)
resultVariable = storeExpression(convertedExpression)
}
return resultVariable
}
@@ -174,21 +126,18 @@ class LLVMBuilder(val arm: Boolean = false) {
}
}
fun storeExpression(target: LLVMSingleValue, expression: LLVMExpression): LLVMVariable {
val resultOp = getNewVariable(expression.variableType)
fun storeExpression(expression: LLVMExpression): LLVMVariable {
val resultOp = getNewVariable(expression.variableType, pointer = expression.pointer)
addAssignment(resultOp, expression)
storeVariable(target, resultOp)
return resultOp
}
fun storeNull(result: LLVMVariable) =
addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.pointerAlign}")
addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.POINTER_ALIGN}")
fun nullCheck(variable: LLVMVariable): LLVMVariable {
val result = getNewVariable(LLVMBooleanType(), pointer = 0)
val loaded = loadVariable(variable)
val loaded = loadAndGetVariable(variable)
addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded")
return result
}
@@ -199,20 +148,11 @@ class LLVMBuilder(val arm: Boolean = false) {
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) =
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}")
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}")
}
fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
is LLVMStringType -> if (from.type.isLoaded) copyVariableValue(to, from) else storeString(to, from, 0)
else -> copyVariableValue(to, from)
}
fun copyVariable(from: LLVMVariable, to: LLVMVariable) =
when {
from.type is LLVMStringType && !from.type.isLoaded -> storeString(to, from, 0)
else -> copyVariableValue(to, from)
}
fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1)
@@ -220,12 +160,6 @@ class LLVMBuilder(val arm: Boolean = false) {
return allocVar
}
fun loadVariable(source: LLVMVariable): LLVMVariable {
val target = getNewVariable(source.type, pointer = source.pointer - 1)
addLLVMCodeToLocalPlace("$target = load ${source.pointedType} $source, align ${target.type.align}")
return target
}
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}")
@@ -234,7 +168,7 @@ class LLVMBuilder(val arm: Boolean = false) {
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.pointerSize else target.type.size
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 "*")
@@ -251,7 +185,6 @@ class LLVMBuilder(val arm: Boolean = false) {
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) =
addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}")
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
= "{ ${args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString()} }"
@@ -265,15 +198,12 @@ class LLVMBuilder(val arm: Boolean = false) {
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 createClass(name: String, fields: List<LLVMVariable>) =
addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }")
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}")
@@ -305,4 +235,38 @@ class LLVMBuilder(val arm: Boolean = false) {
override fun toString() = globalCode.toString() + localCode.toString()
private fun initBuilder() {
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*, ...)",
"%class.Nothing = type { }",
"declare void @abort()")
declares.forEach { addLLVMCodeToGlobalPlace(it) }
exceptions = mapOf(
Pair("KotlinNullPointerException", initializeExceptionString("Exception in thread main kotlin.KotlinNullPointerException")))
if (arm) {
val functionAttributes = """attributes #0 = { nounwind "stack-protector-buffer-size"="8" "target-cpu"="cortex-m3" "target-features"="+hwdiv,+strict-align" }"""
addLLVMCodeToGlobalPlace(functionAttributes)
}
}
private fun initializeExceptionString(string: String): LLVMVariable {
val result = getNewVariable(LLVMStringType(string.length), pointer = 0, scope = LLVMVariableScope(), prefix = "exceptions.str.")
addStringConstant(result, string)
return result
}
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}")
}
}
@@ -4,7 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) {
override fun toString(): String =
"call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
}
@@ -2,5 +2,4 @@ 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)
@@ -6,12 +6,8 @@ open class LLVMConstant(value: String,
type: LLVMType,
pointer: Int = 0) : LLVMSingleValue(type, pointer) {
val value: String
val value = type.parseArg(value)
init {
this.value = type.parseArg(value)
}
override fun toString(): String = value
override fun toString() = value
}
@@ -4,6 +4,6 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMExpression(val variableType: LLVMType, val llvmCode: String, val pointer: Int = 0) : LLVMNode() {
override fun toString(): String = llvmCode
override fun toString() = llvmCode
}
@@ -2,6 +2,6 @@ package org.kotlinnative.translator.llvm
class LLVMLabel(val label: String, val scope: LLVMScope) : LLVMNode() {
override fun toString(): String = "$scope$label"
override fun toString() = "$scope$label"
}
@@ -1,6 +1,6 @@
package org.kotlinnative.translator.llvm
open class LLVMScope
abstract class LLVMScope
class LLVMVariableScope : LLVMScope() {
override fun toString() = "@"
@@ -8,6 +8,6 @@ open class LLVMVariable(val label: String,
val scope: LLVMScope = LLVMRegisterScope(),
pointer: Int = 0) : LLVMSingleValue(type, pointer) {
override fun toString(): String = "$scope$label"
override fun toString() = "$scope$label"
}
@@ -18,7 +18,7 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable {
val typeName = type.toString().dropLastWhile { it == '?' }
val pointerMark = if (type.toString().last() == '?') 1 else 0
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)
@@ -36,7 +36,7 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope
else -> {
val declarationDescriptor = type.constructor.declarationDescriptor!!
val refName = declarationDescriptor.fqNameSafe.asString()
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class")
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.POINTER_ALIGN, prefix = "class")
LLVMVariable(name, refType, name, scope, pointer = 1)
}
@@ -52,10 +52,5 @@ fun String.addBeforeIfNotEmpty(add: String): String =
fun String.addAfterIfNotEmpty(add: String): String =
if (this.length > 0) this + add else this
fun String.indexOfOrLast(str: Char, startIndex: Int = 0): Int {
val pos = this.indexOf(str, startIndex)
return if (pos < 0) this.length else pos
}
fun FqName.convertToNativeName(): String =
this.asString().replace(".<init>", "")
@@ -13,43 +13,43 @@ class LLVMFloatType() : LLVMType() {
override val defaultValue = "0.0"
override val isPrimitive = true
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorMinus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMFloatType(), "fsub float $firstOp, $secondOp")
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorTimes(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMFloatType(), "fmul float $firstOp, $secondOp")
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorPlus(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMFloatType(), "fadd float $firstOp, $secondOp")
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorDiv(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMFloatType(), "fdiv float $firstOp, $secondOp")
override fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression =
override fun operatorInc(firstOp: LLVMSingleValue) =
LLVMExpression(LLVMDoubleType(), "fadd float $firstOp, 1.0")
override fun operatorDec(firstOp: LLVMSingleValue): LLVMExpression =
override fun operatorDec(firstOp: LLVMSingleValue) =
LLVMExpression(LLVMDoubleType(), "fsub float $firstOp, 1.0")
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorLt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "fcmp olt float $firstOp, $secondOp")
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorGt(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "fcmp ogt float $firstOp, $secondOp")
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorLeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "fcmp ole float i32 $firstOp, $secondOp")
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
override fun operatorGeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "fcmp oge float i32 $firstOp, $secondOp")
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue): LLVMExpression =
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 =
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 =
override fun operatorMod(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMFloatType(), "frem float $firstOp, $secondOp")
override fun equals(other: Any?) =
@@ -19,7 +19,7 @@ class LLVMIntType() : LLVMType() {
is LLVMBooleanType,
is LLVMByteType,
is LLVMCharType,
is LLVMShortType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i32")
is LLVMShortType -> LLVMExpression(LLVMIntType(), " sext ${source.type} $source to i32")
else -> throw UnimplementedException()
}
@@ -20,7 +20,7 @@ class LLVMLongType() : LLVMType() {
is LLVMByteType,
is LLVMCharType,
is LLVMShortType,
is LLVMIntType -> LLVMExpression(LLVMBooleanType(), " sext ${source.type} $source to i64")
is LLVMIntType -> LLVMExpression(LLVMLongType(), " sext ${source.type} $source to i64")
else -> throw UnimplementedException()
}
@@ -6,12 +6,12 @@ class LLVMNullType(var baseType: LLVMType? = null) : LLVMType() {
override var size = 0
override val defaultValue = "null"
override val mangle = ""
override val typename = baseType?.typename ?: ""
override val typename = baseType?.typename.orEmpty()
override fun parseArg(inputArg: String) = "null"
override fun toString() = baseType?.toString() ?: ""
override fun toString() = baseType?.toString().orEmpty()
override fun equals(other: Any?): Boolean =
override fun equals(other: Any?) =
other is LLVMNullType
override fun hashCode() =
@@ -8,8 +8,8 @@ import org.kotlinnative.translator.llvm.addAfterIfNotEmpty
class LLVMReferenceType(val type: String,
var prefix: String = "",
override var align: Int = TranslationState.pointerAlign,
override var size: Int = TranslationState.pointerSize,
override var align: Int = TranslationState.POINTER_ALIGN,
override var size: Int = TranslationState.POINTER_SIZE,
var byRef: Boolean = true) : LLVMType() {
override val defaultValue: String = "null"