GCC treeの読み方


GCC treeの視覚化 で作成したtreeを読んでみました。

treeはgccのfront endで使われている構文木を表すデータ構造です。

ソースコードとtreeの図

  • 説明するソースコードと、gcc-4.xのtree dumpから作った図です。
int main() {
    return 0;
}

treeの読み方

  • 四角形がtree nodeに1対1に対応しています。
  • 四角形上段の数字はnodeのユニークIDです。
  • 四角形下段の左端の要素はnodeのcodeです。nodeの種類を表します。
  • 四角形下段codeより右にある要素はtree codeや、その他条件により異なります。
  • 矢印がnodeの要素からnodeへ参照していることを示します。
  • nodeの情報はnode内に保持する場合、nodeを参照する場合、ポインタを参照する場合があります。
  • gccのtree dumpは、treeのすべての情報を出力しているわけではないです。もっと詳しい情報が知りたい人はソースコードを読みましょう。

整数定数のtree

  • 整数定数のcodeはinteger_cstです。 要素として型(type)と値(high,low)を持ちます。
  • 値は上位 highと下位 low にわかれています。highが0の場合は、highはdumpで表示されません(例: 13のノード)。dumpでは値をsignedとして表示します。lowにuint64_tの最大値が入っていると-1と表示されます。(例:22のノード)
  • 値が負の場合は、2の補数で格納するので、highが-1 になります。(例:12のノード)
  • tree dumpの図では、9, 11, 12, 13, 20, 21, 22が整数定数のnodeです。
  • 図の中のinteger_cstのtree
    • 9 int型で値が0
    • 11 bitsizetype型で値が32
    • 12 int型-2147483648
    • 13 int型で値が2147483647
    • 20 bitsizetype型で値が64
    • 21 bitsizetype型で値が0
    • 21 bitsizetype型で値が0xFFFFFFFF

型宣言のtree

  • treeの図には、voidの型宣言 と intの型宣言 があります。
  • 型宣言のtree基本形は3つのノードが含まれます。
    • type_decl 型宣言 nameとtypeの参照を持つ
    • identifer_node 型名 文字列のポインタ参照strgと文字列長lengtを持つ
    • なんとか_type 型 型により持つ要素が異なる。nameとalgnは最低限ある。 (algnがよくわからない。)
  • 2, 4, 8がvoidの型宣言です。
    • 4 型宣言
    • 6 型名 "void"
    • 2 型 void_typeでalgnが8
  • 7, 10, 12, 13, 15がintの型宣言です。
    • 10 型を宣言
    • 15 型名 "int"
    • 7 型はintegerで精度、signed、alignが32で、名前、サイズ、最小値、最大値の参照を持つ。
    • 11 型のサイズが32
    • 12 型の最小値が-2147483648
    • 13 型の最大値が2147483647
  • 図を見ると分かるのですが、tree内で型を参照する場合は2,11の型のtreeを参照します。

GCC internal types のtree

  • GCC internal typesはGCCが内部で使う型です。通常と異なり型宣言がありません。
  • 16, 19, 20, 21, 23 がGCC internal types の bitsizetypeのtreeす。 type_declがリンクされていません。  * 16 型 integerでサイズ、精度、unsigned、最小値、最大値  * 19 型名 "bitsizetype"  * 20 型のサイズが64bit  * 21 型の最小値0  * 22 型の最大値0xFFFFFFFF

型宣言を省略したtree の図

  • 型を解説したので、型の宣言を省略した図を描画しました。
  • 2がvoid型、7がint型、16がbitsizetype型です。

式のtree

  • treeでは演算などを式で表現します。 _exprが末尾にあるcodeを持つnodeが式です。
  • tree dumpの図ではbind_exprとreturn_exprとmodify_exprがあります。
  • modify_expr
    • modify_exprは代入文です。ソースコードに代入文はありませんが、関数の戻り値を表すのにmodify_exprを使います。
    • modify_exprは要素にtypeとop1とop2を持ちます。 typeは式の型、op1は代入先のnode、op2は代入元のnode
    • なので5のノードは、整数定数0を戻り値にint型で代入するという意味です。 (戻り値に代入というのがよく分からないのですが…)
  • return_expr
    • return_exprは関数からのリターンです。
    • return_epxrは要素にtypeとexprを持ちます。
    • なので3のノードは、5のmodifi_exprをvoid型でリターンするという意味です。
  • bind_expr
    • bind_exprはblockを表現するnodeです。
    • tree dumpの図ではmain関数全体を一つのブロックとして表現しています。
    • bind_epxrは実際はもっと要素があるのですが、この例では型typeとブロックの中身bodyのみです。

関数のtree

  • 関数の定義は以下のnodeからできています。
    • function_decl 関数宣言
    • function_type 引数の型
    • result_decl 戻り値の宣言
  • 7, 8, 9, 11, 14, 17, 18 が関数定義です。
    • 14 関数宣言 名前は"main"、sizeの参照、ファイル名と行数、extern
    • 18 関数の型 sizeは32 戻り値はint型 unqlがよく分からない unqualified の意味らしい
    • 23 関数の型 sizeは32 戻り値はint型
    • 8 戻り値の宣言 型はint、scpeはノード14、ファイル名と行数、sizeの参照、algnが32

つづく

  • だいぶtreeを読めるようになってきたけど、まだ足りないので、変数、if文、for文、関数呼び出し、などのtreeの読み方を調査する予定。

その他

  • よく分からない return_exprがvoid型なのはどうしてか
  • function_typeが2個あるのはなぜか

tree dump

  • treeのdumpも置いときます。

;; Function main (null)
;; enabled by -tree-original

@1      bind_expr        type: @2       body: @3      
@2      void_type        name: @4       algn: 8       
@3      return_expr      type: @2       expr: @5      
@4      type_decl        name: @6       type: @2      
@5      modify_expr      type: @7       op 0: @8       op 1: @9      
@6      identifier_node  strg: void     lngt: 4       
@7      integer_type     name: @10      size: @11      algn: 32      
                         prec: 32       sign: signed   min : @12     
                         max : @13     
@8      result_decl      type: @7       scpe: @14      srcp: test.c:1      
                         note: artificial              size: @11     
                         algn: 32      
@9      integer_cst      type: @7       low : 0       
@10     type_decl        name: @15      type: @7      
@11     integer_cst      type: @16      low : 32      
@12     integer_cst      type: @7       high: -1       low : -2147483648 
@13     integer_cst      type: @7       low : 2147483647 
@14     function_decl    name: @17      type: @18      srcp: test.c:1      
                         link: extern  
@15     identifier_node  strg: int      lngt: 3       
@16     integer_type     name: @19      size: @20      algn: 64      
                         prec: 64       sign: unsigned min : @21     
                         max : @22     
@17     identifier_node  strg: main     lngt: 4       
@18     function_type    unql: @23      size: @11      algn: 32      
                         retn: @7      
@19     identifier_node  strg: bitsizetype             lngt: 11      
@20     integer_cst      type: @16      low : 64      
@21     integer_cst      type: @16      low : 0       
@22     integer_cst      type: @16      low : -1      
@23     function_type    size: @11      algn: 32       retn: @7  

参考