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