Swift生成中间体语言SIL(Swift Intermediate Language)

1,725 阅读3分钟

前言

iOS开发的语言不管是OC还是Swift后端都是通过LLVM进行编译的,如下图所示:

Swift第一节课:类与结构体(上)_7_1.jpg OC 通过 clang 编译器,编译成 IR,然后再生成可执行文件 .o(这里也就是我们的机器

码) 

Swift 则是通过 Swift 编译器编译成 IR,然后在生成可执行文件。

Swift第一节课:类与结构体(上)_7_2.jpg // 分析输出AST

 // 分析输出AST 
 swiftc main.swift -dump-parse 

 // 分析并且检查类型输出AST 
 swiftc main.swift -dump-ast 

 // 生成中间体语言(SIL),未优化
 swiftc main.swift -emit-silgen 

 // 生成中间体语言(SIL),优化后的
 swiftc main.swift -emit-sil
 
 // 生成LLVM中间体语言 (.ll文件)
swiftc main.swift -emit-ir 

// 生成LLVM中间体语言 (.bc文件)
swiftc main.swift -emit-bc 

// 生成汇编
swiftc main.swift -emit-assembly 

// 编译生成可执行.out文件
swiftc -o main.o main.swift

实例生成SIL

创建一个命令行的工程 image.png 这样生成的项目只有一个main.swift文件,不会含有其他的干扰项。

image.png

然后去终端进入main.swift所在的文件夹,输入如下指令:

swiftc -emit-sil main.swift

便可以在终端中看见Swift Intermediate Language

image.png

名字重整(Name Mangling)

我们可以从SIL中看到一些奇怪无规律的名字,例如:s4main6personAA7TeacherCvp。这其实是swift采用了名字重整技术,swift中的类名、方法名等会被重整,这样可以实现方法的重载,更好的实现多态设计。 幸运的是,我们通过命令xcrun swift-demangle还原成原来的名字

image.png 这样,我们可以通过管道符将整个SIL中的名字还原回来

swiftc -emit-sil main.swift | xcrun swift-demangle

可以对比下,名字很容易就还原了回来 image.png

选择适合的编辑器

当然,在终端里面看很不方便,我们可以将它保存到文件,后缀名可以定义为.sil,添加如下命令输出

swiftc -emit-sil main.swift | xcrun swift-demangle > ./main.sil

这样,在main.swift的同级目录下,可以看到main.sil,右键显示简介,可以调到你喜欢的编辑器软件打开,应用到所有该类文件就行了。

我用的是Sublime,你也可以用VSCode,看个人喜欢了。

脚本自动生成SIL文件并打开

由于你会频繁的修改代码并查看SIL文件,每次敲一遍命令会很烦(我是一个很懒的人啦),所以写一个简单的脚本插入到Xcode。

先在刚项目中新建一个Target,如下图:

image.png

image.png

image.png 在命令行内复制如下命令,需要注意的是,脚本的当前目录是xcodeproj同级目录,所以下面命令中的SwiftSIL改成你的项目名称,这样才可以找到文件

swiftc -emit-sil SwiftSIL/main.swift | xcrun swift-demangle > ./main.sil && open main.sil

切换target运行,就能直接调出你的编译器看你生成的SIL文件了,是不是很方便?

其他

  • 在SIL文件中,你会看到很多不懂的关键词,你可以查看GitHub上的官方文档查阅
  • 如果你在iOS里生成SIL文件,难免会碰到UIKit之类的sdk,那么命令需要带参数了,模拟版本改成你当前的版本
swiftc -emit-sil -target x86_64-apple-ios14.2-simulator -sdk $(xcrun --show-sdk-path --sdk iphonesimulator) ViewController.swift > ViewController.sil