使用LLVM JIT编译lua包装的C函数?

时间:2011-05-28 11:17:06

标签: optimization lua jit llvm

我已经将一些C函数编译成LLVM字节码。 现在我想让Lua脚本引擎可以访问这些函数,然后将Lua脚本编译成本机代码。

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

,例如,我有这两个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");

有可能实现吗?

干杯,

曼努埃尔

1 个答案:

答案 0 :(得分:3)

对于任何类型的复杂程序转换,例如您要在此处尝试实现的转换,最好删除尽可能多的中间步骤以增加复杂性。首先证明它适用于最简单的情况,然后逐步添加复杂性。对于您的特定问题,这转换为:尝试在纯C代码上进行所需的优化,同一文件中的所有代码,然后是不同文件中的纯C代码等。如果你不能在所有代码中实现它对于更简单的情况,那么你不太可能使它在原始目标上运行并具有所有额外的复杂性(并且通过逐步完成它你也会对你遇到的任何问题的可能原因有更好的了解)

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

我建议考虑一下你的动机是什么,试图让Lua编译成LLVM bitcode并与来自C的LLVM bitcode一起优化。我确信有合理的理由,但除非你绝对相信这是实现目标的唯一途径,然后我个人尝试不同的方法。

让我们说你的主要动机是表现。正如Andrew Y已提到的那样,我建议您好好了解luajit。它支持纯(写得很好)Lua to perform close to Cmany times better than standard Lua,还包含Foreign Function Interface (FFI),可能对您的问题有所帮助。从FFI页面:

  

FFI库允许从纯Lua代码中调用外部C函数使用C数据结构

     

FFI库在很大程度上避免了在C中编写繁琐的手动Lua / C绑定的需要。无需学习单独的绑定语言 - 它解析普通的C声明!这些可以从C头文件或参考手册中剪切粘贴。这取决于绑定大型库而不需要处理脆弱的绑定生成器。

     

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