天天看點

GCC-3.4.6源代碼學習筆記(2)

1.1.1. tree_code —— 樹節點的ID

在tree_node的定義中,結構體,象tree_type,tree_decl 等,用于代表相應的文法成分。比如,tree_type用于類的定義,而type_decl用于聲明。但如果需要進一步分别,比如tree_decl節點為何種聲明,則我們需要用到在tree_node中的另一個位。這就是在tree_common定義中,第134行的code。

31    #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,

32   

33    enum tree_code {                                                                                              in tree.h

34    #include "tree.def"

35   

36      LAST_AND_UNUSED_TREE_CODE   

38    };

39   

40    #undef DEFTREECODE

另外在C++前端中,枚舉類型(enum)cplus_tree_code被附加到上述枚舉定義的最後。

887  enum cplus_tree_code {                                                                              in cp-tree.h

888    CP_DUMMY_TREE_CODE = LAST_C_TREE_CODE,

889  #include "cp-tree.def"

890    LAST_CPLUS_TREE_CODE

891  };

檔案tree.def定義了tree_code中前端通用的值。這個檔案的内容是一系列的DEFTREECODE。而上面第31行,DEFTREECODE被定義成其中的一個域。這是GCC大量使用的技術。檔案tree.def的内容顯示在下面的表中。

節點碼(tree code) 類型 描述
ERROR_MARK x 一個錯誤構造的解析。
IDENTIFIER_NODE x 代表名字(例如,代表聲明的節點的DECL_NAME 成員)。
TREE_LIST x tree_list的集合。
TREE_VEC x tree_vec節點
BLOCK b 代碼塊
VOID_TYPE t Void類型
INTEGER_TYPE t 所有語言的整數類型,包括C中的char。
REAL_TYPE t C的float和double。
COMPLEX_TYPE t
VECTOR_TYPE t
ENUMERAL_TYPE t C的enum。
BOOLEAN_TYPE t Pascal的boolean類型(true或者false是唯一的值)。
CHAR_TYPE t Pascal的CHAR類型,不用于C。
POINTER_TYPE t 所有指針類型。
OFFSET_TYPE t 偏移,相對于對象的指針。
REFERENCE_TYPE t C++的引用。
METHOD_TYPE t 第一個參數不出現在參數清單,且指向“自己”的函數類型(C++中的類成員函數)。
FILE_TYPE t 僅用于Pascal;
ARRAY_TYPE t
SET_TYPE t Pascal中的sets類型。
RECORD_TYPE t C中的struct,或者Pascal中的record。
UNION_TYPE t C中的union。和struct類似,但所有成員的偏移均為0。
QUAL_UNION_TYPE t
FUNCTION_TYPE t 函數類型
LANG_TYPE t 特定于語言的類型
INTEGER_CST c 包含32位長的成員TREE_INT_CST_LOW 和TREE_INT_CST_HIGH , 可表示64位大小的常量。
REAL_CST c 代表浮點常量。
COMPLEX_CST c 表示複數常量
VECTOR_CST c 表示vector類型常量
STRING_CST c 表示字元串常量
FUNCTION_DECL d 函數聲明
LABEL_DECL d 标示(label)聲明
CONST_DECL d 常量聲明
TYPE_DECL d 類型聲明(例如:class A;)
VAR_DECL d 局部變量,全局變量,外部變量,靜态變量的聲明
PARM_DECL d 函數參數聲明
RESULT_DECL d 函數傳回值聲明
FIELD_DECL d Struct/union/class的非方法(method)成員聲明
NAMESPACE_DECL d 名字空間聲明
TRANSLATION_UNIT_DECL d 編譯單元,由GCC使用
COMPONENT_REF r Struct/union/class的非方法(method)成員的引用
BIT_FIELD_REF r Struct/union/class的位集(bit-field)成員的引用
INDIRECT_REF r C中的一進制操作符*或者Pascal中的^
BUFFER_REF r Pascal中,用于檔案的^
ARRAY_REF r 通過索引指定的數組元素
ARRAY_RANGE_REF r 通過索引指定的數組子集
VTABLE_REF r 通過索引指定的虛表元素。帶有虛表垃圾收集器需要的資料。其中操作數0是一個ARRAY_REF(或等效的表達式),操作數1是虛表的基位址(必須是VAR_DECL),操作數2是索引(必須為INTEGER_CST)
CONSTRUCTOR e 構造函數
COMPOUND_EXPR e 複合表達式
MODIFY_EXPR e 指派表達式
INIT_EXPR e 用于初始化的表達式。其中,操作數0是被初始化的變量,操作數1是初始值
TARGET_EXPR e 其中,操作數0是初始化的目标,操作數1是初始值,操作數2,如果有,是清除操作。操作數3則是該節點展開後(亦即初始化執行後)所儲存的初始值,這樣我們可以反複展開這個節點。
COND_EXPR e 條件表達式(C中為:... ? ... : ...)。其中,操作數0為條件。操作數1為then的值。操作數2為else的值。操作數0可以為任意類型。操作數1必須和整個表達式的類型相同,除非它無條件地抛出異常,而在這種情況下,它應該是void類型。對操作數2,有同樣的要求。
BIND_EXPR e 聲明臨時變量,包括生成對應的RTL對象及配置設定空間。操作數0是一串VAR_DECL節點。操作數1是使用這些變量的表達式,其值是BIND_EXPR的值。操作數3是對于的代碼塊,用于debug的目的。
CALL_EXPR e 函數調用。操作數0是所調用的函數。操作數1是參數清單。
WITH_CLEANUP_EXPR e 指定一個求值,連同相應的清除操作。操作數0為對應的表達式。操作數1是對應的清除操作。操作數2是最終代表這個值的RTL_EXPR。
CLEANUP_POINT_EXPR e 指定一個清除操作。操作數0是需要執行清除操作的表達式。在該表達式展開後,這些清除操作被執行。
PLACEHOLDER_EXPR x 表示一個,在對該表達式求值時,由一個WITH_RECORD_EXPR 支援的record(GCC内部表示struct/union/class的結構)。該表達式的類型用于尋找替代它的record。
WITH_RECORD_EXPR x 提供引用了用于替代PLACEHOLDER_EXPR的record的表達式。操作數1為要使用的record,它具有和PLACEHOLDER_EXPR的操作數0相同的類型。
PLUS_EXPR 2 加法表達式
MINUS_EXPR 2 減法表達式
MULT_EXPR 2 乘法表達式
TRUNC_DIV_EXPR 2 整數除法,商向0取整(丢棄小數位)。
CEIL_DIV_EXPR 2 整數除法,商向正無窮取整(丢棄小數位,加1)。
FLOOR_DIV_EXPR 2 整數除法,商向負無窮取整(丢棄小數位,減1)。
ROUND_DIV_EXPR 2 整數除法,商四舍五入。
TRUNC_MOD_EXPR 2 對應的餘數
CEIL_MOD_EXPR 2
FLOOR_MOD_EXPR 2
ROUND_MOD_EXPR 2
RDIV_EXPR 2 浮點除法
EXACT_DIV_EXPR 2 假定不需要取整的除法。在C中用于指針相減。
FIX_TRUNC_EXPR 1 浮點到整型的轉換。
FIX_CEIL_EXPR 1
FIX_FLOOR_EXPR 1
FIX_ROUND_EXPR 1
FLOAT_EXPR 1 整型到浮點的轉換。
NEGATE_EXPR 1 一進制取反操作符
MIN_EXPR 2
MAX_EXPR 2
ABS_EXPR 1 取絕對值
LSHIFT_EXPR 2 對于無符号值為邏輯移位,對有符号值為算術移位
RSHIFT_EXPR 2
LROTATE_EXPR 2
RROTATE_EXPR 2
BIT_IOR_EXPR 2 位操作表達式
BIT_XOR_EXPR 2
BIT_AND_EXPR 2
BIT_NOT_EXPR 2
TRUTH_ANDIF_EXPR e ANDIF和ORIF允許不計算第二個操作數,如果表達式的值可以從第一個操作數确定。AND,OR和XOR則永遠對第二個操作數求值,不管它的值是否需要。操作數的類型應為BOOLEAN_TYPE或者INTEGER_TYPE
TRUTH_ORIF_EXPR e
TRUTH_AND_EXPR e
TRUTH_OR_EXPR e
TRUTH_XOR_EXPR e
TRUTH_NOT_EXPR e
LT_EXPR 關系操作符表達式。其中EQ_EXPR和NE_EXPR允許為任何類型。其他操作符隻允許為整型(包括指針或枚舉類型),或者浮點類型。在所有情況下,操作數必須有相同的類型,而表達式的類型為語言所定義的布爾類型。
LE_EXPR
GT_EXPR
GE_EXPR
EQ_EXPR
NE_EXPR
UNORDERED_EXPR 非序浮點數的比較操作符。
ORDERED_EXPR
UNLT_EXPR 非序關系表達式,由GCC使用。(GCC提供了内建的宏,進行C99浮點比較操作,以避免在碰到非序操作數時,抛出異常。NaN的浮點數就是非序的)。
UNLE_EXPR
UNGT_EXPR
UNGE_EXPR
UNEQ_EXPR
IN_EXPR 2 Pascal中sets的操作。該版本GCC沒有使用。
SET_LE_EXPR
CARD_EXPR 1
RANGE_EXPR 2
CONVERT_EXPR 1 表示對一個值的類型轉換
NOP_EXPR 1 表示一個不需要額外産生代碼的轉換
NON_LVALUE_EXPR 1 非左值的表達式
VIEW_CONVERT_EXPR 1 代表把一個類型看作為另一個類型。對應于C中的用法:*(type2 *)&X
SAVE_EXPR e 代表隻能求值一次,卻會被多次使用的結構(在GCC中,使用一般都會涉及求值,進而對子樹進行簡化)
UNSAVE_EXPR e 表示諸如TARGET_EXPRs,SAVE_EXPRs,CALL_EXPRs和RTL_EXPRs,這些被防止多次求值的表達式,需被重置。這樣新的expand_expr函數調用将對它們重新求值(re-evaluated)
RTL_EXPR e 表示對應的RTL結構已被展開成一個序列,當該表達式被展開時,這個序列将被導出(emitted)
ADDR_EXPR e C裡的‘&’
REFERENCE_EXPR e 對一個對象的非左值引用或者指針
ENTRY_VALUE_EXPR e C++/C不用
FDESC_EXPR e
COMPLEX_EXPR 2 複數表達式
CONJ_EXPR 1 共轭操作符表達式
REALPART_EXPR 1 實部表達式
IMAGPART_EXPR 1 虛部表達式
PREDECREMENT_EXPR e C裡的++和--。第二個操作數指明增加或減少的值。對于指針,則是指向對象的大小
PREINCREMENT_EXPR e
POSTDECREMENT_EXPR e
POSTINCREMENT_EXPR e
VA_ARG_EXPR e 用于實作va_arg
TRY_CATCH_EXPR e
TRY_FINALLY_EXPR e
GOTO_SUBROUTINE_EXPR e 在編譯器内部,用于實作TRY_FINALLY_EXPR時,需要的清除操作
LABEL_EXPR s 被封裝為語句的标示定義(A label definition,)
GOTO_EXPR s
RETURN_EXPR s
EXIT_EXPR s 有條件地退出最内層循環
LOOP_EXPR s 循環
LABELED_BLOCK_EXPR e 帶辨別的代碼塊
EXIT_BLOCK_EXPR e 退出帶辨別的代碼塊,通常傳回一個值
EXPR_WITH_FILE_LOCATION e 用源代碼位置資訊诠釋一個樹節點(通常為比表達式)。包括檔案名(EXPR_WFL_FILENAME);行号(EXPR_WFL_LINENO);和列号(EXPR_WFL_COLNO)
SWITCH_EXPR e Switch表達式
EXC_PTR_EXPR e 運作時的異常對象

表1 在tree.def中定義的樹節點

在上表中的Type列,下列字母用作類識别碼(class code),它們的含義如下:

Ø       'x'表示用于例外(不适合其它類别)。

Ø       't'表示用于類型對象。

Ø       'b'用于代碼塊。

Ø       'c'用于代表常量的節點

Ø       'd'用于代表聲明的節點(同時用于臨時變量的引用)。

Ø       'r'用于代表通路存儲位址的節點。

Ø       '<'用于比較表達式。

Ø       '1'用于代表一進制算術表達式的節點。

Ø       '2'用于代表二進制算術表達式的節點。

Ø       's'用于代表“語句”(statement)的表達式的節點,該表達式有副作用(side-effects),但其值不被關注(例如,語句“i=5;”有值5,但這個值被忽略了)。

Ø       'e'用于代表其他類型表達式的節點。

對于r,e,<,1,2,和s類型的節點,它們對應于結構體tree_exp,在DEFTREECODE 的定義中,第四個元素為需要在tree_exp中配置設定的參數的個數。進而确定了節點對象的大小。而對于其他類型節點,結構體本身大小确定,這第四個元素必須為0。如果定義了特定于語言的x或c類别的節點, 該語言的前端必須對langhook的tree_size挂鈎(hook)提供函數,以确定這些節點的大小。

對于C++前端,特定于C++的節點定義于檔案cp-tree.def。它們的含義如下。

節點碼(tree code) 類型 描述
OFFSET_REF r

OFFSET_REF節點用于下列兩種情形:

1      形如A::m的表達式,其中 A是類(a class)而m是非靜态成員(a non-static member)。在這種情況下,操作數0應該為對應于A的類型,操作數1可為FIELD_DECL,BASELINK,,或TEMPLATE_ID_EXPR(對應于m)。

如果位址被使用,這個表達式為指向成員的指針(a pointer-to-member),但如果位址沒有被使用,表達式僅表示對象的成員。

這個形式隻用于解析階段;當語義分析完成後,它便不複存在。

2      形如x.*p的表達式。在這種情況下,操作數0 是對應于x的表達式,而操作數1則是類型為指向成員指針的表達式。

PTRMEM_CST c 指向成員的指針常量。對于指針常量X::Y,宏PTRMEM_CST_CLASS得到X對應的RECORD_TYPE,而PTRMEM_CST_MEMBER得到的是Y對應的聲明。

NEW_EXPR

VEC_NEW_EXPR

e

e

對于NEW_EXPR,操作數0定位操作符中的定位位址(placement list)。操作數1是new聲明符(例如:new char[8])。操作數2是初始值。

DELETE_EXPR

VEC_DELETE_EXPR

e

e

對于DELETE_EXPR,操作數0是要被摧毀的存儲區,操作數1是傳給銷毀函數的值,以訓示是否回收存儲區。
SCOPE_REF r 引用特定的重載的類方法(particular overloaded class method)。操作數0是這個類,操作數1是方法。節點中的COMPLEXITY域訓示類的層次(通常為0)
MEMBER_REF r 引用對象的資料成員。操作數0是對象。操作數1是資料成員(通常由解引用指針得到)
TYPE_EXPR e C++中的類型轉換操作符。在節點中,TREE_TYPE是該轉換符的目标類型。操作數0是要轉換的表達式
AGGR_INIT_EXPR e 在節點中,操作數0是執行初始化操作的函數,操作數1是函數的參數清單,操作數2是為該表達式配置設定的記憶體
THROW_EXPR e (異常)抛出表達式。操作數0是該表達式,如果該表達式存在,否則為NULL_TREE(C++要求表達式必須出現,但需要考慮混合語言程式設計的情況)。
EMPTY_CLASS_EXPR e 表示空的類對象。在節點中TREE_TYPE給出了類的類型。我們使用這種節點避免為空的類生成執行個體。
ALIAS_DECL d 作為一個表達式的占位符的聲明。用于實作非類域中的匿名union。
BASELINK x

表示從基類引用的成員函數。在節點中,BASELINK_FUNCTIONS給出對應的FUNCTION_DECL,或者TEMPLATE_DECL,或者OVERLOAD,或者TEMPLATE_ID_EXPR 。BASELINK_BINFO給出了定義該方法的基類,換而言之,當調用這個方法時,this指針需要被轉換至的類型。BASELINK_ACCESS_BINFO則給出了最初定義這個方法的基類。

BASELINK代表一個表達式。它的TREE_TYPE給出了該表達式的類型。該類型或者是函數類型(FUNCTION_TYPE),獲者是方法類型(METHOD_TYPE),或者是以unknown_type_node 代表的重載函數。

TEMPLATE_DECL d

模闆定義。以下節點中的域都有特定用途,雖然在cp-tree.h中,有其他宏會使用這些域。

DECL_ARGUMENTS – 模闆參數vector

DECL_TEMPLATE_INFO – 模闆特定的資訊

DECL_VINDEX – 已具現的模闆清單;該版本僅用于函數模闆。

TREE_TYPE  -- 建構對象的類型

DECL_TEMPLATE_RESULT – 建構對象的聲明(例如:對以具現函數模闆的FUNCTION_DECL)

TEMPLATE_PARM_INDEX x

模闆參數清單的索引。其中TEMPLATE_PARM_IDX 給出實參的索引(從0開始),而TEMPLATE_PARM_LEVEL給出模闆參數的層次(從1開始)。例如:

   template <class T> // Index 0, Level 1.

   struct S

   {

      template <class U, // Index 0, Level 2.

                class V> // Index 1, Level 2.

      void f();

   };

域TEMPLATE_PARM_DESCENDANTS是由該節點降階(descend)後的TEMPLATE_PARM_INDEX節點組成的連結清單。連結清單中第一個節點将有相同的索引(IDX),但層次(LEVEL)少一級。連結清單中節點的TREE_CHAIN域将這些降階的節點(descendants)鍊在一起。

域TEMPLATE_PARM_DECL則對應這個模闆參數的聲明,它要麼是個類型聲明(TYPE_DECL)要麼是個常量聲明(CONST_DECL)。

域TEMPLATE_PARM_ORIG_LEVEL則是最外層父節點的層次(the LEVEL of the most distant parent),也即最初聲明這個模闆參數時,對應的層次(the LEVEL that the parameter originally had when it was declared)。例如,如果我們具現S<int>,我們将得到:

 struct S<int>

 {

   template <class U, // Index 0, Level 1, Orig Level 2

           class V> // Index 1, Level 1, Orig Level 2

   void f();

 }; 

如果我們關注模闆的類型,TEMPLATE_PARM_LEVEL表示模闆參數的層次;如果我們關注具現,則TEMPLATE_PARM_ORIG_LEVEL是關聯的層次。

TEMPLATE_TYPE_PARM t 類型模闆參數。對應的模闆參數必須是類類型。而TYPE_FIELDS将包含一個TEMPLATE_PARM_INDEX節點。
TEMPLATE_TEMPLATE_PARM t

模闆模闆參數。它必須是類類型。TYPE_FIELDS将包含一個TEMPLATE_PARM_INDEX節點。它不綁定任何模闆實參,就像C<TT>中的TT。

TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO 則是NULL_TREE,TYPE_NAME 則是對應的TEMPLATE_DECL。

BOUND_TEMPLATE_TEMPLATE_PARM t 類似TEMPLATE_TEMPLATE_PARM,但用于已綁定實參的模闆參數,像TT<int>。在此情形下,TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO 包含模闆名和綁定的實參。TYPE_NAME 是一個TYPE_DECL。
TYPENAME_TYPE t 由類似typename T::t指定的類型。  TYPE_CONTEXT對應T, TYPE_NAME是一個對應于t的IDENTIFIER_NODE 。如果該類型通過template-id來命名, TYPENAME_TYPE_FULLNAME将持有 TEMPLATE_ID_EXPR節點。如果TREE_TYPE不為空,該類型由隐式的類型擴充生成(generated by the implicit typename extension),TREE_TYPE儲存了T基類的類型節點(_TYPE from a baseclass of T)。
UNBOUND_CLASS_TEMPLATE t 形如T::template C的模闆模闆實參。 TYPE_CONTEXT表示T,模闆參數所依賴的對象。TYPE_NAME則是對應C的IDENTIFIER_NODE, 成員類模闆。
TYPEOF_TYPE t 代表由__typeof (expr)指出的類型。TYPE_FIELDS則是要詢問的表達式(即例中的expr)。
USING_DECL d 代表using聲明。DECL_INITIAL指明指定的作用域(specified scope)。它不是别名(an alias),但随後它會被展開成多個别名。如果作用域(scope)是依賴的(dependent),該節點的類型是NULL_TYPE,否則就是void類型。
USING_STMT e 代表using directive。它唯一的操作數是USING_STMT_NAMESPACE
DEFAULT_ARG x 未被解析的預設實參(un-parsed default argument)。域TREE_CHAIN用于儲存那些,必須在此實參被解析時,已被具現好的函數執行個體(instantiations of functions that had to be instantiated before the argument was parsed)。注:用于模闆
TEMPLATE_ID_EXPR e 形如foo<int>的template-id。其中第一個操作數是所對應的模闆節點。如果沒有顯式的實參,則第二個操作數是NULL,否則就是代表實參的TREE_VEC。所對應的模闆節點可以是FUNCTION_DECL,TEMPLATE_DECL,或者OVERLOAD。而如果template-id表示一個成員模闆(member template),所對應的模闆節點可能是IDENTIFIER_NODE。
OVERLOAD x 用于連結候選的重載函數。
WRAPPER x 用于封裝非樹節點結構,使其可以鍊如樹結構。
MODOP_EXPR e
CAST_EXPR 1
REINTERPRET_CAST_EXPR 1
CONST_CAST_EXPR 1
STATIC_CAST_EXPR 1
DYNAMIC_CAST_EXPR 1
DOTSTAR_EXPR e
TYPEID_EXPR e
PSEUDO_DTOR_EXPR e
NON_DEPENDENT_EXPR e 用于模闆中非類型依賴表達式(expression that is not type-dependent)的展位符(placeholder)。當一個非類型依賴的表達式出現在另一個表達式中,我們必須計算這個更大的表達式的類型(compute the type of that larger expression)。這個計算通常會改變原有的表達式,如果那個表達式出現在模闆實參清單,這會改變表達式的修飾名(the mangling of that expression)。在這種情況下,我們建立NON_DEPENDENT_EXPR節點來記錄原始的表達式(take the place of the original expression)。這個表達式是唯一的操作數,它隻用于診斷目的。
CTOR_INITIALIZER e
TRY_BLOCK e
EH_SPEC_BLOCK e
HANDLER e HANDLER節點封裝了一個對應catch句柄(catch handler)的HANDLER_TYPE節點。在HANDLER_PARMS 中是catch變量的聲明,HANDLER_BODY則是catch塊
MUST_NOT_THROW_EXPR e MUST_NOT_THROW_EXPR封裝的是不會抛出異常的表達式,如果這表達式抛出了異常,程式必須調用terminate結束。
TAG_DEFN e 用于表示,在C++标準,[over.best.ics]節意義下的隐式轉換序列。轉換序列通過節點的第一個操作數連結在一起,連結清單中的轉換以相反的次序執行。最裡層的轉換(亦即在連結清單尾端的節點)必須是代表自身變換(identity conversion)的IDENTITY_CONV)。
IDENTITY_CONV e
LVALUE_CONV e
QUAL_CONV e
STD_CONV e
PTR_CONV e
PMEM_CONV e
BASE_CONV e
REF_BIND e
USER_CONV e
AMBIG_CONV e
RVALUE_CONV e

表2 cp-tree.def中定義的樹節點

繼續閱讀