translator: nullable tests, fix null reassignment, fix reference assignment

This commit is contained in:
e5l
2016-07-20 10:54:18 +03:00
parent e190c2a377
commit a8d2798e58
14 changed files with 58 additions and 40 deletions
+25 -14
View File
@@ -1,29 +1,40 @@
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
declare i8* @malloc(i32)
%class.MyClass = type { i32 }
define void @MyClass(%class.MyClass* %classvariable.this, i32 %i)
%class.MyAwesomeClass = type { i32 }
define void @MyAwesomeClass(%class.MyAwesomeClass* %classvariable.this, i32 %i)
{
%classvariable.this.addr = alloca %class.MyClass, align 4
%classvariable.this.addr = alloca %class.MyAwesomeClass, align 4
%i.addr = alloca i32, align 4
store i32 %i, i32* %i.addr, align 4
%var1 = load i32* %i.addr, align 4
%var2 = getelementptr inbounds %class.MyClass* %classvariable.this.addr, i32 0, i32 0
%var2 = getelementptr inbounds %class.MyAwesomeClass* %classvariable.this.addr, i32 0, i32 0
store i32 %var1, i32* %var2, align 4
%var3 = bitcast %class.MyClass* %classvariable.this to i8*
%var4 = bitcast %class.MyClass* %classvariable.this.addr to i8*
%var3 = bitcast %class.MyAwesomeClass* %classvariable.this to i8*
%var4 = bitcast %class.MyAwesomeClass* %classvariable.this.addr to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %var3, i8* %var4, i64 4, i32 4, i1 false)
ret void
}
define i32 @nullable_test(i32 %i)
{
%i.addr = alloca i32, align 4
store i32 %i, i32* %i.addr, align 4
%var6 = call i8* @malloc(i32 4)
%var5 = bitcast i8* %var6 to %class.MyAwesomeClass*
call void @MyAwesomeClass(%class.MyAwesomeClass* %var5, i32 1)
%var8 = call i8* @malloc(i32 4)
%var7 = bitcast i8* %var8 to %class.MyAwesomeClass*
call void @MyAwesomeClass(%class.MyAwesomeClass* %var7, i32 2)
%var9 = load %class.MyAwesomeClass* %var5, align 4
%var10 = load %class.MyAwesomeClass* %var7, align 4
%var11 = getelementptr inbounds %class.MyAwesomeClass* %var7, i32 0, i32 0
%var12 = load i32* %var11, align 4
ret i32 %var12
}
define void @main()
{
%a = alloca %class.MyClass*, align 4
store %class.MyClass* null, %class.MyClass** %a, align 4
%var5 = load %class.MyClass** %a, align 4
%var7 = call i8* @malloc(i32 4)
%var6 = bitcast i8* %var7 to %class.MyClass*
call void @MyClass(%class.MyClass* %var6, i32 2)
%var8 = load %class.MyClass* %var5, align 4
%var9 = load %class.MyClass* %var6, align 4
%var13 = call i32 @nullable_test(i32 0)
%var14 = alloca i32, align 4
store i32 %var13, i32* %var14, align 4
ret void
}
@@ -231,7 +231,13 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
val right = evaluateExpression(expr.lastChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception")
val operator = expr.operationToken
return codeBuilder.addPrimitiveBinaryOperation(operator, expr.operationReference, left, right)
val result = codeBuilder.addPrimitiveBinaryOperation(operator, expr.operationReference, left, right)
if (left.type is LLVMReferenceType && left.pointer > 0 && right.pointer > 0) {
variableManager.addVariable((left as LLVMVariable).kotlinName!!, result, scopeDepth)
}
return result
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMConstant {
@@ -359,9 +365,12 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
val allocVar = variableManager.receiveVariable(identifier, assignExpression.type, LLVMRegisterScope(), pointer = 0)
codeBuilder.allocStackVar(allocVar)
allocVar.pointer++
allocVar.kotlinName = identifier
variableManager.addVariable(identifier, allocVar, scopeDepth)
copyVariable(assignExpression, allocVar)
} else {
assignExpression.kotlinName = identifier
variableManager.addVariable(identifier, assignExpression, scopeDepth)
}
}
@@ -15,7 +15,7 @@ class VariableManager(val globalVariableCollection: HashMap<String, LLVMVariable
}
fun pullUpwardsLevel(level: Int) {
fileVariableCollectionTree.forEach { s, stack -> if (!stack.empty() && stack.peek().second >= level) stack.pop() else Unit }
fileVariableCollectionTree.forEach { s, stack -> while (!stack.empty() && stack.peek().second >= level) stack.pop() }
}
fun addVariable(name: String, variable: LLVMVariable, level: Int) {
@@ -93,7 +93,7 @@ class LLVMBuilder(val arm: Boolean) {
return result
}
if (firstOp.pointer > 1 && secondOp.pointer > 0) {
if (firstOp.type is LLVMReferenceType && firstOp.pointer > 0 && secondOp.pointer > 0) {
return secondOp as LLVMVariable
}
@@ -13,13 +13,13 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
}?.joinToString()}) ${if (arm) "#0" else ""}"
fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when {
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type), type.toString(), scope, pointer = 1)
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), type.toString(), scope)
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), type.toString(), scope)
type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), type.toString(), scope)
type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), type.toString(), scope)
type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), type.toString(), scope)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), "", scope)
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type), name, scope, pointer = 1)
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope)
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope)
type.toString() == "Byte" -> LLVMVariable(name, LLVMByteType(), name, scope)
type.toString() == "Char" -> LLVMVariable(name, LLVMCharType(), name, scope)
type.toString() == "Boolean" -> LLVMVariable(name, LLVMBooleanType(), name, scope)
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType("${type.toString().dropLast(1)}"), name, scope, pointer = 1)
else -> LLVMVariable(name, LLVMReferenceType("$type"), name, scope, pointer = 1)
}
@@ -1 +1 @@
class_init_section(523) == 12868
class_init_section(523) == 12868
@@ -1 +1 @@
class_methods_1(55) == 60
class_methods_1(55) == 60
@@ -1,2 +1,2 @@
do_while_test_1(5) == 6
do_while_test_1(57) == 68
do_while_test_1(57) == 68
@@ -1,2 +1,2 @@
nullable_test(1) == 2
nullable_test_2(1) == 1
nullable_test(1) == 1
nullable_test_2(4) == 5
@@ -1 +1 @@
Singleton.create(5) == 40
Singleton.create(5) == 40
@@ -1 +1 @@
reassigment_0(5) == 6
reassigment_0(5) == 6
@@ -1 +1 @@
reassigment_1(5) == 7
reassigment_1(5) == 7
@@ -1 +1 @@
simply_class_1(6789) == 6794
simply_class_1(6789) == 6794
@@ -4,15 +4,13 @@ class MyAwesomeClass(var i: Int)
fun nullable_test(i: Int): Int {
var x: MyAwesomeClass? = null
x = MyAwesomeClass(i)
// x = MyAwesomeClass(i + 1)
return i + 1
return x.i
}
fun nullable_test_2(i: Int): Int {
// var x: MyAwesomeClass? = MyAwesomeClass(i)
// x = null
// x = MyAwesomeClass(i)
var x: MyAwesomeClass? = MyAwesomeClass(i)
x = null
x = MyAwesomeClass(i)
return i
return x.i + 1
}