在LLVM中输入时,我想我不了解优势和phi节点的位置
我的目标是在LLVM中做一些简单的事情。我想使用C库函数getchar定义一个LLVM函数,该函数从命令行读取输入。以下是我的伪代码算法:在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
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表单的经验,通过示例学习是一种很好的学习方式。