2016-11-20 60 views
1

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

甲演示代码是

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

IR它产生的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. 对于每一个参数,所述锵使用alloc指令来定义 局部变量

  2. alloc指令后,store指令是用来给 赋值的吗?

我的问题是:

  1. 是所有功能LLVM IR在此allocstore模式产生的?或者LLVM如何处理这些参数?
  2. parameters的顺序是由它使用的惯例决定的?
+0

次要评论:您似乎在问如何clang生成LLVM IR,而不是LLVM如何生成代码。 –

+0

@IsmailBadawi感谢您的评论,我编辑了这个问题。 – Qoros

回答

1

我认为这种模式适用于没有编译时优化的代码;但是,如果你不是编译-O3(或任何适用的mem2reg优化)的代码,这种模式优化了:

(铛-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 
} 

(选择-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中的任何其他值的使用方式相同。

+0

谢谢,Brian。我按照你的指示尝试过,但是它打印的是'i32%x'。我想知道如何测试两个值是否相等,例如,在二进制文件中,每个指针存储它指向的地址。 – Qoros

+0

这是一个不同的问题。检索每个函数参数的Value *后,您就可以使用它进行进一步分析。这可能与最初标记的一样是静态的,在这种情况下,您可能需要构建控制流图以及通过每个函数使用变量。动态地,您可以通过添加额外的IR来检查相等性,即通过构建比较或将值传递给单独的支持例程来检查输入值。 我的例子是为了展示一种简单的方式来初始访问这些值并对它们做些什么。 – Brian

+0

感谢您的指导。 – Qoros

相关问题