Skip to content

语义保持的编译器阶段

Semantics-preserving compiler pass · Correct compiler transformation · 编译阶段语义保持

在固定观察、错误与未定义行为契约下,要求一次编译变换的目标程序不产生源程序未允许的行为。

条目类型
定义

形式陈述 ​

设编译阶段 C 把源中间表示程序 P 成功变换为目标程序 Q=C(P)。先用小步语义为两层语言定义完整行为,包括有限可观察事件迹 t 后正常返回 v、以错误或 trap 终止、产生无限迹或静默发散。将这些行为集合记作 BehS(P) 与 BehT(Q)。本页采用实现精化规格的方向:

BehT(C(P))⊆BehS(P).

这正是精化关系的“目标不新增源未允许观察”口径。源语义若非确定,目标可以选择其中一种合法行为,未必保持集合相等;若源程序安全且语义确定,并另证不丢失终止或发散行为,才可能加强为相同观察。

命题还要规定未定义行为。若源一旦 UB 就允许任意后续行为,可把 UB 状态解释为行为全集的顶部,编译器在该点之后无需提供通常保证;trap 若是确定、可观察的终止事件,则不能与 UB 混同。外部调用、I/O 顺序、终止值、发散与资源耗尽是否进入观察,都属于定理参数而不是自然语言省略项。

环境也须满足共同假设。例如源、目标调用同名外部函数时,参数编码与返回关系要一致,环境不得在两层观察本应隐藏的内部临时状态。对开放程序,定理通常量化所有满足接口约束的环境;只固定测试时使用的一套库,会把链接假设误装成编译器本身的正确性。

直觉

语义保持不是要求源、目标逐条指令相同,而是要求外部观察者无法看到契约禁止的新结果。优化可以删除临时量、合并基本块或把一条指令扩成数步;状态形状和步数因此不同。证明需要一座桥,把两边状态及若干步对应起来,最终比较完整行为。

“保持”也不总是双向相等。源语言可能允许表达式求值顺序的多种结果,编译器固定其中一种,这是减少非确定性,仍满足目标行为包含于源行为。反过来,若目标新增一个崩溃结果,即使它还保留所有正常结果,也破坏上述精化方向。

例子与边界

设源 IR 的常量计算分两步:

(t:=2+3; y:=t×x; returny,ρ)⟶(y:=t×x; returny,ρ[t↦5])⟶(returny,ρ[t↦5][y↦5ρ(x)]).

这里假定 t,x,y 是不同的变量;ρ(x) 是初态中 x 的值,第二次更新必须保留第一次写入的 t。常量折叠、传播并删除死临时量后,目标直接含 y:=5×x;returny。若整数运算均为同一宽度的模运算且赋值无可见事件,源的第一步可由目标零步匹配,第二步由一次目标步匹配,随后返回相同位串。

两边最终环境并不完全相同:源更新了 t,目标可能没有。因此状态关系应要求可观察变量相等,并允许死临时量 t 不同;若后续又读取 t,这个忽略就不合法。减少内部步能够保持观察,依赖的是“该临时量此后确实不用”的条件,而不只是算术恒等式。

边界例取 0×load(p)↦0。在纯数学中等式成立;若读取 p 可能越界 trap、触发 volatile 设备或参与原子顺序,目标删除了源的可见事件或错误,便不是同一契约下的语义保持。类似地,把有符号除法替换为右移可能对负数采用不同舍入方向,几个正数测试全部通过也无法覆盖反例。

回归测试只检查有限输入和有限运行。即使一百万次测试都相等,也不能推出所有状态、路径、发散执行与环境交互上的集合包含。测试适合发现实现错误,语义定理则量化全部合法程序和执行;两者作用互补,不能互相改名。

未定义行为还必须说明采用哪种放宽。若采用本文的“已产生事件前缀之后任意延续”模型,源在第十步越界,并不允许目标抹去前九步已经规定的可见事件。若某语言规范直接对任何会触发 UB 的整个执行不作要求,则不能从规范推出这种前缀保证。精化定理必须固定其中一种解释;不能把一个模型中的前缀结论自动推广到所有 C 编译器契约。

推论与应用

若每个阶段 Ci 都在相容观察下满足行为精化,则集合包含的传递性给出整条编译流水线

Beh(Cn⋯C1(P))⊆Beh(P).

组合要求相邻 IR 对事件、返回和错误的编码一致;一层把 trap 当事件、下一层把它当 UB,会让形式上可复合的符号失去实际含义。

常用证明方法包括编译器前向模拟、编译器后向模拟、逻辑关系和翻译验证。它们是建立语义保持的不同证据接口,并不等于性质本身。选择方法应由确定性、非确定性、内部停顿与阶段实现的可信边界决定。

参考资料
  • CompCert 开发团队,The CompCert C Verified Compiler: Documentation and User's Manual,在线版,2026 年访问,§1.2 Formal verification of compilers:行为改进、观察与分阶段组合。

  • Xavier Leroy, “Formal Verification of a Realistic Compiler,” Communications of the ACM 52(7), 2009, pp. 107–115.

  • Xavier Leroy, “A Formally Verified Compiler Back-end,” Journal of Automated Reasoning 43(4), 2009, pp. 363–446.

  • John C. Reynolds, Theories of Programming Languages, Cambridge University Press, 1998, Chapters 6–8.

关系图谱14 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系