LLVM自动C ++链接

时间:2010-08-23 21:11:22

标签: c++ llvm

在一些LLVM教程中,我看到将C函数绑定到基于LLVM的自定义语言相当容易。 LLVM向程序员提供指向该函数的指针,然后该函数可以与LLVM生成的代码混合在一起。

使用C ++库执行此操作的最佳方法是什么。假设我有一个相当复杂的库,比如Qt或Boost,我想绑定到我的自定义语言。我是否需要创建存根库(如Python或Lua需要),或者LLVM是否提供某种外部函数接口(FFI)?

2 个答案:

答案 0 :(得分:13)

在我的LLVM代码中,我为此创建了extern "C"包装器函数,并将LLVM函数声明插入到模块中以便调用它们。然后,让LLVM了解函数的一个好方法是不要让它使用dlopen并在执行二进制文件中搜索函数名称(这是一个痛苦的屁股,因为函数名称需要在.dynsym部分,也很慢),但要使用ExecutionEngine::addGlobalMapping手动执行映射。

只需获取该声明的llvm::Function*和C ++中给出的&functionname转换为void*的函数的地址,并将这两项内容传递给LLVM。执行您的东西的JIT将知道在哪里找到该功能。

例如,如果你想包装QString,你可以创建几个创建,销毁和调用这种对象函数的函数

extern "C" void createQString(void *p, char const*v) {
  new (p) QString(v); // placement-new
}

extern "C" int32_t countQString(void *p) {
  QString *q = static_cast<QString*>(p);
  return q->count();
}

extern "C" void destroyQString(void *p) {
  QString *q = static_cast<QString*>(p);
  q->~QString();
}

并创建适当的声明和映射。然后你可以call这些函数,传递一个适当的对齐和大小适合QString(可能是alloca'ed)的内存区域和一个指向C字符串数据的i8*初始化。

答案 1 :(得分:3)

如果你用C ++编译一些代码,用另一种语言编译一些代码到LLVM bitcode,那么完全可以将这些代码链接在一起,让一个人调用另一个...理论上。

实际上,您需要使用胶水代码在不同语言的类型之间进行转换(例如,除非您使用CPython,否则在C ++中没有等效的Python字符串,因此void reverse(std::string s)可以使用{{1}进行调用你需要一个转换 - 更糟糕的是,整个对象模型是非常不同的)。而Qt特别具有很多魔力,可能需要更多努力才能在编译后暴露出来。此外,还有一些我不知道的潜在问题。

即使这样有效,使用它也可能非常难看。尽管Python是非常方便的描述符,但PyQt上仍然有strget*个函数 - 并且PyQt付出了很多努力,它们不只是创建了一些存根。