在 llvm 教程和示例中,编译器通过这样的调用输出 LLVM IR
return Builder.CreateAdd(L, R, "addtmp");
但是很多解释器都是这样写的:
switch (opcode) {
case ADD:
result = L + R;
break;
...
您将如何提取这些代码片段中的每一个以使用 LLVM 制作 JIT,而无需在 LLVM IR 中重新实现每个操作码?
在 llvm 教程和示例中,编译器通过这样的调用输出 LLVM IR
return Builder.CreateAdd(L, R, "addtmp");
但是很多解释器都是这样写的:
switch (opcode) {
case ADD:
result = L + R;
break;
...
您将如何提取这些代码片段中的每一个以使用 LLVM 制作 JIT,而无需在 LLVM IR 中重新实现每个操作码?
好的,首先获取所有代码片段并将它们重构为它们自己的函数。所以你的代码去:
void addOpcode(uint32_t *result, uint32_t L, uint32_t R) {
*result = L + R;
}
switch (opcode) {
case ADD:
addOpcode(&result, L, R);
break;
....
好的,所以在这样做之后你的解释器应该仍然运行。现在获取所有新功能并将它们放在自己的文件中。现在使用 llvm-gcc 或 clang 编译该文件,而不是生成本机代码,而是使用“cpp”后端(-march -cpp) 编译它。这将生成为编译单元实例化字节码的 C++ 代码。您可以指定选项以将其限制为特定功能等。您可能想要使用 "-cppgen module" 。
现在将您的解释器循环粘合在一起对生成的 C++ 代码的调用,而不是直接执行原始代码,然后将其传递给一些优化器和本机代码生成器。Gratz 在 JIT 上 ;-) 你可以在几个 LLVM 项目中看到一个这样的例子,比如llvm-lua中的 vm_ops 。