菜单

中间表示

相关源文件

本页面提供了 Swift 编译器中使用的中间表示 (IRs) 的技术概述。这些 IRs 作为 Swift 源代码和机器代码之间的桥梁,在整个编译过程中实现各种优化和转换。

有关编译器整体架构的信息,请参阅 Swift 编译器概述

Swift 编译管线概述

Swift 编译器会经历多个阶段,前端和后端之间有两个主要的中间表示

来源:lib/IRGen/IRGenSIL.cpp1-15 lib/SILGen/SILGen.cpp1-19

Swift 中间语言 (SIL)

SIL 是 Swift 主要的高级中间表示,专门设计用于表示类型检查后的 Swift 代码,直至平台特定的代码生成。

SIL 的目的

Swift 中间语言 serve several critical purposes

  1. 语义分析:为 AST 的初始代码生成提供合适的 target
  2. 优化:为 Swift 特定的优化提供平台无关的表示
  3. ARC 管理:显式表示内存管理操作(保留/释放)
  4. 所有权语义:捕获 Swift 的所有权模型
  5. 可调试性:保留足够的高级结构以供调试信息使用

SIL 结构

来源:lib/SILGen/SILGenFunction.h380-670 lib/SILGen/SILGen.cpp50-75

SIL 值表示

SIL 在编译过程中使用几种抽象来表示值

  1. RValue:表示一个已求值的表达式结果,可以使用但不能对其进行赋值
  2. LValue:表示内存中的一个位置,可以对其进行赋值
  3. ManagedValue:用所有权语义(拥有、借用等)包装一个 SILValue

来源:lib/SILGen/SILGenExpr.cpp67-419 lib/SILGen/SILGenLValue.cpp45-65

SIL 生成

SIL 通过 SILGenFunction 和 SILGenModule 类从 AST 生成,这些类会遍历 AST 并发出适当的 SIL 指令。

来源:lib/SILGen/SILGenFunction.cpp52-54 lib/SILGen/SILGenApply.cpp249-276

LLVM IR 生成

LLVM IR 是 Swift 编译器使用的第二个主要中间表示。它是一个更低级别的表示,通过 LLVM 基础架构将 SIL 连接到机器代码。

LLVM IR 结构

来源:lib/IRGen/IRGenModule.h129-200 lib/IRGen/IRGenModule.cpp233-250

IR 生成过程

从 SIL 到 LLVM IR 的转换由 IRGenModule 和 IRGenFunction 类处理。将 SIL 翻译成 LLVM IR 的关键类是 IRGenSILFunction。

来源:lib/IRGen/IRGenSIL.cpp120-155 lib/IRGen/IRGenSIL.cpp387-390

LoweredValue 类

LoweredValue 类是 SIL 转换为 LLVM IR 的关键组件,表示一个 SIL 值在被降级到 LLVM IR 后的样子。

来源:lib/IRGen/IRGenSIL.cpp153-371

SIL 到 LLVM IR 的转换

从 SIL 到 LLVM IR 的转换涉及几个复杂的步骤

1. 类型降级

Swift 类型必须转换为 LLVM 类型,这涉及到

  • 处理所有权语义
  • 管理间接 vs. 直接值传递
  • 处理存在性容器
  • 生成元数据结构

来源:lib/IRGen/GenType.cpp lib/IRGen/IRGenModule.cpp233-250

2. 函数转换

SIL 函数被转换为 LLVM 函数,这涉及到

  • 转换函数类型
  • 设置参数和返回值
  • 管理调用约定
  • 创建函数体

来源:lib/IRGen/GenFunc.cpp lib/IRGen/GenCall.cpp377-401

3. 指令访问者模式

IRGenSILFunction 类使用访问者模式来遍历 SIL 指令并发出相应的 LLVM IR。

来源:lib/IRGen/IRGenSIL.cpp387-427

4. 值降级

SIL 值使用 LoweredValue 抽象进行降级,它可以表示各种类型的值

来源:lib/IRGen/IRGenSIL.cpp469-615

元数据和运行时支持

Swift 的 IR 生成包含大量用于生成元数据和运行时支持的代码

类型元数据

类型元数据对于 Swift 的运行时功能(如反射、动态转换和泛型实例化)至关重要。

来源:lib/IRGen/GenMeta.cpp144-179

协议一致性

Swift 生成 witness 表来表示协议一致性

来源:lib/IRGen/GenProto.cpp95-170

异步函数和协程

Swift 使用协程来实现 async/await,这些协程同时在 SIL 和 LLVM IR 中表示

来源:lib/IRGen/GenCall.cpp100-168

结论

Swift 编译器利用两种主要的中间表示——SIL 和 LLVM IR——来弥合 Swift 源代码和机器代码之间的差距。SIL 提供了一个 Swift 特定的表示,它捕获所有权语义并启用 Swift 特定的优化,而 LLVM IR 提供了一个利用 LLVM 成熟的优化和代码生成基础设施的途径。

这些表示能够支持从ARC内存管理到泛型特化再到协议见证分派等各种编译时和运行时特性。

这些表示之间的转换由IRGenSILFunction等专门组件处理,它们在更高级别的Swift抽象和更低级别的LLVM构造之间进行映射,在暴露优化机会的同时保持语义。