LLVM IR中函数的参数编号与源代码不同

时间:2019-07-27 07:10:32

标签: c llvm llvm-clang llvm-ir

我想对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参数来避免那些“拆分”情况?

1 个答案:

答案 0 :(得分:0)

简短的回答:不,您需要处理它。

长答案:不,您需要处理它。更糟糕的是,这里的IR非常依赖于目标,因为参数传递规则是由平台ABI定义的。这是许多并发症,因为它们通常是根据源语言声明的。因此,我们需要找到一种通过LLVM IR为这些规则建模的方法,该方法通常比原始方法低很多。通常,这是一个非常重要的过程(例如,通过值,向量,齐次聚合等传递结构),并且该过程在某种意义上可能对原始源具有“破坏性”,并且映射不是一对一的。您不能“关闭”此过程,因为这是正确的事情。