translator: rewrite assignment for primitive nullable types

This commit is contained in:
Alexey Stepanov
2016-08-23 09:46:33 +03:00
parent c99d4e35df
commit a4e1416ad0
3 changed files with 41 additions and 27 deletions
@@ -849,8 +849,16 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return result
}
val result = firstOp as LLVMVariable
val sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp
val sourceArgument: LLVMSingleValue
if (secondOp.type!!.isPrimitive() && (secondOp.pointer == 0) && (firstOp.pointer == 2)) {
sourceArgument = codeBuilder.getNewVariable(secondOp.type!!, 1)
codeBuilder.allocStaticVar(sourceArgument, true)
codeBuilder.storeVariable(sourceArgument, secondOp)
} else {
sourceArgument = if (result.pointer == secondOp.pointer + 1) secondOp else secondNativeOp
}
codeBuilder.storeVariable(result, sourceArgument)
codeBuilder.addComment("end variable assignment")
return result
@@ -1036,26 +1044,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? {
val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!!
val identifier = variable.name.toString()
val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth)
val expectedExpressionType = LLVMMapStandardType(variable.type, state)
val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state)
val assignExpressionType = assignExpression?.type
val isPrimitive = LLVMMapStandardType(variable.type, state) !is LLVMReferred
val primitivePointer = LLVMMapStandardType(variable.type, state) !is LLVMReferred
when (assignExpression) {
null,
is LLVMVariable -> {
val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType, LLVMRegisterScope(), pointer =
if (isPrimitive) 0 else 1)
val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer =
expectedExpressionType.pointer)
codeBuilder.allocStackVar(allocVar)
allocVar.pointer++
allocVar.kotlinName = identifier
variableManager.addVariable(identifier, allocVar, scopeDepth)
if (assignExpression != null) {
if ((isPrimitive) && (assignExpression.type is LLVMReferenceType)) {
if ((primitivePointer) && (assignExpression.type is LLVMReferenceType)) {
throw UnexpectedException(element.text)
}
addPrimitiveBinaryOperation(KtTokens.EQ, null, allocVar, assignExpression)
@@ -76,8 +76,9 @@ class LLVMBuilder(val arm: Boolean = false) {
var result = value
while (argument.pointer < result.pointer) {
result = getNewVariable(argument.type, pointer = result.pointer - 1)
loadVariable(result, value as LLVMVariable)
val currentArgument = getNewVariable(result.type!!, pointer = result.pointer - 1)
loadVariable(currentArgument, result as LLVMVariable)
result = currentArgument
}
when (value.type) {
@@ -15,26 +15,30 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
"${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}"
}?.joinToString()}) #0"
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable = when {
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope)
type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope)
type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope)
type.toString() == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope)
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope)
type.toString() == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope)
type.toString() == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope)
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope)
type.toString() == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope)
type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1), prefix = "class"), name, scope, pointer = 1)
else -> {
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(type.toString(), align = state.pointerAlign, prefix = "class")
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
return when {
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark)
typeName == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope, pointerMark)
typeName == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope, pointerMark)
typeName == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope, pointerMark)
typeName == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope, pointerMark)
typeName == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope, pointerMark)
typeName == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope, pointerMark)
typeName == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope, pointerMark)
typeName == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope, pointerMark)
type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(typeName, prefix = "class"), name, scope, pointer = pointerMark)
else -> {
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(typeName, align = state.pointerAlign, prefix = "class")
val result = LLVMVariable(name, refType, name, scope, pointer = 1)
refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1))
result
val result = LLVMVariable(name, refType, name, scope, pointer = 1)
refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1))
result
}
}
}