我正在为Timber语言编写LLVM代码生成器,当前的编译器会发出C代码。我的问题是我需要从生成的LLVM文件中调用C函数,例如编译器有一个实时垃圾收集器,我需要调用函数来通知何时在堆上分配新对象。我不知道如何将这些函数与生成的LLVM文件链接起来。
代码生成是通过生成.ll文件然后手动编译它们来完成的。
我正在尝试从LLVM调用外部函数,但我没有运气。在示例中,我发现只有“put”和“printf”等C标准函数被调用,但我想调用一个>自制函数。我被卡住了。
答案 0 :(得分:12)
我假设您正在编写LLVM转换,并且您希望将对外部函数的调用添加到转换后的代码中。如果不是这种情况,请编辑您的问题并提供更多信息。
在从LLVM代码调用外部函数之前,需要为其插入声明。例如:
virtual bool runOnModule(Module &m) {
Constant *log_func = m.getOrInsertFunction("log_func",
Type::VoidTy,
PointerType::getUnqual(Type::Int8Ty),
Type::Int32Ty,
Type::Int32Ty,
NULL);
...
}
上面的代码声明了一个函数log_func
,它返回void并接受三个参数:一个字节指针(字符串)和两个32位整数。 getOrInsertFunction
是Module
的一种方法。
要实际调用该函数,您必须插入CallInst
。有几种静态Create
方法。
答案 1 :(得分:5)
使用llvm-as:
正常编译LLVM程序集文件llvm-as *.ll
将bitcode文件编译为.s汇编语言文件:
llc *.bc
使用运行时库GCC它们:
gcc *.s runtime.c -o executable
必要时替换真实的makefile,共享库等。你明白了。
答案 2 :(得分:3)
我正在将您的问题解释为“我如何使用C或C ++为我的语言实现运行时库,并将其编译为LLVM?”
正如Jonathan Tang所详述的,一种方法是将编译器的输出从LLVM IR转换为bitcode转换为汇编,并使vanilla gcc
将程序集链接到运行时源(或目标文件)。 / p>
另一种可能更灵活的方法是使用llvm-gcc
将运行时本身编译为LLVM bitcode,然后使用llvm-ld
将编译器中的bitcode与运行时的bitcode链接起来。然后可以使用opt
重新优化此bitcode,使用llvm-dis
转换回IR,直接使用lli
进行解释(这将是afaik,仅当LLVM针对{{1}构建时才有效}},或者使用libffi
编译成程序集(然后编译为带有vanilla llc
的本机二进制文件)。