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

1.2.2. 内建类型的树节点

对于语言中的内建类型,例如,C/C++中的intunsigned short等,编译器在启动时便会为这些类型创建节点。

1.2.2.1.            初始化临时的size_t节点

在创建内建类型的节点前,先要创建临时的size_t节点(一个用作size_t,另一个用作bitsize_tsize_tsizeof的返回类型,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_nodeunsigned_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组数据主要为了满足不同目标机器的要求)。

最开始,只有临时的sizetypebitsizetype节点被函数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则构建了整型常量01000,作为临时size_t的取值范围。而这个临时的integer_type_node 被作为这些常量的类型值(tree_type)。注意,在1874行,临时的integer_type_node 被同时用作sizetypebitsizetype的类型。 不过,这些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将是一个值为32INTEGER_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_VALUETYPE_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_sizemode_nunitsmode_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_type15481549行,bitsize_intsize_int为类型节点构建了记录了类型尺寸信息的节点。这2个函数需要sizetypebitsizetype这样的类型信息。这也是为什么首先要创建临时的sizetypebitsizetype节点。

处理bitsize_intsize_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…1000000Bforce_fit_type将这个值保存在域highlow,然后清除多余位,再按符号位扩展它们。因此我们得到1…10000000Blow ^ TREE_INT_CST_LOW (t)将会返回非零值。而如果没有溢出发生,highlow部分在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_nodeC/C++中代表size_tSIZE_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 oprecision32。而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_UNIT8(比特的大小),因此BITS_PER_UNIT_LOG返回3

前面在使用临时的sizetypebitsizetype创建内建的整型类型节点,这些节点由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根据参数lowhi创建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  }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值