好的,也许有人可以帮助我。
我正在编写一个小型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类应该知道最好生成什么代码,所以我不知道这是不是是不是问题。
答案 0 :(得分:0)
嗯,就我而言,答案是我在LLVM模块中使用了错误的目标三元组。没有有效的三元组列表,我通过编译和拆解C程序以一种不起眼的方式获得了我的,但事实证明这是错误的。
如果有人使用cygwin,正确的目标三元组是:
x86_64-unknown-windows-cygnus
看来,如果错误的目标三元组,对外部函数的调用使用了错误的参数传递类型,结果是没有参数到达它。