Implemented support for loop codegeneration: "while" and "do-while".
for code "while loop":
-------------8<-------------
> cat ../backend.native/tests/codegen/cycles/cycle.kt
fun cycle(cnt: Int): Int {
var sum = 1
while (sum == cnt) {
sum = sum + 1
}
return sum
}
-------------8<-------------
translator generates:
-------------8<-------------
> llvm-dis-mp-3.8 ../backend.native/tests/codegen/cycles/cycle.kt.bc -o -
; ModuleID = '../backend.native/tests/codegen/cycles/cycle.kt.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
...
define i32 @"kfun:cycle"(i32) {
entry:
%cnt = alloca i32
store i32 %0, i32* %cnt
%sum = alloca i32
store i32 1, i32* %sum
br label %label_0
label_0: ; preds = %label_1, %entry
%tmp1 = load i32, i32* %sum
%tmp2 = load i32, i32* %cnt
%tmp0 = icmp eq i32 %tmp1, %tmp2
br i1 %tmp0, label %label_1, label %label_2
label_1: ; preds = %label_0
%tmp6 = load i32, i32* %sum
%tmp5 = add i32 %tmp6, 1
store i32 %tmp5, i32* %sum
br label %label_0
label_2: ; preds = %label_0
%tmp8 = load i32, i32* %sum
ret i32 %tmp8
}
-------------8<-------------
for "do-while" code:
-------------8<-------------
> cat ../backend.native/tests/codegen/cycles/cycle_do.kt
fun cycle_do(cnt: Int): Int {
var sum = 1
do {
sum = sum + 2
} while (sum == cnt)
return sum
}
-------------8<-------------
translator produces:
-------------8<-------------
> llvm-dis-mp-3.8 ../backend.native/tests/codegen/cycles/cycle_do.kt.bc -o -
; ModuleID = '../backend.native/tests/codegen/cycles/cycle_do.kt.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
define i32 @"kfun:cycle_do"(i32) {
entry:
%cnt = alloca i32
store i32 %0, i32* %cnt
%sum = alloca i32
store i32 1, i32* %sum
br label %label_0
label_0: ; preds = %label_1, %entry
%tmp3 = load i32, i32* %sum
%tmp2 = add i32 %tmp3, 2
store i32 %tmp2, i32* %sum
br label %label_1
label_1: ; preds = %label_0
%tmp6 = load i32, i32* %sum
%tmp7 = load i32, i32* %cnt
%tmp5 = icmp eq i32 %tmp6, %tmp7
br i1 %tmp5, label %label_0, label %label_2
label_2: ; preds = %label_1
%tmp8 = load i32, i32* %sum
ret i32 %tmp8
}
-------------8<-------------
This commit is contained in:
committed by
vvlevchenko
parent
152e738e23
commit
4e5e7d37ee
+74
-27
@@ -97,6 +97,52 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitLoop(loop: IrLoop) {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitWhileLoop(loop: IrWhileLoop) {
|
||||||
|
val loopEnter = generator.basicBlock()
|
||||||
|
val loopBody = generator.basicBlock()
|
||||||
|
val loopExit = generator.basicBlock()
|
||||||
|
|
||||||
|
LLVMBuildBr(context.llvmBuilder, loopEnter)
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopEnter)
|
||||||
|
val condition = evaluateExpression(generator.tmpVariable(), loop.condition)
|
||||||
|
LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit)
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopBody)
|
||||||
|
evaluateExpression(generator.tmpVariable(), loop.body)
|
||||||
|
|
||||||
|
LLVMBuildBr(context.llvmBuilder, loopEnter)
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopExit)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
override fun visitDoWhileLoop(loop: IrDoWhileLoop) {
|
||||||
|
val loopBody = generator.basicBlock()
|
||||||
|
val loopCheck = generator.basicBlock()
|
||||||
|
val loopExit = generator.basicBlock()
|
||||||
|
|
||||||
|
LLVMBuildBr(context.llvmBuilder, loopBody)
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopBody)
|
||||||
|
evaluateExpression(generator.tmpVariable(), loop.body)
|
||||||
|
LLVMBuildBr(context.llvmBuilder, loopCheck)
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopCheck)
|
||||||
|
val condition = evaluateExpression(generator.tmpVariable(), loop.condition)
|
||||||
|
LLVMBuildCondBr(context.llvmBuilder, condition, loopBody, loopExit)
|
||||||
|
|
||||||
|
LLVMPositionBuilderAtEnd(context.llvmBuilder, loopExit)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
override fun visitConstructor(declaration: IrConstructor) {
|
override fun visitConstructor(declaration: IrConstructor) {
|
||||||
generator.initFunction(declaration)
|
generator.initFunction(declaration)
|
||||||
val thisValue = generator.variable("this")
|
val thisValue = generator.variable("this")
|
||||||
@@ -166,9 +212,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
logger.log("visitVariable : ${ir2string(declaration)}")
|
logger.log("visitVariable : ${ir2string(declaration)}")
|
||||||
val variableName = declaration.descriptor.name.asString()
|
val variableName = declaration.descriptor.name.asString()
|
||||||
val variableType = declaration.descriptor.type
|
val variableType = declaration.descriptor.type
|
||||||
val newVariable = generator.alloca(variableType, variableName) // Create LLVM variable.
|
val newVariable = generator.alloca(variableType, variableName) // Create LLVM variable.
|
||||||
generator.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable.
|
generator.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable.
|
||||||
evaluateExpression(variableName, declaration.initializer) // Generate initialization code.
|
val value = evaluateExpression(variableName, declaration.initializer) // Generate initialization code.
|
||||||
|
generator.store(value!!, generator.variable(variableName)!!) // Store init result in the variable
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -192,16 +239,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
private fun evaluateExpression(tmpVariableName: String, value: IrElement?): LLVMOpaqueValue? {
|
private fun evaluateExpression(tmpVariableName: String, value: IrElement?): LLVMOpaqueValue? {
|
||||||
when (value) {
|
when (value) {
|
||||||
is IrCall -> return evaluateCall (tmpVariableName, value)
|
is IrCall -> return evaluateCall (tmpVariableName, value)
|
||||||
is IrGetValue -> return evaluateGetValue (tmpVariableName, value)
|
is IrGetValue -> return evaluateGetValue (tmpVariableName, value)
|
||||||
is IrSetVariable -> return evaluateSetVariable( value)
|
is IrSetVariable -> return evaluateSetVariable ( value)
|
||||||
is IrVariable -> return evaluateVariable ( value)
|
is IrVariable -> return evaluateVariable ( value)
|
||||||
is IrGetField -> return evaluateGetField ( value)
|
is IrGetField -> return evaluateGetField ( value)
|
||||||
is IrConst<*> -> return evaluateConst ( value)
|
is IrConst<*> -> return evaluateConst ( value)
|
||||||
is IrReturn -> return evaluateReturn ( value)
|
is IrReturn -> return evaluateReturn ( value)
|
||||||
is IrBlock -> return evaluateBlock ( value)
|
is IrBlock -> return evaluateBlock ( value)
|
||||||
null -> return null
|
null -> return null
|
||||||
else -> {
|
else -> {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,16 +258,17 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
private fun evaluateCall(tmpVariableName: String, value: IrMemberAccessExpression?): LLVMOpaqueValue? {
|
private fun evaluateCall(tmpVariableName: String, value: IrMemberAccessExpression?): LLVMOpaqueValue? {
|
||||||
logger.log("evaluateCall : $tmpVariableName = ${ir2string(value)}")
|
logger.log("evaluateCall : $tmpVariableName = ${ir2string(value)}")
|
||||||
val args = mutableListOf<LLVMOpaqueValue?>()
|
val args = mutableListOf<LLVMOpaqueValue?>() // Create list of function args.
|
||||||
value!!.acceptChildrenVoid(object:IrElementVisitorVoid{
|
value!!.acceptChildrenVoid(object: IrElementVisitorVoid { // Iterate args of the function.
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) { // Visit arg.
|
||||||
val tmp = generator.tmpVariable()
|
val tmp = generator.tmpVariable() // Create variable representing the arg in generator
|
||||||
args.add(evaluateExpression(tmp, element as IrExpression))
|
args.add(evaluateExpression(tmp, element as IrExpression)) // Evaluate expression and get LLVM arg
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
when {
|
when {
|
||||||
value is IrDelegatingConstructorCall -> return generator.superCall(tmpVariableName, value.descriptor, args)
|
|
||||||
value.descriptor is FunctionDescriptor -> return evaluateFunctionCall(tmpVariableName, value as IrCall, args)
|
value.descriptor is FunctionDescriptor -> return evaluateFunctionCall(tmpVariableName, value as IrCall, args)
|
||||||
|
value is IrDelegatingConstructorCall -> return generator.superCall(tmpVariableName, value.descriptor, args)
|
||||||
else -> {
|
else -> {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
@@ -335,11 +383,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
private fun evaluateFunctionCall(tmpVariableName: String, callee: IrCall, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue? {
|
private fun evaluateFunctionCall(tmpVariableName: String, callee: IrCall, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue? {
|
||||||
val descriptor:FunctionDescriptor = callee.descriptor as FunctionDescriptor
|
val descriptor:FunctionDescriptor = callee.descriptor as FunctionDescriptor
|
||||||
when {
|
when {
|
||||||
descriptor.isOperator || descriptor is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall(tmpVariableName, callee, args)
|
descriptor.isOperator -> return evaluateOperatorCall(tmpVariableName, callee.origin!!, args)
|
||||||
descriptor is ClassConstructorDescriptor -> return evaluateConstructorCall(tmpVariableName, callee, args)
|
descriptor is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall(tmpVariableName, callee.origin!!, args)
|
||||||
else -> {
|
descriptor is ClassConstructorDescriptor -> return evaluateConstructorCall(tmpVariableName, callee, args)
|
||||||
return evaluateSimpleFunctionCall(tmpVariableName, callee, args)
|
else -> return evaluateSimpleFunctionCall(tmpVariableName, callee, args)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,9 +407,9 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluateOperatorCall(tmpVariableName: String, callee: IrCall, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue {
|
private fun evaluateOperatorCall(tmpVariableName: String, origin: IrStatementOrigin, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue {
|
||||||
logger.log("evaluateCall $tmpVariableName = ${ir2string(callee)}")
|
logger.log("evaluateCall $tmpVariableName origin:$origin")
|
||||||
when (callee.origin) {
|
when (origin) {
|
||||||
IrStatementOrigin.PLUS -> return generator.plus (args[0]!!, args[1]!!, tmpVariableName)
|
IrStatementOrigin.PLUS -> return generator.plus (args[0]!!, args[1]!!, tmpVariableName)
|
||||||
IrStatementOrigin.MINUS -> return generator.minus (args[0]!!, args[1]!!, tmpVariableName)
|
IrStatementOrigin.MINUS -> return generator.minus (args[0]!!, args[1]!!, tmpVariableName)
|
||||||
IrStatementOrigin.PLUSEQ -> return generator.plus (args[0]!!, args[1]!!, tmpVariableName)
|
IrStatementOrigin.PLUSEQ -> return generator.plus (args[0]!!, args[1]!!, tmpVariableName)
|
||||||
|
|||||||
Reference in New Issue
Block a user