I'm using tinygo's LLVM bindings for Go (don't know if this is relevant) and I'm trying to implement If/Then branching without the else block.
I've found this answer on stackoverflow: LLVM IRBuilder If-Then Codegen but it's using the C++ API and tinygo's bindings don't provide a way to "push_back" a block into a function.
I have this piece of code that I'm trying to compile:
func factorial(x: i8) -> i8 {
if x == 0 {
return 1;
}
return x * factorial(x - 1);
}
I'm going to omit some stuff for simplicity, so here's the generated IR:
define i8 @factorial(i8 %x) {
entry:
%RETURN_VALUE = alloca i8, align 1
%0 = alloca i8, align 1
store i8 %x, i8* %0, align 1
%1 = load i8, i8* %0, align 1
%2 = icmp eq i8 %1, 0
br i1 %2, label %3, label %merge
3: ; preds = %entry
store i8 1, i8* %RETURN_VALUE, align 1
br label %merge
merge: ; preds = %3, %entry
%4 = load i8, i8* %0, align 1
%5 = load i8, i8* %0, align 1
%6 = sub i8 %5, 1
%7 = call i8 @factorial(i8 %6)
%8 = mul i8 %4, %7
store i8 %8, i8* %RETURN_VALUE, align 1
%9 = load i8, i8* %RETURN_VALUE, align 1
ret i8 %9
}
My approach is to have a variable of some sort and then if a return statement is encountered, just change it's value, so it can be returned once at the end of the function. This works perfectly fine with If/Then/Else branching, but I want my language to be imperative instead of functional and allow If/Then branching.
Also, I've tried compiling C code to LLVM IR (clang -S -emit-llvm x.c
) and see what it looks like on the inside.
There are some dummy statements, because clang is always trying to make optimizations, but I want the IR to be as raw as possible.
int main() {
int x = 8;
if (x) {
return 1;
}
x = 3;
return 0;
}
this C code compiles to
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 8, i32* %2, align 4
%3 = load i32, i32* %2, align 4
%4 = icmp ne i32 %3, 0
br i1 %4, label %5, label %6
5: ; preds = %0
store i32 1, i32* %1, align 4
br label %7
6: ; preds = %0
store i32 3, i32* %2, align 4
store i32 0, i32* %1, align 4
br label %7
7: ; preds = %6, %5
%8 = load i32, i32* %1, align 4
ret i32 %8
}
I honestly have no idea how to implement this type of branching.