Clang: Как выглядит AST (абстрактное синтаксическое дерево)?
Привет Я новичок в разработке компилятора, и мне интересно, как выглядит 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;
}
Спасибо
Ответы
Ответ 1
Существует небольшая путаница между различными доступными опциями:
-
-ast-print
будет довольно печатать текущий АСТ, то есть он сделает код, который он понимает, как можно ближе к тому, что он анализирует (но делая некоторые вещи явными, как привидение this
)
-
-ast-dump
будет генерировать lisp -подобное представление текущего AST
Симпатичный принтер может быть полезен для проверки того, что AST без потерь (т.е. сохранил const
-ность такого выражения и т.д.), но на самом деле не касается разработки.
Если вы хотите взломать компилятор, вам понадобится -ast-dump
, который будет генерировать вывод, который напрямую отображает представление в памяти кода, который был разобран.
Ответ 2
AST - связанная структура в памяти ( "дерево" не учитывает сложность вещи, но это имя используется людьми). То, что -ast-print
производит, представляет собой текстовое представление AST. Поскольку человек, который установил этот параметр, уже знаком с синтаксисом типа C/С++, он печатается в представлении, которое следует за этим синтаксисом. Это выбор дизайна, а не счастливое совпадение.
Если вы хотите посмотреть, как выглядит AST, когда он не печатается специально в знакомом синтаксисе, вы можете, например, посмотреть GIMPLE, внутреннее представление GCC.
Ответ 3
И если вы хотите играть с GIMPLE, вы можете использовать GCC MELT для этой цели. MELT - это высокоуровневый доменный язык для работы с GIMPLE!
И внутри компиляторов внутреннее представление часто - это не деревья, а как-то круговые структуры. В GCC базовый блок знает, что это gimple-s, но gimple-s могут знать свои базовые блоки... (это немного сложнее, но у вас есть идея).