在LLVM中输入,我想我不了解优势和phi节点的位置

时间:2013-05-25 22:01:59

标签: llvm llvm-ir

我的目标是在LLVM中做一些简单的事情。我想使用C库函数getchar定义一个LLVM函数,该函数从命令行读取输入。这是我在伪代码中的算法:

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

所以现在,我提出的LLVM代码是我最直接的将上述内容转换为LLVM IR的方法。但是,我得到了错误 “PHI节点未分组在基本块的顶部。”如果我移动一些东西来修复这个错误,我会得到关于支配地位的错误。下面是LLVM IR代码,它给出了PHI节点错误。我相信我误解了LLVM IR的基本内容,所以你能给予的任何帮助都是非常感激的。

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
}

1 个答案:

答案 0 :(得分:3)

但是你得到了一个非常明确的错误。根据LLVM IR language reference

  

在基本开始之间必须没有非phi指令   块和PHI指令:即PHI指令必须是第一个   基本块。

phi中的L1违反了这一规定。

为什么%_L1作为其来源之一?其他任何地方都没有跳转到%_L1。我想你应该首先了解phi是如何工作的,可能是通过使用Clang将小块C代码编译成LLVM IR,看看会产生什么。

简单地说,需要phi以保持SSA形式的一致性,同时能够将多个值中的一个分配到同一个寄存器中。请务必阅读SSA - 它也解释了Phi节点。另外一个好的资源是你应该经历的LLVM教程。特别是part 5 covers Phis。如上所述,通过Clang运行小块C是了解事物如何工作的好方法。这绝不是“hacky” - 这是科学的方法!你阅读理论,仔细思考,形成关于事物如何运作的假设,然后通过运行Clang来验证这些假设,并了解它为实际控制流程所产生的结果。