如何使用LLVM将基于堆栈的虚拟机字节码转换为SSA格式 [英] How to use LLVM to convert stack-based virtual machine bytecode to SSA form
本文介绍了如何使用LLVM将基于堆栈的虚拟机字节码转换为SSA格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
有许多关于如何将SSA表示转换为堆栈计算机的问题,但我对相反的情况很感兴趣。
问题
考虑具有有条件/无条件跳转的基于堆栈的VM,其中每个操作码都有固定数量的它消耗和生成的堆栈元素。
LLVM框架中是否有工具/方法可以从字节码输出重构SSA表单。这实质上是一种反汇编形式。
llvm
推荐答案本身没有工具,只是sSMoP。我已经做到了。有些是困难的,但任何事情都是困难的。我会回答,而不是评论,对最困难的部分漫无边际。
堆栈通常是无类型的;位于堆栈顶部的值具有类型,但"堆栈顶部"没有类型。LLVMValue
总是有一个类型,当代码包含循环时,这两个系统会发生冲突。请考虑以下代码:
int a = b();
while(a<10)
a++;
a
有一个类型,其所有值都将为int(在LLVM IR中可能为I32)。当第一行将返回值从b()
推送到堆栈上时,堆栈顶部的类型为int。您可能可以想象这些线条在堆栈机器上是什么样子。应该这样翻译成IR:
entry:
%a1 = call @b();
br label %b1
b1:
%stack.0.b1 = phi i32 [%entry, %a1], [%b1, %a2]
%a2 = add i32 1, %stack.0.b1
%done = icmp ult i32 %stack.0.b1, 10
br i1 %done, label %b1, label %b2
b2:
(很抱歉出现语法错误,我手写的IR不多。)
您可能会看到,除了phi
之外的每条指令都可以从堆栈语言中的一条指令生成。可能堆栈语言中的指令会导致多个IR指令,或者不会导致IR指令,例如DUP或Push-Constant-Zero,它们只会修改堆栈。
phi
不同,它表示该点的堆栈。
挡路b1
条目上的堆栈是根据entry
和b1
中每一个结尾处的堆栈计算出来的。您可以在每个基本挡路的开头为堆栈上的每个值生成一个Phi节点;挑战在于每个Phi节点的类型取决于前面块末尾的堆栈上的类型。在这种情况下,entry
末尾的堆栈有一个条目a1
,b1
结尾的堆栈有一个条目a2
。因此,stack.0.b1
的类型取决于a2
的类型,而a2
的类型又取决于stack.0.b1
。您需要认真考虑这一点,特别是如果您的语言包含隐式类型提升或强制转换(从I32到I64,从字符串到对象等)。
(我本可以从类似Ruby的系统和代码开始,而不是类似于c;我认为最后的问题是相同的,只是您的解决方案不同。)
这篇关于如何使用LLVM将基于堆栈的虚拟机字节码转换为SSA格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文