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

4.3.1.7.5.3.      其他内建类型节点

c_common_nodes_and_builtins接下来的代码如下:

 

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.              常用常量的节点

在编译器内部,常量如:013等也必须是树节点形式(在前端为前端树的形式,在后端为rtx节点)。因此,编译器将创建相应的,唯一的节点。现在,整型类型节点已经好了,具有这些类型的常用的常量的节点就可以创建了。注意size_NUM_node表示NUM字节的大小,而bitsize_NUM_node表示NUM比特的大小。

 

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));

 

null_pointer_node的创建很有意思。首先创建一个由0填充的integer_type_node节点,它的type被设置为void_type_node的指针类型——这等同于(void*)0。对于void*ptr_type_node,而对于const void*const_ptr_type_node,通过build_type_variant,从ptr_type_node创建出来。

 

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))

 

注意到把23062307行接起来的操作符是“|”,这表示constvolatile可以一起用。

 

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   }

 

cv-qualifiedcv-unqualified类型被链接在一起,并且cv-unqualified类型位于链表头。在创建cv-qualified类型之前,我们要确认其尚未被创建。

 

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   }

 

为了创建cv-qualified类型,我们采用类型拷贝,不过pointer_toreference_to域都不做拷贝,要在相应的指针及引用类型构建出来后,它们才能得到填充。

 

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   }

 

然后cv-qualifier的信息被存入创建的节点。

 

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   }

 

接下来,浮点及复数类型节点的创建与整型类型没有什么不同。浮点数的细节,参考创建浮常量节点

 

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);

 

4942~4945行还准备了指针类型的节点。

4.3.1.7.5.3.2.              va_list类型节点

C/C++中,当在函数中使用“”作为参数时,需要一个特别的对象va_list,如下例。

 

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是一个特殊的类型,它被传递给va_startva_argva_end,这个类型由编译器负责创建。这在接下来的build_common_tree_nodes_2中。

 

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     }

 

显然va_list的实际类型取决于机器(这进一步确定其所在的库)不同的机器架构会有不同的方案。对于x86机器build_builtin_va_list实际引用x86_build_builtin_va_list

 

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   }

 

对于32位的x86机器,va_list实际上是char*。而对于64x86机器,va_list是一个名为__va_list_tag的结构体(这里省略了这部分代码)。

4.3.1.7.5.3.3.              Vector类型节点

在图形、视频这样的多媒体应用中,大量使用了矩阵运算。作为一种优化,例如,32x86体系的CPU中引入了128位的寄存器,这样一个寄存器就可以存放4个长整形数或单精度浮点数,配合专门的指令(如SSE1SSE2指令集,具体寄存器的类型、数量,参见初始化寄器集),可以大大加快多媒体的处理。这样一个寄存器中存放多个数值的形式,称为vector,以区别于数组。

在下面,模式名开头的V[num]指出了该vector包含了num个数值,而这些数值的模式是XXmode(那么vector的长度是: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   }

 

函数make_vector专用于创建vector类型的节点。对于x86机器,没有别的地方使用它。

 

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   }

 

Vector类型的另一种表示形式是RECORD_TYPE,例如,对于V16QI_type_node,其另一种表示形式就像:

RECORD_TYPE {

        Field:

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

}

章节创建索引节点创建数组类型节点描述了ARRAY_TYPE和数组索引的过程。

 

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   }

 

c_common_nodes_and_builtins中接下来的节点是为Fortran创建的,我们跳过这些代码。之后,在3249行,创建了void类型,3251行为((void) 0)节点,而void_list_node2void_type_node组成的链表。下面的char_array_type_nodewchar_array_type_node,只用在lexer中,来临时区分传入字符串为wchar_t抑或char。而int_array_type_node 则尚无用处。

 

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     }

 

3308行的default_function_type代表C中的隐式声明的函数类型 int ()()”。而3314行的__builtin_va_list则是内建的(即编译器自带)va_list类型声明(类似typedef),同样还有__builtin_ptrdiff_t __builtin_size_t

 

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