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:
Konstantin Anisimov
2016-11-02 16:14:55 +03:00
committed by vvlevchenko
parent 152e738e23
commit 4e5e7d37ee
@@ -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) {
generator.initFunction(declaration)
val thisValue = generator.variable("this")
@@ -166,9 +212,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
logger.log("visitVariable : ${ir2string(declaration)}")
val variableName = declaration.descriptor.name.asString()
val variableType = declaration.descriptor.type
val newVariable = generator.alloca(variableType, variableName) // Create LLVM variable.
generator.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable.
evaluateExpression(variableName, declaration.initializer) // Generate initialization code.
val newVariable = generator.alloca(variableType, variableName) // Create LLVM variable.
generator.registerVariable(variableName, newVariable) // Map variableName -> LLVM variable.
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? {
when (value) {
is IrCall -> return evaluateCall (tmpVariableName, value)
is IrGetValue -> return evaluateGetValue (tmpVariableName, value)
is IrSetVariable -> return evaluateSetVariable( value)
is IrVariable -> return evaluateVariable ( value)
is IrGetField -> return evaluateGetField ( value)
is IrConst<*> -> return evaluateConst ( value)
is IrReturn -> return evaluateReturn ( value)
is IrBlock -> return evaluateBlock ( value)
null -> return null
else -> {
is IrCall -> return evaluateCall (tmpVariableName, value)
is IrGetValue -> return evaluateGetValue (tmpVariableName, value)
is IrSetVariable -> return evaluateSetVariable ( value)
is IrVariable -> return evaluateVariable ( value)
is IrGetField -> return evaluateGetField ( value)
is IrConst<*> -> return evaluateConst ( value)
is IrReturn -> return evaluateReturn ( value)
is IrBlock -> return evaluateBlock ( value)
null -> return null
else -> {
TODO()
}
}
@@ -211,16 +258,17 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateCall(tmpVariableName: String, value: IrMemberAccessExpression?): LLVMOpaqueValue? {
logger.log("evaluateCall : $tmpVariableName = ${ir2string(value)}")
val args = mutableListOf<LLVMOpaqueValue?>()
value!!.acceptChildrenVoid(object:IrElementVisitorVoid{
override fun visitElement(element: IrElement) {
val tmp = generator.tmpVariable()
args.add(evaluateExpression(tmp, element as IrExpression))
val args = mutableListOf<LLVMOpaqueValue?>() // Create list of function args.
value!!.acceptChildrenVoid(object: IrElementVisitorVoid { // Iterate args of the function.
override fun visitElement(element: IrElement) { // Visit arg.
val tmp = generator.tmpVariable() // Create variable representing the arg in generator
args.add(evaluateExpression(tmp, element as IrExpression)) // Evaluate expression and get LLVM arg
}
})
when {
value is IrDelegatingConstructorCall -> return generator.superCall(tmpVariableName, value.descriptor, args)
value.descriptor is FunctionDescriptor -> return evaluateFunctionCall(tmpVariableName, value as IrCall, args)
value is IrDelegatingConstructorCall -> return generator.superCall(tmpVariableName, value.descriptor, args)
else -> {
TODO()
}
@@ -335,11 +383,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
private fun evaluateFunctionCall(tmpVariableName: String, callee: IrCall, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue? {
val descriptor:FunctionDescriptor = callee.descriptor as FunctionDescriptor
when {
descriptor.isOperator || descriptor is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall(tmpVariableName, callee, args)
descriptor is ClassConstructorDescriptor -> return evaluateConstructorCall(tmpVariableName, callee, args)
else -> {
return evaluateSimpleFunctionCall(tmpVariableName, callee, args)
}
descriptor.isOperator -> return evaluateOperatorCall(tmpVariableName, callee.origin!!, args)
descriptor is IrBuiltinOperatorDescriptorBase -> return evaluateOperatorCall(tmpVariableName, callee.origin!!, args)
descriptor is ClassConstructorDescriptor -> return evaluateConstructorCall(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 {
logger.log("evaluateCall $tmpVariableName = ${ir2string(callee)}")
when (callee.origin) {
private fun evaluateOperatorCall(tmpVariableName: String, origin: IrStatementOrigin, args: MutableList<LLVMOpaqueValue?>): LLVMOpaqueValue {
logger.log("evaluateCall $tmpVariableName origin:$origin")
when (origin) {
IrStatementOrigin.PLUS -> return generator.plus (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)