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



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

我已经找到了使用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");

有可能实施吗?

干杯,

Manuel

对于任何类型的复杂程序转换,如您试图在这里实现的转换,最好删除尽可能多的增加复杂性的中间步骤。首先证明它适用于最简单的情况,然后逐步增加复杂性。对于您的特定问题,这意味着:尝试在同一文件中的所有代码都在纯C代码上进行所需的优化,然后在不同文件中的纯C代码中进行优化,等等。如果您不能在所有更简单的情况下实现这一点,那么,你不太可能用额外的复杂性来实现最初的目标(通过一步一步地做,你也会对遇到的任何问题的可能原因有更好的了解)。

如果你遵循上面的建议,我很有信心(尽管我还没有尝试过),你想要的优化将不会由LLVM优化器完成,即使是在最简单的情况下,将所有内容都放在一个C文件中,并以完全优化的方式运行。原因是您希望优化器更改代码的语义,因为两个连续的for循环不能保证具有与两个主体按顺序执行的单个for循环相同的副作用(可观察到的变化)(您提供的代码就是一个很好的例子)。为了使优化安全,编译器必须能够保证(证明)从循环体执行的所有代码的副作用的各种属性。虽然并非不可能,但在一般情况下,在C等具有不受控制的副作用的语言中,这是非常困难的,而且在大多数情况下,如果你正在跨越任何库边界(就像你可能在这里做的那样),这是不可行的,因为你实际上没有一个统一的优化步骤,(至少在理论上)可以考虑所有必要的代码。如果你真的想更深入地研究LLVM及其优化器框架,我建议你从阅读这篇概述LLVM动机和设计的优秀文章开始,然后找出优化器必须能够在一个步骤中查看哪些代码才能实现。

我建议你思考一下,让Lua编译成LLVM比特码并与C的LLVM比特代码一起优化的动机是什么。我相信有正当的理由,但除非你绝对相信这是实现目标的唯一途径,否则我个人会尝试不同的方法。

假设你的主要动机是表现。正如Andrew Y已经提到的,我建议好好看看luajit。它使纯(写得很好)Lua的性能接近C,比标准Lua好很多倍,而且它还包括一个可能有助于解决问题的外部函数接口(FFI)。从外国金融机构页面:

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

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

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

最新更新