我最近一直在研究编译器设计。我已经成功掌握了解析阶段,但在理解代码生成方式方面遇到了一些麻烦。
根据我的阅读,代码生成阶段似乎有三个主要步骤:
现在,指令调度有点超出了我此刻想要做的事情,而且我认为通过更多的研究和原型设计,我可以将注意力集中在用于寄存器分配的图着色算法上。
困扰我的是第一步,指令选择。根据我所读到的内容,目标机器语言中的每条指令都由一个磁贴表示;并且目标是找到与树的最大部分匹配的指令(因此昵称,贪婪的平铺)。
我感到困惑的是,当他们实际上没有与语法树1:1对应时,如何选择说明?
例如,基于累加器的体系结构,如Z80或MIPs单指令体系结构。在Z80上执行偶数16位整数运算可能需要使用累加器或影子寄存器。
还有一些指令只能用于某些寄存器,尽管它们是通用的。
我是否正确地承担以下事项?
a)磁贴可能包含一系列与语法树模式匹配的指令,而不仅仅是1:1匹配。
b)代码生成器首先为基于堆栈的架构(或具有无限临时寄存器的架构)生成代码,并在寄存器分配阶段以某种方式扩展和替换指令。答案 0 :(得分:3)
a)磁贴可以发出任意数量的指令。例如,如果您有%x <- %y + %z
之类的指令,但目标机器只有两个地址指令,那么匹配的磁贴可能会发出汇编序列(目标是第一个操作数)
mov %x, %y
add %x, %z
b)允许哪种寄存器(或const或mem引用)作为指令的操作数由指令本身决定,因此指令选择阶段必须使用符号寄存器名称(伪寄存器)进行表示。寄存器分配阶段确实可以发出附加指令,例当所需类的寄存器不可用于分配时溢出/加载代码。
检查一下 Survey on Instruction Selection: an Extensive and Modern Literature Review