2

我的目标是在 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 节点未分组在基本块的顶部”。如果我移动一些东西来修复这个错误,我会得到关于支配地位的错误。下面是给我 PHI 节点错误的 LLVM IR 代码。我相信我误解了有关 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
}
4

1 回答 1

3

但是,您会得到一个非常明显的错误。根据 LLVM IR语言参考

在基本块的开头和 PHI 指令之间不能有非 phi 指令:即 PHI 指令必须在基本块中的第一个。

你有一个phi违反L1这个的。

为什么它有%_L1它的来源之一?没有跳转到%_L1其他任何地方。我认为您应该首先了解其phi工作原理,可能通过使用 Clang 将一小段 C 代码编译到 LLVM IR 中,然后查看生成了什么。

简而言之,aphi需要在 SSA 形式中具有一致性,同时能够将多个值之一分配到同一个寄存器中。确保您阅读了有关SSA的信息——它也解释了 Phi 节点。额外的好资源是你应该阅读的 LLVM 教程。特别是,第 5 部分涵盖了 Phis。如上所述,通过 Clang 运行小块 C 是了解事物如何工作的好方法。这绝不是“hacky”——这是科学的方法!你阅读理论,认真思考,形成关于事物如何工作的假设,然后通过运行 Clang 并查看它为现实生活中的控制流生成什么来验证这些假设。

于 2013-05-25T22:16:59.197 回答