LLVM recursive function IR can be defined but not run

Hi all,
I’m a llvm beginner and using it to run my own toy-c-compiler. And I use my compiler to C-like code into following llvm IR:

C-like code: 
extern void printi(int n); 

int F(int n){
    if(n <= 1){
        return 1;
    }
    else{
        return n * F(n-1);
    }
    return 0; 
}

int main(){
    int a = 3; 
    int b = F(a); 
    return 0; 
}

llvm IR: 
declare i32 @printf(ptr, ...)

declare i32 @scanf(ptr, ...)

declare void @printi(i32)

define i32 @F(i32 %n) {
entry:
  %n1 = alloca i32, align 4, addrspace(4)
  store i32 %n, ptr addrspace(4) %n1, align 4
  %n2 = load i32, ptr addrspace(4) %n1, align 4
  %letmp = icmp sle i32 %n2, 1
  br i1 %letmp, label %then, label %else

then:                                             ; preds = %entry
  ret i32 1
  br label %ifcont

else:                                             ; preds = %entry
  %n3 = load i32, ptr addrspace(4) %n1, align 4
  %n4 = load i32, ptr addrspace(4) %n1, align 4
  %subtmp = sub i32 %n4, 1
  %calltmp = call i32 @F(i32 %subtmp)
  %multmp = mul i32 %n3, %calltmp
  ret i32 %multmp
  br label %ifcont

ifcont:                                           ; preds = %else, %then
  ret i32 0
}

define i32 @main() {
entry:
  %a = alloca i32, align 4, addrspace(4)
  store i32 3, ptr addrspace(4) %a, align 4
  %b = alloca i32, align 4, addrspace(4)
  %a1 = load i32, ptr addrspace(4) %a, align 4
  %calltmp = call i32 @F(i32 %a1)
  store i32 %calltmp, ptr addrspace(4) %b, align 4
  ret i32 0
}

But it cannot run and error with segmentation fault when I use My engine trying to run it:

llvm::ExecutionEngine* EE = llvm::EngineBuilder(std::unique_ptr<llvm::Module>(_module)).create();
    EE->finalizeObject();
    std::vector<llvm::GenericValue> noargs;
    llvm::GenericValue v = EE->runFunction(_module->getFunction("main"), noargs);

I don’t know where the problem is and I want to find a solution to debug my function. Thank you in advance!

This looks like it should be F(a) since b is uninitialized before the call. That could easily lead to stack exhaustion if the random value it loads is too big.

Other than that all the addrspace(4)s are weird but not really something you’d stumble into by accident so I assume they make sense on your platform.

Sorry about my oversight and I’ve edited my code, however problem does still exist. As for the addrspace(4) you mentioned, I use the following c++ code to generate it:

llvm::AllocaInst* alloc = new llvm::AllocaInst(arg->getType(), 4, args->args[i]->id->name.c_str(), __Context.getCurrentBlock());
new llvm::StoreInst(arg, alloc, false, __Context.getCurrentBlock());

It maybe happens due to llvm-16 opaque pointer but I’m not quite sure. However if the function is someting simple like adding 2 numbers shown below, it runs well.

C-like code: 
int add(int a, int b){
    return a + b;
}

int main(){
    int a = 3; 
    int b = 4;
    int c = add(a, b);
    printi(c);
    return 0; 
}
llvm IR:
declare i32 @printf(ptr, ...)

declare i32 @scanf(ptr, ...)

declare void @printi(i32)

define i32 @add(i32 %a, i32 %b) {
entry:
  %a1 = alloca i32, align 4, addrspace(4)
  store i32 %a, ptr addrspace(4) %a1, align 4
  %b2 = alloca i32, align 4, addrspace(4)
  store i32 %b, ptr addrspace(4) %b2, align 4
  %a3 = load i32, ptr addrspace(4) %a1, align 4
  %b4 = load i32, ptr addrspace(4) %b2, align 4
  %addtmp = add i32 %a3, %b4
  ret i32 %addtmp
}

define i32 @main() {
entry:
  %a = alloca i32, align 4, addrspace(4)
  store i32 3, ptr addrspace(4) %a, align 4
  %b = alloca i32, align 4, addrspace(4)
  store i32 4, ptr addrspace(4) %b, align 4
  %c = alloca i32, align 4, addrspace(4)
  %a1 = load i32, ptr addrspace(4) %a, align 4
  %b2 = load i32, ptr addrspace(4) %b, align 4
  %calltmp = call i32 @add(i32 %a1, i32 %b2)
  store i32 %calltmp, ptr addrspace(4) %c, align 4
  %c3 = load i32, ptr addrspace(4) %c, align 4
  %calltmp4 = call void @printi(i32 %c3)
  ret i32 0
}

output: 7
 

Friends I finally locate the problem, That my function has multiple return value. When I use gdb to debug my code, it fails in the ‘ret’. I try with the new code and now it can run. Hope this can help you:)

int F(int n){
    int retval; 
    if(n == 1){
        retval = 1;
    }
    else{
        retval = n * F(n-1);
    }
    return retval; 
}


define i32 @F(i32 %n) {
entry:
  %n1 = alloca i32, align 4, addrspace(4)
  store i32 %n, ptr addrspace(4) %n1, align 4
  %retval = alloca i32, align 4, addrspace(4)
  %n2 = load i32, ptr addrspace(4) %n1, align 4
  %eqtmp = icmp eq i32 %n2, 1
  br i1 %eqtmp, label %then, label %else

then:                                             ; preds = %entry
  store i32 1, ptr addrspace(4) %retval, align 4
  br label %ifcont

else:                                             ; preds = %entry
  %n3 = load i32, ptr addrspace(4) %n1, align 4
  store i32 %n3, ptr addrspace(4) %retval, align 4
  %n4 = load i32, ptr addrspace(4) %n1, align 4
  %subtmp = sub i32 %n4, 1
  %calltmp = call i32 @F(i32 %subtmp)
  %multmp = mul i32 %n3, %calltmp
  br label %ifcont

ifcont:                                           ; preds = %else, %then
  %retval5 = load i32, ptr addrspace(4) %retval, align 4
  ret i32 %retval5
}