您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (57)

2010-07-13 09:16 393 查看
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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: