【发布时间】:2020-02-14 08:18:32
【问题描述】:
我正在尝试使用 LLVM C++ API 编写编译器,并且我正在尝试访问函数中的数组参数。
据我从 clang 的 IR 生成中可以看出,这两个代码具有不同的 LLVM IR 代码:
void foo(void) {
int a[2];
a[0] = 1;
// %1 = getelementptr inbounds [2 x i32], [2 x i32]* %0, i32 0, i32 0
// store i32 1, i32* %1
void bar(int a[]) {
a[0] = 1;
// store i32* %0, i32** %3, align 8
// %4 = load i32*, i32** %3, align 8
// %5 = getelementptr inbounds i32, i32* %4, i64 0
// store i32 1, i32* %5, align 4
如果将数组作为参数传递,我需要先使用builder.CreateStore(),然后使用llvm::GetElementPtrInst::CreateInBounds() 来获取指向索引的指针。
但是,在编写编译器时,我使用 访问者模式 并将 a[0] = 1 之类的代码视为 assign expression。在访问树节点assign_expression时,需要判断是否需要load。
有没有办法判断数组是局部定义的变量还是参数?
更新 1: 例如,在 C 中,如果一个函数是这样定义的:
void test(int a[]) {
a[0] = 1;
}
a[0] = 1 对应的 LLVM C++ 代码如下:
for(auto arg = theFunction->arg_begin(); arg != theFunction->arg_end(); arg ++) {
auto param = builder.CreateAlloca(llvm::Type::getInt32Ty(context)->getPointerTo());
builder.CreateStore(arg, param);
}
// a[0] = 1
auto loaded_tmp = builder.CreateLoad(param);
auto value = llvm::GetElementPtrInst::CreateInBounds(tmp, {Const(0), Const(0)}, "", the_basic_block);
但是,当数组在本地定义时,不需要代码auto loaded_tmp = builder.CreateLoad(param);。所以我的问题是:我如何知道我是否需要CreateLoad?
更新 2: clang 为以下 C 代码生成的 LLVM IR:
int h(int a[]) {
a[0] = 1;
a[1] = 2;
}
是
define dso_local i32 @h(i32*) #0 {
%2 = alloca i32, align 4
%3 = alloca i32*, align 8
store i32* %0, i32** %3, align 8
%4 = load i32*, i32** %3, align 8
%5 = getelementptr inbounds i32, i32* %4, i64 0
store i32 1, i32* %5, align 4
%6 = load i32*, i32** %3, align 8
%7 = getelementptr inbounds i32, i32* %6, i64 1
store i32 2, i32* %7, align 4
%8 = load i32, i32* %2, align 4
ret i32 %8
}
在每个 store 之前都有一个 load 指令
【问题讨论】:
-
您可以使用例如测试值
if(isa<Argument>(value)){…但我感觉你在做坏事。也许我的直觉是您不应该有时需要加载,它应该总是或都不需要。不管怎样,isa 就是你现在想要的。玩得开心。 -
@arnt 嗨,正如您在我的帖子中看到的,在将数组作为参数传递的函数中,生成的 IR clang 总是在
getelementptr之前使用store。但是,在本地定义数组的函数中,没有store。所以我认为需要检查代码a[0] = 1表达式中的数组是本地定义的还是作为参数传递的。感谢您的回复,我会尝试isa看看是否有效。 -
哦,等等,我现在明白了。并非 LLVM 需要 clang 所做的一切。有些东西是 LLVM 需要的,有些东西是 clang 自己的架构需要的,还有一些东西是使用中的 C/C++ ABI 需要的,最后 clang 做了很多其他方式也可以做到的事情。
-
@arnt 嗨,我认为我的问题与 LLVM 相关。我已经更新了我的帖子,你可以看看吗?
-
我不在 C/C++ 编译器中工作。我的编译器永远不会生成这样的商店。在这里猜测一下:Clang 可以创建调试信息,说明该变量可以在某某位置被调试器访问,并发出额外的指令来存储调试器将在其中查找它的变量,以防万一最终会创建调试信息并使用了调试器。这是猜测,我再说一遍,猜测。
标签: c++ llvm llvm-c++-api