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 return result
} }
val result = firstOp as LLVMVariable 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.storeVariable(result, sourceArgument)
codeBuilder.addComment("end variable assignment") codeBuilder.addComment("end variable assignment")
return result return result
@@ -1036,26 +1044,27 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
} }
private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? { private fun evaluateValExpression(element: KtProperty, scopeDepth: Int): LLVMVariable? {
val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!! val variable = state.bindingContext.get(BindingContext.VARIABLE, element)!!
val identifier = variable.name.toString() val identifier = variable.name.toString()
val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth) val assignExpression = evaluateExpression(element.delegateExpressionOrInitializer, scopeDepth)
val expectedExpressionType = LLVMMapStandardType(variable.type, state) val expectedExpressionType = LLVMInstanceOfStandardType("", variable.type, state = state)
val assignExpressionType = assignExpression?.type val assignExpressionType = assignExpression?.type
val isPrimitive = LLVMMapStandardType(variable.type, state) !is LLVMReferred val primitivePointer = LLVMMapStandardType(variable.type, state) !is LLVMReferred
when (assignExpression) { when (assignExpression) {
null, null,
is LLVMVariable -> { is LLVMVariable -> {
val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType, LLVMRegisterScope(), pointer = val allocVar = variableManager.receiveVariable(identifier, expectedExpressionType.type, LLVMRegisterScope(), pointer =
if (isPrimitive) 0 else 1) expectedExpressionType.pointer)
codeBuilder.allocStackVar(allocVar) codeBuilder.allocStackVar(allocVar)
allocVar.pointer++ allocVar.pointer++
allocVar.kotlinName = identifier allocVar.kotlinName = identifier
variableManager.addVariable(identifier, allocVar, scopeDepth) variableManager.addVariable(identifier, allocVar, scopeDepth)
if (assignExpression != null) { if (assignExpression != null) {
if ((isPrimitive) && (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, null, allocVar, assignExpression)
@@ -76,8 +76,9 @@ class LLVMBuilder(val arm: Boolean = false) {
var result = value var result = value
while (argument.pointer < result.pointer) { while (argument.pointer < result.pointer) {
result = getNewVariable(argument.type, pointer = result.pointer - 1) val currentArgument = getNewVariable(result.type!!, pointer = result.pointer - 1)
loadVariable(result, value as LLVMVariable) loadVariable(currentArgument, result as LLVMVariable)
result = currentArgument
} }
when (value.type) { 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}" "${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}"
}?.joinToString()}) #0" }?.joinToString()}) #0"
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable = when { fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable {
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1) val typeName = type.toString().dropLastWhile { it == '?' }
type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope) val pointerMark = if (type.toString().last() == '?') 1 else 0
type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope) return when {
type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope) type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type, state), name, scope, pointer = 1)
type.toString() == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope) typeName == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope, pointerMark)
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope) typeName == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope, pointerMark)
type.toString() == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope) typeName == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope, pointerMark)
type.toString() == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope) typeName == "Short" -> LLVMVariable(name, LLVMShortType(), name, scope, pointerMark)
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope) typeName == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope, pointerMark)
type.toString() == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope) typeName == "Long" -> LLVMVariable(name, LLVMLongType(), name, scope, pointerMark)
type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope) typeName == "Float" -> LLVMVariable(name, LLVMFloatType(), name, scope, pointerMark)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope) typeName == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope, pointerMark)
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1), prefix = "class"), name, scope, pointer = 1) typeName == "String" -> LLVMVariable(name, LLVMStringType(0), name, scope, pointerMark)
else -> { type.nameIfStandardType.toString() == "Nothing" -> LLVMVariable(name, LLVMNullType(), name, scope)
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(type.toString(), align = state.pointerAlign, prefix = "class") 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) val result = LLVMVariable(name, refType, name, scope, pointer = 1)
refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1)) refType.location.addAll(type.getSubtypesPredicate().toString().split(".").dropLast(1))
result result
}
} }
} }