Search code examples
assemblyllvmbytecode

LLVM IR printing a number


I'm trying to print a number, but I'm getting errors saying my print function is wrong:

define i32 @main() {
entry:
  %d = shl i32 2, 3
  %call = call i32 (i8*, ...)* @printf(i8* %d)
  ret i32 1
}

declare i32 @printf(i8*, ...)

And here's the error:

Error in compilation: /bin/this.program: llvm.ll:4:44: error: '%d' defined with type 'i8'
  %call = call i32 (i8*, ...)* @printf(i8* %d)
                                       ^

Is there some other print function that fixes this?


Solution

  • LLVM IR has no implicit casts (and explicit casts are separate instructions). Your %d variable has type i32, from the first instruction (it's odd that error message is '%d' defined with type 'i8', probably your example is not your real code?).

    As for printf function, it is exactly C printf. And you should pass exactly the same arguments - a format string (i8* pointing to null terminated "%d"), and a number.

    For string, you should define global

    @formatString = private constant [2 x i8] c"%d" 
    

    And pass it as first argument to printf:

    %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @formatString , i32 0, i32 0), i32 %d)
    

    Full code:

    @formatString = private constant [2 x i8] c"%d" 
    
    define i32 @main() {
    entry:
      %d = shl i32 2, 3
      %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([2 x i8], [2 x i8]* @formatString , i32 0, i32 0), i32 %d)
      ret i32 1
    }
    
    declare i32 @printf(i8*, ...)