有没有可能直接遍历AST生成SSA形式的中间代码,而不是先生成quad四元式,再转换为SSA形式?

软件工程师、主攻高级编程语言虚拟机的设计与实现

158 👍 / 13 💬

问题描述

我看的代码lcc, ucc,分别都是生成的DAG和传统的quad四元式,而书上,比如龙书,data flow analysis: theory and pratice都是讲的将普通的四元式转换成SSA形式。据我所知,hotspot的client compiler将HIR改成了SSA形式,但是有没有文档参考。。。
求问有什么资料参考的?

嗯这个问题问得好。答案是:可以从AST直接生成SSA,而且这是种很好的做法。

——前提是,输入语言是一种遵守结构化编程思想的语言。Wiki传送门:

Structured programming

(我最近业余在做的一个编译器就是直接从AST进SSA的。回头等进展更多之后我再把链接更新到这个回答)

龙书和其它一些编译原理的书在介绍进入SSA形式的算法时,以四元式为输入,原因我猜有这么几个:

事实上,比较新一点的编译器有不少都是让SSA形式尽可能贯穿整个编译流程的。

例如说LLVM,除了最终的code gen之外,都使用同一种IR——LLVM IR,而它就是始终都是SSA形式的。同时它留了个后门给编译器前端:前端可以选择用alloca来“声明”局部变量,然后让LLVM的mem2reg pass把这些局部变量转进SSA形式,这样前端就不总需要担心生成SSA的负担了。

又例如说HotSpot Client Compiler (C1)、V8 Crankshaft、ART Optimizing Compiler这仨同源兄弟都采用了SSA形式的HIR用于优化,和传统形式的LIR用于寄存器分配和代码生成,

(更新:哈哈,我才回答这个问题,ART就准备把SsaBuilder合并到HGraphBuilder里了——就变得跟C1的结构一样了。参考这里:

Change 202670: ART: Run SsaBuilder from HGraphBuilder

这仨兄弟进入SSA形式的方式,ART Optimizing虽然比C1多了一个中间步骤(生成了非SSA形式的HIR),但本质上差别不大,前者可能只是比后者在处理irreducible loop要略好一些;但V8 Crankshaft则跟另外俩兄弟都不一样。差异在哪里?

我觉得最重要的差异在于:

讲述直接从AST(或者甚至从源码)构造SSA形式的论文,有这么几篇是我比较喜欢的(从老到新):

上面第三篇论文其实也提到了,构造SSA的简易做法其实很容易从只能处理结构化控制流扩展为可以处理任意控制流(包括irreducible loop)。不过,如果已知输入的程序是结构化的,就不用那么高端的方法而可以用更简单的做法了,何乐而不为。