Studying note of GCC-3.4.6 source (7)

1.2.4. Create node for address concept

In C++, concept of pointer, reference, and address are exchangable at certain level. The langauage allows to manipulate the content of the address directly via pointer or reference, and the invocation of function in fact is jumping to the address of the function, and the name of an array always refers to the address of the array, so the compiler may need build node for the address concept first and make it the base of other nodes, for example for function, array, etc.

1.2.4.1.    Create node for pointer type

1.2.4.1.1.            Node of tree_type

The kind of tree node standing for type of the language is tree_type which has following definition.

 

1089 struct tree_type GTY(())                                                                                   in tree.h

1090 {

1091   struct tree_common common;

1092   tree values;

1093   tree size;

1094   tree size_unit;

1095   tree attributes;

1096   unsigned int uid;

1097

1098   unsigned int precision : 9;

1099   ENUM_BITFIELD(machine_mode) mode : 7;

1100

1101   unsigned string_flag : 1;

1102   unsigned no_force_blk_flag : 1;

1103   unsigned needs_constructing_flag : 1;

1104   unsigned transparent_union_flag : 1;

1105   unsigned packed_flag : 1;

1106   unsigned restrict_flag : 1;

1107   unsigned spare : 2;

1108

1109   unsigned lang_flag_0 : 1;

1110   unsigned lang_flag_1 : 1;

1111   unsigned lang_flag_2 : 1;

1112   unsigned lang_flag_3 : 1;

1113   unsigned lang_flag_4 : 1;

1114   unsigned lang_flag_5 : 1;

1115   unsigned lang_flag_6 : 1;

1116   unsigned user_align : 1;

1117

1118   unsigned int align;

1119   tree pointer_to;

1120   tree reference_to;

1121   union tree_type_symtab {

1122     int GTY ((tag ("0"))) address;

1123     char * GTY ((tag ("1"))) pointer;

1124     struct die_struct * GTY ((tag ("2"))) die;

1125   } GTY ((desc ("debug_hooks == &sdb_debug_hooks? 1: debug_hooks == &dwarf2_debug_hooks? 2: 0"),

1126         descbits ("2"))) symtab;

1127   tree name;

1128   tree minval;

1129   tree maxval;

1130   tree next_variant;

1131   tree main_variant;

1132   tree binfo;

1133   tree context;

1134   HOST_WIDE_INT alias_set;

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

1136   struct lang_type *lang_specific;

1137 };

 

For above fields, following macros are defined for the accessment.

Ø         TYPE_BINFO (TYPE_CHECK (NODE)->type.binfo)

²      For aggregate types, information about this type, as a base type for itself. Used in a language-dependent way for types that are neither a RECORD_TYPE, QUAL_UNION_TYPE, nor a UNION_TYPE.

Ø         TYPE_ALIAS_SET (TYPE_CHECK (NODE)->type.alias_set)

 

²      The (language-specific) typed-based alias set for this type. Objects whose TYPE_ALIAS_SETs are different cannot alias each other. If the TYPE_ALIAS_SET is -1, no alias set has yet been assigned to this type. If the TYPE_ALIAS_SET is 0, objects of this type can alias objects of any type (for example, char*).

Ø         TYPE_ALIAS_SET_KNOWN_P (TYPE_CHECK (NODE)->type.alias_set != -1)

²      Nonzero iff the typed-based alias set for this type has been calculated.

 

Ø         TYPE_ATTRIBUTES (TYPE_CHECK (NODE)->type.attributes)

 

²      A TREE_LIST of IDENTIFIER nodes of the attributes that apply to this type. GCC supports a rich attribute set as extension.

Ø         TYPE_ALIGN (TYPE_CHECK (NODE)->type.align)

 

²      The alignment necessary for objects of this type. The value is an int, measured in bits.

Ø         TYPE_USER_ALIGN (TYPE_CHECK (NODE)->type.user_align)

²      1 if the alignment for this type was requested by "aligned" attribute, 0 if it is the default for this type.

Ø         TYPE_ALIGN_UNIT (TYPE_ALIGN (NODE) / BITS_PER_UNIT)

²      The alignment for NODE, in bytes.

 

Ø         TYPE_NO_FORCE_BLK (TYPE_CHECK (NODE)->type.no_force_blk_flag)

 

²      In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type has BLKmode only because it lacks the alignment requirement for its size.

Ø         TYPE_IS_SIZETYPE (INTEGER_TYPE_CHECK (NODE)->type.no_force_blk_flag)

 

²      In an INTEGER_TYPE, it means the type represents a size. We use this both for validity checking and to permit optimizations that are unsafe for other types. Note that the C `size_t' type should *not* have this flag set. The `size_t' type is simply a typedef for an ordinary integer type that happens to be the type of an expression returned by `sizeof'; `size_t' has no special properties. Expressions whose type have TYPE_IS_SIZETYPE set are always actual sizes.

Ø         TYPE_RETURNS_STACK_DEPRESSED

(FUNCTION_TYPE_CHECK (NODE)->type.no_force_blk_flag)

 

²      In a FUNCTION_TYPE, indicates that the function returns with the stack pointer depressed.

Ø         TYPE_STRING_FLAG (TYPE_CHECK (NODE)->type.string_flag)

²      If set in an ARRAY_TYPE, indicates a string type (for languages that distinguish string from array of char). If set in a SET_TYPE, indicates a bitstring type.

Ø         TYPE_VECTOR_SUBPARTS

GET_MODE_NUNITS (VECTOR_TYPE_CHECK (VECTOR_TYPE)->type.mode)

 

²      For a VECTOR_TYPE, this is the number of sub-parts of the vector.

Ø         TYPE_NEEDS_CONSTRUCTING

(TYPE_CHECK (NODE)->type.needs_constructing_flag)

 

²      Indicates that objects of this type must be initialized by calling a function when they are created.

Ø         TYPE_TRANSPARENT_UNION

(UNION_TYPE_CHECK (NODE)->type.transparent_union_flag)

 

²      Indicates that objects of this type (a UNION_TYPE), should be passed the same way that the first union alternative would be passed.

Ø         TYPE_NONALIASED_COMPONENT

(ARRAY_TYPE_CHECK (NODE)->type.transparent_union_flag)

 

²      For an ARRAY_TYPE, indicates that it is not permitted to take the address of a component of the type.

Ø         TYPE_PACKED (TYPE_CHECK (NODE)->type.packed_flag)

 

²      Indicated that objects of this type should be laid out in as compact a way as possible.

Ø         TYPE_LANG_FLAG_0 ~ TYPE_LANG_FLAG_6

²      These flags are available for each language front end to use internally.

Ø         TYPE_NEXT_VARIANT (TYPE_CHECK (NODE)->type.next_variant)

²      Used to chain together types that are variants made by type modifiers such as "const" and "volatile".

Ø         TYPE_MAIN_VARIANT (TYPE_CHECK (NODE)->type.main_variant)

²      In any member of such a chain (previous), points to the start of the chain.

List 2 flags in tree_type

1.2.4.1.2.            Node creation

The node of pointer type is built by following function.

 

3653 tree

3654 build_pointer_type (tree to_type)                                                                       in tree.c

3655 {

3656   return build_pointer_type_for_mode (to_type, ptr_mode);

3657 }

 

Here, to_type is the type to which it will create the node of pointer type, and note that the second parameter for build_pointer_type_for_mode is ptr_mode. This function will also be invoked to create pointer for vector mode data (refer to Back-end 7. Tool of genmodes for detail).

 

3625 tree

3626 build_pointer_type_for_mode (tree to_type, enum machine_mode mode)                     in tree.c

3627 {

3628   tree t = TYPE_POINTER_TO (to_type);

3629

3630   /* First, if we already have a type for pointers to TO_TYPE, use it.  */

3631   if (t != 0 && mode == ptr_mode)

3632     return t;

3633

3634   t = make_node (POINTER_TYPE);

3635

3636   TREE_TYPE (t) = to_type;

3637   TYPE_MODE (t) = mode;

3638

3639   /* Record this type as the pointer to TO_TYPE.  */

3640   if (mode == ptr_mode)

3641     TYPE_POINTER_TO (to_type) = t;

3642

3643   /* Lay out the type. This function has many callers that are concerned

3644     with expression-construction, and this simplifies them all.

3645     Also, it guarantees the TYPE_SIZE is in the same obstack as the type.  */

3646   layout_type (t);

3647

3648   return t;

3649 }

 

For the type pointed to, it should ensure that the inforamtion about it has been collect, it includes: size in unit (accessed by TYPE_SIZE_UNIT), size in bits (accessed by TYPE_SIZE), and fittest mode. While for aggregate types (for example, array type, struct or union in C/C++), besides, every data member in it must have the alignment, offset from the beginning of the aggregate type, both size in bits and bytes after adjusted by alignment settled. This is done by layout_type below.

1.2.4.1.3.            Layout the type

Below we just focus on the code related to the pointer type; while for other situations we have to leave them to other chapters. All information about size, sign and alignment is indicated by the tree mode (refer to 1.2.2.1.5.1.2 The Concept of Mode) for fundmental types.

 

1516     void

1517     layout_type (tree type)                                                                             in stor-layout..c

1518     {

1519       if (type == 0)

1520         abort ();

1521      

1522       /* Do nothing if type has been laid out before.  */

1523       if (TYPE_SIZE (type))

1524         return;

1525      

1526       switch (TREE_CODE (type))

1527       {

        

1602         case POINTER_TYPE:

1603         case REFERENCE_TYPE:

1604         {

1605      

1606           enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE

1607                                   && reference_types_internal)

1608                                   ? Pmode : TYPE_MODE (type));

1609      

1610           int nbits = GET_MODE_BITSIZE (mode);

1611      

1612           TYPE_SIZE (type) = bitsize_int (nbits);

1613           TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));

1614           TREE_UNSIGNED (type) = 1;

1615           TYPE_PRECISION (type) = nbits;

1616         }

1617         break;

         

1795       }

      

1797       if (TREE_CODE (type) != RECORD_TYPE

1798           && TREE_CODE (type) != UNION_TYPE

1799           && TREE_CODE (type) != QUAL_UNION_TYPE)

1800         finalize_type_size (type);

      

1818     }

 

At line 1607 reference_types_internal is nonzero, if all REFERENCE_TYPEs are internal and hence should be allocated in Pmode (Pmode is a macro aliases to appropriate mode in target machine), not ptr_mode (which only indicates mode size of POINTER_SIZE, see following section 1.2.1.2 node for reference type). This global variable is set only by internal_reference_types called only by front end. But for C++, it stays with 0.

And finalize_type_size at line 1804 gets alignment information by mode.

 

1363     static void

1364     finalize_type_size (tree type)

1365     {

1366       /* Normally, use the alignment corresponding to the mode chosen.

1367         However, where strict alignment is not required, avoid

1368         over-aligning structures, since most compilers do not do this

1369         alignment.  */

1370      

1371       if (TYPE_MODE (type) != BLKmode && TYPE_MODE (type) != VOIDmode

1372          && (STRICT_ALIGNMENT

1373         || (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE

1374                && TREE_CODE (type) != QUAL_UNION_TYPE

1375                && TREE_CODE (type) != ARRAY_TYPE)))

1376       {

1377         TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));

1378         TYPE_USER_ALIGN (type) = 0;

1379       }

      

1412       /* Also layout any other variants of the type.  */

1413       if (TYPE_NEXT_VARIANT (type)

1414           || type != TYPE_MAIN_VARIANT (type))

1415       {

1416         tree variant;

1417         /* Record layout info of this variant.  */

1418         tree size = TYPE_SIZE (type);

1419         tree size_unit = TYPE_SIZE_UNIT (type);

1420         unsigned int align = TYPE_ALIGN (type);

1421         unsigned int user_align = TYPE_USER_ALIGN (type);

1422         enum machine_mode mode = TYPE_MODE (type);

1423      

1424         /* Copy it into all variants.  */

1425         for (variant = TYPE_MAIN_VARIANT (type);

1426             variant != 0;

1427             variant = TYPE_NEXT_VARIANT (variant))

1428         {

1429           TYPE_SIZE (variant) = size;

1430           TYPE_SIZE_UNIT (variant) = size_unit;

1431           TYPE_ALIGN (variant) = align;

1432           TYPE_USER_ALIGN (variant) = user_align;

1433           TYPE_MODE (variant) = mode;

1434         }

1435       }

1436     }

 

For types qualified by keywords “const”, “volatile”, “register”, they are chained tegother with TYPE_MAIN_VARIANT points to the unqualified version, and visiting others via TYPE_NEXT_VARIANT. All these versions are updated from line 1413.

1.2.4.2.    Create node for reference type

Reference type is no different than pointer type, see line 3693, the mode of reference type is ptr_mode. As result, the creation is very similar with that of pointer type.

 

3690 tree

3691 build_reference_type (tree to_type)                                                                   in tree.c

3692 {

3693   return build_reference_type_for_mode (to_type, ptr_mode);

3694 }

 

3663 tree

3664 build_reference_type_for_mode (tree to_type, enum machine_mode mode)           in tree.c

3665 {

3666   tree t = TYPE_REFERENCE_TO (to_type);

3667

3668   /* First, if we already have a type for pointers to TO_TYPE, use it.  */

3669   if (t != 0 && mode == ptr_mode)

3670     return t;

3671

3672   t = make_node (REFERENCE_TYPE);

3673

3674   TREE_TYPE (t) = to_type;

3675   TYPE_MODE (t) = mode;

3676

3677   /* Record this type as the pointer to TO_TYPE.  */

3678   if (mode == ptr_mode)

3679   TYPE_REFERENCE_TO (to_type) = t;

3680

3681   layout_type (t);

3682

3683   return t;

3684 }

1.2.4.3.    Create node for address

The return type of build_address is tree_exp (more precisely, it is an address expression), as line 3683 indicates. Something about ADDR_EXPR is shown below:

 

ADDR_EXPR[2]

²        These nodes are used to represent the address of an object. (These expressions will always have pointer or reference type.) The operand may be another expression, or it may be a declaration. As an extension, GCC allows users to take the address of a label. In this case, the operand of the ADDR_EXPR will be a LABEL_DECL. The type of such an expression is void*. If the object addressed is not an lvalue, a temporary is created, and the address of the temporary is used.

 

3675 tree

3676 build_address (tree t)                                                                                in typeck.c

3677 {

3678   tree addr;

3679

3680   if (error_operand_p (t) || !cxx_mark_addressable (t))

3681     return error_mark_node;

3682

3683   addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);

3684   if (staticp (t))

3685     TREE_CONSTANT (addr) = 1;

3686

3687   return addr;

3688 }

 

At line 3680, cxx_mark_addressable marks t saying that we need to be able to take the address of t; t should not be allocated in a register. The function returns true if successful. And staticp at line 3684 checks if the address refers to static memory (for example, a string constant, label, and static/global variable). Address of this kind will not change in run time, on the contrary local variable in a function may have different address in each invocation - considering recursion, this address of such type is not constant.

1.2.4.4.    Create node for OFFSET_TYPE

In C/C++ programing, we can use macro offsetof to find out the offset of certain data member from the beginning of the containing struct/class. What the macro finds out is the OFFSET_TYPE created here. It is used when we access data member like A.b or A->b.

 

3956 tree

3957 build_offset_type (tree basetype, tree type)                                                         in tree.c

3958 {

3959   tree t;

3960   unsigned int hashcode;

3961

3962   /* Make a node of the sort we want.  */

3963   t = make_node (OFFSET_TYPE);

3964

3965   TYPE_OFFSET_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);

3966   TREE_TYPE (t) = type;

3967

3968   /* If we already have such a type, use the old one and free this one.  */

3969   hashcode = TYPE_HASH (basetype) + TYPE_HASH (type);

3970   t = type_hash_canon (hashcode, t);

3971

3972   if (!COMPLETE_TYPE_P (t))

3973     layout_type (t);

3974

3975   return t;

3976 }

 

As we have known, TYPE_MAIN_VARIANT returns the unqualified version of a type, and other type variants made by type modifiers such as "const" and "volatile" are chained together by TYPE_NEXT_VARIANT. We use unqualified version as the base type for offset.

 

你可能感兴趣的:(function,tree,Build,reference,alignment,attributes)