Input in LLVM, I think I do not understand dominance and the location of phi nodes

StackOverflow https://stackoverflow.com/questions/16754324

  •  30-05-2022
  •  | 
  •  

Frage

My goal is to do something simple in LLVM. I want to, using the C library function getchar, define an LLVM function that reads an input from the commandline. Here is my algorithm in pseudocode:

getInt:
  get a character, set the value to VAL
  check if VAL is '-'
    if yes then set SGN to -1 and set VAL to the next character else set SGN to 1
  set NV = to the next char minus 48
  while (NV >= 0) // 48 is the first ASCII character that represents a number
    set VAL = VAL*10
    set VAL = VAL + NV
    set NV to the next char minus 48
  return SGN*VAL

So now, the LLVM code I come up with for doing this is in my head the most straightforward way to translate the above into LLVM IR. However, I get the error "PHI nodes not grouped at the top of the basic block." If I move some things around to fix this error, I get errors about dominance. Below is the LLVM IR code that gives me the PHI nodes error. I believe I am misunderstanding something basic about LLVM IR, so any help you can give is super appreciated.

define i32 @getIntLoop() {
_L1:
  %0 = call i32 @getchar()
  %1 = phi i32 [ %0, %_L1 ], [ %3, %_L2 ], [ %8, %_L4 ]
  %2 = icmp eq i32 %1, 45
  br i1 %2, label %_L2, label %_L5

_L2:                                              ; preds = %_L1
  %3 = call i32 @getchar()
  br label %_L3

_L3:                                              ; preds = %_L4, %_L2
  %4 = call i32 @getchar()
  %5 = icmp slt i32 %4, 40
  br i1 %5, label %_L5, label %_L4

_L4:                                              ; preds = %_L3
  %6 = sub i32 %4, 48
  %7 = mul i32 %1, 10
  %8 = add i32 %6, %7
  br label %_L3

_L5:                                              ; preds = %_L3, %_L1
  br i1 %2, label %_L6, label %_L7

_L6:                                              ; preds = %_L5
  %9 = mul i32 -1, %1
  ret i32 %9

_L7:                                              ; preds = %_L5
  ret i32 %1
}
War es hilfreich?

Lösung

You're getting a very clear error, though. According to the LLVM IR language reference:

There must be no non-phi instructions between the start of a basic block and the PHI instructions: i.e. PHI instructions must be first in a basic block.

You have a phi in L1 which violates this.

Why does it have %_L1 as one of its sources? There are no jumps to %_L1 anywhere else. I think you should first understand how phi works, possibly by compiling small pieces of C code into LLVM IR with Clang and see what gets generated.

Put simply, a phi is needed to have consistency in SSA form while being able to assign one of several values into the same register. Make sure you read about SSA - it explains Phi node as well. And additional good resource is the LLVM tutorial which you should go through. In particular, part 5 covers Phis. As suggested above, running small pieces of C through Clang is a great way to understand how things work. This is in no way "hacky" - it's the scientific method! You read the theory, think hard about it, form hypotheses about how things work and then verify those hypotheses by running Clang and seeing what it generates for real-life control flow.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top