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