test.c:
#include <stdlib.h>
typedef struct node{
int size;
float value;
char a;
}Node;
int main(){
Node* n ;
n =(Node *)malloc(sizeof(Node));
n->size = sizeof(Node);
n->value = 1.5;
n->a = 'a';
return 0;
}
使用dump命令打印ast:
gcc test.c -fdump-tree-original-raw
生成的ast中间文件:
;; Function main (null)
;; enabled by -tree-original
@1 statement_list 0 : @2 1 : @3
@2 bind_expr type: @4 vars: @5 body: @6
@3 return_expr type: @4 expr: @7
@4 void_type name: @8 algn: 8
@5 var_decl name: @9 type: @10 scpe: @11
srcp: mcf.c:4 size: @12
algn: 64 used: 1
@6 statement_list 0 : @13 1 : @14 2 : @15
3 : @16 4 : @17 5 : @18
@7 modify_expr type: @19 op 0: @20 op 1: @21
@8 type_decl name: @22 type: @4
@9 identifier_node strg: n lngt: 1
@10 pointer_type size: @12 algn: 64 ptd : @23
@11 function_decl name: @24 type: @25 srcp: mcf.c:3
link: extern
@12 integer_cst type: @26 int: 64
@13 decl_expr type: @4
@14 modify_expr type: @10 op 0: @5 op 1: @27
@15 modify_expr type: @19 op 0: @28 op 1: @29
@16 modify_expr type: @30 op 0: @31 op 1: @32
@17 modify_expr type: @33 op 0: @34 op 1: @35
@18 return_expr type: @4 expr: @36
@19 integer_type name: @37 size: @38 algn: 32
prec: 32 sign: signed min : @39
max : @40
@20 result_decl type: @19 scpe: @11 srcp: mcf.c:3
note: artificial size: @38
algn: 32
@21 integer_cst type: @19 int: 0
@22 identifier_node strg: void lngt: 4
@23 record_type name: @41 unql: @42 size: @43
algn: 32 tag : struct flds: @44
@24 identifier_node strg: main lngt: 4
@25 function_type unql: @45 size: @46 algn: 8
retn: @19
@26 integer_type name: @47 size: @48 algn: 128
prec: 128 sign: unsigned min : @49
max : @50
@27 nop_expr type: @10 op 0: @51
@28 component_ref type: @19 op 0: @52 op 1: @44
@29 integer_cst type: @19 int: 12
@30 real_type name: @53 size: @38 algn: 32
prec: 32
@31 component_ref type: @30 op 0: @54 op 1: @55
@32 real_cst type: @30 valu: 1.5e+0
@33 integer_type name: @56 size: @46 algn: 8
prec: 8 sign: signed min : @57
max : @58
@34 component_ref type: @33 op 0: @59 op 1: @60
@35 integer_cst type: @33 int: 97
@36 modify_expr type: @19 op 0: @20 op 1: @21
@37 type_decl name: @61 type: @19
@38 integer_cst type: @26 int: 32
@39 integer_cst type: @19 int: -2147483648
@40 integer_cst type: @19 int: 2147483647
@41 type_decl name: @62 type: @23 srcp: mcf.h:7
@42 record_type name: @63 size: @43 algn: 32
tag : struct flds: @44
@43 integer_cst type: @26 int: 96
@44 field_decl name: @64 type: @19 scpe: @42
srcp: mcf.h:4 size: @38
algn: 32 bpos: @49
@45 function_type size: @46 algn: 8 retn: @19
@46 integer_cst type: @26 int: 8
@47 identifier_node strg: bitsizetype lngt: 11
@48 integer_cst type: @26 int: 128
@49 integer_cst type: @26 int: 0
@50 integer_cst type: @26 int: -1
@51 call_expr type: @65 fn : @66 0 : @67
@52 indirect_ref type: @23 op 0: @5
@53 type_decl name: @68 type: @30
@54 indirect_ref type: @23 op 0: @5
@55 field_decl name: @69 type: @30 scpe: @42
srcp: mcf.h:5 size: @38
algn: 32 bpos: @38
@56 type_decl name: @70 type: @33
@57 integer_cst type: @33 int: -128
@58 integer_cst type: @33 int: 127
@59 indirect_ref type: @23 op 0: @5
@60 field_decl name: @71 type: @33 scpe: @42
srcp: mcf.h:6 size: @46
algn: 8 bpos: @12
@61 identifier_node strg: int lngt: 3
@62 identifier_node strg: Node lngt: 4
@63 identifier_node strg: node lngt: 4
@64 identifier_node strg: size lngt: 4
@65 pointer_type size: @12 algn: 64 ptd : @4
@66 addr_expr type: @72 op 0: @73
@67 integer_cst type: @74 int: 12
@68 identifier_node strg: float lngt: 5
@69 identifier_node strg: value lngt: 5
@70 identifier_node strg: char lngt: 4
@71 identifier_node strg: a lngt: 1
@72 pointer_type size: @12 algn: 64 ptd : @75
@73 function_decl name: @76 type: @75 srcp: stdlib.h:466
body: undefined link: extern
@74 integer_type name: @77 size: @12 algn: 64
prec: 64 sign: unsigned min : @78
max : @79
@75 function_type size: @46 algn: 8 retn: @65
prms: @80
@76 identifier_node strg: malloc lngt: 6
@77 type_decl name: @81 type: @74
@78 integer_cst type: @74 int: 0
@79 integer_cst type: @74 int: -1
@80 tree_list valu: @82 chan: @83
@81 identifier_node strg: long unsigned int lngt: 17
@82 integer_type name: @84 unql: @74 size: @12
algn: 64 prec: 64 sign: unsigned
min : @78 max : @79
@83 tree_list valu: @4
@84 type_decl name: @85 type: @82 srcp: stddef.h:216
@85 identifier_node strg: size_t lngt: 6
看起来有些复杂,但是掌握ast中tree结点的关系,看起来就非常清晰了。
gcc里tree结点是在gcc/tree-core.h中定义,结点之间是union的关系:
什么是union呢,举个小例子:
#include <stdio.h>
union Var{
int a;
char b;
};
int main(){
union Var v;
v.a=66;
printf("%d\n", v.a); // 66
printf("%c\n", v.b); // B
printf("%ld\n", sizeof(v)); // 4
}
v被实例化为int 类型的a, 自行体会三个打印结果吧。
写个小例子模拟gcc里结点的形式:
#include <stdio.h>
enum CODE{
BASE, COMMON
};
typedef struct{
enum CODE code;
float value;
} tree_base;
typedef struct{
tree_base base;
char* name;
} tree_common;
union tree{
tree_base base;
tree_common common;
};
int main(){
union tree node;
printf("%ld\n", sizeof(tree_base)); // 8
printf("%ld\n", sizeof(tree_common)); // 16
printf("%ld\n", sizeof(union tree)); //16
printf("%ld\n", sizeof(node)); // 16
node.base.value = 1.23456789;
printf("%f\n", node.common.base.value);
}
在gdb gcc源码打印ast时, 断点可以设在gcc/toplev.c:compile_file:
打印时几点总结:
- 查看name: .decl_minimal.name.identifier
- point_type -> var_type 可以为 .typed.type.typed.type 这样前一对为point_type, 后一对为record_type
- record_type 在tree-core.h中, type_common.name找到struct name, type_no_common.values找到field_decl
- expand_location(.locus)可以打印具体行号
- call_expr operands[0]打印参数,operands[1].expr.operands[0]打印function_decl,表示的是函数的调用
- function_decl.saved_tree打印函数体