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

在LLVM中输入时,我想我不了解优势和phi节点的位置,llvm,llvm-ir,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

我的目标是在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
}

不过,你犯了一个非常明显的错误。根据LLVM IR:

在基本指令开始之间不得有非phi指令 块和PHI指令:即PHI指令必须在 基本块

L1
中有一个
phi
,它违反了这一点

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


简言之,
phi
需要具有SSA形式的一致性,同时能够将多个值中的一个分配到同一寄存器中。确保您阅读了相关内容-它还解释了Phi节点。另外一个好的资源是LLVM教程,您应该阅读它。特别是。如上所述,通过叮当声运行一小段C是了解事物如何工作的一个好方法。这绝对不是“黑客”——这是科学的方法!你阅读理论,认真思考,形成关于事物如何运作的假设,然后通过运行Clang并查看它为实际控制流生成的内容来验证这些假设。

是的,我知道错误是什么。我不知道如何解决这个问题,我想要的是有一个变量,比如伪代码中的VAL,它被初始化为getchar的结果。我承认,这可能是设计上的一个错误。我想知道的是如何在LLVM中看待这个问题,这样我就可以想出一个正确的解决方案。谢谢你对CLANG的建议。然而,我很少用这种方式有效地学习。我更喜欢理解事物的本意,而不是以我的方式去理解。我可能有点痴迷于想要以尽可能干净的方式理解事物。这就是为什么我把问题贴在这里。另一方面,我有一种在LLVM中编写此函数的方法,只是与我的直觉不符。任何进一步的反馈都将不胜感激。我试着用Clang编译,我得到的正是我认为我会得到的,也是我不想要的。Clang生成的IR分配变量,并使用store和load更新和访问这些变量——不使用phi。不幸的是,最后这并不能帮助我理解LLVM。虽然Clang编译这条语句的方式肯定是一个更健壮的解决方案,而且据我所知,这是在LLVM中理智地编写编译器后端的唯一方法。。。我仍然想知道如何以更直接的方式在LLVM中执行此功能。只是出于教育目的。一个无耻的自我插件:如果这是你第一次使用LLVM IR,你可能会感兴趣的第一个原型你的代码手动使用,这将给你即时反馈的东西,如支配问题。然而,我承认学习IR的最好方法之一就是编写C代码片段并查看从Clang生成的IR。IR不是微不足道的,尤其是如果您之前没有SSA表单的经验,通过示例学习是一种很好的学习方式。