菜单

IR 生成

相关源文件

本页面详细介绍了 Sway 编译器中中间表示 (IR) 生成的过程。IR 生成阶段将静态类型的抽象语法树 (AST) 转换为更低级的表示,该表示更接近目标 Fuel VM 字节码,同时仍易于优化。有关从 IR 生成汇编的信息,请参阅汇编生成

编译流程中的 IR 生成

IR 生成阶段位于 Sway 编译流程中的语义分析/类型检查和汇编生成之间

来源:sway-core/src/ir_generation.rs1-218 sway-core/src/ir_generation/compile.rs1-753

关键组件和工作流程

IR 生成过程使用几个关键组件将类型化 AST 转换为 IR

来源:sway-core/src/ir_generation/compile.rs26-753 sway-core/src/ir_generation.rs120-217

程序级编译

IR 生成的入口点是 compile_program 函数,它接受一个类型化程序 (TyProgram) 并生成一个包含所生成 IR 的 Sway IR 上下文。

编译过程根据程序类型(脚本、谓词、合约或库)略有不同。对于所有程序类型,编译流程包括:

  1. 创建具有相应类型的 IR 模块
  2. 编译常量
  3. 编译可配置项(库除外)
  4. 编译入口函数(如果适用)
  5. 编译 ABI 方法(用于合约)
  6. 编译测试函数

来源:sway-core/src/ir_generation.rs120-217 sway-core/src/ir_generation/compile.rs26-253

函数编译

函数是 Sway 程序的主要构建块。函数编译过程将 TyFunctionDecl 转换为 IR Function

函数的编译包括:

  1. 将函数参数转换为 IR 类型
  2. 将返回类型转换为 IR 类型
  3. 创建新的 IR 函数
  4. 创建一个 FnCompiler 来编译函数体
  5. 如果需要,添加返回指令
  6. 检查函数纯度

来源:sway-core/src/ir_generation/compile.rs426-693 sway-core/src/language/ty/declaration/function.rs25-671

表达式编译

IR 生成的核心是表达式编译。FnCompiler 提供了多种编译表达式的方法:

表达式编译方法

compile_expression 方法将 TyExpression 转换为 IR Value。它根据表达式变体分派到专门的方法。编译过程处理:

  1. 字面量(数字、布尔值、字符串)
  2. 函数调用
  3. 运算符
  4. 控制流(if、match、循环)
  5. 结构体和数组创建
  6. 存储访问
  7. 以及更多表达式类型

来源:sway-core/src/ir_generation/function.rs324-764 sway-core/src/language/ty/expression/expression.rs25-146 sway-core/src/language/ty/expression/expression_variant.rs24-183

终止符值

某些表达式,例如 returnbreak,会终止控制流。这些表达式通过 TerminatorValue 结构体进行特殊处理,该结构体封装了一个 IR Value 并指示它是否终止控制流。

return_on_termination_or_extract 用于处理终止符值。

macro_rules! return_on_termination_or_extract {
    ($value:expr) => {{
        let val = $value;
        if val.is_terminator {
            return Ok(val);
        };
        val.value
    }};
}

这确保了终止表达式会立即从当前的编译函数返回,而无需进一步处理。

来源:sway-core/src/ir_generation/function.rs65-89

常量求值

IR 生成阶段包含一个常量求值器,用于在编译时计算常量表达式的值。这由 const_eval 模块处理。

常量求值器可以处理多种表达式类型,包括:

  1. 字面量(Literals)
  2. 带有常量参数的函数调用
  3. 带有常量字段的结构体和数组
  4. 元组表达式
  5. 枚举实例化
  6. 常量上的简单操作

常量在 IR 生成过程中用于多个地方,特别是用于数组长度、可配置项和优化。

来源:sway-core/src/ir_generation/const_eval.rs35-810

纯度检查

Sway 函数可以用纯度属性进行标注,以指示它们是否访问存储。在 IR 生成过程中,编译器会检查这些标注是否与函数的实际行为匹配。

纯度检查器检查:

  1. 直接存储访问指令
  2. 带有存储 VM 指令的 ASM 块
  3. 调用不纯函数

如果函数的行为与其纯度标注不匹配,编译器会根据情况发出错误或警告。

来源:sway-core/src/ir_generation/purity.rs30-217

编译缓存

为了避免函数的重复编译,IR 生成器使用 CompiledFunctionCache

该缓存将函数声明映射到其编译后的 IR 表示。当需要编译函数时,编译器首先检查缓存中是否存在。如果存在,则使用缓存版本;否则,将编译该函数并添加到缓存中。

这对于代码中可能从多个地方调用的库函数尤其重要。

来源:sway-core/src/ir_generation.rs30-118

总结

Sway 编译器中的 IR 生成阶段将类型化 AST 转换为更低级的中间表示,该表示:

  1. 保留原始程序的语义
  2. 更易于优化
  3. 可以直接翻译为汇编和字节码

此转换涉及编译常量、可配置项、函数和测试,并对不同程序类型进行特殊处理。FnCompiler 是核心组件,它递归地将表达式编译为 IR 值,并支持常量求值和纯度检查。

来源:sway-core/src/ir_generation.rs1-218 sway-core/src/ir_generation/compile.rs1-753 sway-core/src/ir_generation/function.rs1-891