Clang: AST(抽象语法树)是什么样子的?

Clang : What does AST (abstract syntax tree) look like?

本文关键字:什么样 语法树 AST 抽象 Clang      更新时间:2023-10-16

嗨,我是编译器开发的新手,我想知道AST是什么样子的。我有一小段代码,我使用Clang生成AST。我没有从中获得太多信息。从它的外观来看,语法树与源代码完全相同,除了一个结构体被添加到我测试的几乎所有示例中。

源:

class A {
public:
  int *a, *b, *c;
  int i;
  void sum() {
    a = new int[5];
    b = new int[5];
    c = new int[5];
    for (i = 0; i < 5; i++) {
      a[i] = i;
      b[i] = i;
    }
    for (i = 0; i < 5; i++) {
      c[i] = a[i] + b[i];
    }
    delete[] a;   delete[] b;   delete[] c;
  }
};
class B : public A {
};
int main() {
  B bclass; 
  bclass.sum();
  return 0;
} 

生成AST命令:

clang++ -cc1 -ast-print ~/sum.cpp
AST输出:

struct __va_list_tag {
    unsigned int gp_offset;
    unsigned int fp_offset;
    void *overflow_arg_area;
    void *reg_save_area;
};
typedef struct __va_list_tag __va_list_tag;
class A {
public:
    int *a;
    int *b;
    int *c;
    int i;
    void sum()     {
        this->a = new int [5];
        this->b = new int [5];
        this->c = new int [5];
        for (this->i = 0; this->i < 5; this->i++) {
            this->a[this->i] = this->i;
            this->b[this->i] = this->i;
        }
        for (this->i = 0; this->i < 5; this->i++) {
            this->c[this->i] = this->a[this->i] + this->b[this->i];
        }
        delete [] this->a;
        delete [] this->b;
        delete [] this->c;
    }

};
class B : public A {
};
int main() {
    B bclass;
    bclass.sum();
    return 0;
}

谢谢

各种可用的选项之间有一点混淆:

  • -ast-print将漂亮地打印当前的AST,也就是说,它将呈现它所理解的代码尽可能接近它所解析的(但使一些东西显式,如this的幻影)
  • -ast-dump将生成当前AST的lisp样表示

漂亮的打印机可以用来检查AST是无损的(即,保留了这种表达式的const -ness,等等…),但实际上与开发无关。

如果您想破解编译器,您需要-ast-dump,它将生成一个输出,该输出直接映射已解析代码的内存表示。

AST是内存中的一个链接结构(用"树"来形容它的复杂性并不恰当,但这是人们使用的名称)。-ast-print生成的是AST的文本表示形式。由于设置该选项的人已经熟悉类似C/c++的语法,因此它以遵循该语法的表示形式打印。这是一个设计选择,而不是一个愉快的巧合。

如果您想看看AST在不以熟悉的语法打印时是什么样子,您可以查看GCC的内部表示GIMPLE。

如果您想使用GIMPLE,您甚至可以为此目的使用GCC MELT。MELT是处理GIMPLE的高级领域特定语言!

在编译器内部,内部表示通常不是树,而是某种循环结构。在GCC中,一个基本块知道它的模块,但是这些模块可能知道它们的基本块....(它有点复杂,但你已经有了想法)。