【发布时间】:2019-01-02 15:07:53
【问题描述】:
我是初学者,想构建可以将 LLVM 位码转换为 Java 字节码的翻译器。
有人可以简要告诉我或列出一些主要步骤如何完成它。
【问题讨论】:
-
除了@Regis Portalez 的回答之外,这个 github 项目lljvm 可能有助于了解所需的数量
标签: llvm llvm-clang llvm-ir java-bytecode-asm
我是初学者,想构建可以将 LLVM 位码转换为 Java 字节码的翻译器。
有人可以简要告诉我或列出一些主要步骤如何完成它。
【问题讨论】:
标签: llvm llvm-clang llvm-ir java-bytecode-asm
在我们公司 (Altimesh) 中,我们为 CIL 做了同样的事情。对于 Java 字节码,任务可能非常相似。
我可以告诉你这是一项相当长的任务。
第一件事:LLVM 库是用 C++ 编写的
这意味着您要么必须学习 c++,并且要找到一种从 C++ 生成 java 字节码 的方法,要么将所需的符号从 LLVM 库导出到 JNI。我强烈推荐第二个选项,因为您将获得一个纯 Java 实现(并且您很快就会发现您不需要来自 LLVM API 的那么多符号)。
一旦你弄清楚了,你需要:
这是一个简单的例子(使用 llvm 3.9 API,现在已经很老了):
llvm::Module* llvm__Module_buildFromFile (llvm::LLVMContext* context, const char* filename)
{
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buf = llvm::MemoryBuffer::getFile(filename);
llvm::SMDiagnostic diag;
return llvm::parseIR(buf->get()->getMemBufferRef(), diag, *context).release();
}
解析调试信息
void llvm__DebugInfoFinder__processModule(llvm::DebugInfoFinder* self, llvm::Module* M) { self->processModule(*M); }
调试信息或元数据对于 llvm 来说非常麻烦,因为它们变化非常频繁(与指令相比)。因此,您要么必须坚持使用 LLVM 的版本(可能是一个糟糕的选择),要么在新的 LLVM 版本发布后立即更新您的代码。
一旦你到达那里,大部分的痛苦都会过去,你就会进入有趣的世界。
我强烈建议从非常简单的东西开始,例如简单的addition program。
然后始终打开两个窗口,godbolt 显示您需要解析的输入 llvm,以及一个 java 窗口显示您的目标 (here is an example for MSIL)。
一旦您能够转换您的第一个程序(哇,我可以添加两个整数 :)),您很快就会想要转换 more stuff,很快您将面临两个疯狂:
getelementptr。这就是在 LLVM 中访问数组、内存、结构...的方式。这是一个非常神奇的指令。
phi。 LLVM 系统中的关键指令,因为它允许 Single Static Assignment,这对于后端(寄存器分配器和 co)相当重要。我不知道在 Java 中,但这显然在 MSIL 中不可用。
一旦完成所有这些,你就会进入无尽的世界,充满特殊情况的痛苦、奇怪的 C 构造 you didn't know about、gcc 扩展等等......
祝你好运!
【讨论】: