translator: erase nullable type in LLVMSingleValue

This commit is contained in:
Alexey Stepanov
2016-08-30 16:10:43 +03:00
parent 6d5b505d11
commit c8d7f53e64
14 changed files with 83 additions and 88 deletions
@@ -47,7 +47,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
codeBuilder.addReturnOperator(result) codeBuilder.addReturnOperator(result)
} }
} }
else -> codeBuilder.addAnyReturn(result.type!!, result.toString()) else -> codeBuilder.addAnyReturn(result.type, result.toString())
} }
wasReturnOnTopLevel = true wasReturnOnTopLevel = true
@@ -155,7 +155,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val result = codeBuilder.getNewVariable(expectedType, pointer = 2) val result = codeBuilder.getNewVariable(expectedType, pointer = 2)
codeBuilder.allocStaticVar(result, pointer = true) codeBuilder.allocStaticVar(result, pointer = true)
val condition = left.type!!.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType())) val condition = left.type.operatorEq(loadedLeft, LLVMVariable("", LLVMNullType()))
val thenLabel = codeBuilder.getNewLabel(prefix = "safe.access") val thenLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val elseLabel = codeBuilder.getNewLabel(prefix = "safe.access") val elseLabel = codeBuilder.getNewLabel(prefix = "safe.access")
val endLabel = codeBuilder.getNewLabel(prefix = "safe.access") val endLabel = codeBuilder.getNewLabel(prefix = "safe.access")
@@ -351,7 +351,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val names = parseValueArguments(callMaker.valueArguments, scope) val names = parseValueArguments(callMaker.valueArguments, scope)
val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}" val methodName = "$targetClassName.$arrayActionType${LLVMType.mangleFunctionArguments(names)}"
val type = receiver.type as LLVMReferenceType val type = receiver.type
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString()) val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text) val method = clazz.methods[methodName] ?: throw UnexpectedException(expr.text)
@@ -720,36 +720,36 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
return when (operator) { return when (operator) {
"||", "||",
"or" -> firstNativeOp.type!!.operatorOr(firstNativeOp, secondNativeOp) "or" -> firstNativeOp.type.operatorOr(firstNativeOp, secondNativeOp)
"xor" -> firstNativeOp.type!!.operatorXor(firstNativeOp, secondNativeOp) "xor" -> firstNativeOp.type.operatorXor(firstNativeOp, secondNativeOp)
"&&", "&&",
"and" -> firstNativeOp.type!!.operatorAnd(firstNativeOp, secondNativeOp) "and" -> firstNativeOp.type.operatorAnd(firstNativeOp, secondNativeOp)
"%" -> firstNativeOp.type!!.operatorMod(firstNativeOp, secondNativeOp) "%" -> firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp)
"shl" -> firstNativeOp.type!!.operatorShl(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!)) "shl" -> firstNativeOp.type.operatorShl(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"shr" -> firstNativeOp.type!!.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!)) "shr" -> firstNativeOp.type.operatorShr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"ushr" -> firstNativeOp.type!!.operatorUshr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type!!)) "ushr" -> firstNativeOp.type.operatorUshr(firstNativeOp, codeBuilder.convertVariableToType(secondNativeOp, firstNativeOp.type))
"+=" -> { "+=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorPlus(firstNativeOp, secondNativeOp)) val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorPlus(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}") return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
} }
"-=" -> { "-=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorMinus(firstNativeOp, secondNativeOp)) val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMinus(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}") return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
} }
"*=" -> { "*=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorTimes(firstNativeOp, secondNativeOp)) val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorTimes(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}") return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
} }
"%=" -> { "%=" -> {
val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type!!.operatorMod(firstNativeOp, secondNativeOp)) val resultOp = codeBuilder.storeExpression(firstOp, firstNativeOp.type.operatorMod(firstNativeOp, secondNativeOp))
return LLVMExpression(resultOp.type, "load ${firstOp.getType()} $firstOp, align ${firstOp.type!!.align}") return LLVMExpression(resultOp.type, "load ${firstOp.pointedType} $firstOp, align ${firstOp.type.align}")
} }
".." -> { ".." -> {
val descriptor = state.classes["kotlin.ranges.IntRange"] val descriptor = state.classes["kotlin.ranges.IntRange"]
val arguments = listOf(firstOp, secondNativeOp) val arguments = listOf(firstOp, secondNativeOp)
val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type!! }) val detectedConstructor = LLVMType.mangleFunctionTypes(arguments.map { it.type })
val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments) val result = evaluateConstructorCallExpression(LLVMVariable(descriptor!!.fullName + detectedConstructor, descriptor.type, scope = LLVMVariableScope()), arguments)
return LLVMExpression(result!!.type!!, "load ${descriptor.type}** $result, align ${descriptor.type.align}", pointer = 1) return LLVMExpression(result!!.type, "load ${descriptor.type}** $result, align ${descriptor.type.align}", pointer = 1)
} }
else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})") else -> throw UnsupportedOperationException("Unknown binary operator: $operator(${firstNativeOp.type}, ${secondNativeOp.type})")
} }
@@ -760,38 +760,38 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val secondNativeOp = codeBuilder.receiveNativeValue(secondOp) val secondNativeOp = codeBuilder.receiveNativeValue(secondOp)
val llvmExpression = when (operator) { val llvmExpression = when (operator) {
KtTokens.PLUS -> firstOp.type!!.operatorPlus(firstNativeOp, secondNativeOp) KtTokens.PLUS -> firstOp.type.operatorPlus(firstNativeOp, secondNativeOp)
KtTokens.MINUS -> firstOp.type!!.operatorMinus(firstNativeOp, secondNativeOp) KtTokens.MINUS -> firstOp.type.operatorMinus(firstNativeOp, secondNativeOp)
KtTokens.MUL -> firstOp.type!!.operatorTimes(firstNativeOp, secondNativeOp) KtTokens.MUL -> firstOp.type.operatorTimes(firstNativeOp, secondNativeOp)
KtTokens.DIV -> firstOp.type!!.operatorDiv(firstNativeOp, secondNativeOp) KtTokens.DIV -> firstOp.type.operatorDiv(firstNativeOp, secondNativeOp)
KtTokens.LT -> firstOp.type!!.operatorLt(firstNativeOp, secondNativeOp) KtTokens.LT -> firstOp.type.operatorLt(firstNativeOp, secondNativeOp)
KtTokens.GT -> firstOp.type!!.operatorGt(firstNativeOp, secondNativeOp) KtTokens.GT -> firstOp.type.operatorGt(firstNativeOp, secondNativeOp)
KtTokens.LTEQ -> firstOp.type!!.operatorLeq(firstNativeOp, secondNativeOp) KtTokens.LTEQ -> firstOp.type.operatorLeq(firstNativeOp, secondNativeOp)
KtTokens.GTEQ -> firstOp.type!!.operatorGeq(firstNativeOp, secondNativeOp) KtTokens.GTEQ -> firstOp.type.operatorGeq(firstNativeOp, secondNativeOp)
KtTokens.EQEQ -> KtTokens.EQEQ ->
if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorEq(firstPointedArgument, secondPointedArgument) firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument)
} else } else
firstOp.type!!.operatorEq(firstNativeOp, secondNativeOp) firstOp.type.operatorEq(firstNativeOp, secondNativeOp)
KtTokens.EQEQEQ -> { KtTokens.EQEQEQ -> {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorEq(firstPointedArgument, secondPointedArgument) firstOp.type.operatorEq(firstPointedArgument, secondPointedArgument)
} }
KtTokens.EXCLEQ -> { KtTokens.EXCLEQ -> {
if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) { if (LLVMType.isReferredType(firstOp.type) && LLVMType.isReferredType(secondOp.type)) {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorNeq(firstPointedArgument, secondPointedArgument) firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument)
} else } else
firstOp.type!!.operatorNeq(firstNativeOp, secondNativeOp) firstOp.type.operatorNeq(firstNativeOp, secondNativeOp)
} }
KtTokens.EXCLEQEQEQ -> { KtTokens.EXCLEQEQEQ -> {
val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1) val firstPointedArgument = codeBuilder.receivePointedArgument(firstOp, 1)
val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1) val secondPointedArgument = codeBuilder.receivePointedArgument(secondOp, 1)
firstOp.type!!.operatorNeq(firstPointedArgument, secondPointedArgument) firstOp.type.operatorNeq(firstPointedArgument, secondPointedArgument)
} }
KtTokens.EQ -> { KtTokens.EQ -> {
if (secondOp.type is LLVMNullType) { if (secondOp.type is LLVMNullType) {
@@ -801,8 +801,8 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
val result = firstOp as LLVMVariable val result = firstOp as LLVMVariable
val sourceArgument: LLVMSingleValue val sourceArgument: LLVMSingleValue
if ((firstOp.pointer == 2) && secondOp.type!!.isPrimitive && (secondOp.pointer == 0)) { if ((firstOp.pointer == 2) && secondOp.type.isPrimitive && (secondOp.pointer == 0)) {
sourceArgument = codeBuilder.getNewVariable(secondOp.type!!, 1) sourceArgument = codeBuilder.getNewVariable(secondOp.type, 1)
codeBuilder.allocStaticVar(sourceArgument, asValue = true) codeBuilder.allocStaticVar(sourceArgument, asValue = true)
codeBuilder.storeVariable(sourceArgument, secondOp) codeBuilder.storeVariable(sourceArgument, secondOp)
} else { } else {
@@ -137,12 +137,12 @@ class FunctionCodegen(state: TranslationState,
private fun generateLoadArguments() { private fun generateLoadArguments() {
args.forEach(fun(it: LLVMVariable) { args.forEach(fun(it: LLVMVariable) {
if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && (it.type as LLVMReferenceType).byRef)) { if (it.type is LLVMFunctionType || (it.type is LLVMReferenceType && it.type.byRef)) {
variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevel) variableManager.addVariable(it.label, LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = 1), topLevel)
return return
} }
if (it.type !is LLVMReferenceType || (it.type as LLVMReferenceType).byRef) { if (it.type !is LLVMReferenceType || it.type.byRef) {
val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer) val loadVariable = LLVMVariable(it.label, it.type, it.label, LLVMRegisterScope(), pointer = it.pointer)
val allocVar = codeBuilder.loadArgument(loadVariable) val allocVar = codeBuilder.loadArgument(loadVariable)
variableManager.addVariable(it.label, allocVar, topLevel) variableManager.addVariable(it.label, allocVar, topLevel)
@@ -243,7 +243,7 @@ abstract class StructCodegen(val state: TranslationState,
val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state) val result = LLVMInstanceOfStandardType(fieldName, ktType, LLVMRegisterScope(), state = state)
if (result.type is LLVMReferenceType) { if (result.type is LLVMReferenceType) {
val type = result.type as LLVMReferenceType val type = result.type
type.prefix = "class" type.prefix = "class"
type.byRef = true type.byRef = true
} }
@@ -93,8 +93,8 @@ class LLVMBuilder(val arm: Boolean = false) {
result = loadVariable(result as LLVMVariable) result = loadVariable(result as LLVMVariable)
} }
if ((value.type is LLVMStringType) && (!(value.type as LLVMStringType).isLoaded)) { if ((value.type is LLVMStringType) && !(value.type.isLoaded)) {
val newVariable = getNewVariable(value.type!!, pointer = result.pointer + 1) val newVariable = getNewVariable(value.type, pointer = result.pointer + 1)
allocStackVar(newVariable, asValue = true) allocStackVar(newVariable, asValue = true)
copyVariable(result as LLVMVariable, newVariable) copyVariable(result as LLVMVariable, newVariable)
result = loadVariable(newVariable) result = loadVariable(newVariable)
@@ -104,7 +104,7 @@ class LLVMBuilder(val arm: Boolean = false) {
} }
fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue = fun downLoadArgument(value: LLVMSingleValue, pointer: Int): LLVMSingleValue =
loadOneArgumentIfRequired(value, LLVMVariable("", value.type!!, pointer = pointer)) loadOneArgumentIfRequired(value, LLVMVariable("", value.type, pointer = pointer))
fun clean() { fun clean() {
localCode = StringBuilder() localCode = StringBuilder()
@@ -134,10 +134,10 @@ class LLVMBuilder(val arm: Boolean = false) {
addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1") addLLVMCodeToGlobalPlace("$variable = private unnamed_addr constant ${(variable.type as LLVMStringType).fullArrayType} c\"${value.replace("\"", "\\\"")}\\00\", align 1")
fun convertVariableToType(variable: LLVMSingleValue, targetType: LLVMType): LLVMSingleValue { fun convertVariableToType(variable: LLVMSingleValue, tarpointedType: LLVMType): LLVMSingleValue {
var resultVariable = variable var resultVariable = variable
if (variable.type != targetType) { if (variable.type != tarpointedType) {
val convertedExpression = targetType.convertFrom(variable) val convertedExpression = tarpointedType.convertFrom(variable)
resultVariable = getNewVariable(convertedExpression.variableType) resultVariable = getNewVariable(convertedExpression.variableType)
addAssignment(resultVariable, convertedExpression) addAssignment(resultVariable, convertedExpression)
} }
@@ -146,20 +146,20 @@ class LLVMBuilder(val arm: Boolean = false) {
fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) { fun addGlobalInitialize(target: LLVMVariable, fields: ArrayList<LLVMVariable>, initializers: Map<LLVMVariable, String>, classType: LLVMType) {
val code = "$target = internal global $classType { ${ val code = "$target = internal global $classType { ${
fields.map { it.getType() + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString() fields.map { it.pointedType + " " + if (initializers.containsKey(it)) initializers[it] else "0" }.joinToString()
} }, align ${classType.align}" } }, align ${classType.align}"
globalCode.appendln(code) globalCode.appendln(code)
} }
fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) { fun storeString(target: LLVMVariable, source: LLVMVariable, offset: Int) {
val code = "store ${target.type} getelementptr inbounds (" + val code = "store ${target.type} getelementptr inbounds (" +
"${(source.type as LLVMStringType).fullArrayType}* $source, i32 0, i32 $offset), ${target.getType()} $target, align ${source.type.align}" "${(source.type as LLVMStringType).fullArrayType}* $source, i32 0, i32 $offset), ${target.pointedType} $target, align ${source.type.align}"
(target.type as LLVMStringType).isLoaded = true (target.type as LLVMStringType).isLoaded = true
localCode.appendln(code) localCode.appendln(code)
} }
fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) = fun loadClassField(target: LLVMVariable, source: LLVMVariable, offset: Int) =
addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.getType()} $source, i32 0, i32 $offset") addLLVMCodeToLocalPlace("$target = getelementptr inbounds ${source.pointedType} $source, i32 0, i32 $offset")
fun markWithLabel(label: LLVMLabel?) { fun markWithLabel(label: LLVMLabel?) {
if (label != null) if (label != null)
@@ -167,10 +167,10 @@ class LLVMBuilder(val arm: Boolean = false) {
} }
fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) { fun storeVariable(target: LLVMSingleValue, source: LLVMSingleValue) {
if ((source.type is LLVMStringType) && (!(source.type as LLVMStringType).isLoaded)) { if ((source.type is LLVMStringType) && !(source.type.isLoaded)) {
storeString(target as LLVMVariable, source as LLVMVariable, 0) storeString(target as LLVMVariable, source as LLVMVariable, 0)
} else { } else {
addLLVMCodeToLocalPlace("store ${source.getType()} $source, ${target.getType()} $target, align ${source.type?.align!!}") addLLVMCodeToLocalPlace("store ${source.pointedType} $source, ${target.pointedType} $target, align ${source.type.align}")
} }
} }
@@ -183,13 +183,13 @@ class LLVMBuilder(val arm: Boolean = false) {
} }
fun storeNull(result: LLVMVariable) = fun storeNull(result: LLVMVariable) =
addLLVMCodeToLocalPlace("store ${result.getType().dropLast(1)} null, ${result.getType()} $result, align ${TranslationState.pointerAlign}") addLLVMCodeToLocalPlace("store ${result.pointedType.dropLast(1)} null, ${result.pointedType} $result, align ${TranslationState.pointerAlign}")
fun nullCheck(variable: LLVMVariable): LLVMVariable { fun nullCheck(variable: LLVMVariable): LLVMVariable {
val result = getNewVariable(LLVMBooleanType(), pointer = 0) val result = getNewVariable(LLVMBooleanType(), pointer = 0)
val loaded = loadVariable(variable) val loaded = loadVariable(variable)
addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.getType()} null, $loaded") addLLVMCodeToLocalPlace("$result = icmp eq ${loaded.pointedType} null, $loaded")
return result return result
} }
@@ -204,13 +204,13 @@ class LLVMBuilder(val arm: Boolean = false) {
var from = source var from = source
if (source.pointer > 0) { if (source.pointer > 0) {
from = getNewVariable(source.type, source.pointer) from = getNewVariable(source.type, source.pointer)
addLLVMCodeToLocalPlace("$from = load ${source.getType()} $source, align ${from.type.align}") addLLVMCodeToLocalPlace("$from = load ${source.pointedType} $source, align ${from.type.align}")
} }
addLLVMCodeToLocalPlace("store ${target.type} $from, ${target.getType()} $target, 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) { fun copyVariable(from: LLVMVariable, to: LLVMVariable) = when (from.type) {
is LLVMStringType -> if ((from.type as LLVMStringType).isLoaded) copyVariableValue(to, from) else storeString(to, from, 0) is LLVMStringType -> if (from.type.isLoaded) copyVariableValue(to, from) else storeString(to, from, 0)
else -> copyVariableValue(to, from) else -> copyVariableValue(to, from)
} }
@@ -222,12 +222,12 @@ class LLVMBuilder(val arm: Boolean = false) {
fun loadVariable(source: LLVMVariable): LLVMVariable { fun loadVariable(source: LLVMVariable): LLVMVariable {
val target = getNewVariable(source.type, pointer = source.pointer - 1) val target = getNewVariable(source.type, pointer = source.pointer - 1)
addLLVMCodeToLocalPlace("$target = load ${source.getType()} $source, align ${target.type.align}") addLLVMCodeToLocalPlace("$target = load ${source.pointedType} $source, align ${target.type.align}")
return target return target
} }
fun allocStackVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) { fun allocStackVar(target: LLVMVariable, asValue: Boolean = false, pointer: Boolean = false) {
val type = if (asValue) target.type.toString() else target.getType() val type = if (asValue) target.type.toString() else target.pointedType
addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}") addLLVMCodeToLocalPlace("$target = alloca ${if (pointer) type.removeSuffix("*") else type}, align ${target.type.align}")
} }
@@ -237,19 +237,19 @@ class LLVMBuilder(val arm: Boolean = false) {
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.pointerSize else target.type.size
addLLVMCodeToLocalPlace("$allocated = call i8* @malloc_heap(i32 $size)") addLLVMCodeToLocalPlace("$allocated = call i8* @malloc_heap(i32 $size)")
addLLVMCodeToLocalPlace("$target = bitcast ${allocated.getType()} $allocated to ${if (asValue) target.type.toString() else target.getType()}" + if (pointer) "" else "*") addLLVMCodeToLocalPlace("$target = bitcast ${allocated.pointedType} $allocated to ${if (asValue) target.type.toString() else target.pointedType}" + if (pointer) "" else "*")
} }
fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) { fun addVariableByRef(targetVariable: LLVMVariable, sourceVariable: LLVMVariable, store: Boolean) {
addLLVMCodeToLocalPlace("$targetVariable = alloca ${sourceVariable.getType()}, align ${sourceVariable.type.align}") addLLVMCodeToLocalPlace("$targetVariable = alloca ${sourceVariable.pointedType}, align ${sourceVariable.type.align}")
if (store) { if (store) {
addLLVMCodeToLocalPlace("store ${sourceVariable.getType()} $sourceVariable, ${targetVariable.getType()} $targetVariable, align ${targetVariable.type.align}") addLLVMCodeToLocalPlace("store ${sourceVariable.pointedType} $sourceVariable, ${targetVariable.pointedType} $targetVariable, align ${targetVariable.type.align}")
} }
} }
fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) = fun defineGlobalVariable(variable: LLVMVariable, defaultValue: String = variable.type.defaultValue) =
addLLVMCodeToLocalPlace("$variable = global ${variable.getType()} $defaultValue, align ${variable.type.align}") addLLVMCodeToLocalPlace("$variable = global ${variable.pointedType} $defaultValue, align ${variable.type.align}")
fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>) fun makeStructInitializer(args: List<LLVMVariable>, values: List<String>)
@@ -258,12 +258,12 @@ class LLVMBuilder(val arm: Boolean = false) {
fun loadAndGetVariable(source: LLVMVariable): LLVMVariable { fun loadAndGetVariable(source: LLVMVariable): LLVMVariable {
assert(source.pointer > 0) assert(source.pointer > 0)
val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName) val target = getNewVariable(source.type, source.pointer - 1, source.kotlinName)
addLLVMCodeToLocalPlace("$target = load ${source.getType()} $source, align ${target.type.align}") addLLVMCodeToLocalPlace("$target = load ${source.pointedType} $source, align ${target.type.align}")
return target return target
} }
fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) = fun addCondition(condition: LLVMSingleValue, thenLabel: LLVMLabel, elseLabel: LLVMLabel) =
addLLVMCodeToLocalPlace("br ${condition.getType()} $condition, label $thenLabel, label $elseLabel") addLLVMCodeToLocalPlace("br ${condition.pointedType} $condition, label $thenLabel, label $elseLabel")
fun addUnconditionalJump(label: LLVMLabel) = fun addUnconditionalJump(label: LLVMLabel) =
@@ -271,12 +271,12 @@ class LLVMBuilder(val arm: Boolean = false) {
fun createClass(name: String, fields: List<LLVMVariable>) = fun createClass(name: String, fields: List<LLVMVariable>) =
addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.getType() }.joinToString()} }") addLLVMCodeToGlobalPlace("%class.$name = type { ${fields.map { it.pointedType }.joinToString()} }")
fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable { fun bitcast(src: LLVMVariable, llvmType: LLVMVariable): LLVMVariable {
val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer) val empty = getNewVariable(llvmType.type, pointer = llvmType.pointer)
addLLVMCodeToLocalPlace("$empty = bitcast ${src.getType()} $src to ${llvmType.getType()}") addLLVMCodeToLocalPlace("$empty = bitcast ${src.pointedType} $src to ${llvmType.pointedType}")
return empty return empty
} }
@@ -5,5 +5,5 @@ import org.kotlinnative.translator.llvm.types.LLVMType
class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) { class LLVMCall(val returnType: LLVMType, val name: String, val arguments: Collection<LLVMSingleValue>) : LLVMSingleValue(returnType) {
override fun toString(): String = override fun toString(): String =
"call $returnType $name(${arguments.joinToString { "${it.getType()} ${it.toString()}" }})" "call $returnType $name(${arguments.joinToString { "${it.pointedType} ${it.toString()}" }})"
} }
@@ -3,16 +3,15 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMConstant(value: String, open class LLVMConstant(value: String,
type: LLVMType? = null, type: LLVMType,
pointer: Int = 0) : LLVMSingleValue(type, pointer) { pointer: Int = 0) : LLVMSingleValue(type, pointer) {
val value: String val value: String
init { init {
this.value = type?.parseArg(value) ?: value this.value = type.parseArg(value)
} }
override fun getType(): String = type.toString() + "*".repeat(pointer)
override fun toString(): String = value override fun toString(): String = value
} }
@@ -1,10 +1,10 @@
package org.kotlinnative.translator.llvm package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.exceptions.UnimplementedException
import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMSingleValue(open val type: LLVMType? = null, open var pointer: Int = 0) : LLVMNode() { open class LLVMSingleValue(val type: LLVMType, var pointer: Int = 0) : LLVMNode() {
open fun getType(): String = throw UnimplementedException() open val pointedType: String
get() = type.toString() + "*".repeat(pointer)
} }
@@ -3,13 +3,11 @@ package org.kotlinnative.translator.llvm
import org.kotlinnative.translator.llvm.types.LLVMType import org.kotlinnative.translator.llvm.types.LLVMType
open class LLVMVariable(val label: String, open class LLVMVariable(val label: String,
override val type: LLVMType, type: LLVMType,
var kotlinName: String? = null, var kotlinName: String? = null,
val scope: LLVMScope = LLVMRegisterScope(), val scope: LLVMScope = LLVMRegisterScope(),
pointer: Int = 0) : LLVMSingleValue(type, pointer) { pointer: Int = 0) : LLVMSingleValue(type, pointer) {
override fun getType(): String = type.toString() + "*".repeat(pointer)
override fun toString(): String = "$scope$label" override fun toString(): String = "$scope$label"
} }
@@ -1,7 +1,6 @@
package org.kotlinnative.translator.llvm package org.kotlinnative.translator.llvm
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate
import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -14,7 +13,7 @@ import org.kotlinnative.translator.llvm.types.*
fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false) = fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnType: LLVMType, declare: Boolean = false) =
"${if (declare) "declare" else "define weak"} $returnType @$name(${ "${if (declare) "declare" else "define weak"} $returnType @$name(${
argTypes?.mapIndexed { i: Int, s: LLVMVariable -> argTypes?.mapIndexed { i: Int, s: LLVMVariable ->
"${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}" "${s.pointedType} ${if (s.type is LLVMReferenceType && !s.type.byRef) "byval" else ""} %${s.label}"
}?.joinToString()}) #0" }?.joinToString()}) #0"
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable { fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope(), state: TranslationState): LLVMVariable {
@@ -58,6 +57,5 @@ fun String.indexOfOrLast(str: Char, startIndex: Int = 0): Int {
return if (pos < 0) this.length else pos return if (pos < 0) this.length else pos
} }
fun FqName.convertToNativeName(): String = fun FqName.convertToNativeName(): String =
this.asString().replace(".<init>", "") this.asString().replace(".<init>", "")
@@ -26,7 +26,7 @@ class LLVMFunctionType(type: KotlinType, state: TranslationState) : LLVMType() {
fun mangleArgs() = LLVMType.mangleFunctionArguments(arguments) fun mangleArgs() = LLVMType.mangleFunctionArguments(arguments)
override fun toString() = override fun toString() =
"${returnType.type} (${arguments.map { it.getType() }.joinToString()})" "${returnType.type} (${arguments.map { it.pointedType }.joinToString()})"
override fun equals(other: Any?) = override fun equals(other: Any?) =
(other is LLVMFunctionType) && (mangle == other.mangle) (other is LLVMFunctionType) && (mangle == other.mangle)
@@ -15,7 +15,7 @@ class LLVMIntType() : LLVMType() {
override val isPrimitive = true override val isPrimitive = true
override fun convertFrom(source: LLVMSingleValue) = override fun convertFrom(source: LLVMSingleValue) =
when (source.type!!) { when (source.type) {
is LLVMBooleanType, is LLVMBooleanType,
is LLVMByteType, is LLVMByteType,
is LLVMCharType, is LLVMCharType,
@@ -15,7 +15,7 @@ class LLVMLongType() : LLVMType() {
override val isPrimitive = true override val isPrimitive = true
override fun convertFrom(source: LLVMSingleValue) = override fun convertFrom(source: LLVMSingleValue) =
when (source.type!!) { when (source.type) {
is LLVMBooleanType, is LLVMBooleanType,
is LLVMByteType, is LLVMByteType,
is LLVMCharType, is LLVMCharType,
@@ -4,7 +4,7 @@ import org.kotlinnative.translator.TranslationState
import org.kotlinnative.translator.llvm.LLVMExpression import org.kotlinnative.translator.llvm.LLVMExpression
import org.kotlinnative.translator.llvm.LLVMSingleValue import org.kotlinnative.translator.llvm.LLVMSingleValue
import org.kotlinnative.translator.llvm.addAfterIfNotEmpty import org.kotlinnative.translator.llvm.addAfterIfNotEmpty
import java.util.*
class LLVMReferenceType(val type: String, class LLVMReferenceType(val type: String,
var prefix: String = "", var prefix: String = "",
@@ -19,10 +19,10 @@ class LLVMReferenceType(val type: String,
override fun toString() = "%$typename" override fun toString() = "%$typename"
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}") LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.pointedType} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) = override fun operatorNeq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "icmp ne ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}") LLVMExpression(LLVMBooleanType(), "icmp ne ${firstOp.pointedType} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
override fun equals(other: Any?) = override fun equals(other: Any?) =
(other is LLVMReferenceType) and (typename.equals((other as LLVMReferenceType).typename)) (other is LLVMReferenceType) and (typename.equals((other as LLVMReferenceType).typename))
@@ -8,7 +8,7 @@ abstract class LLVMType() : Cloneable {
companion object { companion object {
fun mangleFunctionArguments(names: List<LLVMSingleValue>) = fun mangleFunctionArguments(names: List<LLVMSingleValue>) =
mangleFunctionTypes(names.map { it.type!! }) mangleFunctionTypes(names.map { it.type })
fun mangleFunctionTypes(names: List<LLVMType>) = fun mangleFunctionTypes(names: List<LLVMType>) =
if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.mangle })}" else "" if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.mangle })}" else ""