我想对LLVM IR中的每个功能进行一些分析。但是,当我从示例c代码生成LLVM IR代码时,我发现在某些情况下,函数的参数编号与示例c代码不同。例如:
我的示例c代码如下:
struct outer_s{
int a;
int b;
int c;
};
void func_a(struct outer_s z){
// nothing
}
但是,生成的LLVM IR代码如下:
%struct.outer_s = type { i32, i32, i32 }
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @func_a(i64, i32) #0 {
%3 = alloca %struct.outer_s, align 4
%4 = alloca { i64, i32 }, align 4
%5 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %4, i32 0, i32 0
store i64 %0, i64* %5, align 4
%6 = getelementptr inbounds { i64, i32 }, { i64, i32 }* %4, i32 0, i32 1
store i32 %1, i32* %6, align 4
%7 = bitcast %struct.outer_s* %3 to i8*
%8 = bitcast { i64, i32 }* %4 to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %7, i8* align 4 %8, i64 12, i1 false)
ret void
}
如上所述,“ struct external_s z”参数分为两部分。如果我使用API来获取函数参数,那么我得到的参数编号也是2。
由于我的分析是从函数参数开始的,因此错误的参数num会导致错误的结果。因此,我想知道是否可以使用LLVM Pass或clang参数来避免那些“拆分”情况?
答案 0 :(得分:0)
简短的回答:不,您需要处理它。
长答案:不,您需要处理它。更糟糕的是,这里的IR非常依赖于目标,因为参数传递规则是由平台ABI定义的。这是许多并发症,因为它们通常是根据源语言声明的。因此,我们需要找到一种通过LLVM IR为这些规则建模的方法,该方法通常比原始方法低很多。通常,这是一个非常重要的过程(例如,通过值,向量,齐次聚合等传递结构),并且该过程在某种意义上可能对原始源具有“破坏性”,并且映射不是一对一的。您不能“关闭”此过程,因为这是正确的事情。