Studying note of GCC-3.4.6 source (57)

4.3.1.7.5.3.      Nodes of other builtin types

Next part of c_common_nodes_and_builtins is given below:

 

c_common_nodes_and_builtins (continue)

 

3177     build_common_tree_nodes_2 (flag_short_double);

3178  

3179     record_builtin_type (RID_FLOAT, NULL, float_type_node);

3180     record_builtin_type (RID_DOUBLE, NULL, double_type_node);

3181     record_builtin_type (RID_MAX, "long double", long_double_type_node);

3182  

3183     (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,

3184                                        get_identifier ("complex int"),

3185                                        complex_integer_type_node));

3186     (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,

3187                                        get_identifier ("complex float"),

3188                                        complex_float_type_node));

3189     (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,

3190                                        get_identifier ("complex double"),

3191                                        complex_double_type_node));

3192     (*lang_hooks.decls.pushdecl)

3193       (build_decl (TYPE_DECL, get_identifier ("complex long double"),

3194               complex_long_double_type_node));

4.3.1.7.5.3.1.              Nodes of commonly used constants

In the compiler, constants like: 0, 1, 3 etc., must be in form of tree node (in front-end, it is the node of intermediate tree, in back-end it is a rtx node). Thus, the compiler will create corresponding and unique nodes. Now nodes of integer types are ready, nodes of constants of these type commonly in used can be created. Below size_NUM_node presents size of NUM bytes, and bitsize_NUM_node stands for size of NUM bits.

 

4894   void

4895   build_common_tree_nodes_2 (int short_double)                                                in tree.c

4896   {

4897     /* Define these next since types below may used them.  */

4898     integer_zero_node = build_int_2 (0, 0);

4899     integer_one_node = build_int_2 (1, 0);

4900     integer_minus_one_node = build_int_2 (-1, -1);

4901  

4902     size_zero_node = size_int (0);

4903     size_one_node = size_int (1);

4904     bitsize_zero_node = bitsize_int (0);

4905     bitsize_one_node = bitsize_int (1);

4906     bitsize_unit_node = bitsize_int (BITS_PER_UNIT);

4907  

4908     boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);

4909     boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);

4910  

4911     void_type_node = make_node (VOID_TYPE);

4912     layout_type (void_type_node);

4913  

4914     /* We are not going to have real types in C with less than byte alignment,

4915       so we might as well not have any types that claim to have it.  */

4916     TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;

4917     TYPE_USER_ALIGN (void_type_node) = 0;

4918  

4919     null_pointer_node = build_int_2 (0, 0);

4920     TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);

4921     layout_type (TREE_TYPE (null_pointer_node));

4922  

4923     ptr_type_node = build_pointer_type (void_type_node);

4924     const_ptr_type_node

4925       = build_pointer_type (build_type_variant (void_type_node, 1, 0));

 

The creation of null_pointer_node is interesting. It is first created as 0 filled integer_type_node, its type then is set as pointer of void_type_node – it is the same as (void*)0. For void* is ptr_type_node, and for const void* is const_ptr_type_node created out of ptr_type_node by build_type_variant.

 

2304   #define build_type_variant(TYPE, CONST_P, VOLATILE_P) /                           in tree.h

2305     build_qualified_type ((TYPE),                                         /

2306                      ((CONST_P) ? TYPE_QUAL_CONST : 0)         /

2307                      | ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))

 

Notice that operator to join line 2306 and 2307 is “|”, const and volatile can come tegother.

 

2908   tree

2909   build_qualified_type (tree type, int type_quals)                                                 in tree.c

2910   {

2911     tree t;

2912  

2913     /* See if we already have the appropriate qualified variant.  */

2914     t = get_qualified_type (type, type_quals);

2915  

2916     /* If not, build it.  */

2917     if (!t)

2918     {

2919       t = build_type_copy (type);

2920       set_type_quals (t, type_quals);

2921     }

2922  

2923     return t;

2924   }

 

Types cv-qualified and cv-unqualified are linked tegother with the cv-unqualified type at head, we need first ensure the requested cv-qualified type has not been created.

 

2888   tree

2889   get_qualified_type (tree type, int type_quals)                                                    in tree.c

2890   {

2891     tree t;

2892  

2893     /* Search the chain of variants to see if there is already one there just

2894       like the one we need to have. If so, use that existing one. We must

2895       preserve the TYPE_NAME, since there is code that depends on this.  */

2896     for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))

2897       if (TYPE_QUALS (t) == type_quals && TYPE_NAME (t) == TYPE_NAME (type)

2898           && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)

2899           && attribute_list_equal (TYPE_ATTRIBUTES (t), TYPE_ATTRIBUTES (type)))

2900         return t;

2901  

2902     return NULL_TREE;

2903   }

 

To create the cv-qualified type, we just copy type, but pointer_to and reference_to fields are set as 0, as they will be filled until the corresponding pointer and reference types are constructed.

 

2929   tree

2930   build_type_copy (tree type)                                                                                    in tree.c

2931   {

2932     tree t, m = TYPE_MAIN_VARIANT (type);

2933  

2934     t = copy_node (type);

2935  

2936     TYPE_POINTER_TO (t) = 0;

2937     TYPE_REFERENCE_TO (t) = 0;

2938  

2939     /* Add this type to the chain of variants of TYPE.  */

2940     TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);

2941     TYPE_NEXT_VARIANT (m) = t;

2942  

2943     return t;

2944   }

 

Then information about cv-qualifier can be saved into the tree node created.

 

2876   static void

2877   set_type_quals (tree type, int type_quals)                                                          in tree.c

2878   {

2879     TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;

2880     TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;

2881     TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;

2882   }

 

Next, creating floating and complex types is not different from integer type. Refers to Create node for real constant for details of floating point number.

 

build_common_tree_nodes_2 (continue)

 

4927     float_type_node = make_node (REAL_TYPE);

4928     TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;

4929     layout_type (float_type_node);

4930  

4931     double_type_node = make_node (REAL_TYPE);

4932     if (short_double)

4933       TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;

4934     else

4935       TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;

4936     layout_type (double_type_node);

4937  

4938     long_double_type_node = make_node (REAL_TYPE);

4939     TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;

4940     layout_type (long_double_type_node);

4941  

4942     float_ptr_type_node = build_pointer_type (float_type_node);

4943     double_ptr_type_node = build_pointer_type (double_type_node);

4944     long_double_ptr_type_node = build_pointer_type (long_double_type_node);

4945     integer_ptr_type_node = build_pointer_type (integer_type_node);

4946  

4947     complex_integer_type_node = make_node (COMPLEX_TYPE);

4948     TREE_TYPE (complex_integer_type_node) = integer_type_node;

4949     layout_type (complex_integer_type_node);

4950  

4951     complex_float_type_node = make_node (COMPLEX_TYPE);

4952     TREE_TYPE (complex_float_type_node) = float_type_node;

4953     layout_type (complex_float_type_node);

4954  

4955     complex_double_type_node = make_node (COMPLEX_TYPE);

4956     TREE_TYPE (complex_double_type_node) = double_type_node;

4957     layout_type (complex_double_type_node);

4958  

4959     complex_long_double_type_node = make_node (COMPLEX_TYPE);

4960     TREE_TYPE (complex_long_double_type_node) = long_double_type_node;

4961     layout_type (complex_long_double_type_node);

 

Line 4942 ~ 4945 also prepare nodes of the pointer types.

4.3.1.7.5.3.2.              Node of va_list

In C/C++, when using “…” as parameter in function, special object va_list is needed as below example.

 

int average( int first,int second, ... )

{

   int count = 0, sum = 0,

i = first;                  //i=2

   va_list marker;

   va_start( marker, second );     // Initialize variable arguments.

   i = va_arg( marker, int);

   va_end( marker );              /* Reset variable arguments.      */

   return( sum ? (sum / count) : 0 );

}

 

va_list is a special type passed to va_start, va_arg and va_end, it is responsibility of compiler to create the type, which is within build_common_tree_nodes_2 as below.

 

build_common_tree_nodes_2 (continue)

 

4963     {

4964       tree t = (*targetm.build_builtin_va_list) ();

4965  

4966       /* Many back-ends define record types without setting TYPE_NAME.

4967         If we copied the record type here, we'd keep the original

4968         record type without a name. This breaks name mangling. So,

4969         don't copy record types and let c_common_nodes_and_builtins()

4970         declare the type to be __builtin_va_list.  */

4971       if (TREE_CODE (t) != RECORD_TYPE)

4972         t = build_type_copy (t);

4973  

4974       va_list_type_node = t;

4975     }

 

Obviously, va_list depends on machine (it further determines the library it belongs to), different architecture may have different solution. build_builtin_va_list points to x86_build_builtin_va_list for x86 machine.

 

2968   static tree

2969   ix86_build_builtin_va_list (void)                                                                     in i386.c

2970   {

2971     tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;

2972  

2973     /* For i386 we use plain pointer to argument area.  */

2974     if (!TARGET_64BIT)

2975       return build_pointer_type (char_type_node);

       

3005   }

 

For 32 bits x86 machine, va_list in fact is char*. While for 64 bits x86 machine, va_list is a struct named __va_list_tag (the code is not shown here).

4.3.1.7.5.3.3.              Nodes of vector types

In multimedia application, like photo, vedio, matrix operation is everywhere. Being a kind of optimization, for example, in CPU of 32 bits x86 system, 128 bits registers are introduced, thus 4 long integers or single floating number can be placed within a single register, co-operated with specialized instructions (for instance, instruciton sets of SSE1, SSE2, refers to Initialize registers sets, for an example of register sets), it accelates the multimedia operation greatly. The form placing mulitply values within a register, is called vector to distiguished from array.

Below, the mode name beginning V[num] points out the number of values the vector contains, and the values are of mode XXmode (then the lengthe of the vector is: num*sizeof(XXmode) ).

 

build_common_tree_nodes_2 (continue)

 

4977     unsigned_V4SI_type_node

4978       = make_vector (V4SImode, unsigned_intSI_type_node, 1);

4979     unsigned_V2HI_type_node

4980       = make_vector (V2HImode, unsigned_intHI_type_node, 1);

4981     unsigned_V2SI_type_node

4982       = make_vector (V2SImode, unsigned_intSI_type_node, 1);

4983     unsigned_V2DI_type_node

4984       = make_vector (V2DImode, unsigned_intDI_type_node, 1);

4985     unsigned_V4HI_type_node

4986       = make_vector (V4HImode, unsigned_intHI_type_node, 1);

4987     unsigned_V8QI_type_node

4988       = make_vector (V8QImode, unsigned_intQI_type_node, 1);

4989     unsigned_V8HI_type_node

4990       = make_vector (V8HImode, unsigned_intHI_type_node, 1);

4991     unsigned_V16QI_type_node

4992       = make_vector (V16QImode, unsigned_intQI_type_node, 1);

4993     unsigned_V1DI_type_node

4994       = make_vector (V1DImode, unsigned_intDI_type_node, 1);

4995  

4996     V16SF_type_node = make_vector (V16SFmode, float_type_node, 0);

4997     V4SF_type_node = make_vector (V4SFmode, float_type_node, 0);

4998     V4SI_type_node = make_vector (V4SImode, intSI_type_node, 0);

4999     V2HI_type_node = make_vector (V2HImode, intHI_type_node, 0);

5000     V2SI_type_node = make_vector (V2SImode, intSI_type_node, 0);

5001     V2DI_type_node = make_vector (V2DImode, intDI_type_node, 0);

5002     V4HI_type_node = make_vector (V4HImode, intHI_type_node, 0);

5003     V8QI_type_node = make_vector (V8QImode, intQI_type_node, 0);

5004     V8HI_type_node = make_vector (V8HImode, intHI_type_node, 0);

5005     V2SF_type_node = make_vector (V2SFmode, float_type_node, 0);

5006     V2DF_type_node = make_vector (V2DFmode, double_type_node, 0);

5007     V16QI_type_node = make_vector (V16QImode, intQI_type_node, 0);

5008     V1DI_type_node = make_vector (V1DImode, intDI_type_node, 0);

5009     V4DF_type_node = make_vector (V4DFmode, double_type_node, 0);

5010   }

 

Function make_vector specially creates node for vector types. It will not be used in other place for x86 machine.

 

5061   tree

5062   make_vector (enum machine_mode mode, tree innertype, int unsignedp)             in tree.c

5063   {

5064     tree t;

5065  

5066     t = make_node (VECTOR_TYPE);

5067     TREE_TYPE (t) = innertype;

5068     TYPE_MODE (t) = mode;

5069     TREE_UNSIGNED (TREE_TYPE (t)) = unsignedp;

5070     finish_vector_type (t);

5071  

5072     return t;

5073   }

 

The alternative representation of vector type is the form of RECORD_TYPE, for example, for V16QI_type_node, the alternative representation will like:

RECORD_TYPE {

        Field:

               QI/*array_type*/ f [15/*index_type*/]

}

Sections Create node for index and Create node for array type describe the creation of ARRAY_TYPE and the array index.

 

4786   static void

4787   finish_vector_type (tree t)                                                                                in tree.c

4788   {

4789     layout_type (t);

4790  

4791     {

4792       tree index = build_int_2 (TYPE_VECTOR_SUBPARTS (t) - 1, 0);

4793       tree array = build_array_type (TREE_TYPE (t),

4794                                build_index_type (index));

4795       tree rt = make_node (RECORD_TYPE);

4796  

4797       TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);

4798       DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;

4799       layout_type (rt);

4800       TYPE_DEBUG_REPRESENTATION_TYPE (t) = rt;

4801       /* In dwarfout.c, type lookup uses TYPE_UID numbers. We want to output

4802         the representation type, and we want to find that die when looking up

4803         the vector type. This is most easily achieved by making the TYPE_UID

4804         numbers equal.  */

4805       TYPE_UID (rt) = TYPE_UID (t);

4806     }

4807   }

 

Following nodes created in c_common_nodes_and_builtins are for Fortran, we just skip the code. After that, at line 3249, void type is created, and line 3251 generates node of “((void) 0)”. Then node void_list_node is a chain of 2 void_type_node. Next char_array_type_node and wchar_array_type_node only would be used in lexer, to distinguish whether put in string is of wchar_t or char. But int_array_type_node  is still useless.

 

c_common_nodes_and_builtins (continue)

 

3249     record_builtin_type (RID_VOID, NULL, void_type_node);

3250  

3251     void_zero_node = build_int_2 (0, 0);

3252     TREE_TYPE (void_zero_node) = void_type_node;

3253  

3254     void_list_node = build_void_list_node ();

3255  

3256    /* Make a type to be the domain of a few array types

3257       whose domains don't really matter.

3258       200 is small enough that it always fits in size_t

3259       and large enough that it can hold most function names for the

3260       initializations of __FUNCTION__ and __PRETTY_FUNCTION__.  */

3261     array_domain_type = build_index_type (size_int (200));

3262  

3263     /* Make a type for arrays of characters.

3264       With luck nothing will ever really depend on the length of this

3265       array type.  */

3266     char_array_type_node

3267       = build_array_type (char_type_node, array_domain_type);

3268  

3269    /* Likewise for arrays of ints.  */

3270     int_array_type_node

3271       = build_array_type (integer_type_node, array_domain_type);

3272  

3273     string_type_node = build_array_type (char_type_node);

3274     const_string_type_node

3275       = build_array_type (build_qualified_type

3276                             (char_type_node, TYPE_QUAL_CONST));

3277  

3278    /* This is special for C++ so functions can be overloaded.  */

3279     wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);

3280     wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));

3281     wchar_type_size = TYPE_PRECISION (wchar_type_node);

3282     if (c_dialect_cxx ())

3283     {

3284       if (TREE_UNSIGNED (wchar_type_node))

3285         wchar_type_node = make_unsigned_type (wchar_type_size);

3286       else

3287         wchar_type_node = make_signed_type (wchar_type_size);

3288       record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);

3289     }

3290     else

3291     {

3292       signed_wchar_type_node = c_common_signed_type (wchar_type_node);

3293       unsigned_wchar_type_node = c_common_unsigned_type (wchar_type_node);

3294     }

3295  

3296    /* This is for wide string constants.  */

3297     wchar_array_type_node

3298       = build_array_type (wchar_type_node, array_domain_type);

3299  

3300     wint_type_node =

3301       TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));

3302  

3303     intmax_type_node =

3304       TREE_TYPE (identifier_global_value (get_identifier (INTMAX_TYPE)));

3305     uintmax_type_node =

3306       TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));

3307  

3308     default_function_type = build_function_type (integer_type_node, NULL_TREE);

3309     ptrdiff_type_node

3310       = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));

3311     unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);

3312  

3313     (*lang_hooks.decls.pushdecl)

3314       (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),

3315                 va_list_type_node));

3316  

3317     (*lang_hooks.decls.pushdecl)

3318       (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),

3319                 ptrdiff_type_node));

3320  

3321     (*lang_hooks.decls.pushdecl)

3322       (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),

3323                 sizetype));

3324  

3325     if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)

3326     {

3327       va_list_arg_type_node = va_list_ref_type_node =

3328               build_pointer_type (TREE_TYPE (va_list_type_node));

3329     }

3330     else

3331     {

3332       va_list_arg_type_node = va_list_type_node;

3333       va_list_ref_type_node = build_reference_type (va_list_type_node);

3334     }

 

At line 3308, default_function_type stands for C’s assuming implicit declared function of type int ()(). And at line 3314, __builtin_va_list is the builtin (that is the self-defined by compiler) type declaraton of va_list (via the way similar with typedef), similarly are __builtin_ptrdiff_t and  __builtin_size_t.

 

你可能感兴趣的:(vector,list,tree,Integer,Build,float)