0

I'm currently working on programming language compiler that generated LLVM-IR. I'm not using any library for the emitting, so I'm just writing instructions to a file. The problem is mutable variables, I'm registering a %i, %i.(index) with the value and then loading %i with %i.(index). This may not be the right way to have mutable variables in llvm, but is the best of what I've tried before as i need them to work with recursion for example when looping over i as long as the value is less than ten which is what this code does.

LLVM out code:

@.str_0 = private unnamed_addr constant [4 x i8] c"%i\0A\00"
declare i32 @printf(i8*, ...) nounwind

define i32 @add(i32 %a, i32 %b) nounwind {
entry:
    %t1 = add i32 %a, %b
    ret i32 %t1
}

define i32 @main() nounwind {
entry:
    %i = alloca i32
    %i.0 = alloca i32
    store i32 0, i32* %i.0
    store i32 %i.0, i32* %i
    %t2 = icmp slt i32 %i, 10
    br i1 %t2, label %lb1, label %lb2
lb1:
    %t3 = getelementptr [4 x i8], [4 x i8]* @.str_0, i32 0, i32 0
    %t4 = call i32 @printf(i8* %t3, i32 %i)
    %t5 = call i32 @add(i32 %i, i32 1)
    %i.1 = alloca i32
    store i32 %t5, i32* %i
    store i32 %i.1, i32* %i
    %t6 = icmp slt i32 %i, 10
    br i1 %t6, label %lb1, label %lb2
lb2:
    ret i32 0
}

The code my compiler is generating from:

fn add(a: int, b: int): int {
    return a + b;
}

fn main(): void {
    let i: int = 0;
    while (i < 10) {
        printf("%i\n", i);
        i = add(i, 1);
    }
    return;
}

Error:

./out/test.zk.ll:15:15: error: '%i.0' defined with type 'ptr' but expected 'i32'
   15 |     store i32 %i.0, i32* %i
      |               ^
1 error generated.

I expect to be able to define a mutable variable then change it's value after the fact with it working in recursion.

Thanks in advance for any help.

1
  • I know almost nothing about llvm-ir, but isn't the error pretty clear? You have two i32 pointers (%i and %i.0). In line 14 you store a value of 0 at i32 pointed to by %i. In line 15, you try to store a pointer (modern systems this is generally 64 bits) into the i32 pointed to by %i.0, and the tool complains about a type error because of that. Commented Oct 19, 2024 at 13:47

1 Answer 1

1

You only need to manipulate the pointer from %i = alloca i32 in the LLVM IR, use load when read it, and store when updating it.

there is a similar loop example while tests , it generate the IR code below.

define i32 @test_func(i32 %x, i32 %y) {
 entry:
  %0 = alloca i32, align 4
  %1 = alloca i32, align 4
  store i32 %x, ptr %1, align 4
  %2 = alloca i32, align 4
  store i32 %y, ptr %2, align 4
  br label %while_cond_0

 while_cond_0:                                     ; preds =        %while_body_0, %entry
   %3 = load i32, ptr %1, align 4
   %4 = icmp sgt i32 %3, 0
   br i1 %4, label %while_body_0, label %while_end_0

  while_body_0:                                     ; preds = %while_cond_0
   %5 = load i32, ptr %2, align 4
   %6 = add i32 %5, 10
   store i32 %6, ptr %2, align 4
   %7 = load i32, ptr %1, align 4
   %8 = sub i32 %7, 1
   store i32 %8, ptr %1, align 4
   br label %while_cond_0

 while_end_0:                                      ; preds = %while_cond_0
 %9 = load i32, ptr %2, align 4
 store i32 %9, ptr %0, align 4
 br label %exit

exit:                                             ; preds = %while_end_0
 %10 = load i32, ptr %0, align 4
 ret i32 %10

}

Sign up to request clarification or add additional context in comments.

1 Comment

I ended up fixing this by doing the same as you are showing before seeing your answer, but thank you very much nevertheless.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.