2011-05-28 51 views
2

我已将一些C函数编译为LLVM字节码。 现在我想让这些功能可以通过Lua脚本引擎访问,然后将Lua脚本编译为本地机器代码。使用LLVM JIT编译lua包装的C函数?

我找到了使用llvm编译lua脚本的llvm-lua项目。 我现在想知道是否可以执行从lua脚本调用的C函数的jit编译和优化。

例如,我有这两个C函数:

void func1() { 
    for(int i = 1; i < 5; ++i) 
    printf("hello from func1"); 
} 
void func2() { 
    for(int i = 1; i < 5; ++i) 
    printf("hello from func2"); 
} 

和我揭露他们的一个Lua脚本引擎并运行Lua中那样:

func1() 
func2() 

然后我想的llvm-lua编译器将其优化并编译成相应程序

for(int i = 1; i < 5; ++i) { 
    printf("hello from func1"); 
    printf("hello from func2"); 
} 

不是分成

for(int i = 1; i < 5; ++i) 
    printf("hello from func1"); 
for(int i = 1; i < 5; ++i) 
    printf("hello from func2"); 

有没有可能实现这一点?

干杯,

曼努埃尔

+0

是的,这听起来像是可能的,至少在抽象中......你有什么特别的麻烦? – servn 2011-05-29 23:19:39

+4

没有编译器会执行该优化,因为它执行可观察的差异(输出将按不同顺序排列)。 – celion 2011-05-30 01:07:10

+2

你看过luajit吗?最新的版本是非常有前途的速度 - 也许你可以完全摆脱C。 – 2011-06-23 02:39:23

回答

3

对于任何一种像你想在这里实现了一个复杂的程序改造,这是最好的去除尽可能多的中间环节增加复杂性越好。首先证明它适用于最简单的情况,然后逐步将复杂性添加回来。对于你的特定问题,这可以转化为:尝试获得所需的优化,以便在纯C代码中使用同一文件中的所有代码,然后在不同文件中使用纯C代码等。如果不能在所有代码中都发生这种情况的更简单的情况下,那么你可以使它为最初的目标工作并且增加所有的复杂性是相当不可能的(并且通过一步一步地做,你也会更好地了解你遇到的任何问题的可能原因) 。

如果你按照上面的建议,我非常有信心(虽然我还没有尝试过),你需要的优化将由LLVM优化器来完成,即使在具有一切最简单的情况单一的C文件并运行完全优化。原因在于你希望优化器改变你的代码的语义,因为两个连续的for循环不能保证有一个单一的for循环具有相同的副作用(可观察到的变化)你提供的代码就是一个很好的例子)。为了优化是安全的,编译器必须能够保证(证明)关于从循环体执行的所有代码的副作用的各种属性。虽然不是不可能,但在一般情况下,使用C等不受控制的副作用的语言很难做到,并且在大多数情况下,如果您跨越任何图书馆边界(如您在此处可能会遇到的情况)则不可行,因为你实际上没有一个统一的优化步骤(至少在理论上)可以考虑所有必要的代码。如果您真的想深入研究LLVM及其优化器框架,我建议您首先阅读excellent article outlining the motivations and design of LLVM,然后找出优化器必须能够在一个步骤中查看哪些代码才能实现。

我推荐你想想你的动机是什么,试图让Lua编译成LLVM位码,并与来自C的LLVM位码一起优化。我确信有合理的理由,但除非你绝对相信这是实现你的目标的唯一方法,那么我个人会尝试一种不同的方法。

可以说你的主要动机是表现。正如Andrew Y已经提到,我建议看看luajit。它使纯(正确书写)Lua to perform close to Cmany times better than standard Lua,它还包括一个Foreign Function Interface (FFI)这可能会有助于您的问题。从FFI页:

的FFI库允许主叫用C数据结构从纯Lua代码外部C函数

FFI库很大程度上避免了在C中编写乏味的手动Lua/C绑定的需要。无需学习单独的绑定语言 - 它分析纯C语言声明!这些可以从C头文件或参考手册中剪切粘贴。无需处理脆弱的绑定生成器就可以完成绑定大型库的任务。

FFI库紧密集成到LuaJIT中(它不作为单独的模块提供)。由JIT编译器生成的用于访问来自Lua代码的C数据结构的代码与C编译器将生成的代码一致。调用C函数可以在JIT编译的代码中内联,不像调用通过传统的Lua/C API绑定的函数。