2013-07-11 97 views
10

我正在学习llvm并希望对我的想法进行概念验证。从ExecutionEngine调用C/C++函数

基本上,我想拆分我的编译器和我的运行时。编译器会给出一个.bc,运行时会通过ParseBitcodeFile加载它,并使用ExecutionEngine来运行它。这部分工作。我希望能够在我的运行时实现所有系统调用(文件io,标准输出打印等)的C/C++函数。我的问题是,我怎么能从我的玩具编译器的代码中调用这些函数,这个编译器在llvm的另一个步骤中编译,并允许它在执行时使用。

回答

9

好消息:使用JIT ExecutionEngine时,这将只是工作。当JIT-er发现IR使用的外部符号在IR本身中找不到时,它会在JIT进程本身中查找,因此可以调用从主机程序中可见的任何符号。

这在part 4 of the LLVM tutorial直接解释:

哇,怎么了JIT了解正弦和余弦?答案是 令人惊讶的简单:在这个例子中,JIT开始执行一个 函数并进入一个函数调用。它意识到功能是 还没有JIT编译和调用标准的例程集到 来解析函数。在这种情况下,没有为 函数定义主体,因此JIT最终在“万花筒”过程本身上调用了“dlsym(”sin“)”。由于“罪恶”是在JIT的地址空间中定义的,因此它只是将模块中的调用修正为直接调用 libm版本。

对于血淋淋的细节看lib/ExecutionEngine/JIT/JIT.cpp - 特别是DynamicLibrary它的用法。

8

Eli的回答非常好,你应该接受它。还有另一种方法,即将运行时的源文件分别编译为LLVM模块(例如使用Clang)并使用ExecutionEngine::addModule()来添加它们。

它不太方便,它意味着编译两次相同的文件(一次用于您的主机程序,另一次从中获取Module),但其优点是它可以从JITted代码启用内联和其他跨功能优化。