背景
Swift 语言的实现借助了 LLVM,Swift 和 LLVM 的发明人 Chris Lattner,曾说过,Swift 语言就是 LLVM 的巨大语法糖。LLVM 定义了一种中间语言。所有经过前端编译的语言,在经过词法分析、语法分析、语义分析之后,LLVM 会帮助其生成对应的 LLVM 中间语言,然后这些中间语言表示的程序就可以进行各种优化处理,然后转换成不同平台的汇编语言。 LLVM 的出现可以说让发明一门语言的难度大幅减少了。关于 LLVM 更多介绍可以查看 Chris 自己的文章 ,见引用1。
Swift 语言在编译的时候会转换成 Swift 中间语言(Swift Intermediate Language,简称 SIL)。那么在已经有 LLVM IR (中间语言)的情况下,为什么不是直接转换成 LLVM 中间语言呢?而是多了一步先是转换成 SIL 然后才转换到 LLVM IR?
前言
具体内容可以查看 Youtube LLVM 官方视频的介绍(见引用2),以下内容是对该视频内容前半部分的总结,同时包含了一些作者自己的理解。(视频的后半部分是 Chris 举了几个例子来描述 SIL 是如何工作的。对于编译感兴趣的可以看看,能学到很多)
为什么需要 SIL
从 clang 中吸取的教训
类 c 语言的编译过程如下:
但是在实际编译的代码实现中是这样的:
很容易就能看出来这两张图想要表达的意思,在第二张图中,语法分析和语义分析之间很乱,然后语义分析生成 的 AST‘ 在转换成 IR 的时候也是相当的曲折,同时 AST‘ 也承担了支持代码的静态分析的前置责任。在静态分析和生成 IR 这两者之间其实有很多重复的逻辑。
总结一下:
- 源代码和 LLVM IR 之间有一个巨大的抽象层(但是这个抽象层在 clang 里面实现的并不完美)
- IR 对于源代码级别的静态分析不够友好
- clang 的静态分析实现(CFG)不够好同时,和 IR 有很多重复。
Swift 的特点
Swift 是一门高级的语言,很多语言的特性是靠语言自身实现的(比如 Swift 的 Int 这些就是 Swift 语言实现的),并且 Swift 的范型基于 Protocol。Swift 也是一门安全的语言,很多不安全的操作,比如未初始化的变量,死代码等等需要在尽早的阶段就能发现(意味则代码的静态分析很重要)。
以下是 Swift 的编译过程:
可以看到,SIL 将原本在 clang 中独立的静态分析和 IR 生成阶段整合了起来。
(通俗的说就是,clang 在实现的时候开发者们发现很多阶段是交织在一起,没有很好的独立开来,导致代码耦合度高,现在加入了一个中间层,来解决这种情况)
SIL 的特点
- 能够完整的表达程序的语义。
- 被设计用于代码生成和静态分析
- 处于编译的流水线中,而不是独立与之外
- 在源代码和 LLVM 之间架起了抽象的桥梁