现在的位置: 首页 > 综合 > 正文

Studying note of GCC-3.4.6 source (5)

2013年07月03日 ⁄ 综合 ⁄ 共 7890字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.