Studying note of GCC-3.4.6 source (5)

1.2.2. Create node for internal types

For internal types of the language, for example, int, unsigned short in C/C++, the compiler will create nodes for these types first when it starts up.

1.2.2.1.            Initialize temperary nodes for size_t

To create nodes for internal types, temprary nodes for size_t (one for size_t, the other for bitsize_t. size_t is the returned type of sizeof, and bitsize_t is only used by internal) should be first created, as they will be used in layout internal types. Normally, the invocation sequence is like:

 

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

 

Above signed_char_type_node and unsigned_char_type_node are alias for certain elements of a global array which described in below section.

1.2.2.1.1.      Node for integer types

Integer types are very important and basic part of the language. They are used so heavily (appear in every program in fact), to make the accession as efficient as possible, GCC instead of placing them into hash-table as other types, uses global array to hold them.

 

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.      Create temparory node for size_t

The sizes of internal types are another extensively used data in the compiler. So GCC also saves them into a global array.

 

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]

 

Above nodes mean, normal representation of sizes in bytes; normal representation of sizes in bits; signed representation of sizes in bytes; unsigned representation of sizes in bytes; signed representation of sizes in bits; unsigned representation of sizes in bits; in turn (these 3 groups data aim to satisfy different requirement from different target machine).

Originally, only temperary sizetype and bitsizetype are created. The procedure is quite simple.

 

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 }

 

First at line 1852 a temperary nteger_type_node created. From line 1858 to 1864, data relate to mode is generated by back-end tool genmodes from machmode.def, which is used to fill toye node here. Following, build_int_2 will build node for integer constant of 0 and 1000 as the range of the value these temparory size_t can get. And the temparory integer_type_node is used as type of these constants. Note at line 1874, integer_type_node is also used as the type of sizetype and bitsizetype. However, this sizetype will be abandoned after internal integer type created.

1.2.2.1.3.      Create node for integer type

We just take signed integer type as example. For unsigned type, the procedure is very similar with that we see here.

 

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 }

 

The `TYPE_PRECISION' is the number of bits used in the representation, represented as an `unsigned int'. (Note that in the general case this is not the same value as `TYPE_SIZE'; suppose that there were a 24-bit integer type, but that alignment requirements for the ABI required 32-bit alignment. Then, `TYPE_SIZE' would be an `INTEGER_CST' for 32, while `TYPE_PRECISION' would be 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.      Determine the range of value

Every integer type has its own ability to present certain range of values. For the tree_type nodes created for the types, fields TYPE_MIN_VALUE and TYPE_MAX_VALUE save the low and up boundary of the range. As integer constant, these two fields are 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  };

 

And above at line 688, in tree_int_cst_lowhi, the low part and the high part construct an intact value presented (note that the value represented can be up to 128 bits long). The range is determined according to the precision of the type by set_min_and_max_values_for_integral_type below.

 

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 }

 

Above build_int_2 will create node of INTEGER_CST (detail in T.3 Creates Node of Intege Constant - build_int_2). Notice that min_value and max_value of the type should also contain the same type information.

1.2.2.1.5.      Layout integer types

After creating the node, it should make sure it is correctly filled up. It is the work of layout_type. This function is always invoked as last step in creating node for types. Before the nodes handled by this funciton, TYPE_SIZE field will always be NULL, and this field will be set in layout_type. To avoid duplicate layout, so if TYPE_SIZE is not NULL, the function will exit at line 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.              Information of integer type

Above, macros having name beginning with TYPE just access the corresponding field of tree_type as indicated by the rest part of the name. And those beginning with TREE just access that of tree_common.

1.2.2.1.5.1.1.        Determine the sign of type

Sign of the type is the key information. In tree_common node, field TREE_UNSIGNED is used to indicate the type’s sign if appropriate. Find out the sign for integer is very simple as following.

 

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.        Determine the machine mode

In GCC source code, mode just serves as an index. To describe the type groups (for example, integer type of different size), there is mode_class array, and to describe the size, there are mode_size, mode_nunits, mode_precision arrays. And to describe the relation between modes belonging to the same group, there are mode_wider array. Also there are arrays for other purpose for mode. For current version, the information about available modes for the target platform are generated by tool genmodes (Back-end 7. Tool of genmodes).

At line 1547 above, as we know the group, we can find out the fittest mode with the precision in hand.

 

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 returns the narrowest mode of the class, for example, INT class here. class_narrowest_mode is also generated by genmodes and records narrowest mode for the class.

 

150  #define GET_CLASS_NARROWEST_MODE(CLASS) class_narrowest_mode[CLASS]

 

Again, mode_wider is generated by genmodes which is indexed by MODE (which is enum value) and contains next wider mode in the position.

 

116  #define GET_MODE_WIDER_MODE(MODE) mode_wider[MODE]

 

mode_precision, generated by genmodes too, records the number of significant bits of the mode.

 

87    #define GET_MODE_PRECISION(MODE)  mode_precision[MODE]

 

So smallest_mode_for_size just finds out the narrowest mode belonging to the class and capable to hold size bits data. With that information we can find out the exact size for the type as following.

 

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

 

These information are important when a field of the type is laid out without aggregate type.

1.2.2.1.5.1.3.        Determine the size of type

At line 1548 and 1549 in layout_type, bitsize_int and size_int create nodes record size information for the type. These functions will need sizetype and bitsizetype as type information for the nodes created. That is why temperary sizetype and bitsizetype must be created first.

Besides bitsize_int and size_int, there are series macros defined.

 

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)

 

Parameter L stands for the length of the type.

 

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 }

 

Notice that parameter tree of size_int_type_wide is the temperary 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 will also be invoked to create nodes for size of other integer type, these sizes information are also system wide unique, and will be accessed frequently, so they are worth to be put into hashtable. Notice that size nodes of internal integer types are also saved in another hashtable. As we have seen, in tree_int_cst, field int_cst is in fact 128 bits in size. It is obviously in most cases the constant will not occupy the whole bits. So the constant needs be extended to all bits (just regards it as type cast to the version of 128 bits).

 

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  }

 

Notice that negative number is represented by 2 complement presentation. And force_fit_type also is used to check if certain integer constant is overflowed during constant folding (a kind of optimization – for example, sums the values of constants in the same expression).

Just see the way to check overflow. For signed integer type, if overflow, the signed field changes. Assuming 127+1 for char type, the value changes from 0…01111111B to 0…1000000B, force_fit_type saves this value into high and low, then cleans the extra bits and extend these bits according to the signed bit again, and we get 1…10000000B, low ^ TREE_INT_CST_LOW (t) will return nonzero. And if no overflow occurs, it will be zero for high and low parts at line 252.

1.2.2.1.5.4.              Finish layout

 

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 }

 

finalize_type_size at line 1804 above, computes size and alignment for the type again after is is laid out. Notice that at line 1808, now at this stage, flag sizetype_size is still not set which means nodes for size_t is not ready yet (still temperary ones). Then we save these nodes before real node of size_t is ready into early_type_list. Since they use size_t, when real node of size_t is ready, we need use it to replace with that temparory one.

1.2.2.2.            The real node for size_t

After the compiler has nodes for internal integer types created with aid of node of temperary size_t, it can settle down the real size_t. In current GCC, it lies in following code snippet.

 

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

 

Above size_type_node is the node present size_t in C/C++. SIZE_TYPE indicates the type of size_t, in x86 Linux, it is 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 }

 

Notice that at line 1890, oprecision is 32 for x86/Linux. And BITS_PER_UNIT_LOG is defined as following.

 

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

 

In x86/Linux, BITS_PER_UNIT is 8 (size of byte), so BITS_PER_UNIT_LOG returns 3.

Remember that, when using temperary sizetype and bitsizetype to create nodes for internal integer types, all these nodes are chained tegother with early_type_list. Now as regular nodes for size_t are ready, the temperary size_t nodes can be replaced.

1.2.2.3.    Create node for integer constant

As we have seen, in GCC, integer constant is presented by nodes of tree_int_cst. To create nodes of this kind, GCC uses build_int_2, which is a macro invoking build_int_2_wide inside.

 

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 constructs INTEGER_CST node from its parameters low and hi.

 

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  }

 

你可能感兴趣的:(tree,layout,Integer,Build,alignment,Types)