LLVM:访问函数中的数组参数 我试图用LLVM C++ API编写编译器,我试图在函数中访问数组参数。

LLVM:访问函数中的数组参数 我试图用LLVM C++ API编写编译器,我试图在函数中访问数组参数。,c++,llvm,llvm-c++-api,C++,Llvm,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 如果将数组作为参数传递,我需要首先使用builder.CreateStore(),然后使用llvm::GetElementPtrInst::

就我从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
如果将数组作为参数传递,我需要首先使用
builder.CreateStore()
,然后使用
llvm::GetElementPtrInst::CreateInBounds()
获取指向索引的指针

但是,在编写编译器时,我使用了访问者模式,并将
a[0]=1
等代码视为
assign expression
。当访问树节点
assign_expression
时,我需要确定是否需要
加载

有没有办法确定数组是本地定义的变量还是参数

更新1: 例如,在C中,如果函数定义如下:

Analysis/BasicAliasAnalysis.cpp

 167   if (isa<Argument>(V))
 168     return true;
无效测试(int a[]{
a[0]=1;
}
<> >对应的LVVM C++代码,<代码> A[0 ]=1 < /C> >如下:

for(auto arg=theFunction->arg_begin();arg!=theFunction->arg_end();arg++){
auto param=builder.CreateAlloca(llvm::Type::getInt32Ty(上下文)->getPointerTo());
builder.CreateStore(arg,param);
}
//a[0]=1
自动加载\u tmp=builder.CreateLoad(参数);
auto value=llvm::GetElementPtrInst::CreateInBounds(tmp,{Const(0),Const(0)},“,基本块);
但是,当数组定义为本地时,代码
auto-load\u tmp=builder.CreateLoad(param)是不需要的。所以我的问题是:我如何知道我是否需要
CreateLoad

更新2: clang为以下C代码生成的LLVM IR:

inth(inta[]{
a[0]=1;
a[1]=2;
}

在每个
存储之前都有
load
指令

有没有办法确定数组是本地定义的变量还是参数

方法1:


使用
isa

您可以使用例如
if(isa(值))测试值{…
但我有一种感觉,你在做坏事。也许我的直觉是,你不需要有时加载,应该总是加载,或者两者都不加载。总之,isa就是你现在想要的。玩得开心。@arnt嗨,正如你在我的帖子中看到的,在一个数组作为参数传递的函数中,生成的IR clang总是使用
存储
getelementptr
之前。但是,在本地定义数组的函数中,没有
store
。因此我认为需要检查代码
a[0]中的数组=1
表达式是本地定义的或作为参数传递的。感谢您的回复,我将尝试
isa
看看它是否有效。哦,等等,我现在明白了。不是clang所做的每件事都是LLVM所要求的。有些东西是LLVM所要求的,有些东西是clang自己的体系结构所要求的,还有一些东西是C/C所要求的++ABI正在使用中,最后clang做了许多也可以用其他方式完成的事情。@arnt嗨,我想我的问题与LLVM有关。我已经更新了我的帖子,你能检查一下吗?我不是在C/C++编译器中工作的。我的编译器永远不会生成这样的存储。这里猜测一下:clang可以创建表示变量为accessib的调试信息le在某个位置发送给调试器,并发出额外指令将变量存储在调试器将查找它的位置,以防最终创建调试信息并使用调试器。这是猜测,我重复一遍,猜测。感谢您的回复,但是,
加载
指令之前有一个
存储
函数UCION,与以下llvm ir类似:
store i32*%0,i32**%3;%4=load i32*,i32**%3
,使值加载不是函数的参数……在分析之前运行mem2reg似乎应该消除冗余的store+load对。如果不可能,则需要遵循def use链,直到最后一个并使用
isa
对您有利。
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
}
Analysis/BasicAliasAnalysis.cpp

 167   if (isa<Argument>(V))
 168     return true;