Clang如何为函数参数生成代码?

时间:2016-11-20 20:53:29

标签: llvm static-analysis callstack llvm-ir

在函数中,我想知道参数如何传递到函数体中,以便跟踪参数的流动。我尝试了一个简单的代码,发现每个参数似乎都有alloc - store模式,我想知道它是否真实?

演示代码

int add(int x, int y){
    return x+y;
}

它产生的llvm是:

; Function Attrs: nounwind uwtable
define i32 @add(i32 %x, i32 %y) #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 %x, i32* %1, align 4
  store i32 %y, i32* %2, align 4
  %3 = load i32, i32* %1, align 4
  %4 = load i32, i32* %2, align 4
  %5 = add nsw i32 %3, %4
  ret i32 %5
}

在示例中我们可以看到,

  1. 对于每个参数,Clang使用alloc指令来定义a     局部变量

  2. 遵循alloc指令,我会使用store条指令     分配值?

  3. 我的问题是:

    1. 是否所有功能LLVM IR都以此allocstore模式生成?或者LLVM究竟对参数做了什么?
    2. parameters的顺序由其使用的惯例决定?

1 个答案:

答案 0 :(得分:1)

我认为这种模式适用于没有编译时优化的代码;但是,如果您使用-O3(或任何应用mem2reg优化的代码)编译代码,则此模式已经过优化:

(clang -emit-llvm -S -O0 add.c)

define i32 @add(i32 %x, i32 %y) #0 {
  %1 = alloca i32, align 4
  %2 = alloca i32, align 4
  store i32 %x, i32* %1, align 4
  store i32 %y, i32* %2, align 4
  %3 = load i32, i32* %1, align 4
  %4 = load i32, i32* %2, align 4
  %5 = add nsw i32 %3, %4
  ret i32 %5
}

(opt -mem2reg add.ll -o add_m.ll)

define i32 @add(i32 %x, i32 %y) #0 {
  %1 = add nsw i32 %y, %x
  ret i32 %1
}

因此,如果您正在控制所分析的所有代码,那么您可以依赖此模式。我建议您使用LLVM API来获取函数参数。下面的代码遍历函数F的参数,并在转换为值后打印它们。

for (auto AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI)
{
    Value* v = &*AI;
    errs() << *v << "\n";
}

上述样本中的值可以与IR中任何其他值相同的方式使用。