理解编译器

我们有两种状态机

  • 高级语言代码 $.c$
    • 状态:栈、全局变量;状态迁移:语句执行
  • 汇编指令序列 $.s$
    • 状态:$(M, R)$;状态迁移:指令执行
  • 编译器是二者之间的桥梁:$$.s = \textrm{compile}(.c)$$

到底什么是编译器

  • 不同的优化级别产生不同的指令序列
  • 凭什么说一个 $.s = \textrm{compile}(.c)$ 是 “对的” 还是 “错的”?

🌶️ $.s = \textrm{compile}(.c)$:编译正确性

$.c$ 执行中所有外部观测者可见的行为,必须在 $.s$ 中保持一致

  • External function calls (链接时确定)
    • 如何调用由 Application Binary Interface (ABI) 规定
    • 可能包含系统调用,因此不可更改、不可交换
  • 编译器提供的 “不可优化” 标注
    • volatile [load | store | inline assembly]
  • Termination
    • $.c$ 终止当且仅当 $.s$ 终止

在此前提下,任何翻译都是合法的 (例如我们期望更快或更短的代码)

  • 编译优化的实际实现:(context-sensitive) rewriting rules
  • 代码示例:观测编译器优化行为和 compiler barrier