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) {
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user