01-📝Swift5常用核心语法|了解Swift【Swift简介、Swift的版本、Swift编译原理、几种函数派发】

1,582 阅读9分钟

image.png

一、概述

本系列文章旨在复习Swift5核心语法且适当进行底层原理探索,属于阶段性复习和巩固,以供日后进一步探索Swift语言的底层原理做铺垫。

整个系列文章如下,每一文章知识点独立成篇,欢迎各位按需或按兴趣点击阅读:

二、Swift简介

1. Swift

在学习Swift之前,我们先来了解下什么是Swift

  • 在Swift刚发布那会,百度\Google一下Swift,出现最多的搜索结果是 p美国著名女歌手Taylor Swift,中国歌迷称她为“霉霉” image.png
  • 现在的搜索结果以Swift编程语言相关的内容居多
  • Swift是Apple在2014年6月WWDC发布的全新编程语言,中文名和LOGO是”雨燕“

2. Swift之父Chris Lattner

image.png

三、Swift版本

Swift历时8年,从Swift 1.*更新到Swift 5.*,经历了多次重大改变,ABI终于稳定

  • API(Application Programming Interface):应用程序编程接口
    • 源代码和库之间的接口
  • ABI(Application Binary Interface):应用程序二进制接口
    • 应用程序和操作系统之间的底层接口
    • 涉及的内容有:目标文件格式数据类型的大小/布局/对齐函数调用约定
  • 随着ABI的稳定,Swift语法基本不会再有太大的变动,此时正是学习Swift的最佳时刻
  • 截止至2022年11月,目前最新版本:Swift5.8.x
  • Swift完全开源: github.com/apple/swift 主要采用C++编写
  • Swift是完全开源的,下载地址:github.com/apple/swift

image.png

四、Swift编译原理

-w727

-w525

1. 了解LLVM项目

LLVM项目的架构如图: image.png 从上图我们可以清晰看到,整个程序编译链可以划分为三部分:编译器前端(左边部分)、优化器(中间部分)、编译器后端(右边部分)。(从我的这篇文章可以更详细了解编译相关的知识:计算机编译原理)

  • 编译器前端(Frontend) :词法分析语法分析语义分析生成中间代码llvm-ir
  • 优化器(Optimizer) :对中间代码进行优化改造,使之变成性能更加高效的中间代码llvm-ir(内存空间、执行效率)
  • 编译器后端(Backend) :生成指定硬件架构的可执行文件

对编译器王者LLVM的进一步认识:

  • 使用统一的中间代码: 不同的编译器前端、编译器后端使用统一的中间代码LLVM Intermediate Representation (LLVM IR)
  • 只需实现一个前端: 如果需要支持一种新的编程语言,那么只需要实现一个新的前端
  • 只需实现一个后端: 如果需要支持一种新的硬件设备,那么只需要实现一个新的后端
  • 通用优化器: 优化阶段是一个通用的阶段,它针对的是统一的LLVM IR,不论是支持新的编程语言,还是支持新的硬件设备,都不需要对优化阶段做修改

2. 编译流程

我们知道OC的编译器前端是Clang,而Swift的编译器前端是swiftc
通过LLVM编译链,不同的编译型语言的编译器前端可能不同,但在同一个硬件架构的硬件中,最终都会通过同一个编译器的后端生成二进制代码

-w727

整个编译流程如下图所示

-w525

  • 代码编辑/阅读阶段:
    • Swift Code: 我们编写的Swift代码
  • 编译器前端工作阶段:
    • Swift AST: Swift语法树
    • Raw Swift IL: Swift特有的中间代码
  • 优化器工作阶段:
    • Canonical Swift IL: 更简洁的Swift特有的中间代码
    • LLVM IR: LLVM的中间代码
  • 编译器后端工作阶段:
    • Assembly: 汇编代码
    • Executable: 二进制可执行文件

关于Swift编译流程的详细讲解可以参考以下网址:swift.org/swift-compi…

3. swiftc

我们打开终端,输入swiftc -help,会打印出相关指令,这也说明了swiftc已经存在于Xcode中 image.png

我们可以在应用程序中找到Xcode,然后右键显示包内容,通过该路径找到swiftc 路径:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

image.png

4. SwiftC 命令行指令

// 假设原始文件为main.swift

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

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

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

// 生成中间体语言(SIL),优化后的
swiftc main.swift -emit-sil -o main.sil 

// 生成优化后的中间体语言(SIL),并将结果导入到main.sil文件中
swiftc main.swift -emit-sil  -o main.sil 

// 生成优化后的中间体语言(SIL),并将sil文件中的乱码字符串进行还原,并将结果导入到main.sil文件中
swiftc main.swift -emit-sil | xcrun swift-demangle > main.sil

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

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

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

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

image.png

5.更详尽的iOS编译相关的知识

在本篇文章中,只是粗略介绍Swift编译,若您想了解 更详尽的iOS编译相关的知识,可以参考我这篇文章:探究iOS底层原理|编译器LLVM项目【Clang、SwiftC、优化器、LLVM、Xcode编译的过程】

五、Swift中的函数派发方式

Swift既有静态语言特性,又有动态语言特性。它的有几种函数派发方式

  • 静态派发
    • 值类型(enum、struct),在编译器就决定了其属性、方法的内存地址。
    • 使用的时候直接寻址调用
  • 动态派发
      1. 继承自OC的NSObject类,共用一套Runtime,走objcmsgSend的消息派发
      1. 底层是基于 C++写的,有虚函数表,在表中找到函数的实现,进行动态派发 参考文章
  • Swift 函数派发机制
  • Swift的静态派发和动态派发机制

专题系列文章

1. 前知识

2. 基于OC语言探索iOS底层原理

3. 基于Swift语言探索iOS底层原理

关于函数枚举可选项结构体闭包属性方法swift多态原理StringArrayDictionary引用计数MetaData等Swift基本语法和相关的底层原理文章有如下几篇:

其它底层原理专题

1. 底层原理相关专题

2. iOS相关专题

3. webApp相关专题

4. 跨平台开发方案相关专题

5. 阶段性总结:Native、WebApp、跨平台开发三种方案性能比较

6. Android、HarmonyOS页面渲染专题

7. 小程序页面渲染专题