您的位置:首页 > 编程语言

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

2010-07-13 09:08 399 查看
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. 常用常量的节点
在编译器内部,常量如:0,1,3等也必须是树节点形式(在前端为前端树的形式,在后端为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))

注意到把2306及2307行接起来的操作符是“|”,这表示const和volatile可以一起用。

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-qualified和cv-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_to及reference_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_start,va_arg及va_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*。而对于64位x86机器,va_list是一个名为__va_list_tag的结构体(这里省略了这部分代码)。
4.3.1.7.5.3.3. Vector类型节点
在图形、视频这样的多媒体应用中,大量使用了矩阵运算。作为一种优化,例如,32位x86体系的CPU中引入了128位的寄存器,这样一个寄存器就可以存放4个长整形数或单精度浮点数,配合专门的指令(如SSE1,SSE2指令集,具体寄存器的类型、数量,参见初始化寄存器集),可以大大加快多媒体的处理。这样一个寄存器中存放多个数值的形式,称为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_node是2个void_type_node组成的链表。下面的char_array_type_node及wchar_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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: