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

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

2010-02-24 11:40 429 查看

1.2.2. 内建类型的树节点

对于语言中的内建类型,例如,C/C++中的int,unsigned short等,编译器在启动时便会为这些类型创建节点。
1.2.2.1. 初始化临时的size_t节点
在创建内建类型的节点前,先要创建临时的size_t节点(一个用作size_t,另一个用作bitsize_t。size_t是sizeof的返回类型,bitsize_t由前端使用),它们将被用于内建类型节点的构建。在C++前端中,节点创建的次序如下所示。

build_common_tree_nodes

4840 initialize_sizetypes (); in tree.c
4841
4842 /* Define both `signed char' and `unsigned char'. */
4843 signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
4844 unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);

这里signed_char_type_node和unsigned_char_type_node都是一个全局数组的成员。这个全局数组在下面章节中描述。
1.2.2.1.1. 整型类型的节点
对于C++,整型是语言基础而重要的部分。它们的使用频率(事实上出现在每个程序中),使得对这些节点的访问必须尽可能有效。因此,这些节点放在下面的全局数组中,而不像其它类型节点被放在哈希表里(hash-table)。

2001 extern GTY(()) tree integer_types[itk_none]; in tree.h
2002
2003 #define char_type_node integer_types[itk_char]
2004 #define signed_char_type_node integer_types[itk_signed_char]
2005 #define unsigned_char_type_node integer_types[itk_unsigned_char]
2006 #define short_integer_type_node integer_types[itk_short]
2007 #define short_unsigned_type_node integer_types[itk_unsigned_short]
2008 #define integer_type_node integer_types[itk_int]
2009 #define unsigned_type_node integer_types[itk_unsigned_int]
2010 #define long_integer_type_node integer_types[itk_long]
2011 #define long_unsigned_type_node integer_types[itk_unsigned_long]
2012 #define long_long_integer_type_node integer_types[itk_long_long]
2013 #define long_long_unsigned_type_node integer_types[itk_unsigned_long_long]
1.2.2.1.2. 创建临时的size_t节点
事实上,在GCC中有关size_t的节点也是放在下面的全局数组中。

2427 extern GTY(()) tree sizetype_tab[(int) TYPE_KIND_LAST]; n tree.h
2428
2429 #define sizetype sizetype_tab[(int) SIZETYPE]
2430 #define bitsizetype sizetype_tab[(int) BITSIZETYPE]
2431 #define ssizetype sizetype_tab[(int) SSIZETYPE]
2432 #define usizetype sizetype_tab[(int) USIZETYPE]
2433 #define sbitsizetype sizetype_tab[(int) SBITSIZETYPE]
2434 #define ubitsizetype sizetype_tab[(int) UBITSIZETYPE]

上面的这些节点分别表示,该size_t类型:以字节衡量的一般表示方式大小,以比特衡量的一般表示方式大小;以字节衡量的有符号表示方式大小,以比特衡量的有符号表示方式大小;以字节衡量的无符号表示方式大小,以比特衡量的无符号表示方式大小。(这3组数据主要为了满足不同目标机器的要求)。
最开始,只有临时的sizetype和bitsizetype节点被函数initialize_sizetypes创建。

1849 void
1850 initialize_sizetypes (void) in stor-layout.c
1851 {
1852 tree t = make_node (INTEGER_TYPE);
1853
1854 /* Set this so we do something reasonable for the build_int_2 calls
1855 below. */
1856 integer_type_node = t;
1857
1858 TYPE_MODE (t) = SImode;
1859 TYPE_ALIGN (t) = GET_MODE_ALIGNMENT (SImode);
1860 TYPE_USER_ALIGN (t) = 0;
1861 TYPE_SIZE (t) = build_int_2 (GET_MODE_BITSIZE (SImode), 0);
1862 TYPE_SIZE_UNIT (t) = build_int_2 (GET_MODE_SIZE (SImode), 0);
1863 TREE_UNSIGNED (t) = 1;
1864 TYPE_PRECISION (t) = GET_MODE_BITSIZE (SImode);
1865 TYPE_MIN_VALUE (t) = build_int_2 (0, 0);
1866 TYPE_IS_SIZETYPE (t) = 1;
1867
1868 /* 1000 avoids problems with possible overflow and is certainly
1869 larger than any size value we'd want to be storing. */
1870 TYPE_MAX_VALUE (t) = build_int_2 (1000, 0);
1871
1872 /* These two must be different nodes because of the caching done in
1873 size_int_wide. */
1874 sizetype = t;
1875 bitsizetype = copy_node (t);
1876 integer_type_node = 0;
1877 }

首先在1852行,创建临时的integer_type_node。从1858行到1864行,相应的有关模式的数据,由后端的genmodes工具从文件machmode.def生成,类型节点对应的域根据这些数据来设置。随后的build_int_2则构建了整型常量0和1000,作为临时size_t的取值范围。而这个临时的integer_type_node 被作为这些常量的类型值(tree_type)。注意,在1874行,临时的integer_type_node 被同时用作sizetype和bitsizetype的类型。 不过,这些size_t节点在内建的整型类型节点被创建后,就会被更新。
1.2.2.1.3. 创建整型的类型节点
我们仅以有符号整数类型作为例子。无符号整数类型的过程与这里看到的十分相似。

1822 tree
1823 make_signed_type (int precision) in stor-layout.c
1824 {
1825 tree type = make_node (INTEGER_TYPE);
1826
1827 TYPE_PRECISION (type) = precision;
1828
1829 fixup_signed_type (type);
1830 return type;
1831 }

TYPE_PRECISION是用于表达该类型的比特数,它是一个unsigned int。(注意通常它的值不同于TYPE_SIZE。比如有一个24位的整型,但ABI(抽象2进制接口)要求32位的对齐量。这样,TYPE_SIZE将是一个值为32的INTEGER_CST,而TYPE_PRECISION则是24)。

2014 void
2015 fixup_signed_type (tree type) in stor-layout.c
2016 {
2017 int precision = TYPE_PRECISION (type);
2018
2019 /* We can not represent properly constants greater then
2020 2 * HOST_BITS_PER_WIDE_INT, still we need the types
2021 as they are used by i386 vector extensions and friends. */
2022 if (precision > HOST_BITS_PER_WIDE_INT * 2)
2023 precision = HOST_BITS_PER_WIDE_INT * 2;
2024
2025 set_min_and_max_values_for_integral_type (type, precision,
2026 /*is_unsigned=*/false);
2027
2028 /* Lay out the type: set its alignment, size, etc. */
2029 layout_type (type);
2030 }
1.2.2.1.4. 确定取值范围
每个整型类型都有所能表达的数值范围,超出这个范围即发生溢出。因此,对每个整数类型节点,要设定其表达范围,以方便检查溢出情况。在为类型所创建的tree_type节点中,域TYPE_MIN_VALUE及TYPE_MAX_VALUE保存了取值范围的上下边界。这些域都是tree_int_cst,包含有整型常量。

682 struct tree_int_cst GTY(()) in tree.h
683 {
684 struct tree_common common;
685 /* A sub-struct is necessary here because the function `const_hash'
686 wants to scan both words as a unit and taking the address of the
687 sub-struct yields the properly inclusive bounded pointer. */
688 struct tree_int_cst_lowhi {
689 unsigned HOST_WIDE_INT low;
690 HOST_WIDE_INT high;
691 } int_cst;
692 };

在上面688行,在结构tree_int_cst_lowhi中,low部分和high部分构成了完整的表达值(注意可表达值可以是128位)。其取值范围由其精度通过下面的函数set_min_and_max_values_for_integral_type确定。

1965 void
1966 set_min_and_max_values_for_integral_type (tree type, in stor-layout.c
1967 int precision,
1968 bool is_unsigned)
1969 {
1970 tree min_value;
1971 tree max_value;
1972
1973 if (is_unsigned)
1974 {
1975 min_value = build_int_2 (0, 0);
1976 max_value
1977 = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
1978 ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
1979 precision - HOST_BITS_PER_WIDE_INT > 0
1980 ? ((unsigned HOST_WIDE_INT) ~0
1981 >> (HOST_BITS_PER_WIDE_INT
1982 - (precision - HOST_BITS_PER_WIDE_INT)))
1983 : 0);
1984 }
1985 else
1986 {
1987 min_value
1988 = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
1989 ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
1990 (((HOST_WIDE_INT) (-1)
1991 << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
1992 ? precision - HOST_BITS_PER_WIDE_INT - 1
1993 : 0))));
1994 max_value
1995 = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
1996 ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
1997 (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
1998 ? (((HOST_WIDE_INT) 1
1999 << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
2000 : 0));
2001 }
2002
2003 TREE_TYPE (min_value) = type;
2004 TREE_TYPE (max_value) = type;
2005 TYPE_MIN_VALUE (type) = min_value;
2006 TYPE_MAX_VALUE (type) = max_value;
2007 }

上面的build_int_2将创建一个INTEGER_CST的节点。注意对有符号数与无符号数取值范围的确定方法。
1.2.2.1.5. 整型类型的布局
在创建了这个节点后,它需要被正确地填充。这是函数layout_type的工作。这个函数是创建类型节点的最后一步。在节点被这个函数处理前,它的TYPE_SIZE一直是NULL,而这个域将被layout_type设置。为了避免重复对节点布局,如果TYPE_SIZE不是NULL,函数既在1524行退出。

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 {
1528 case LANG_TYPE:
1529 /* This kind of type is the responsibility
1530 of the language-specific code. */
1531 abort ();
1532
1533 case BOOLEAN_TYPE: /* Used for Java, Pascal, and Chill. */
1534 if (TYPE_PRECISION (type) == 0)
1535 TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
1536
1537 /* ... fall through ... */
1538
1539 case INTEGER_TYPE:
1540 case ENUMERAL_TYPE:
1541 case CHAR_TYPE:
1542 if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
1543 && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
1544 TREE_UNSIGNED (type) = 1;
1545
1546 TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type),
1547 MODE_INT);
1548 TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
1549 TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
1550 break;
1.2.2.1.5.1. 整型的类型信息
在上面,那些名字以TYPE开头的宏访问的是,由它名字剩余部分所指示的tree_type中的域。而那些以TREE开头的宏则访问tree_common.的域。
1.2.2.1.5.1.1. 确定类型的符号
类型的符号是重要的信息。在tree_common节点中,域TREE_UNSIGNED被用于表示类型的符号。而确定类型的符号,则通过以下简单的方法。

3337 int
3338 tree_int_cst_sgn (tree t) in tree.c
3339 {
3340 if (TREE_INT_CST_LOW (t) == 0 && TREE_INT_CST_HIGH (t) == 0)
3341 return 0;
3342 else if (TREE_UNSIGNED (TREE_TYPE (t)))
3343 return 1;
3344 else if (TREE_INT_CST_HIGH (t) < 0)
3345 return -1;
3346 else
3347 return 1;
3348 }
1.2.2.1.5.1.2. 确定机器模式
在GCC的代码中,机器模式实际上作为数组索引。要描述类型的组别(比如,不同尺寸的整型),代码中有数组mode_class。描述类型的大小,则有数组mode_size,mode_nunits,mode_precision。而描述同一组别,不同模式间的关系,有数组mode_wider。另外,还有其他用于模式的数组。在当前版本的GCC中,有关目标机器的可用模式的信息都是通过后端工具genmodes产生。
在上面1547行,我们已知模式的类别,通过已知的精度我们可找到最合适的模式。

247 enum machine_mode
248 smallest_mode_for_size (unsigned int size, enum mode_class class) in stor-layout.c
249 {
250 enum machine_mode mode;
251
252 /* Get the first mode which has at least this size, in the
253 specified class. */
254 for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
255 mode = GET_MODE_WIDER_MODE (mode))
256 if (GET_MODE_PRECISION (mode) >= size)
257 return mode;
258
259 abort ();
260 }

GET_CLASS_NARROWEST_MODE为指定类别返回最小的可行的模式,例如,这里的MODE_INT类别。数组class_narrowest_mode同样是genmodes产生的记录了模式类别中的最小的模式。

150 #define GET_CLASS_NARROWEST_MODE(CLASS) class_narrowest_mode[CLASS]

同样,mode_wider也是由genmodes产生,它由MODE索引,对应于模式在同一类别中的下一个更大的模式。

116 #define GET_MODE_WIDER_MODE(MODE) mode_wider[MODE]

还是由genmodes生成,mode_precision记录了模式中的有意义的比特数(精度)。

87 #define GET_MODE_PRECISION(MODE) mode_precision[MODE]

因此smallest_mode_for_size将找出属于class类别,能容纳size位大小数据的,最小的模式。有了这样的数据,通过下面的宏我们可以找出类型确切的大小。

#define GET_MODE_SIZE(MODE) ((unsigned short) mode_size[MODE]) in machmode.h
#define GET_MODE_BITSIZE(MODE) ((unsigned short) (GET_MODE_SIZE (MODE) * BITS_PER_UNIT))

当在聚合类型中布置具有该类型的数据成员时,这些信息非常重要。
1.2.2.1.5.1.3. 确定类型大小
在layout_type的1548和1549行,bitsize_int和size_int为类型节点构建了记录了类型尺寸信息的节点。这2个函数需要sizetype和bitsizetype这样的类型信息。这也是为什么首先要创建临时的sizetype和bitsizetype节点。
处理bitsize_int和size_int,这个系列的宏还有:

2441 #define size_int_type(L, T) size_int_type_wide ((HOST_WIDE_INT) (L), T)
2442 #define size_int(L) size_int_wide ((HOST_WIDE_INT) (L), SIZETYPE)
2443 #define ssize_int(L) size_int_wide ((HOST_WIDE_INT) (L), SSIZETYPE)
2444 #define bitsize_int(L) size_int_wide ((HOST_WIDE_INT) (L), BITSIZETYPE)
2445 #define sbitsize_int(L) size_int_wide ((HOST_WIDE_INT) (L), SBITSIZETYPE)

参数L代表类型的长度。

1544 tree
1545 size_int_wide (HOST_WIDE_INT number, enum size_type_kind kind) in fold-const.c
1546 {
1547 return size_int_type_wide (number, sizetype_tab[(int) kind]);
1548 }

注意到size_int_type_wide的参数tree是临时的sizetype节点。

1552 static GTY (()) tree new_const;
1553 static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node))) in fold-const.c
1554 htab_t size_htab;
1555
1556 tree
1557 size_int_type_wide (HOST_WIDE_INT number, tree type)
1558 {
1559 void **slot;
1560
1561 if (size_htab == 0)
1562 {
1563 size_htab = htab_create_ggc (1024, size_htab_hash, size_htab_eq, NULL);
1564 new_const = make_node (INTEGER_CST);
1565 }
1566
1567 /* Adjust NEW_CONST to be the constant we want. If it's already in the
1568 hash table, we return the value from the hash table. Otherwise, we
1569 place that in the hash table and make a new node for the next time. */
1570 TREE_INT_CST_LOW (new_const) = number;
1571 TREE_INT_CST_HIGH (new_const) = number < 0 ? -1 : 0;
1572 TREE_TYPE (new_const) = type;
1573 TREE_OVERFLOW (new_const) = TREE_CONSTANT_OVERFLOW (new_const)
1574 = force_fit_type (new_const, 0);
1575
1576 slot = htab_find_slot (size_htab, new_const, INSERT);
1577 if (*slot == 0)
1578 {
1579 tree t = new_const;
1580
1581 *slot = new_const;
1582 new_const = make_node (INTEGER_CST);
1583 return t;
1584 }
1585 else
1586 return (tree) *slot;
1587 }

函数size_int_type_wide同样被用于创建其他大小的整形类型节点。这些节点代表的类型信息同样也是系统内唯一,而且经常被访问,因此它们被存放在哈希表中。注意到代表这些内建整形类型的尺寸的节点亦保持在另一哈希表内。正如我们在tree_int_cst中看到的,域 int_cst实际上是128位的。很明显在绝大数情况下,常量都不会使用所有的比特,因此这些常量需要被位扩展以使用所有的比特位(就像类型转换至128位的类型)。

181 int
182 force_fit_type (tree t, int overflow) in fold-const.c
183 {
184 unsigned HOST_WIDE_INT low;
185 HOST_WIDE_INT high;
186 unsigned int prec;
187
188 if (TREE_CODE (t) == REAL_CST)
189 {
190 /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
191 Consider doing it via real_convert now. */
192 return overflow;
193 }
194
195 else if (TREE_CODE (t) != INTEGER_CST)
196 return overflow;
197
198 low = TREE_INT_CST_LOW (t);
199 high = TREE_INT_CST_HIGH (t);
200
201 if (POINTER_TYPE_P (TREE_TYPE (t))
202 || TREE_CODE (TREE_TYPE (t)) == OFFSET_TYPE)
203 prec = POINTER_SIZE;
204 else
205 prec = TYPE_PRECISION (TREE_TYPE (t));
206
207 /* First clear all bits that are beyond the type's precision. */
208
209 if (prec == 2 * HOST_BITS_PER_WIDE_INT)
210 ;
211 else if (prec > HOST_BITS_PER_WIDE_INT)
212 TREE_INT_CST_HIGH (t)
213 &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
214 else
215 {
216 TREE_INT_CST_HIGH (t) = 0;
217 if (prec < HOST_BITS_PER_WIDE_INT)
218 TREE_INT_CST_LOW (t) &= ~((unsigned HOST_WIDE_INT) (-1) << prec);
219 }
220
221 /* Unsigned types do not suffer sign extension or overflow unless they
222 are a sizetype. */
223 if (TREE_UNSIGNED (TREE_TYPE (t))
224 && ! (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE
225 && TYPE_IS_SIZETYPE (TREE_TYPE (t))))
226 return overflow;
227
228 /* If the value's sign bit is set, extend the sign. */
229 if (prec != 2 * HOST_BITS_PER_WIDE_INT
230 && (prec > HOST_BITS_PER_WIDE_INT
231 ? 0 != (TREE_INT_CST_HIGH (t)
232 & ((HOST_WIDE_INT) 1
233 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
234 : 0 != (TREE_INT_CST_LOW (t)
235 & ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))))
236 {
237 /* Value is negative:
238 set to 1 all the bits that are outside this type's precision. */
239 if (prec > HOST_BITS_PER_WIDE_INT)
240 TREE_INT_CST_HIGH (t)
241 |= ((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
242 else
243 {
244 TREE_INT_CST_HIGH (t) = -1;
245 if (prec < HOST_BITS_PER_WIDE_INT)
246 TREE_INT_CST_LOW (t) |= ((unsigned HOST_WIDE_INT) (-1) << prec);
247 }
248 }
249
250 /* Return nonzero if signed overflow occurred. */
251 return
252 ((overflow | (low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t)))
253 != 0);
254 }

注意负数采用了2进制补码。函数force_fit_type用于检查在常量折叠中(一种优化方法,比如,将加法表达式中的多个常量操作数,用其和来取代它们),整形常量是否溢出。
对于有符号整形,如果符号发生改变,表明发生了溢出。假定对于char类型,执行127+1,其保持在tree_int_cst中的值从0…01111111B改变至0…1000000B,force_fit_type将这个值保存在域high和low,然后清除多余位,再按符号位扩展它们。因此我们得到1…10000000B,low ^ TREE_INT_CST_LOW (t)将会返回非零值。而如果没有溢出发生,high和low部分在252行的操作都应该得到0.
1.2.2.1.5.2. 完成布局

Layout_t (continued)

1798 /* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE. For
1799 records and unions, finish_record_layout already called this
1800 function. */
1801 if (TREE_CODE (type) != RECORD_TYPE
1802 && TREE_CODE (type) != UNION_TYPE
1803 && TREE_CODE (type) != QUAL_UNION_TYPE)
1804 finalize_type_size (type);
1805
1806 /* If this type is created before sizetype has been permanently set,
1807 record it so set_sizetype can fix it up. */
1808 if (! sizetype_set)
1809 early_type_list = tree_cons (NULL_TREE, type, early_type_list);
1810
1811 /* If an alias set has been set for this aggregate when it was incomplete,
1812 force it into alias set 0.
1813 This is too conservative, but we cannot call record_component_aliases
1814 here because some frontends still change the aggregates after
1815 layout_type. */
1816 if (AGGREGATE_TYPE_P (type) && TYPE_ALIAS_SET_KNOWN_P (type))
1817 TYPE_ALIAS_SET (type) = 0;
1818 }

上面1804行的finalize_type_size在类型完成布局后,为其计算尺寸和对齐量。注意在1808行,现阶段,标识sizetype_size仍未设置,表明size_t is的节点还没有准备好(仍是还是临时的)。这样,我们需要把这些在size_t正式节点被创建前的节点,保存到early_type_list中。因为它们用到了size_t,在正式的size_t节点创建好后,我们需要用这个节点来替换那个临时的size_t。
1.2.2.2. size_t的正式的节点
在临时size_t节点的帮助下,编译器为内建的整型类型创建了节点,接着它可以确定正式的size_t节点。在当前的GCC中,由如下代码片段实现。

c_common_nodes_and_builtins

3172 size_type_node = in c-common.c
3173 TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
3174 signed_size_type_node = c_common_signed_type (size_type_node);
3175 set_sizetype (size_type_node);

上面的size_type_node在C/C++中代表size_t。SIZE_TYPE则指明size_t类型,在x86/Linux中,它是unsigned int。

1882 void
1883 set_sizetype (tree type) in stor-layout.c
1884 {
1885 int oprecision = TYPE_PRECISION (type);
1886 /* The *bitsizetype types use a precision that avoids overflows when
1887 calculating signed sizes / offsets in bits. However, when
1888 cross-compiling from a 32 bit to a 64 bit host, we are limited to 64 bit
1889 precision. */
1890 int precision = MIN (oprecision + BITS_PER_UNIT_LOG + 1,
1891 2 * HOST_BITS_PER_WIDE_INT);
1892 unsigned int i;
1893 tree t;
1894
1895 if (sizetype_set)
1896 abort ();
1897
1898 /* Make copies of nodes since we'll be setting TYPE_IS_SIZETYPE. */
1899 sizetype = copy_node (type);
1900 TYPE_DOMAIN (sizetype) = type;
1901 TYPE_IS_SIZETYPE (sizetype) = 1;
1902 bitsizetype = make_node (INTEGER_TYPE);
1903 TYPE_NAME (bitsizetype) = TYPE_NAME (type);
1904 TYPE_PRECISION (bitsizetype) = precision;
1905 TYPE_IS_SIZETYPE (bitsizetype) = 1;
1906
1907 if (TREE_UNSIGNED (type))
1908 fixup_unsigned_type (bitsizetype);
1909 else
1910 fixup_signed_type (bitsizetype);
1911
1912 layout_type (bitsizetype);
1913
1914 if (TREE_UNSIGNED (type))
1915 {
1916 usizetype = sizetype;
1917 ubitsizetype = bitsizetype;
1918 ssizetype = copy_node (make_signed_type (oprecision));
1919 sbitsizetype = copy_node (make_signed_type (precision));
1920 }
1921 else
1922 {
1923 ssizetype = sizetype;
1924 sbitsizetype = bitsizetype;
1925 usizetype = copy_node (make_unsigned_type (oprecision));
1926 ubitsizetype = copy_node (make_unsigned_type (precision));
1927 }
1928
1929 TYPE_NAME (bitsizetype) = get_identifier ("bit_size_type");
1930
1931 /* Show is a sizetype, is a main type, and has no pointers to it. */
1932 for (i = 0; i < ARRAY_SIZE (sizetype_tab); i++)
1933 {
1934 TYPE_IS_SIZETYPE (sizetype_tab[i]) = 1;
1935 TYPE_MAIN_VARIANT (sizetype_tab[i]) = sizetype_tab[i];
1936 TYPE_NEXT_VARIANT (sizetype_tab[i]) = 0;
1937 TYPE_POINTER_TO (sizetype_tab[i]) = 0;
1938 TYPE_REFERENCE_TO (sizetype_tab[i]) = 0;
1939 }
1940
1941 /* Go down each of the types we already made and set the proper type
1942 for the sizes in them. */
1943 for (t = early_type_list; t != 0; t = TREE_CHAIN (t))
1944 {
1945 if (TREE_CODE (TREE_VALUE (t)) != INTEGER_TYPE
1946 && TREE_CODE (TREE_VALUE (t)) != BOOLEAN_TYPE)
1947 abort ();
1948
1949 TREE_TYPE (TYPE_SIZE (TREE_VALUE (t))) = bitsizetype;
1950 TREE_TYPE (TYPE_SIZE_UNIT (TREE_VALUE (t))) = sizetype;
1951 }
1952
1953 early_type_list = 0;
1954 sizetype_set = 1;
1955 }

在1890行,对于x86/Linux oprecision是32。而BITS_PER_UNIT_LOG则定义如下:

2456 #define BITS_PER_UNIT_LOG / in tree.h
2457 ((BITS_PER_UNIT > 1) + (BITS_PER_UNIT > 2) + (BITS_PER_UNIT > 4) /
2458 + (BITS_PER_UNIT > 8) + (BITS_PER_UNIT > 16) + (BITS_PER_UNIT > 32) /
2459 + (BITS_PER_UNIT > 64) + (BITS_PER_UNIT > 128) + (BITS_PER_UNIT > 256))

在x86/Linux下,BITS_PER_UNIT是8(比特的大小),因此BITS_PER_UNIT_LOG返回3。
前面在使用临时的sizetype和bitsizetype创建内建的整型类型节点,这些节点由early_type_list串在一起。现在size_t的正式节点已经就绪,临时的size_t节点可以被替代了。

1.2.2.3. 创建整型常量节点

我们已经看到,在GCC中,整型常量由tree_int_cst节点表示。GCC使用build_int_2来创建这些节点,build_int_2是一个宏,它接着调用build_int_2_wide。

2107 #define build_int_2(LO, HI) / in tree.h
2108 build_int_2_wide ((unsigned HOST_WIDE_INT) (LO), (HOST_WIDE_INT) (HI))

build_int_2_wide根据参数low和hi创建INTEGER_CST节点。

403 tree
404 build_int_2_wide (unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi) in tree.c
405 {
406 tree t = make_node (INTEGER_CST);
407
408 TREE_INT_CST_LOW (t) = low;
409 TREE_INT_CST_HIGH (t) = hi;
410 TREE_TYPE (t) = integer_type_node;
411 return t;
412 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: