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( val arm = optionalFlag(
name = "arm", name = "arm",
description = "enable arm build", description = "enable arm build",
aliasNames = listOf("arm") aliasNames = listOf("arm"),
default = false
) )
val output = optionalParameter( 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.ProjectTranslator
import org.kotlinnative.translator.parseAndAnalyze import org.kotlinnative.translator.parseAndAnalyze
import java.io.* import java.io.*
import java.util.*
fun main(args: Array<String>) { fun main(args: Array<String>) {
val arguments = parseArguments(args, ::DefaultArguments) val arguments = parseArguments(args, ::DefaultArguments)
val disposer = Disposer.newDisposable() val disposer = Disposer.newDisposable()
val analyzedFiles = ArrayList<String>() val analyzedFiles = arguments.sources.toMutableList()
val stdlib = mutableListOf<String>()
if (arguments.includeDir != null) { if (arguments.includeDir != null) {
val libraryFile = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath } val libraryFiles = File(arguments.includeDir).walk().filter { !it.isDirectory }.map { it.absolutePath }
stdlib.addAll(libraryFile) analyzedFiles.addAll(libraryFiles)
analyzedFiles.addAll(stdlib)
} }
analyzedFiles.addAll(arguments.sources) val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm)
val state = parseAndAnalyze(analyzedFiles, disposer, arguments.mainClass, arguments.arm ?: false)
val files = state.environment.getSourceFiles() val files = state.environment.getSourceFiles()
val code = ProjectTranslator(files, state).generateCode() 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) { abstract class BlockCodegen(val state: TranslationState, val variableManager: VariableManager, val codeBuilder: LLVMBuilder) {
val topLevel = 2 val topLevelScopeDepth = 2
var returnType: LLVMVariable? = null var returnType: LLVMVariable? = null
var wasReturnOnTopLevel = false 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) var result = evaluateExpression(expr, scopeDepth) ?: throw UnexpectedException("Can't evaluate expression " + expr!!.text)
when (result) { when (result) {
is LLVMVariable -> { is LLVMVariable -> {
if (result.pointer == 1 && result.type !is LLVMReferenceType) {
result = codeBuilder.loadAndGetVariable(result)
}
if (result.type is LLVMReferenceType) { if (result.type is LLVMReferenceType) {
generateReferenceReturn(result) generateReferenceReturn(result)
} else { } else {
result = codeBuilder.receivePointedArgument(result, 0)
codeBuilder.addReturnOperator(result) codeBuilder.addReturnOperator(result)
} }
} }
@@ -105,9 +103,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
is KtThisExpression -> evaluateThisExpression() is KtThisExpression -> evaluateThisExpression()
is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth) is KtSafeQualifiedExpression -> evaluateSafeAccessExpression(expr, scopeDepth)
is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth) is KtParenthesizedExpression -> evaluateExpression(expr.expression, scopeDepth)
null,
is PsiWhiteSpace -> null is PsiWhiteSpace -> null
is PsiElement -> evaluatePsiElement(expr, scopeDepth) is PsiElement -> evaluatePsiElement(expr, scopeDepth)
null -> null
else -> throw UnsupportedOperationException() else -> throw UnsupportedOperationException()
} }
} }
@@ -123,10 +121,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
variableManager["this"] variableManager["this"]
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? { fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr) as TypedCompileTimeConstant
val type = (receiveValue as TypedCompileTimeConstant).type val value = receiveValue.getValue(receiveValue.type) ?: return null
val value = receiveValue.getValue(type) ?: return null val variable = variableManager.receiveVariable(".str", LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0)
val variable = variableManager.receiveVariable(".str" + LLVMBuilder.UniqueGenerator.generateUniqueString(), LLVMStringType(value.toString().length, isLoaded = false), LLVMVariableScope(), pointer = 0)
codeBuilder.addStringConstant(variable, value.toString()) codeBuilder.addStringConstant(variable, value.toString())
return variable return variable
@@ -134,7 +131,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? { private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! 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) 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 loadedLeft = codeBuilder.receiveNativeValue(left)
val expectedType = LLVMMapStandardType(state.bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expr)!!, state) as LLVMReferenceType 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) val result = codeBuilder.getNewVariable(expectedType, pointer = 2)
codeBuilder.allocStaticVar(result, pointer = true) codeBuilder.allocStaticVar(result, pointer = true)
val condition = left.type.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType())) val condition = left.type.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType()))
val thenLabel = codeBuilder.getNewLabel(prefix = "safe.access") val nullLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val elseLabel = codeBuilder.getNewLabel(prefix = "safe.access") val notNullLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val endLabel = codeBuilder.getNewLabel(prefix = "safe.access") val endLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val conditionResult = codeBuilder.getNewVariable(condition.variableType) val conditionResult = codeBuilder.storeExpression(condition)
codeBuilder.addAssignment(conditionResult, condition) codeBuilder.addCondition(conditionResult, nullLabel, notNullLabel)
codeBuilder.addCondition(conditionResult, thenLabel, elseLabel)
codeBuilder.markWithLabel(thenLabel) codeBuilder.markWithLabel(nullLabel)
codeBuilder.storeNull(result) codeBuilder.storeNull(result)
codeBuilder.addUnconditionalJump(endLabel) codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel) codeBuilder.markWithLabel(notNullLabel)
val right = evaluateDotBody(receiver, selector!!, scopeDepth) as LLVMVariable val right = evaluateDotBody(receiver, selector!!, scopeDepth) as LLVMVariable
val rightLoaded = codeBuilder.loadAndGetVariable(right) val rightLoaded = codeBuilder.loadAndGetVariable(right)
codeBuilder.storeVariable(result, rightLoaded) codeBuilder.storeVariable(result, rightLoaded)
@@ -201,7 +193,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
when (referenceContext) { when (referenceContext) {
is PropertyDescriptorImpl -> { is PropertyDescriptorImpl -> {
val receiverThis = variableManager["this"]!! val receiverThis = variableManager["this"]!!
evaluateMemberMethodOrField(receiverThis, receiverName, topLevel, call = null)!! as LLVMVariable evaluateMemberMethodOrField(receiverThis, receiverName, topLevelScopeDepth, call = null)!! as LLVMVariable
} }
else -> variableManager[receiverName] 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? { private fun evaluateExtensionExpression(receiver: KtExpression, receiverExpressionArgument: LLVMVariable?, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver) val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)!!.type!!
val standardType = LLVMMapStandardType(receiverType!!.type!!, state) val receiverType = LLVMMapStandardType(kotlinType, state)
val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression) val targetFunction = state.bindingContext.get(BindingContext.CALL, selector.calleeExpression)
val candidateDescriptor = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)!!.candidateDescriptor val candidateDescriptor = state.bindingContext.get(BindingContext.RESOLVED_CALL, targetFunction)!!.candidateDescriptor
val targetFunctionName = candidateDescriptor.fqNameSafe.convertToNativeName() val targetFunctionName = candidateDescriptor.fqNameSafe.convertToNativeName()
val nameWithoutMangling = candidateDescriptor.name.asString().replace(Regex("""(.?)<init>"""), "") 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 packageNameSecond = candidateDescriptor.containingDeclaration.fqNameSafe.convertToNativeName()
val names = parseArgList(selector, scopeDepth) val names = parseArgList(selector, scopeDepth)
val type = LLVMType.mangleFunctionArguments(names) val type = LLVMType.mangleFunctionArguments(names)
val constructedFunctionName = standardType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type val constructedFunctionName = receiverType.mangle + nameWithoutMangling.addBeforeIfNotEmpty(".") + type
val targetExtension = state.extensionFunctions[standardType.toString()] val targetExtension = state.extensionFunctions[receiverType.toString()]
val extensionCodegen = targetExtension?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?: val extensionCodegen = targetExtension?.get(packageNameFirst.addAfterIfNotEmpty(".") + constructedFunctionName) ?:
targetExtension?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?: targetExtension?.get(packageNameSecond.addAfterIfNotEmpty(".") + constructedFunctionName) ?:
@@ -259,9 +251,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
?: throw UnexpectedException(constructedFunctionName) ?: throw UnexpectedException(constructedFunctionName)
val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!! val receiverExpression = receiverExpressionArgument ?: evaluateExpression(receiver, scopeDepth + 1)!!
val typeThisArgument = LLVMVariable("type", standardType, pointer = if (standardType is LLVMReferenceType) 1 else 0) val args = mutableListOf(codeBuilder.receivePointedArgument(receiverExpression, if (receiverType is LLVMReferenceType) 1 else 0))
val args = mutableListOf(codeBuilder.loadOneArgumentIfRequired(receiverExpression, typeThisArgument))
args.addAll(codeBuilder.loadArgsIfRequired(names, extensionCodegen.args)) args.addAll(codeBuilder.loadArgsIfRequired(names, extensionCodegen.args))
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), 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) { if (field != null) {
return evaluateClassField(receiver, field) return evaluateClassField(receiver, field)
} else { } 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 return result
} }
fun evaluateMemberMethod(receiver: LLVMVariable, selectorName: String, clazz: StructCodegen, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? { fun evaluateMemberMethod(receiver: LLVMVariable, clazz: StructCodegen, scopeDepth: Int, call: KtCallExpression): LLVMSingleValue? {
(call as? KtCallExpression) ?: throw UnexpectedException("$receiver:$selectorName") val resolvedCall = call.getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
val resolvedCall = (call as KtCallExpression).getCall(state.bindingContext)!!.getResolvedCallWithAssert(state.bindingContext)
val functionDescriptor = resolvedCall.candidateDescriptor val functionDescriptor = resolvedCall.candidateDescriptor
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) } val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
val methodName = functionDescriptor.fqNameSafe.asString() + LLVMType.mangleFunctionTypes(functionArguments) 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 returnType = method.returnType!!.type
val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values
val names = parseNamedValueArguments(arguments, method.defaultValues, scopeDepth) val substitutionArguments = parseArgumentsWithDefaultValues(arguments, method.defaultValues, scopeDepth)
val loadedArgs = codeBuilder.loadArgsIfRequired(names, method.args) val loadedArgs = codeBuilder.loadArgsIfRequired(substitutionArguments, method.args)
val callArgs = mutableListOf<LLVMSingleValue>(receiver) val callArgs = mutableListOf<LLVMSingleValue>(receiver)
callArgs.addAll(loadedArgs) 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 arrayActionType = if (callMaker.callType == Call.CallType.ARRAY_SET_METHOD) "set" else "get"
val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver val explicitReceiver = callMaker.explicitReceiver as ExpressionReceiver
val receiver = evaluateExpression(explicitReceiver.expression, scope)!! as LLVMVariable 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 targetClassName = (receiver.type as LLVMReferenceType).type
val names = parseValueArguments(callMaker.valueArguments, scope) val names = parseValueArguments(callMaker.valueArguments, scope)
val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}" val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}"
val type = receiver.type val clazz = resolveClassOrObjectLocation(receiver.type) ?: throw UnexpectedException(receiver.type.toString())
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text) val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text)
val returnType = clazz.methods[methodName]!!.returnType!!.type val returnType = clazz.methods[methodName]!!.returnType!!.type
@@ -388,21 +376,19 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return when { return when {
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1) expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope) isEnumClassField(expr, classScope) -> resolveEnumClassField(expr, classScope)
(targetName != null) && (variableManager[targetName] != null) -> variableManager[targetName] (targetName != null) && variableManager.contains(targetName) -> variableManager[targetName]
((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen!!) ((expr is KtNameReferenceExpression) && (classScope != null)) -> evaluateNameReferenceExpression(targetName!!, classScope.parentCodegen!! as ClassCodegen)
else -> { else -> {
val clazz = classScope ?: resolveCodegen(expr) val clazz = classScope ?: resolveCodegen(expr)
val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"] val receiver = if (clazz != null) variableManager[clazz.structName] ?: variableManager["this"] else variableManager["this"]
targetName ?: throw RuntimeException(expr.firstChild.text) targetName ?: throw UnexpectedException("Can't find target in reference expression " + expr.firstChild.text)
evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevel) evaluateMemberMethodOrField(receiver ?: throw UnexpectedException(targetName), targetName, topLevelScopeDepth)
} }
} }
} }
private fun evaluateNameReferenceExpression(fieldName: String, classScope: ClassCodegen): LLVMSingleValue? {
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen): LLVMSingleValue? { val companionObject = classScope.companionObjectCodegen!!
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
val companionObject = (classScope as ClassCodegen).companionObjectCodegen ?: throw UnexpectedException(expr.text)
val field = companionObject.fieldsIndex[fieldName] ?: return null val field = companionObject.fieldsIndex[fieldName] ?: return null
val receiver = variableManager[companionObject.structName]!! val receiver = variableManager[companionObject.structName]!!
val result = codeBuilder.getNewVariable(field.type, pointer = 1) 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? { private fun resolveCodegen(expr: KtExpression): StructCodegen? {
val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type val type = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)?.type
?: expr.getType(state.bindingContext)
?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext) ?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext)
val name = type?.constructor?.declarationDescriptor?.fqNameSafe?.asString() ?: throw UnexpectedException(expr.text) 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? = private fun resolveCodegenByName(name: String): StructCodegen? =
resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class")) resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class"))
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? { private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
var names = parseArgList(expr, scopeDepth) var names = parseArgList(expr, scopeDepth)
val targetFunction = state.bindingContext.get(BindingContext.CALL, expr.calleeExpression) 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 resolvedCall = resolvedCall.variableCall
} }
val targetFunctionName = resolvedCall!!.candidateDescriptor.fqNameSafe.convertToNativeName() val functionDescriptor = resolvedCall!!.candidateDescriptor
val functionDescriptor = expr.getFunctionResolvedCallWithAssert(state.bindingContext).candidateDescriptor val targetFunctionName = functionDescriptor.fqNameSafe.convertToNativeName()
val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values val arguments = resolvedCall.valueArguments.toSortedMap(compareBy { it.index }).values
val external = state.externalFunctions.containsKey(targetFunctionName) val external = state.externalFunctions.containsKey(targetFunctionName)
val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) } val functionArguments = functionDescriptor.valueParameters.map { it -> it.type }.map { LLVMMapStandardType(it, state) }
val function = "$targetFunctionName${if (!external) LLVMType.mangleFunctionTypes(functionArguments) else ""}" val function = "$targetFunctionName${if (!external) LLVMType.mangleFunctionTypes(functionArguments) else ""}"
if (function in state.functions || function in state.externalFunctions) {
if (state.functions.containsKey(function) || state.externalFunctions.containsKey(function)) { val descriptor = state.functions[function] ?: state.externalFunctions[function]!!
val descriptor = state.functions[function] ?: state.externalFunctions[function] ?: return null names = parseArgumentsWithDefaultValues(arguments, descriptor.defaultValues, scopeDepth)
names = parseNamedValueArguments(arguments, descriptor.defaultValues, scopeDepth)
val args = codeBuilder.loadArgsIfRequired(names, descriptor.args) val args = codeBuilder.loadArgsIfRequired(names, descriptor.args)
return evaluateFunctionCallExpression(LLVMVariable(function, descriptor.returnType!!.type, scope = LLVMVariableScope()), 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 descriptor = state.classes[targetFunctionName] ?: classScope ?: return null
val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments) val detectedConstructor = LLVMType.mangleFunctionTypes(functionArguments)
val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!) val args = codeBuilder.loadArgsIfRequired(names, descriptor.constructorFields[detectedConstructor]!!)
return evaluateConstructorCallExpression(LLVMVariable(descriptor.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args) return evaluateConstructorCallExpression(LLVMVariable(descriptor.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), args)
} }
val localFunction = variableManager[targetFunctionName] if (targetFunctionName in variableManager) {
if (localFunction != null) { val type = variableManager[targetFunctionName]!!.type as LLVMFunctionType
val type = localFunction.type as LLVMFunctionType
val args = codeBuilder.loadArgsIfRequired(names, type.arguments) val args = codeBuilder.loadArgsIfRequired(names, type.arguments)
return evaluateFunctionCallExpression(LLVMVariable(targetFunctionName, type.returnType.type, scope = LLVMRegisterScope()), args) 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) val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
if (nestedConstructor != null) { if (nestedConstructor != null) {
val args = codeBuilder.loadArgsIfRequired(names, nestedConstructor.constructorFields[nestedConstructor.primaryConstructorIndex]!!) 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) { if (caller != null) {
args.add(caller) args.add(caller)
} else if (variableManager[containingClass.structName] != null) { } else if (containingClass.structName in variableManager) {
args.add(variableManager[containingClass.structName]!!) args.add(variableManager[containingClass.structName]!!)
} else { } else {
args.add(variableManager["this"]!!) args.add(variableManager["this"]!!)
@@ -517,6 +484,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
when (returnType) { when (returnType) {
is LLVMVoidType -> { is LLVMVoidType -> {
codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), names).toString()) codeBuilder.addLLVMCodeToLocalPlace(LLVMCall(LLVMVoidType(), function.toString(), names).toString())
return null
} }
is LLVMReferenceType -> { is LLVMReferenceType -> {
val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2) val returnVar = codeBuilder.getNewVariable(returnType, pointer = 2)
@@ -542,8 +510,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return resultPtr return resultPtr
} }
} }
return null
} }
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? { 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 = fun parseOneValueArgument(arg: ValueArgument, scopeDepth: Int): LLVMSingleValue =
evaluateExpression(arg.getArgumentExpression(), scopeDepth) as 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 { args.mapIndexed(fun(i: Int, value: ResolvedValueArgument): LLVMSingleValue {
return when (value) { return when (value) {
is DefaultValueArgument -> evaluateExpression(defaultValues[i], scopeDepth)!! 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) val right = evaluateExpression(expr.right, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") ?: 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? { private fun evaluatePostfixExpression(expr: KtPostfixExpression, scopeDepth: Int): LLVMSingleValue? {
val operator = expr.operationToken val operator = expr.operationToken
val left = evaluateExpression(expr.baseExpression, scopeDepth) val left = evaluateExpression(expr.baseExpression, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression: ${expr.text}") ?: 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? { private fun evaluatePrefixExpression(expr: KtPrefixExpression, scopeDepth: Int): LLVMSingleValue? {
val operator = expr.operationToken val operator = expr.operationToken
val left = evaluateExpression(expr.baseExpression, scopeDepth) val left = evaluateExpression(expr.baseExpression, scopeDepth)
?: throw UnsupportedOperationException("Wrong binary expression") ?: throw UnsupportedOperationException("Wrong binary expression")
return executePrefixExpression(operator, expr.operationReference, left) return addPrimitivePrefixOperation(operator, left)
} }
private fun executePostfixExpression(operator: IElementType?, left: LLVMVariable): LLVMSingleValue? private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? =
= addPrimitivePostfixOperation(operator, left) 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? val llvmExpression = when (operator) {
= addPrimitivePrefixOperation(operator, operationReference, left) KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp)
KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp)
else -> throw IllegalAccessError()
}
private fun addPrimitivePostfixOperation(operator: IElementType?, firstOp: LLVMVariable): LLVMSingleValue? { val resultOp = codeBuilder.storeExpression(llvmExpression)
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) codeBuilder.storeVariable(firstOp, resultOp)
when (operator) {
KtTokens.PLUSPLUS, KtTokens.MINUSMINUS -> {
val oldValue = codeBuilder.getNewVariable(firstOp.type, firstOp.pointer)
codeBuilder.allocStackVar(oldValue, asValue = true)
codeBuilder.copyVariable(firstOp, oldValue)
val llvmExpression = when (operator) { oldValue
KtTokens.PLUSPLUS -> firstOp.type.operatorInc(firstNativeOp)
KtTokens.MINUSMINUS -> firstOp.type.operatorDec(firstNativeOp)
else -> throw IllegalAccessError()
} }
KtTokens.EXCLEXCL -> {
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) var result = firstOp
codeBuilder.addAssignment(resultOp, llvmExpression) val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
codeBuilder.storeVariable(firstOp, resultOp) val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck")
val nullCheck = codeBuilder.nullCheck(firstOp)
return oldValue codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel)
} codeBuilder.markWithLabel(nullLabel)
KtTokens.EXCLEXCL -> { codeBuilder.addExceptionCall("KotlinNullPointerException")
var result = firstOp codeBuilder.addUnconditionalJump(notNullLabel)
val nullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") codeBuilder.markWithLabel(notNullLabel)
val notNullLabel = codeBuilder.getNewLabel(prefix = "nullCheck") if (firstOp.type.isPrimitive) {
val nullCheck = codeBuilder.nullCheck(firstOp) result = codeBuilder.receivePointedArgument(firstOp, 0) as LLVMVariable
codeBuilder.addCondition(nullCheck, nullLabel, notNullLabel) }
codeBuilder.markWithLabel(nullLabel) result
codeBuilder.addExceptionCall("KotlinNullPointerException")
codeBuilder.addUnconditionalJump(notNullLabel)
codeBuilder.markWithLabel(notNullLabel)
if (firstOp.type.isPrimitive) {
result = codeBuilder.downLoadArgument(firstOp, 0) as LLVMVariable
} }
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) { when (operator) {
KtTokens.MINUS, KtTokens.MINUS,
KtTokens.PLUS -> { KtTokens.PLUS -> {
return addPrimitiveBinaryOperation(operator!!, operationReference, LLVMConstant("0", firstOp.type), firstOp) return addPrimitiveBinaryOperation(operator!!, LLVMConstant("0", firstOp.type), firstOp)
} }
KtTokens.EXCL -> { KtTokens.EXCL -> {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) val firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val llvmExpression = addPrimitiveReferenceOperationByName("xor", LLVMConstant("true", LLVMBooleanType()), firstNativeOp) val llvmExpression = addPrimitiveReferenceOperationByName("xor", LLVMConstant("true", LLVMBooleanType()), firstNativeOp)
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType) return codeBuilder.storeExpression(llvmExpression)
codeBuilder.addAssignment(resultOp, llvmExpression)
return resultOp
} }
else -> throw UnsupportedOperationException() 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 { 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") ?: throw UnsupportedOperationException("Wrong binary expression")
val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable) val lptr = codeBuilder.loadAndGetVariable(left as LLVMVariable)
val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType())) val condition = lptr.type.operatorEq(lptr, LLVMVariable("", LLVMNullType()))
val conditionResult = codeBuilder.getNewVariable(condition.variableType) val conditionResult = codeBuilder.storeExpression(condition)
codeBuilder.addAssignment(conditionResult, condition)
val thenLabel = codeBuilder.getNewLabel(prefix = "elvis") val notNull = codeBuilder.getNewLabel(prefix = "elvis")
val elseLabel = codeBuilder.getNewLabel(prefix = "elvis")
val endLabel = codeBuilder.getNewLabel(prefix = "elvis") val endLabel = codeBuilder.getNewLabel(prefix = "elvis")
codeBuilder.addCondition(conditionResult, elseLabel, thenLabel) codeBuilder.addCondition(conditionResult, notNull, endLabel)
codeBuilder.markWithLabel(thenLabel)
codeBuilder.addUnconditionalJump(endLabel)
codeBuilder.markWithLabel(elseLabel) codeBuilder.markWithLabel(notNull)
var right = evaluateExpression(expr.lastChild, scopeDepth + 1) var right = evaluateExpression(expr.right, scopeDepth + 1)
if (right != null) { if (right != null) {
right = codeBuilder.loadAndGetVariable(right as LLVMVariable) right = codeBuilder.loadAndGetVariable(right as LLVMVariable)
codeBuilder.storeVariable(left, right) codeBuilder.storeVariable(left, right)
@@ -717,9 +667,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return left 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 { fun addPrimitiveReferenceOperationByName(operator: String, firstOp: LLVMSingleValue, secondNativeOp: LLVMSingleValue): LLVMExpression {
val firstNativeOp = codeBuilder.receiveNativeValue(firstOp) 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)) "shr" -> firstNativeOp.type.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"ushr" -> firstNativeOp.type.operatorUshr(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}") 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}") 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}") 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}") 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 arguments = listOf(firstOp, secondNativeOp)
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type }) val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type })
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.structName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments) 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 firstNativeOp = codeBuilder.receiveNativeValue(firstOp)
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
@@ -817,18 +768,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.storeVariable(result, sourceArgument) codeBuilder.storeVariable(result, sourceArgument)
return result return result
} }
else -> addPrimitiveReferenceOperation(referenceName!!, firstOp, secondNativeOp) else -> addPrimitiveReferenceOperationByName(referenceName!!.getReferencedName(), firstOp, secondNativeOp)
} }
val resultOp = codeBuilder.getNewVariable(llvmExpression.variableType, pointer = llvmExpression.pointer) return codeBuilder.storeExpression(llvmExpression)
codeBuilder.addAssignment(resultOp, llvmExpression)
return resultOp
} }
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant { private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!! val expressionKotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType) val expressionValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)?.getValue(expressionKotlinType)
val type = LLVMMapStandardType(expressionKotlinType, state) 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? { 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 nextDescriptor = iteratorDescriptor!!.methods["$returnTypeName.next"] ?: throw UnexpectedException("$returnTypeName.nextInt")
val conditionIterator = evaluateFunctionCallExpression(LLVMVariable("$rangeTypeName.iterator", returnType, scope = LLVMVariableScope()), listOf(range))!! 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.addUnconditionalJump(conditionLabel)
codeBuilder.markWithLabel(conditionLabel) codeBuilder.markWithLabel(conditionLabel)
var conditionResult = evaluateFunctionCallExpression(LLVMVariable("$returnTypeName.hasNext", LLVMBooleanType(), scope = LLVMVariableScope()), listOf(iteratorThisArgument))!! 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.addCondition(conditionResult, bodyLabel, exitLabel)
codeBuilder.addUnconditionalJump(bodyLabel) codeBuilder.addUnconditionalJump(bodyLabel)
@@ -881,7 +830,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
variableManager.addVariable(loopParameterDescriptor, allocVar, scopeDepth + 1) variableManager.addVariable(loopParameterDescriptor, allocVar, scopeDepth + 1)
codeBuilder.allocStackVar(allocVar, pointer = true) 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) evaluateCodeBlock(expr.body, null, conditionLabel, exitLabel, scopeDepth + 1)
codeBuilder.markWithLabel(exitLabel) codeBuilder.markWithLabel(exitLabel)
@@ -899,8 +848,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.markWithLabel(nextLabel) codeBuilder.markWithLabel(nextLabel)
nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition") nextLabel = codeBuilder.getNewLabel(prefix = "when_condition_condition")
val currentConditionExpression = evaluateExpression(condition.firstChild, scopeDepth + 1)!! val currentConditionExpression = evaluateExpression((condition as KtWhenConditionWithExpression).expression, scopeDepth + 1)!!
val conditionResult = executeBinaryExpression(KtTokens.EQEQ, null, target, currentConditionExpression) val conditionResult = addPrimitiveBinaryOperation(KtTokens.EQEQ, target, currentConditionExpression)
codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel) codeBuilder.addCondition(conditionResult, successConditionsLabel, nextLabel)
} }
@@ -910,11 +859,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.markWithLabel(successConditionsLabel) codeBuilder.markWithLabel(successConditionsLabel)
var successExpression = evaluateExpression(item.expression, scopeDepth + 1) 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)) { if (successExpression != null && !LLVMType.nullOrVoidType(resultVariable.type)) {
successExpression = codeBuilder.receivePointedArgument(successExpression, 0)
codeBuilder.storeVariable(resultVariable, successExpression) 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.addUnconditionalJump(if (checkConditionBeforeExecute) conditionLabel else bodyLabel)
codeBuilder.markWithLabel(conditionLabel) codeBuilder.markWithLabel(conditionLabel)
var conditionResult = evaluateExpression(condition, scopeDepth + 1)!! var conditionResult = evaluateExpression(condition, scopeDepth + 1)!!
while (conditionResult.pointer > 0) { conditionResult = codeBuilder.receivePointedArgument(conditionResult, 0)
conditionResult = codeBuilder.loadAndGetVariable(conditionResult as LLVMVariable)
}
codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel) codeBuilder.addCondition(conditionResult, bodyLabel, exitLabel)
evaluateCodeBlock(bodyExpression, bodyLabel, conditionLabel, exitLabel, scopeDepth + 1) 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? { private fun evaluateIfOperator(element: KtIfExpression, scopeDepth: Int, isExpression: Boolean = true): LLVMVariable? {
val conditionResult = evaluateExpression(element.condition, scopeDepth)!! val conditionResult = evaluateExpression(element.condition, scopeDepth)!!
val conditionNativeResult = codeBuilder.downLoadArgument(conditionResult, 0) val conditionNativeResult = codeBuilder.receivePointedArgument(conditionResult, 0)
return if (isExpression) return if (isExpression)
executeIfExpression(conditionNativeResult, element.then!!, element.`else`, element, scopeDepth + 1) 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 assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth)
val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state) 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) val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer = expectedExpressionType.pointer + 1)
codeBuilder.allocStackVar(allocVar, pointer = true) codeBuilder.allocStackVar(allocVar, pointer = true)
@@ -1047,7 +992,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) { if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) {
throw UnexpectedException(element.text) throw UnexpectedException(element.text)
} }
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, assignExpression) addPrimitiveBinaryOperation(KtTokens.EQ, allocVar, assignExpression, null)
} }
return null return null
@@ -1068,15 +1013,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
} }
generateReferenceReturn(retVar) generateReferenceReturn(retVar)
} }
is LLVMVoidType -> { is LLVMVoidType -> codeBuilder.addAnyReturn(LLVMVoidType())
codeBuilder.addAnyReturn(LLVMVoidType())
}
else -> { else -> {
val retNativeValue = codeBuilder.receiveNativeValue(retVar!!) val retNativeValue = codeBuilder.receiveNativeValue(retVar!!)
codeBuilder.addReturnOperator(retNativeValue) codeBuilder.addReturnOperator(retNativeValue)
} }
} }
if (scopeDepth == topLevel + 2) { if (scopeDepth == topLevelScopeDepth + 2) {
wasReturnOnTopLevel = true wasReturnOnTopLevel = true
} }
return null return null
@@ -27,13 +27,13 @@ class ClassCodegen(state: TranslationState,
override val type: LLVMReferenceType override val type: LLVMReferenceType
init { 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) descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name)
annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS annotation = descriptor.kind == ClassKind.ANNOTATION_CLASS
enum = descriptor.kind == ClassKind.ENUM_CLASS enum = descriptor.kind == ClassKind.ENUM_CLASS
type.align = TranslationState.pointerAlign type.align = TranslationState.POINTER_ALIGN
} }
private fun indexFields(parameters: MutableList<KtParameter>) { private fun indexFields(parameters: MutableList<KtParameter>) {
@@ -53,8 +53,7 @@ class ClassCodegen(state: TranslationState,
indexFields(parameterList) indexFields(parameterList)
generateInnerFields(clazz.declarations) generateInnerFields(clazz.declarations)
calculateTypeSize() type.size = calculateTypeSize()
type.size = size
if (annotation) { if (annotation) {
return return
@@ -19,18 +19,17 @@ import java.util.*
class FunctionCodegen(state: TranslationState, class FunctionCodegen(state: TranslationState,
variableManager: VariableManager, variableManager: VariableManager,
val function: KtNamedFunction, val function: KtNamedFunction,
codeBuilder: LLVMBuilder, codeBuilder: LLVMBuilder) :
val parentCodegen: StructCodegen? = null) :
BlockCodegen(state, variableManager, codeBuilder) { BlockCodegen(state, variableManager, codeBuilder) {
var name: String var name: String
var args = LinkedList<LLVMVariable>() var args = LinkedList<LLVMVariable>()
val isExtensionDeclaration = function.isExtensionDeclaration() val isExtensionDeclaration = function.isExtensionDeclaration()
var functionNamePrefix = "" var functionNamePrefix = ""
val fullName: String
get() = functionNamePrefix + name
val external: Boolean val external: Boolean
val defaultValues: List<KtExpression?> val defaultValues: List<KtExpression?>
val fullName: String
get() = functionNamePrefix + name
init { init {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!! val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
@@ -58,9 +57,8 @@ class FunctionCodegen(state: TranslationState,
} }
defaultValues = mutableListOf() defaultValues = mutableListOf()
val valueParameters = descriptor.valueParameters for (index in descriptor.valueParameters.indices) {
for (index in valueParameters.indices) { val parameterDescriptor = descriptor.valueParameters[index]
val parameterDescriptor = valueParameters[index]
if (parameterDescriptor.declaresDefaultValue()) { if (parameterDescriptor.declaresDefaultValue()) {
val initializer = (parameterDescriptor.source as KotlinSourceElement).psi val initializer = (parameterDescriptor.source as KotlinSourceElement).psi
val defaultValue = (initializer as KtParameter).defaultValue val defaultValue = (initializer as KtParameter).defaultValue
@@ -69,21 +67,6 @@ class FunctionCodegen(state: TranslationState,
defaultValues.add(null) 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) { fun generate(this_type: LLVMVariable? = null) {
@@ -95,7 +78,7 @@ class FunctionCodegen(state: TranslationState,
codeBuilder.addStartExpression() codeBuilder.addStartExpression()
generateLoadArguments() generateLoadArguments()
evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevel, isBlock = function.hasBlockBody()) evaluateCodeBlock(function.bodyExpression, scopeDepth = topLevelScopeDepth, isBlock = function.hasBlockBody())
if (!wasReturnOnTopLevel) if (!wasReturnOnTopLevel)
codeBuilder.addAnyReturn(returnType!!.type) codeBuilder.addAnyReturn(returnType!!.type)
@@ -138,16 +121,16 @@ class FunctionCodegen(state: TranslationState,
private fun generateLoadArguments() { private fun generateLoadArguments() {
args.forEach(fun(it: LLVMVariable) { args.forEach(fun(it: LLVMVariable) {
if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && it.type.byRef)) { 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 return
} }
if (it.type !is LLVMReferenceType || it.type.byRef) { if (it.type !is LLVMReferenceType || it.type.byRef) {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer) val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer)
val allocVar = codeBuilder.loadArgument(loadVariable) val allocVar = codeBuilder.loadArgument(loadVariable)
variableManager.addVariable(it.label, allocVar, topLevel) variableManager.addVariable(it.label, allocVar, topLevelScopeDepth)
} else { } 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 override val type: LLVMReferenceType
init { 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()) primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
constructorFields.put(primaryConstructorIndex!!, arrayListOf()) constructorFields.put(primaryConstructorIndex!!, arrayListOf())
} }
override fun prepareForGenerate() { override fun prepareForGenerate() {
generateInnerFields(objectDeclaration.declarations) generateInnerFields(objectDeclaration.declarations)
calculateTypeSize() type.size = calculateTypeSize()
type.size = size type.align = TranslationState.POINTER_ALIGN
type.align = TranslationState.pointerAlign
super.prepareForGenerate() super.prepareForGenerate()
@@ -7,10 +7,12 @@ class ProjectTranslator(val files: List<KtFile>, val state: TranslationState) {
fun generateCode(): String { fun generateCode(): String {
codeBuilder.clean() codeBuilder.clean()
files.map { addClassDeclarations(it) } with(files) {
files.map { addObjectDeclarations(it) } map { addClassDeclarations(it) }
files.map { addFunctionDeclarations(it) } map { addObjectDeclarations(it) }
files.map { addPropertyDeclarations(it) } map { addFunctionDeclarations(it) }
map { addPropertyDeclarations(it) }
}
generateProjectBody() generateProjectBody()
return codeBuilder.toString() return codeBuilder.toString()
} }
@@ -33,20 +33,19 @@ abstract class StructCodegen(val state: TranslationState,
open fun prepareForGenerate() { open fun prepareForGenerate() {
generateStruct() generateStruct()
classOrObject.declarations.filter { it is KtNamedFunction }.map {
for (declaration in classOrObject.declarations.filter { it is KtNamedFunction }) { val function = FunctionCodegen(state, variableManager, it as KtNamedFunction, codeBuilder)
val function = FunctionCodegen(state, variableManager, declaration as KtNamedFunction, codeBuilder, this)
methods.put(function.name, function) methods.put(function.name, function)
} }
} }
fun calculateTypeSize() { fun calculateTypeSize(): Int {
val classAlignment = fields.map { it.type.align }.max()?.toInt() ?: 0 val classAlignment = fields.map { it.type.align }.max()?.toInt() ?: 0
var alignmentRemainder = 0 var alignmentRemainder = 0
size = 0 size = 0
for (item in fields) { 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) alignmentRemainder -= (alignmentRemainder % currentFieldSize)
if (alignmentRemainder < currentFieldSize) { if (alignmentRemainder < currentFieldSize) {
size += classAlignment size += classAlignment
@@ -55,6 +54,7 @@ abstract class StructCodegen(val state: TranslationState,
alignmentRemainder -= currentFieldSize alignmentRemainder -= currentFieldSize
} }
} }
return size
} }
open fun generate() { open fun generate() {
@@ -143,7 +143,7 @@ abstract class StructCodegen(val state: TranslationState,
variableManager.addVariable("this", mainConstructorThis, 0) variableManager.addVariable("this", mainConstructorThis, 0)
blockCodegen.evaluateCodeBlock(secondaryConstructor.bodyExpression, scopeDepth = 1) 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.addAnyReturn(LLVMVoidType())
codeBuilder.addEndExpression() codeBuilder.addEndExpression()
} }
@@ -170,11 +170,9 @@ abstract class StructCodegen(val state: TranslationState,
val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0) val thisVariable = LLVMVariable(thisField.label, thisField.type, thisField.label, LLVMRegisterScope(), pointer = 0)
codeBuilder.loadArgument(thisVariable, false) codeBuilder.loadArgument(thisVariable, false)
constructorFields[primaryConstructorIndex]!!.forEach { constructorFields[primaryConstructorIndex]!!.filter { it.type !is LLVMReferenceType }.forEach {
if (it.type !is LLVMReferenceType) { val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope())
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope()) codeBuilder.loadArgument(loadVariable)
codeBuilder.loadArgument(loadVariable)
}
} }
} }
@@ -187,7 +185,7 @@ abstract class StructCodegen(val state: TranslationState,
codeBuilder.storeVariable(classField, it) codeBuilder.storeVariable(classField, it)
} }
else -> { 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) 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.loadClassField(classField, LLVMVariable("classvariable.this.addr", type, scope = LLVMRegisterScope(), pointer = 1), (it as LLVMClassVariable).offset)
codeBuilder.storeVariable(classField, argument) codeBuilder.storeVariable(classField, argument)
@@ -200,9 +198,9 @@ abstract class StructCodegen(val state: TranslationState,
variableManager.addVariable("this", receiverThis, 2) variableManager.addVariable("this", receiverThis, 2)
for ((variable, initializer) in initializedFields) { for ((variable, initializer) in initializedFields) {
val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevel, call = null)!! val left = blockCodegen.evaluateMemberMethodOrField(receiverThis, variable.label, blockCodegen.topLevelScopeDepth, call = null)!!
val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevel)!! val right = blockCodegen.evaluateExpression(initializer, scopeDepth = blockCodegen.topLevelScopeDepth)!!
blockCodegen.executeBinaryExpression(KtTokens.EQ, referenceName = null, left = left, right = right) blockCodegen.addPrimitiveBinaryOperation(KtTokens.EQ, left, right)
} }
variableManager.pullOneUpwardLevelVariable("this") variableManager.pullOneUpwardLevelVariable("this")
@@ -220,15 +218,11 @@ abstract class StructCodegen(val state: TranslationState,
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType, offset: Int): LLVMClassVariable { protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType, offset: Int): LLVMClassVariable {
val annotations = parseFieldAnnotations(field) val annotations = parseFieldAnnotations(field)
val fieldName = state.bindingContext.get(BindingContext.VALUE_PARAMETER, field as?KtParameter)?.fqNameSafe?.convertToNativeName() 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) 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!!)) { if (state.classes.containsKey(field.name!!)) {
return LLVMClassVariable(result.label, state.classes[fieldName]!!.type, result.pointer) return LLVMClassVariable(result.label, state.classes[fieldName]!!.type, result.pointer)
} }
@@ -246,7 +240,7 @@ abstract class StructCodegen(val state: TranslationState,
protected fun genClassInitializers() = protected fun genClassInitializers() =
classOrObject.getAnonymousInitializers().map { classOrObject.getAnonymousInitializers().map {
object : BlockCodegen(state, variableManager, codeBuilder) { object : BlockCodegen(state, variableManager, codeBuilder) {
fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevel) fun generate() = evaluateCodeBlock(it.body, scopeDepth = topLevelScopeDepth)
} }
}.map { it.generate() } }.map { it.generate() }
@@ -27,13 +27,13 @@ import java.util.*
class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) { class TranslationState(val environment: KotlinCoreEnvironment, val bindingContext: BindingContext, val mainFunction: String, arm: Boolean) {
companion object { companion object {
var pointerAlign = 4 var POINTER_ALIGN = 4
var pointerSize = 4 var POINTER_SIZE = 4
} }
init { init {
pointerAlign = if (arm) 4 else 8 POINTER_ALIGN = if (arm) 4 else 8
pointerSize = if (arm) 4 else 8 POINTER_SIZE = if (arm) 4 else 8
} }
var externalFunctions = HashMap<String, FunctionCodegen>() var externalFunctions = HashMap<String, FunctionCodegen>()
@@ -8,12 +8,21 @@ import java.util.*
class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable>) { class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable>) {
private var fileVariableCollectionTree = HashMap<String, Stack<Pair<LLVMVariable, Int>>>() 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? { operator fun get(variableName: String): LLVMVariable? {
return fileVariableCollectionTree[variableName]?.peek()?.first ?: globalVariableCollection[variableName] 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) { fun pullOneUpwardLevelVariable(variableName: String) {
fileVariableCollectionTree[variableName]?.pop() 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 { fun receiveVariable(name: String, type: LLVMType, scope: LLVMScope, pointer: Int): LLVMVariable {
val ourVersion = variableVersion.getOrDefault(name, 0) + 1 return LLVMVariable("managed${generateUniqueString()}.$name", type, name, scope, pointer)
variableVersion.put(name, ourVersion)
return LLVMVariable("managed.$name.$ourVersion", type, name, scope, pointer)
} }
} }
@@ -2,6 +2,7 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.TranslationState import org.kotlinnative.translator.TranslationState
import org.kotlinnative.translator.llvm.types.* import org.kotlinnative.translator.llvm.types.*
import java.rmi.UnexpectedException
import java.util.* import java.util.*
class LLVMBuilder(val arm: Boolean = false) { class LLVMBuilder(val arm: Boolean = false) {
@@ -12,35 +13,11 @@ class LLVMBuilder(val arm: Boolean = false) {
private var labelCount = 0 private var labelCount = 0
var exceptions: Map<String, LLVMVariable> = mapOf() var exceptions: Map<String, LLVMVariable> = mapOf()
object UniqueGenerator {
private var unique = 0
fun generateUniqueString() =
".unique." + unique++
}
init { init {
initBuilder() 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 { fun getNewVariable(type: LLVMType, pointer: Int = 0, kotlinName: String? = null, scope: LLVMScope = LLVMRegisterScope(), prefix: String = "var"): LLVMVariable {
variableCount++ variableCount++
return LLVMVariable("$prefix$variableCount", type, kotlinName, scope, pointer) return LLVMVariable("$prefix$variableCount", type, kotlinName, scope, pointer)
@@ -54,58 +31,44 @@ class LLVMBuilder(val arm: Boolean = false) {
fun addLLVMCodeToLocalPlace(code: String) = fun addLLVMCodeToLocalPlace(code: String) =
localCode.appendln(code) localCode.appendln(code)
fun addLLVMCodeToGlobalPlace(code: String) = fun addLLVMCodeToGlobalPlace(code: String) =
globalCode.appendln(code) globalCode.appendln(code)
fun addStartExpression() = fun addStartExpression() =
addLLVMCodeToLocalPlace("{") addLLVMCodeToLocalPlace("{")
fun addEndExpression() = fun addEndExpression() =
addLLVMCodeToLocalPlace("}") addLLVMCodeToLocalPlace("}")
fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue = fun receiveNativeValue(firstOp: LLVMSingleValue): LLVMSingleValue =
when (firstOp) { when {
is LLVMConstant -> firstOp firstOp is LLVMConstant || firstOp.pointer == 0 -> firstOp
is LLVMVariable -> if (firstOp.pointer == 0) firstOp else loadAndGetVariable(firstOp) firstOp is LLVMVariable -> loadAndGetVariable(firstOp)
else -> throw UnsupportedOperationException() 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>) = fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue { names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
return loadOneArgumentIfRequired(value, args[i]) return receivePointedArgument(value, args[i].pointer)
}).toList() }).toList()
fun loadOneArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue { fun receivePointedArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue {
var result = value var result = value
while (argument.pointer < result.pointer) { while (result.pointer > pointer) {
result = loadVariable(result as LLVMVariable) result = receiveNativeValue(result)
} }
if ((value.type is LLVMStringType) && !(value.type.isLoaded)) { if ((value.type is LLVMStringType) && !(value.type.isLoaded)) {
val newVariable = getNewVariable(value.type, pointer = result.pointer + 1) val newVariable = getNewVariable(value.type, pointer = result.pointer + 1)
allocStackVar(newVariable, asValue = true) allocStackVar(newVariable, asValue = true)
copyVariable(result as LLVMVariable, newVariable) copyVariable(result as LLVMVariable, newVariable)
result = loadVariable(newVariable) result = loadAndGetVariable(newVariable)
} }
return result return result
} }
fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
loadOneArgumentIfRequired(value, LLVMVariable("", value.type, pointer = pointer))
fun clean() { fun clean() {
localCode = StringBuilder() localCode = StringBuilder()
globalCode = StringBuilder() globalCode = StringBuilder()
@@ -115,31 +78,20 @@ class LLVMBuilder(val arm: Boolean = false) {
fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) = fun addAssignment(lhs: LLVMVariable, rhs: LLVMNode) =
addLLVMCodeToLocalPlace("$lhs = $rhs") addLLVMCodeToLocalPlace("$lhs = $rhs")
fun addReturnOperator(llvmVariable: LLVMSingleValue) = fun addReturnOperator(llvmVariable: LLVMSingleValue) =
addLLVMCodeToLocalPlace("ret ${llvmVariable.type} $llvmVariable") addLLVMCodeToLocalPlace("ret ${llvmVariable.type} $llvmVariable")
fun addAnyReturn(type: LLVMType, value: String = type.defaultValue, pointer: Int = 0) = fun addAnyReturn(type: LLVMType, value: String = type.defaultValue, pointer: Int = 0) =
addLLVMCodeToLocalPlace("ret $type${"*".repeat(pointer)} $value") 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) = fun addStringConstant(variable: LLVMVariable, value: String) =
addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1") addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue {
fun convertVariableToType(variable: LLVMSingleValue, tarpointedType: LLVMType): LLVMSingleValue {
var resultVariable = variable var resultVariable = variable
if (variable.type != tarpointedType) { if (variable.type != targetType) {
val convertedExpression = tarpointedType.convertFrom(variable) val convertedExpression = targetType.convertFrom(variable)
resultVariable = getNewVariable(convertedExpression.variableType) resultVariable = storeExpression(convertedExpression)
addAssignment(resultVariable, convertedExpression)
} }
return resultVariable return resultVariable
} }
@@ -174,21 +126,18 @@ class LLVMBuilder(val arm: Boolean = false) {
} }
} }
fun storeExpression(expression: LLVMExpression): LLVMVariable {
fun storeExpression(target: LLVMSingleValue, expression: LLVMExpression): LLVMVariable { val resultOp = getNewVariable(expression.variableType, pointer = expression.pointer)
val resultOp = getNewVariable(expression.variableType)
addAssignment(resultOp, expression) addAssignment(resultOp, expression)
storeVariable(target, resultOp)
return resultOp return resultOp
} }
fun storeNull(result: LLVMVariable) = 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 { fun nullCheck(variable: LLVMVariable): LLVMVariable {
val result = getNewVariable(LLVMBooleanType(), pointer = 0) val result = getNewVariable(LLVMBooleanType(), pointer = 0)
val loaded = loadVariable(variable) val loaded = loadAndGetVariable(variable)
addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded") addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded")
return result return result
} }
@@ -199,20 +148,11 @@ class LLVMBuilder(val arm: Boolean = false) {
fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) = fun loadVariableOffset(target: LLVMVariable, source: LLVMVariable, index: LLVMConstant) =
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}") addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.type} $source, ${index.type} ${index.value}")
fun copyVariable(from: LLVMVariable, to: LLVMVariable) =
private fun copyVariableValue(target: LLVMVariable, source: LLVMVariable) { when {
var from = source from.type is LLVMStringType && !from.type.isLoaded -> storeString(to, from, 0)
if (source.pointer > 0) { else -> copyVariableValue(to, from)
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 loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable { fun loadArgument(llvmVariable: LLVMVariable, store: Boolean = true): LLVMVariable {
val allocVar = LLVMVariable("${llvmVariable.label}.addr", llvmVariable.type, llvmVariable.kotlinName, LLVMRegisterScope(), pointer = llvmVariable.pointer + 1) 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 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) { fun allocStackVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
val type = if (asValue) target.type.toString() else target.pointedType val type = if (asValue) target.type.toString() else target.pointedType
addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}") 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) { fun allocStaticVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
val allocated = getNewVariable(LLVMCharType(), pointer = 1) 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("$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 "*") 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) = fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) =
addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}") addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}")
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>) fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
= "{ ${args.mapIndexed { i: Int, variable: LLVMVariable -> "${variable.type} ${values[i]}" }.joinToString()} }" = "{ ${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) = fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) =
addLLVMCodeToLocalPlace("br ${condition.pointedType} $condition, label $thenLabel, label $elseLabel") addLLVMCodeToLocalPlace("br ${condition.pointedType} $condition, label $thenLabel, label $elseLabel")
fun addUnconditionalJump(label: LLVMLabel) = fun addUnconditionalJump(label: LLVMLabel) =
addLLVMCodeToLocalPlace("br label $label") addLLVMCodeToLocalPlace("br label $label")
fun createClass(name: String, fields: List<LLVMVariable>) = fun createClass(name: String, fields: List<LLVMVariable>) =
addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }") addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }")
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable { fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer) val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}") 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() 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) { class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) {
override fun toString(): String = override fun toString() = "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.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 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) 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, type: LLVMType,
pointer: Int = 0) : LLVMSingleValue(type, pointer) { pointer: Int = 0) : LLVMSingleValue(type, pointer) {
val value: String val value = type.parseArg(value)
init { override fun toString() = value
this.value = type.parseArg(value)
}
override fun toString(): String = 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() { 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() { 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 package org.kotlinnative.translator.llvm
open class LLVMScope abstract class LLVMScope
class LLVMVariableScope : LLVMScope() { class LLVMVariableScope : LLVMScope() {
override fun toString() = "@" override fun toString() = "@"
@@ -8,6 +8,6 @@ open class LLVMVariable(val label: String,
val scope: LLVMScope = LLVMRegisterScope(), val scope: LLVMScope = LLVMRegisterScope(),
pointer: Int = 0) : LLVMSingleValue(type, pointer) { 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 { fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable {
val typeName = type.toString().dropLastWhile { it == '?' } 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 { return when {
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1) type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark) typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark)
@@ -36,7 +36,7 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope
else -> { else -> {
val declarationDescriptor = type.constructor.declarationDescriptor!! val declarationDescriptor = type.constructor.declarationDescriptor!!
val refName = declarationDescriptor.fqNameSafe.asString() 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) LLVMVariable(name, refType, name, scope, pointer = 1)
} }
@@ -52,10 +52,5 @@ fun String.addBeforeIfNotEmpty(add: String): String =
fun String.addAfterIfNotEmpty(add: String): String = fun String.addAfterIfNotEmpty(add: String): String =
if (this.length > 0) this + add else this 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 = fun FqName.convertToNativeName(): String =
this.asString().replace(".<init>", "") this.asString().replace(".<init>", "")
@@ -13,43 +13,43 @@ class LLVMFloatType() : LLVMType() {
override val defaultValue = "0.0" override val defaultValue = "0.0"
override val isPrimitive = true 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") 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") 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") 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") LLVMExpression(LLVMFloatType(), "fdiv float $firstOp, $secondOp")
override fun operatorInc(firstOp: LLVMSingleValue): LLVMExpression = override fun operatorInc(firstOp: LLVMSingleValue) =
LLVMExpression(LLVMDoubleType(), "fadd float $firstOp, 1.0") 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") 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") 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") 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") 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") 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") 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") 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") LLVMExpression(LLVMFloatType(), "frem float $firstOp, $secondOp")
override fun equals(other: Any?) = override fun equals(other: Any?) =
@@ -19,7 +19,7 @@ class LLVMIntType() : LLVMType() {
is LLVMBooleanType, is LLVMBooleanType,
is LLVMByteType, is LLVMByteType,
is LLVMCharType, 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() else -> throw UnimplementedException()
} }
@@ -20,7 +20,7 @@ class LLVMLongType() : LLVMType() {
is LLVMByteType, is LLVMByteType,
is LLVMCharType, is LLVMCharType,
is LLVMShortType, 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() else -> throw UnimplementedException()
} }
@@ -6,12 +6,12 @@ class LLVMNullType(var baseType: LLVMType? = null) : LLVMType() {
override var size = 0 override var size = 0
override val defaultValue = "null" override val defaultValue = "null"
override val mangle = "" override val mangle = ""
override val typename = baseType?.typename ?: "" override val typename = baseType?.typename.orEmpty()
override fun parseArg(inputArg: String) = "null" 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 other is LLVMNullType
override fun hashCode() = override fun hashCode() =
@@ -8,8 +8,8 @@ import org.kotlinnative.translator.llvm.addAfterIfNotEmpty
class LLVMReferenceType(val type: String, class LLVMReferenceType(val type: String,
var prefix: String = "", var prefix: String = "",
override var align: Int = TranslationState.pointerAlign, override var align: Int = TranslationState.POINTER_ALIGN,
override var size: Int = TranslationState.pointerSize, override var size: Int = TranslationState.POINTER_SIZE,
var byRef: Boolean = true) : LLVMType() { var byRef: Boolean = true) : LLVMType() {
override val defaultValue: String = "null" override val defaultValue: String = "null"