GCC-3.4.6源代码学习笔记(13)

2.2.3.1.5.            聚集类型的信息
2.2.3.1.5.1.  概览[2]

一个类类型由一个RECORD_TYPE节点或者UNION_TYPE节点来表示。声明为union 的类由UNION_TYPE来表示,而声明为struct或者class的类由RECORD_TYPE来表示。你可以使用宏CLASSTYPE_DECLARED_CLASS来辨别特定的类是class还是struct。如果类被声明为class,这个宏返回true

几乎所有的非函数成员都出现在节点的TYPE_FIELDS链中。给定一个成员,下一个成员可以通过TREE_CHAIN找到。你不能以任何方式来依赖成员出现在链中的次序。这个链中的所有节点必须为DECL系列节点。其中,FIELD_DECL节点用于表示非静态数据成员, VAR_DECL节点用于表示静态数据成员,而TYPE_DECL节点用于表示类型声明。注意,如果在类中声明了枚举类型,用于枚举常量的CONST_DECL也会出现在链中(当然,枚举类型的TYPE_DECL也会出现)。但在这个链中不会出现代表基类的节点。特别的没有代表基类部分的FIELD_DECL(注:在后面的layout_class_type函数中,实际上代表基类部分的FIELD_DECL会由编译器加到TYPE_FIELDS的头部,不过这在最后完成类节点构造的步骤中)。

TYPE_VFIELD是由编译器生成的域,用于指向虚函数表。它可能会出现在TYPE_FIELDS链(注:取决于类是否需要虚函数表)。不过,在后端看来TYPE_VFIELD和其他TYPE_FIELDS上的节点并无不同。

函数成员则出现在TYPE_METHODS链。同样,后续的函数成员可以通过TREE_CHAIN 访问。如果函数被重载,每个被重载的函数都会出现,但OVERLOAD节点(注:代表重载函数)不出现在TYPE_METHODS链上(注:出现在链的分支)。隐含声明的函数(包括缺省构造函数,拷贝构造函数,赋值操作符,及析构函数)也都会出现在链上。

每个类都一个伴随的binfo,它可以通过TYPE_BINFO访问。Binfo用于代表基类。TYPE_BINFO给出的binfo是退化的,因为每个类都被视为自己的基类。给定一个binfo,其基类可以通过BINFO_BASETYPES来获得。这些基类本身也是binfo。一个binfo对应的类类型则由BINFO_TYPE给出。BINFO_TYPE (TYPE_BINFO (x))总是得到x的类型(除去最上层的类型修饰)。但是TYPE_BINFO (BINFO_TYPE (y))不总是返回与y相同的binfo。原因是,如果y是一个代表派生类D中的基类Bbinfo,那么BINFO_TYPE (y)将是B,而TYPE_BINFO (BINFO_TYPE (y))将是B作为自身基类的binfo,而不是作为D的基类的binfo(注:在后面,我们可以看到,D的基类BbinfoB作为自身基类的binfo是不同的对象。Binfo可以看作base information的缩写)。

BINFO_BASETYPES是一个TREE_VEC。基类以由左到右的顺序出现。通过宏TREE_VIA_PUBLICTREE_VIA_PROTECTEDTREE_VIA_PRIVATE可以知道派生是否为publicprotected或者private。每个宏都需要一个binfo节点,仅当指定的派生方式被应用了,才返回true。如果一个binfoTREE_VIA_VIRTUAL返回true,那么它的 BINFO_TYPE(注:对应的类类型)是一个虚派生。

以下的宏被用于表示类类型节点。

LOCAL_CLASS_P如果类是局部类,即定义于函数体内,返回true(注:这是GNU C++的扩展)。

TYPE_POLYMORPHIC_P如果类包含至少一个虚函数(通过声明或继承),返回true

TYPE_HAS_DEFAULT_CONSTRUCTOR如果类具有缺省构造函数,返回true

CLASSTYPE_HAS_MUTABLETYPE_HAS_MUTABLE_P如果类含有mutable的数据对象,2者返回true

CLASSTYPE_NON_POD_P如果类不是PODplain of data),返回true

TYPE_HAS_NEW_OPERATOR如果类定义了new操作符,返回true

TYPE_HAS_ARRAY_NEW_OPERATOR如果类定义了new[]操作符,返回true

TYPE_OVERLOADS_CALL_EXPR如果类重载了()操作符,返回true

TYPE_OVERLOADS_ARRAY_REF如果类重载了[]操作符,返回true

TYPE_OVERLOADS_ARROW如果类重载了->操作符,返回true

2.2.3.1.5.2.  聚集类型的布局

聚集类型包括以下:

RECORD_TYPE [2]

²        用于表示structclass类型,以及成员函数指针,还有其他语言中类似的构造。TYPE_FIELDS包含这个类所含有的项(item),它们可以是FIELD_DECLVAR_DECLCONST_DECL或者TYPE_DECL。不可以假定类中域在节点中的次序,也不可假定它们中有重叠(overlap)。

如果TYPE_PTRMEMFUNC_P成立,那么这个类型是一个指向成员的指针类型。在这种情况下,TYPE_PTRMEMFUNC_FN_TYPE是一个指向一个METHOD_TYPE POINTER_TYPEMETHOD_TYPE是被这个指向成员函数指针指向的函数类型。如果TYPE_PTRMEMFUNC_P不成立,这个类是类类型。

UNION_TYPE [2]

²        用于表示union类型。类似于RECORD_TYPE,除了在TYPE_FIELD中所有的FIELD_DECL节点都位于起始位置0(注:见后面的类布局)。

QUAL_UNION_TYPE [2]

²        用于表示Ada中的可变基类(variant record)。类似于UNION_TYPE除了每个FIELD_DECL拥有DECL_QUALIFIER域,其中包含一个指示域是否出现在对象中的布尔表达式。这个类型只能有一个有效域,因此只有当,在TYPE_FIELDS中,之前的域都不出现时,域的DECL_QUALIFIER才被求值。通常这些表达式通过PLACEHOLDER_EXPR来引用外部对象(outer object)的一个域。

 

layout_type (continue)

 

1725     case RECORD_TYPE:

1726     case UNION_TYPE:

1727     case QUAL_UNION_TYPE:

1728     {

1729       tree field;

1730       record_layout_info rli;

1731

1732       /* Initialize the layout information.  */

1733       rli = start_record_layout (type);

1734

1735       /* If this is a QUAL_UNION_TYPE, we want to process the fields

1736         in the reverse order in building the COND_EXPR that denotes

1737         its size. We reverse them again later.  */

1738       if (TREE_CODE (type) == QUAL_UNION_TYPE)

1739         TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));

1740

1741       /* Place all the fields.  */

1742       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))

1743         place_field (rli, field);

1744

1745       if (TREE_CODE (type) == QUAL_UNION_TYPE)

1746         TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));

1747

1748       if (lang_adjust_rli)

1749         (*lang_adjust_rli) (rli);

1750

1751       /* Finish laying out the record.  */

1752       finish_record_layout (rli, /*free_p=*/true);

1753     }

1754     break;

 

以上就是前端中用于布局聚集类型的代码片段。需要指出,这只是前端用来对自己人工(artificial)构造的聚集对象布局的方法。使用者定义的聚集类需要复杂得多的方法(见后面的layout_class_type)。

2.2.3.1.5.2.1.              保存信息的结构体

构建RECORD_TYPE/UNION_TYPE/QUAL_UNION_TYPE节点的信息,需要保存在结构体中。下面是它的定义。

 

2332 typedef struct record_layout_info_s                                                             in tree.h

2333 {

2334   /* The RECORD_TYPE that we are laying out.  */

2335   tree t;

2336   /* The offset into the record so far, in bytes, not including bits in

2337     BITPOS.  */

2338   tree offset;

2339   /* The last known alignment of SIZE.  */

2340   unsigned int offset_align;

2341   /* The bit position within the last OFFSET_ALIGN bits, in bits.  */

2342   tree bitpos;

2343   /* The alignment of the record so far, in bits.  */

2344   unsigned int record_align;

2345   /* The alignment of the record so far, ignoring #pragma pack and

2346     __attribute__ ((packed)), in bits.  */

2347   unsigned int unpacked_align;

2348   /* The previous field layed out.  */

2349   tree prev_field;

2350   /* The static variables (i.e., class variables, as opposed to

2351     instance variables) encountered in T.  */

2352   tree pending_statics;

2353   /* Bits remaining in the current alignment group */

2354   int remaining_in_alignment;

2355   /* True if we've seen a packed field that didn't have normal

2356     alignment anyway.  */

2357   int packed_maybe_necessary;

2358 } *record_layout_info;

 

函数start_record_layout创建和初始化了record_layout_info。如果目标平台对这些类型有特殊的对齐要求,在下面564行的STRUCTURE_SIZE_BOUNDARY就会被定义。对于x86/Linux平台,这个宏没有定义。

 

550  record_layout_info

551  start_record_layout (tree t)                                                                  in stor-layout.c

552  {

553    record_layout_info rli = xmalloc (sizeof (struct record_layout_info_s));

554 

555    rli->t = t;

556 

557    /* If the type has a minimum specified alignment (via an attribute

558      declaration, for example) use it -- otherwise, start with a

559      one-byte alignment.  */

560    rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));

561    rli->unpacked_align = rli->record_align;

562    rli->offset_align = MAX (rli->record_align, BIGGEST_ALIGNMENT);

563 

564  #ifdef STRUCTURE_SIZE_BOUNDARY

565    /* Packed structures don't need to have minimum size.  */

566    if (!TYPE_PACKED (t))

567      rli->record_align = MAX (rli->record_align, (unsigned) STRUCTURE_SIZE_BOUNDARY);

568  #endif

569 

570    rli->offset = size_zero_node;

571    rli->bitpos = bitsize_zero_node;

572    rli->prev_field = 0;

573    rli->pending_statics = 0;

574    rli->packed_maybe_necessary = 0;

575 

576    return rli;

577  }

另外注意,在562行,在具有非常量大小的布局中,offset_align记录着已布局部分的对齐量。在布局的开始,offset_align具有最大的对齐量。

2.2.3.1.5.2.2.              收集域的信息

2.2.3.1.5.2.2.1.        tree_decl节点

在上面layout_type1742 行,TYPE_FIELDS是一条由FIELD_DECL节点组成的链。FIELD_DECL节点的类型是下面的tree_decl

 

1647 struct tree_decl GTY(())                                                                                    in tree.h

1648 {

1649   struct tree_common common;

1650   location_t locus;

1651   unsigned int uid;

1652   tree size;

1653   ENUM_BITFIELD(machine_mode) mode : 8;

1654

1655   unsigned external_flag : 1;

1656   unsigned nonlocal_flag : 1;

1657   unsigned regdecl_flag : 1;

1658   unsigned inline_flag : 1;

1659   unsigned bit_field_flag : 1;

1660   unsigned virtual_flag : 1;

1661   unsigned ignored_flag : 1;

1662   unsigned abstract_flag : 1;

1663

1664   unsigned in_system_header_flag : 1;

1665   unsigned common_flag : 1;

1666   unsigned defer_output : 1;

1667   unsigned transparent_union : 1;

1668   unsigned static_ctor_flag : 1;

1669   unsigned static_dtor_flag : 1;

1670   unsigned artificial_flag : 1;

1671   unsigned weak_flag : 1;

1672

1673   unsigned non_addr_const_p : 1;

1674   unsigned no_instrument_function_entry_exit : 1;

1675   unsigned comdat_flag : 1;

1676   unsigned malloc_flag : 1;

1677   unsigned no_limit_stack : 1;

1678   ENUM_BITFIELD (built_in_class) built_in_class : 2;

1679   unsigned pure_flag : 1;

1680

1681   unsigned non_addressable : 1;

1682   unsigned user_align : 1;

1683   unsigned uninlinable : 1;

1684   unsigned thread_local_flag : 1;

1685   unsigned declared_inline_flag : 1;

1686   ENUM_BITFIELD (symbol_visibility) visibility : 2;

1687   unsigned unused : 1;

1688   /* one unused bit.  */

1689

1690   unsigned lang_flag_0 : 1;

1691   unsigned lang_flag_1 : 1;

1692   unsigned lang_flag_2 : 1;

1693   unsigned lang_flag_3 : 1;

1694   unsigned lang_flag_4 : 1;

1695   unsigned lang_flag_5 : 1;

1696   unsigned lang_flag_6 : 1;

1697   unsigned lang_flag_7 : 1;

1698

1699   union tree_decl_u1 {

1700     /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is

1701       DECL_FUNCTION_CODE.  */

1702     enum built_in_function f;

1703     /* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this

1704       is used by language-dependent code.  */

1705     HOST_WIDE_INT i;

1706     /* DECL_ALIGN and DECL_OFFSET_ALIGN. (These are not used for

1707       FUNCTION_DECLs).  */

1708     struct tree_decl_u1_a {

1709       unsigned int align : 24;

1710       unsigned int off_align : 8;

1711     } a;

1712   } GTY ((skip (""))) u1;

1713

1714   tree size_unit;

1715   tree name;

1716   tree context;

1717   tree arguments; /* Also used for DECL_FIELD_OFFSET */

1718   tree result;        /* Also used for DECL_BIT_FIELD_TYPE */

1719   tree initial;       /* Also used for DECL_QUALIFIER */

1720   tree abstract_origin;

1721   tree assembler_name;

1722   tree section_name;

1723   tree attributes;

1724   rtx rtl;       /* RTL representation for object.  */

1725

1726   /* In FUNCTION_DECL, if it is inline, holds the saved insn chain.

1727     In FIELD_DECL, is DECL_FIELD_BIT_OFFSET.

1728     In PARM_DECL, holds an RTL for the stack slot

1729     of register where the data was actually passed.

1730     Used by Chill and Java in LABEL_DECL and by C++ and Java in VAR_DECL.  */

1731   union tree_decl_u2 {

1732     struct function * GTY ((tag ("FUNCTION_DECL"))) f;

1733     rtx GTY ((tag ("PARM_DECL"))) r;

1734     tree GTY ((tag ("FIELD_DECL"))) t;

1735     int GTY ((tag ("VAR_DECL"))) i;

1736   } GTY ((desc ("TREE_CODE((tree) &(%0))"))) u2;

1737

1738   /* In a FUNCTION_DECL, this is DECL_SAVED_TREE.  */

1739   tree saved_tree;

1740

1741   /* In a FUNCTION_DECL, these are function data which is to be kept

1742     as long as FUNCTION_DECL is kept.  */

1743   tree inlined_fns;

1744

1745   tree vindex;

1746   HOST_WIDE_INT pointer_alias_set;

1747   /* Points to a structure whose details depend on the language in use.  */

1748   struct lang_decl *lang_specific;

1749 };

 

在同一个文件,定义了一系列以DECL开头的宏用于访问tree_decl的域(红色部分为定义)[2]

DECL_SECTION_NAME (DECL_CHECK (NODE)->decl.section_name):记录在一个段(section)属性中指定的名字(GNU C++允许在变量声明中使用段属性,来指定目标文件中变量存放的段)。用于从decl_attributes把这个名字传递到make_function_rtlmake_decl_rtl

DECL_CONTEXT (DECL_CHECK (NODE)->decl.context)

DECL_CONTEXT (DECL_CHECK (NODE)->decl.context)

DECL_FIELD_CONTEXT (FIELD_DECL_CHECK (NODE)->decl.context):对于FIELD_DECL,是这个域所属类的RECORD_TYPEUNION_TYPEQUAL_UNION_TYPE节点。对于VAR_DECLPARM_DECLFUNCTION_DECLLABEL_DECLCONST_DECL节点,它指向包含函数的FUNCTION_DECL节点,或者指向包含类的RECORD_TYPEUNION_TYPE节点,或者如果给定的声明是具有文件作用域的,指向NULL_TREE或一个TRANSLATION_UNIT_DECL节点。

DECL_ATTRIBUTES (DECL_CHECK (NODE)->decl.attributes):这是存放属性的地方。

DECL_FIELD_OFFSET (FIELD_DECL_CHECK (NODE)->decl.arguments):对于FIELD_DECL节点,这是域以字节为单位的偏移,它根据最靠近结构体头的字节来计算。

DECL_FIELD_BIT_OFFSET (FIELD_DECL_CHECK (NODE)->decl.u2.t):对于FIELD_DECL节点,这是域以比特为单位的偏移,它根据最靠近结构体头的比特位来计算。

DECL_BIT_FIELD_TYPE (FIELD_DECL_CHECK (NODE)->decl.result) :对于FIELD_DECL节点,如果域是位域(bit-field), 则是其对应的原始类型。节点的TREE_TYPE可能已被更改(通过函数finish_struct)。

DECL_ARGUMENTS (DECL_CHECK (NODE)->decl.arguments):在FUNCTION_DECL节点中,是一个DECL节点链。在VAR_DECLPARM_DECL节点中,保留作语言相关的用途。

DECL_RESULT_FLD (DECL_CHECK (NODE)->decl.result):对于TEMPLATE_DECL节点,这是对应的TYPE_DECL。在语句(statement)中声明的变量的VAR_DECL节点中,这是被屏蔽的局部变量。

DECL_RESULT (FUNCTION_DECL_CHECK (NODE)->decl.result):在FUNCTION_DECL节点中,保存了返回值。

DECL_ORIGINAL_TYPE (TYPE_DECL_CHECK (NODE)->decl.result):对于TYPE_DECL节点,保存“原始”类型。(TREE_TYPE拥有拷贝)

DECL_ARG_TYPE_AS_WRITTEN (PARM_DECL_CHECK (NODE)->decl.result):在PARM_DECL节点,保存声明时的类型(the type as written)(可能是函数或数组)。

DECL_INITIAL (DECL_CHECK (NODE)->decl.initial) :对于FUNCTION_DECL,保存BINDINGS树。对于TRANSLATION_UNIT_DECL,保存名字空间块。对于VAR_DECL,保存初始化值。

DECL_ARG_TYPE (PARM_DECL_CHECK (NODE)->decl.initial):对于PARM_DECL,记录传递实参的数据类型,它可能与程序中看到的类型不同。

DECL_QUALIFIER (FIELD_DECL_CHECK (NODE)->decl.initial):对于在QUAL_UNION_TYPE 中的FIELD_DECL,记录一个表达式,如果这个表达式不为0,表明该域在类型里有效。

DECL_SOURCE_LOCATION (DECL_CHECK (NODE)->decl.locus):这个域描述了这个声明在源代码中的位置。如果声明出现在多个地方(比如一个C函数先声明,然后再定义),这部分指向定义。

DECL_SIZE (DECL_CHECK (NODE)->decl.size):保存数据以比特衡量的大小。它是个树形式,不需要为常量。

DECL_SIZE_UNIT (DECL_CHECK (NODE)->decl.size_unit):以字节衡量的数据大小。

DECL_ALIGN (DECL_CHECK (NODE)->decl.u1.a.align):以比特衡量的对齐量。

DECL_ALIGN_UNIT (DECL_ALIGN (NODE) / BITS_PER_UNIT):以字节衡量的对齐量。

DECL_OFFSET_ALIGN

(((unsigned HOST_WIDE_INT)1) << FIELD_DECL_CHECK (NODE)-> decl.u1.a.off_align):对于FIELD_DECLoff_align保存了DECL_FIELD_OFFSET中为0的低位比特的数目。因此DECL_OFFSET_ALIGN返回了DECL_FIELD_OFFSET所持有的对齐量。

SET_DECL_OFFSET_ALIGN (NODE, X

(FIELD_DECL_CHECK (NODE)->decl.u1.a.off_align = exact_log2 ((X) & -(X)))

DECL_USER_ALIGN (DECL_CHECK (NODE)->decl.user_align):如果类型的对齐量由”aligned”的属性指定,其值为1。如果为这个类型的默认值,则为0

DECL_MODE (DECL_CHECK (NODE)->decl.mode) :保存变量或者域声明的机器模式。它永远等于TYPE_MODE (TREE_TYPE (decl)),除FIELD_DECL外。

DECL_RTL (DECL_CHECK (NODE)->decl.rtl                      /

   ? (NODE)->decl.rtl : (make_decl_rtl (NODE, NULL), (NODE)->decl.rtl)):保存对应变量值或函数的RTL表达式。对于函数,拥有静态存储的变量和标签(label),这个值会被延后评估(evaluated lazily)。

DECL_RTL_SET_P (DECL_CHECK (NODE)->decl.rtl != NULL):如果NODE节点中DECL_RTL已设置,返回非零值。

COPY_DECL_RTL(DECL_CHECK (NODE2)->decl.rtl = DECL_CHECK (NODE1)->decl.rtl):从NODE1拷贝RTLNODE2。如果NODE1RTL未设定,NODE2也不会设定,这是一个迟缓拷贝(lazy copy)。

DECL_INCOMING_RTL (PARM_DECL_CHECK (NODE)->decl.u2.r):对于PARM_DECL,保存用于传递数据的栈位置(stack slot)或寄存器的对应的RTL

DECL_SAVED_INSNS (FUNCTION_DECL_CHECK (NODE)->decl.u2.f) :对于 FUNCTION_DECL,如果它是内联的,保存函数体语句链。

DECL_FUNCTION_CODE (FUNCTION_DECL_CHECK (NODE)->decl.u1.f):对于 FUNCTION_DECL,如果它是内建函数(built-in),表明它为何种内建操作。

DECL_VINDEX (DECL_CHECK (NODE)->decl.vindex):对于FUNCTION_DECL,它有两种用途。在包含该函数的结构体被布局前,DECL_VINDEX可能指向基类中的FUNCTION_DECL,它是虚函数,被当前虚函数覆盖。当类布局完成后,这个指针将变为INTEGER_CST,它作为虚函数表的索引。

DECL_FCONTEXT (FIELD_DECL_CHECK (NODE)->decl.vindex):对于 FIELD_DECLDECL_FCONTEXT是第一个定义这个域的基类。当为虚基类和虚函数准备调试信息时,这是必要的信息。

DECL_UID (DECL_CHECK (NODE)->decl.uid):对每个DECL节点,它是唯一的数字(a unique number)。

DECL_ABSTRACT_ORIGIN (DECL_CHECK (NODE)->decl.abstract_origin):对于各种DECL节点,它指向该节点作为一个(内联或者模板展开)实例的原始抽象声明节点(original (abstract) decl node),否则它是NULL。例如,对于内联函数的一个嵌套声明,它指向函数定义。

DECL_ORIGIN

(DECL_ABSTRACT_ORIGIN(NODE) ? DECL_ABSTRACT_ORIGIN(NODE): (NODE)):类似DECL_ABSTRACT_ORIGIN,但如果没有抽象源头(no abstract origin),返回NODE。当设置DECL_ABSTRACT_ORIGIN时,它有用。

DECL_FROM_INLINE (DECL_ABSTRACT_ORIGIN (NODE) != NULL_TREE /

              && DECL_ABSTRACT_ORIGIN (NODE) != (NODE)):对于各种DECL节点,非零值表示该节点代表了一个内联函数的若干个抽象声明中的一个内联实例。并抑制变量屏蔽的警告。FUNCTION_DECL节点也会把自己设为自身的抽象源头(abstract origin)。

DECL_IGNORED_P (DECL_CHECK (NODE)->decl.ignored_flag):对于DECL节点,非零值表示该节点的名字,在符号调试的目的下,应该忽略。

DECL_ABSTRACT (DECL_CHECK (NODE)->decl.abstract_flag):对给定的DECL节点,非零值表示该节点代表给定声明的“抽象实例”(abstract instance)(例如一个内联函数的原始声明(original declaration))。当生成符号调试信息时,我们不要尝试为标记为“抽象实例”的节点产生地址信息,因为对这种实例为其分配空间的代码不会产生。

DECL_IN_SYSTEM_HEADER (DECL_CHECK (NODE)->decl.in_system_header_flag):非零值表示,如果该声明没有被使用,不要产生警告。

DECL_COMMON (DECL_CHECK (NODE)->decl.common_flag):对给定的DECL节点,非零值表示该节点应该被尽可能放入.common段。如果给定一个DECL_INITIAL,而且它不是error_mark_node,那么该节点不能放入.common段。

DECL_LANG_SPECIFIC (DECL_CHECK (NODE)->decl.lang_specific):语言特定的信息。

DECL_EXTERNAL (DECL_CHECK (NODE)->decl.external_flag):在VAR_DECLFUNCTION_DECL节点中,非零值表示外部引用:不需要分配存储,其定义在其他地方。

TYPE_DECL_SUPPRESS_DEBUG (TYPE_DECL_CHECK (NODE)->decl.external_flag):在TYPE_DECL节点中,非零值表示该类型的详细信息不被转储到块(stab)中。相反它会产生名字的交叉引用(cross reference)。它和DECL_EXTERNAL一起使用。

DECL_REGISTER (DECL_CHECK (NODE)->decl.regdecl_flag):在VAR_DECLPARM_DECL节点中,非零值表示声明为`register'

DECL_PACKED (FIELD_DECL_CHECK (NODE)->decl.regdecl_flag):在FIELD_DECL节点,表示该域是紧凑的。

DECL_NO_STATIC_CHAIN (FUNCTION_DECL_CHECK (NODE)->decl.regdecl_flag):在含有非0DECL_CONTEXT FUNCTION_DECL节点中,表示函数不需要静态链。

DECL_INLINE (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag):在FUNCTION_DECL节点中,非零值表示在调用处,函数体被代入。

DECL_DECLARED_INLINE_P

 (FUNCTION_DECL_CHECK (NODE)->decl.declared_inline_flag):在FUNCTION_DECL节点中,非零值表示函数通过关键字inline被声明为内联。这个标记控制inline的链接语义;但函数是否内联通过DECL_INLINE来决定。

DECL_VISIBILITY (DECL_CHECK (NODE)->decl.visibility):是声明的可见属性。

DECL_UNINLINABLE (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable):在FUNCTION_DECL节点中,非零值表示函数不能被内联。

DECL_THREAD_LOCAL (VAR_DECL_CHECK (NODE)->decl.thread_local_flag):在VAR_DECL节点中,非零值表示该数据不能被分配在线程的局部储存。

DECL_SAVED_TREE (FUNCTION_DECL_CHECK (NODE)->decl.saved_tree):在FUNCTION_DECL节点中,保存了整个函数体。通常是一个COMPOUND_STMT,但在C++这也可能是一个RETURN_INITCTOR_INITIALIZERTRY_BLOCK

DECL_INLINED_FNS (FUNCTION_DECL_CHECK (NODE)->decl.inlined_fns):内联到该函数体的FUNCTION_DECL链。

DECL_IS_MALLOC (FUNCTION_DECL_CHECK (NODE)->decl.malloc_flag):在FUNCTION_DECL节点中,非零值表示该函数应该象malloc那样处理,这意味着它返回一个没有别名的指针(注,参见后面关于别名的章节,或者在wikipedia)。

DECL_IS_PURE (FUNCTION_DECL_CHECK (NODE)->decl.pure_flag):在FUNCTION_DECL节点2,非零值表示函数应被视为纯函数(象常量函数,但可能读全局内存)。

DECL_BIT_FIELD (FIELD_DECL_CHECK (NODE)->decl.bit_field_flag):在FIELD_DECL节点中,非零值表示它是一个位域,需要特殊的访问方式。

DECL_IN_TEXT_SECTION (VAR_DECL_CHECK (NODE)->decl.bit_field_flag):在静态的VAR_DECL节点中,非零值表示其空间分配在代码段。

DECL_BUILT_IN (DECL_BUILT_IN_CLASS (NODE) != NOT_BUILT_IN):在FUNCTION_DECL节点中,非零值表示它是一个内建函数。

DECL_BUILT_IN_CLASS (FUNCTION_DECL_CHECK (NODE)->decl.built_in_class):对于内建函数,这代表编译器的哪部分定义它。

DECL_VIRTUAL_P (DECL_CHECK (NODE)->decl.virtual_flag):用在VAR_DECL节点中,表示该变量为虚函数表。用在FIELD_DECL节点中,表示它为虚函数表指针。用在FUNCTION_DECL节点中表示该函数是虚函数。

DECL_DEFER_OUTPUT (DECL_CHECK (NODE)->decl.defer_output):用于表示这个DECL节点的链接状态尚不清楚,因此它现在不能被输出。

DECL_TRANSPARENT_UNION (PARM_DECL_CHECK (NODE)->decl.transparent_union):用在类型为unionPARM_DECL节点中,表示该参数可以用传递第一个union 成员的方式来传递。

DECL_STATIC_CONSTRUCTOR

(FUNCTION_DECL_CHECK (NODE)->decl.static_ctor_flag)

DECL_STATIC_DESTRUCTOR

(FUNCTION_DECL_CHECK (NODE)->decl.static_dtor_flag):用在FUNCTION_DECL节点中,表示它们需要在程序执行前自动运行。

DECL_ARTIFICIAL (DECL_CHECK (NODE)->decl.artificial_flag):用于表示该DECL节点是编译器声明的。

DECL_WEAK (DECL_CHECK (NODE)->decl.weak_flag) :用于表示该DECL拥有弱链接性(weak linkage)。

DECL_ONE_ONLY (DECL_CHECK (NODE)->decl.transparent_union):用在标记为TREE_PUBLIC的声明节点中,表示该节点的在不同编译单元的拷贝需要被合并。

DECL_COMDAT (DECL_CHECK (NODE)->decl.comdat_flag):用在DECL节点中,表示就算该节点是TREE_PUBLIC的,它也不需要被输出,除非在这个编译单元被用到。这些实体被编译单元所共享(象弱实体,weak entity),而且保证它们被需要它们的编译单元输出,而不被其他编译单元输出。DECL_COMDAT只是对后端的暗示,由前端设定。前端必须保证,如果输出DECL_COMDAT实体,除了使代码膨胀外,没有别的坏处。

DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT

(FUNCTION_DECL_CHECK (NODE)->decl.no_instrument_function_entry_exit) :用于FUNCTION_DECL节点中,表示该函数的进入退出需要加入调用支持例程的代码。

DECL_NO_LIMIT_STACK (FUNCTION_DECL_CHECK (NODE)->decl.no_limit_stack):用在FUNCTION_DECL节点中,表示该函数没有栈大小的限制。

DECL_NON_ADDR_CONST_P (DECL_CHECK (NODE)->decl.non_addr_const_p):用于表示该DECL的指针不能被作为地址常量。

DECL_NONADDRESSABLE_P (FIELD_DECL_CHECK (NODE)->decl.non_addressable):用在FIELD_DECL节点中,表示我们不能构建该部分的地址。

DECL_POINTER_ALIAS_SET (DECL_CHECK (NODE)->decl.pointer_alias_set):用于表示有指针或者引用类型的FIELD_DECLPARM_DECLVAR_DECL所指向的内存的别名集。

DECL_POINTER_ALIAS_SET_KNOWN_P (DECL_POINTER_ALIAS_SET (NODE) != - 1):非零值,如果该声明已设置了别名集。

DECL_FILE_SCOPE_P (! DECL_CONTEXT (EXP)                                          /

   || TREE_CODE (DECL_CONTEXT (EXP)) == TRANSLATION_UNIT_DECL):如果声明具有文件作用域,为非零值。

列表3: 用于TREE_DECL的宏

2.2.3.1.5.2.2.2.            域的布局

layout_type742行,在同一绑定上下文中的声明都通过TREE_CHAIN 域来连接。因此函数place_field的参数field 依次指向这些声明。

 

821  void

822  place_field (record_layout_info rli, tree field)                                       in stor-layout.c

823  {

824    /* The alignment required for FIELD.  */

825    unsigned int desired_align;

826    /* The alignment FIELD would have if we just dropped it into the

827       record as it presently stands.  */

828    unsigned int known_align;

829    unsigned int actual_align;

830    /* The type of this field.  */

831    tree type = TREE_TYPE (field);

832 

833    if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)

834      return;

835 

836   /* If FIELD is static, then treat it like a separate variable, not

837      really like a structure field. If it is a FUNCTION_DECL, it's a

838      method. In both cases, all we do is lay out the decl, and we do

839      it *after* the record is laid out.  */

840    if (TREE_CODE (field) == VAR_DECL)

841    {

842      rli->pending_statics = tree_cons (NULL_TREE, field,

843                                     rli->pending_statics);

844      return;

845    }

2.2.3.1.5.2.2.3.        VAR_DECL类型

我们已经看到VAR_DECL可以代表类的静态数据成员,它详细的描述如下:

VAR_DECL[2]

²        这些节点表示在名字空间或块(block)范围内的变量,以及类的静态数据成员。其中 DECL_SIZEDECL_ALIGN类似于TYPE_SIZETYPE_ALIGN。对于一个声明,应该使用DECL_SIZEDECL_ALIGN,而不是由TREE_TYPE中得到的TYPE_SIZETYPE_ALIGN,因为该变量可能应用了特定的属性,从而具有特定的尺寸和对齐量。可以使用判定DECL_THIS_STATICDECL_THIS_EXTERN来检查,变量声明是否应用了存储类别符(storage class specifiersstaticextern

如果这个变量是需要初始化的(但不需要构造函数),DECL_INITIAL将是初始化值的表达式。这个初始化值会被求值并按位拷贝入变量。如果DECL_INITIALerror_mark_node,表明有初始化值,但它由后续代码中的显式语句(即非编译器添加)给出,不需要按位拷贝。

GCC提供一个扩展,允许自动变量或全局变量被放入特定的寄存器。如果对该VAR_DECLDECL_REGISTER成立而且DECL_ASSEMBLER_NAME不等于 DECL_NAME,表明该扩展被用于这个VAR_DECL。在这种情况下, DECL_ASSEMBLER_NAME是变量将被放入的寄存器名。

842行,函数tree_cons创建一个tree_list节点,并将这个VAR_DECL对象链入rlipending_statics域。这些链入pending_statics的对象会在类布局的最后阶段才被处理,其原因是这些对象可能会引用类本身(例如单件模式)。

 

1039 tree

1040 tree_cons (tree purpose, tree value, tree chain)                                                    in tree.c

1041 {

1042   tree node;

1043

1044   node = ggc_alloc_tree (sizeof (struct tree_list));

1045

1046   memset (node, 0, sizeof (struct tree_common));

1047

1048 #ifdef GATHER_STATISTICS

1049   tree_node_counts[(int) x_kind]++;

1050   tree_node_sizes[(int) x_kind] += sizeof (struct tree_list);

1051 #endif

1052

1053   TREE_SET_CODE (node, TREE_LIST);

1054   TREE_CHAIN (node) = chain;

1055   TREE_PURPOSE (node) = purpose;

1056   TREE_VALUE (node) = value;

1057   return node;

1058 }

 

节点tree_list有域TREE_VALUETREE_PURPOSEtree_list节点通过TREE_CHAIN域连接构成链表。TREE_VALUE域保存需要链接起来的值,而TREE_PURPOSE域偶尔也会使用来实现Lisp中的关联链表(association lists)。

 

767  struct tree_list GTY(())                                                                                      in tree.h

768  {

769    struct tree_common common;

770    tree purpose;

771    tree value;

772  };

2.2.3.1.5.2.2.4.        CONST_DECLTYPE_DECL类型

在一个类中,只会出现VAR_DECLFIELD_DECLCONST_DECLTYPE_DECL,因此下面849行的条件语句筛选出CONST_DECLTYPE_DECLCONST_DECLTYPE_DECL的细节如下:

CONST_DECL[2]

²        这些节点用于表示枚举常量。常量的值由DECL_INITIAL给出,它必须是与CONST_DECLTREE_TYPE类型相同的INTEGER_CST,即一个ENUMERAL_TYPE类型。

TYPE_DECL[2]

²        这些节点表示typedef声明。TREE_TYPE是被声明为有由DECL_NAME指定名字的类型。在某些情况下,会没有关联的名字。

 

place_field (continue)

 

847    /* Enumerators and enum types which are local to this class need not

848      be laid out. Likewise for initialized constant fields.  */

849    else if (TREE_CODE (field) != FIELD_DECL)

850      return;

851 

852    /* Unions are laid out very differently than records, so split

853      that code off to another function.  */

854    else if (TREE_CODE (rli->t) != RECORD_TYPE)

855    {

856      place_union_field (rli, field);

857      return;

858    }

 

C/C++,常量被保持在bss段,不占用类实例的空间。同样typedef声明创建了新的类型,也不会占用类实例空间。因此它们不需要被place_field处理。

 

你可能感兴趣的:(function,struct,tree,layout,alignment,structure)