三地址代码和符号表

Three-address code and symbol tables

我正在 OCaml 中开发一个可重定目标的业余爱好 C 编译器,我正在自下而上地构建它。到目前为止,我有一个带注释的 AST 类型,删节:

type 'e expr =
    | Int of 'e * int
    | Var of 'e * var
    | Neg of 'e * 'e expr
    | Add of 'e * 'e expr * 'e expr
    | Sub of 'e * 'e expr * 'e expr

和三地址代码类型(再次删节):

type node = Copy of location * location
          | Unary of location * unary_op * location
          | Binary of location * location * binary_op * location

and location = Temp of int | Int of int | Var of string

and unary_op = Neg

and binary_op = Add | Sub

我编写了将 AST 转换为 TAC 节点列表的函数忽略注释。关于这个我有两个问题:

  1. 将带类型注释的 AST 转换为 TAC 节点列表时,我需要做哪些不同的事情?我是否也应该向 TAC 节点添加注释?这将允许我稍后将高级 int/char 类型转换为较低级别的类型,例如 I16/I8.

  2. 如何处理范围界定?如果我有两个在不同范围内具有相同名称的 Var 怎么办?

如何将注释传递给 TAC 是一个非常悬而未决的问题,但我同意您可能想要这样做。

范围界定的一种方法是名称擦除;在解析范围时,您将每个唯一标识符替换为唯一的 "name"(或直接使用对符号 table 条目的引用。)(有时称为 gensymming, after the traditional Lisp gensym function.) More formally, it is α-reduction,该术语取自λ 演算。这适用于 C 等语言,在这些语言中名称不可用于运行时。

运行时内省可以访问名称的语言(Python、Javascript)使这个过程稍微复杂一些,但您仍然可以将名称的每次使用与特定范围相关联。在范围可以是动态的语言(Perl、Lisp)中,您必须在 TAC 中引入名称解析操作。