LLVM将0作为参数传递给外部函数调用

时间:2015-05-17 09:59:47

标签: llvm llvm-clang llvm-ir llvm-gcc

好的,也许有人可以帮助我。

我正在编写一个小型LLVM IR测试程序:

; ModuleID = 'main'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-cygwin"
define i32 @my_main() {
entry:
  %0 = alloca i64
  store i64 42, i64* %0
  %1 = load i64* %0
  call void @put_integer(i32 15)
  ret i32 0
}
declare void @put_integer(i32)

实际上它可以被剥夺:

; ModuleID = 'main'
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-cygwin"
define i32 @my_main() {
entry:
  call void @put_integer(i32 15)
  ret i32 0
}
declare void @put_integer(i32)

其中_put_integer是我用gcc或clang编译的外部程序(对问题没有关系)。

外部程序是:

#include <stdio.h>
void put_integer(int Value)
{
    printf("%d", Value);
}

我按照这样编译:

clang -c -Wall -g source/put_integer.c -o object/put_integer.o

我还有一个小型的c-main程序,可以调用我的IR程序:

#include <stdio.h>
extern int my_main(void);
int main(int argc, char *args[])
{
    printf("Calling Mainprogram\n\n");
    int n_return_value = my_main();
    printf("\n\nMainprogram Returned: %u\n", n_return_value); 
    return n_return_value;
}

使用与上面相同的参数进行编译。我将两个外部目标文件放入一个库中,然后组装我的LLVM IR程序,并通过以下方式将它与两个外部C函数链接:

llc -filetype=obj test.bc -o test.o
gcc -L ./../RuntimeSystem/ test.o -lmy_runtime  -o test.exe

这很好用,程序启动并运行。

问题是实际的printf()调用打印0而不是我作为IR调用的参数给出的15。我使用gdb进入创建的程序并检查了put_integer()函数中的堆栈框架,并且确定它将0作为参数传递。

所以现在有一个问题,就是我传递给LLVM IR调用的参数不会被传递给外部C函数,而是传递给0。

有人可以告诉我我做错了吗?

谢谢

编辑: 基于下面的评论,我在此处包含了IRBuilder代码,该代码在第一个块中创建了上述IR代码的相关部分。

Constant *left = ConstantInt::get( getGlobalContext(), APInt( 32, 15 ) );

FunctionType *printf_type =
    TypeBuilder<void( int ), false>::get( getGlobalContext() );

Function *func = cast<Function>( MODULE.getOrInsertFunction(
    "put_integer", printf_type ) );

BUILDER.CreateCall(func,left );

我的理解是,在IR中对函数的正确调用必须包含函数类型,如本例中的LLVM参考手册所示:

call i32 (i8*, ...)* @printf(i8* %msg, i32 12, i8 42)

然而,我的代码(我从这里得到的答案中得到的)并没有产生,但是我猜想IRBuilder类应该知道最好生成什么代码,所以我不知道这是不是是不是问题。

1 个答案:

答案 0 :(得分:0)

嗯,就我而言,答案是我在LLVM模块中使用了错误的目标三元组。没有有效的三元组列表,我通过编译和拆解C程序以一种不起眼的方式获得了我的,但事实证明这是错误的。

如果有人使用cygwin,正确的目标三元组是:

x86_64-unknown-windows-cygnus

看来,如果错误的目标三元组,对外部函数的调用使用了错误的参数传递类型,结果是没有参数到达它。