Compiler construction 将堆栈推送循环转换为三地址码基本块

Compiler construction 将堆栈推送循环转换为三地址码基本块,compiler-construction,ssa,Compiler Construction,Ssa,我一直在为一个超级简单的基于堆栈的语言开发一个小型编译器(使用llvm,但应该没关系) 我已经阅读了很多关于将基于计算堆栈的语言转换为TAC或SSA的文章,通常概述的基本过程是将代码划分为基本块,然后分析每个指令的堆栈高度,并以此为名称为堆栈中的每个位置分配寄存器。然后,分析基本块的净推送和POP,并根据需要转发它们之间的注册表 然而,有了这些信息,有一个简单的案例我无法理解。例如,以下伪代码: 1: ... 2: READ 3: IF 0 GO TO 4 ELSE GOTO 2 4: ...

我一直在为一个超级简单的基于堆栈的语言开发一个小型编译器(使用llvm,但应该没关系)

我已经阅读了很多关于将基于计算堆栈的语言转换为TAC或SSA的文章,通常概述的基本过程是将代码划分为基本块,然后分析每个指令的堆栈高度,并以此为名称为堆栈中的每个位置分配寄存器。然后,分析基本块的净推送和POP,并根据需要转发它们之间的注册表

然而,有了这些信息,有一个简单的案例我无法理解。例如,以下伪代码:

1: ...
2: READ
3: IF 0 GO TO 4 ELSE GOTO 2
4: ...
假设READ是一个从某处获取值并将其推入堆栈的函数,该函数将使用READ指令创建一个简单的基本块,可能是一个减法,最后是一个分支(假设if没有从堆栈中弹出值)

问题是,如果我只分析堆栈的使用情况,就没有POP,只有一次推送,所以我只需要传递一个值。但是,随着循环的进行,因为只有一个用于存储的注册表,所有读取都将丢失

我没有找到任何关于这个案子的文字。一个程序应该和转换后的程序一起保存一个真正的堆栈吗?如果是这种情况,那么确定何时必须将值从实际堆栈中推出或弹出似乎并不简单,因为它取决于所有基本块之间的关系


有关于这方面的文章或报纸吗?非常感谢您的帮助。

在本例中,您的
IF
测试会弹出(消耗)由
读取推送的值。不一定。在我的例子中,它不是。我将对问题进行编辑以反映这一点。您的
0
是什么,那么,如果不是
READ
的结果,JVM字节码堆栈机器通过要求堆栈在所有控制流合并时具有相同的高度和数据类型来避免这个问题(循环中“堆叠”的任何数据都必须放在堆上)。如果您不能强制执行,则需要一个真正的运行时堆栈,可能还需要一些动态类型检查(如果您的语言有多个类型)。