11

我正在为 Timber 语言编写 LLVM 代码生成器,当前编译器发出 C 代码。我的问题是我需要从生成的 LLVM 文件中调用 C 函数,例如编译器有一个实时垃圾收集器,我需要调用函数来通知何时在堆上分配新对象。我不知道如何将这些函数与我生成的 LLVM 文件链接起来。

代码生成是通过生成 .ll 文件然后手动编译这些文件来完成的。

我正在尝试从 LLVM 调用外部函数,但我没有运气。在示例中,我发现只调用了“puts”和“printf”等 C 标准函数,但我想调用 >homemade 函数。我被困住了。

4

3 回答 3

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方法。

于 2009-10-23T04:49:25.680 回答
5

使用 llvm-as 正常编译 LLVM 程序集文件:

llvm-as *.ll

将位码文件编译为 .s 汇编语言文件:

llc *.bc

将它们与运行时库一起 GCC:

gcc *.s runtime.c -o executable

如有必要,请替换为真实的 makefile、共享库等。你明白了。

于 2010-01-01T18:54:55.613 回答
3

我将您的问题解释为“如何在 C 或 C++ 中为编译为 LLVM 的语言实现运行时库?”

正如 Jonathan Tang 所详述的,一种方法是将编译器的输出从 LLVM IR 转换为 bitcode 再到程序集,并让 vanillagcc将程序集与运行时源(或目标文件)链接起来。

另一种可能更灵活的方法是llvm-gcc将运行时本身编译为 LLVM 位码,然后llvm-ld将编译器中的位码与运行时的位码链接起来。然后可以使用 重新优化此位码opt,使用 转换回 IR llvm-dis,使用 直接解释lli(这将,afaik,仅当 LLVM 是针对 构建时才有效libffi),或编译为汇编llc(然后使用 vanilla 编译为本机二进制文件gcc)。

于 2010-01-27T03:20:00.593 回答