完成标识符哈希表的初始化后,general_init调用init_ttree来初始化类型哈希表。
116 void
117 init_ttree (void) in tree.c
118 {
119 /* Initialize the hash table of types. */
120 type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
121 type_hash_eq, 0);
122 }
注意,这个哈希表指定了哈希函数及比较函数。
该哈希表的对象是type_hash_table。它的定义如下。
94 /* Now here is the hash table. When recording a type, it is added to
95 the slot whose index is the hash code. Note that the hash table is
96 used for several kinds of types (function types, array types and
97 array index range types, for now). While all these live in the
98 same table, they are completely independent, and the hash code is
99 computed differently for each of these. */
100
101 static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
102 htab_t type_hash_table;
type_hash_table的类型是htab_t,它是指向htab的指针。
90 struct htab GTY(()) in hashtab.h
91 {
92 /* Pointer to hash function. */
93 htab_hash hash_f;
94
95 /* Pointer to comparison function. */
96 htab_eq eq_f;
97
98 /* Pointer to cleanup function. */
99 htab_del del_f;
100
101 /* Table itself. */
102 PTR * GTY ((use_param (""), length ("%h.size"))) entries;
103
104 /* Current size (in entries) of the hash table */
105 size_t size;
106
107 /* Current number of elements including also deleted elements */
108 size_t n_elements;
109
110 /* Current number of deleted elements in the table */
111 size_t n_deleted;
112
113 /* The following member is used for debugging. Its value is number
114 of all calls of `htab_find_slot' for the hash table. */
115 unsigned int searches;
116
117 /* The following member is used for debugging. Its value is number
118 of collisions fixed for time of work with the hash table. */
119 unsigned int collisions;
120
121 /* Pointers to allocate/free functions. */
122 htab_alloc alloc_f;
123 htab_free free_f;
124
125 /* Alternate allocate/free functions, which take an extra argument. */
126 PTR GTY((skip (""))) alloc_arg;
127 htab_alloc_with_arg alloc_with_arg_f;
128 htab_free_with_arg free_with_arg_f;
129 };
130
131 typedef struct htab *htab_t;
哈希表的创建函数htab_create_ggc的定义如下。
236 #define htab_create_ggc(SIZE, HASH, EQ, DEL) / in ggc.h
237 htab_create_alloc (SIZE, HASH, EQ, DEL, ggc_calloc, NULL)
ggc_alloc是由GC(垃圾收集器)提供的方法。它负责分配由GC管理的对象。上面126行的PTR是void*或char*。
167 htab_t
168 htab_create_alloc (size, hash_f, eq_f, del_f, alloc_f, free_f) in hashtab.c
169 size_t size;
170 htab_hash hash_f;
171 htab_eq eq_f;
172 htab_del del_f;
173 htab_alloc alloc_f;
174 htab_free free_f;
175 {
176 htab_t result;
177
178 size = higher_prime_number (size);
179 result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
180 if (result == NULL)
181 return NULL;
182 result->entries = (PTR *) (*alloc_f) (size, sizeof (PTR));
183 if (result->entries == NULL)
184 {
185 if (free_f != NULL)
186 (*free_f) (result);
187 return NULL;
188 }
189 result->size = size;
190 result->hash_f = hash_f;
191 result->eq_f = eq_f;
192 result->del_f = del_f;
193 result->alloc_f = alloc_f;
194 result->free_f = free_f;
195 return result;
196 }
上面178行,higher_prime_number返回比size大而又小于比size大的最小2的指数的质数。目的为了减少哈希碰撞。
在上面102行虽然这个表被声明为void*,它的元素实际上是type_hash类型。
85 struct type_hash GTY(()) in tree.c
86 {
87 unsigned long hash;
88 tree type;
89 };
type_hash的type域实际是tree_type类型。
在这个哈希表中的查找是由函数type_hash_lookup执行,函数的type参数也是tree_type类型。
3008 tree
3009 type_hash_lookup (unsigned int hashcode, tree type) in tree.c
3010 {
3011 struct type_hash *h, in;
3012
3013 /* The TYPE_ALIGN field of a type is set by layout_type(), so we
3014 must call that routine before comparing TYPE_ALIGNs. */
3015 layout_type (type);
3016
3017 in.hash = hashcode;
3018 in.type = type;
3019
3020 h = htab_find_with_hash (type_hash_table, &in, hashcode);
3021 if (h)
3022 return h->type;
3023 return NULL_TREE;
3024 }
htab_find_with_hash不能用于添加或删除元素,它只能返回与hashcode匹配的表项,这表项可以为空。
参考内建类型的树节点。
实数和复数类型所要求的信息与整数类型相同。见如下代码片段。
layout_type (continue)
1552 case REAL_TYPE:
1553 TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0);
1554 TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
1555 TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
1556 break;
1557
1558 case COMPLEX_TYPE:
1559 TREE_UNSIGNED (type) = TREE_UNSIGNED (TREE_TYPE (type));
1560 TYPE_MODE (type)
1561 = mode_for_size (2 * TYPE_PRECISION (TREE_TYPE (type)),
1562 (TREE_CODE (TTREE_TYPE (type)) == INTEGER_TYPE
1563 ? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT),
1564 0);
1565 TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
1566 TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
1567 break;
函数mode_for_size和smallest_mode_for_size相似,它返回对应有size比特的非标量的机器模式。这个模式必须是参数class指定的类别,而且确实具有那么多有效比特位,它可能还包含有填充位。如果参数limit非零,不能使用比MAX_FIXED_MODE_SIZE更宽的模式。
211 enum machine_mode
212 mode_for_size (unsigned int size, enum mode_class class, int limit) in stor_layout.c
213 {
214 enum machine_mode mode;
215
216 if (limit && size > MAX_FIXED_MODE_SIZE)
217 return BLKmode;
218
219 /* Get the first mode which has this size, in the specified class. */
220 for (mode = GET_CLASS_NARROWEST_MODE (class); mode != VOIDmode;
221 mode = GET_MODE_WIDER_MODE (mode))
222 if (GET_MODE_PRECISION (mode) == size)
223 return mode;
224
225 return BLKmode;
226 }
在没有合适的固定模式(fixed mode)时,只能选用BLKmode。它是用于结构或数组等的模式。
以x86系统为例,系统提供SSE或MMX寄存器用于操作64位或更多位数据。因此数个总大小不超过特定尺寸的同型的整型或浮点型数据可以被存入这类寄存器。这组整数或浮点数就被定义为VECTOR_TYPE(向量类型)。
layout_type (continue)
1569 case VECTOR_TYPE:
1570 {
1571 tree subtype;
1572
1573 subtype = TREE_TYPE (type);
1574 TREE_UNSIGNED (type) = TREE_UNSIGNED (subtype);
1575 TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
1576 TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
1577 }
1578 break;
1579
1580 case VOID_TYPE:
1581 /* This is an incomplete type and so doesn't have a size. */
1582 TYPE_ALIGN (type) = 1;
1583 TYPE_USER_ALIGN (type) = 0;
1584 TYPE_MODE (type) = VOIDmode;
1585 break;
1586
1587 case OFFSET_TYPE:
1588 TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
1589 TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
1590 /* A pointer might be MODE_PARTIAL_INT,
1591 but ptrdiff_t must be integral. */
1592 TYPE_MODE (type) = mode_for_size (POINTER_SIZE, MODE_INT, 0);
1593 break;
1594
1595 case FUNCTION_TYPE:
1596 case METHOD_TYPE:
1597 TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
1598 TYPE_SIZE (type) = bitsize_int (2 * POINTER_SIZE);
1599 TYPE_SIZE_UNIT (type) = size_int ((2 * POINTER_SIZE) / BITS_PER_UNIT);
1600 break;
1601
1602 case POINTER_TYPE:
1603 case REFERENCE_TYPE:
1604 {
1605
1606 enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE
1607 && reference_types_internal)
1608 ? Pmode : TYPE_MODE (type));
1609
1610 int nbits = GET_MODE_BITSIZE (mode);
1611
1612 TYPE_SIZE (type) = bitsize_int (nbits);
1613 TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
1614 TREE_UNSIGNED (type) = 1;
1615 TYPE_PRECISION (type) = nbits;
1616 }
1617 break;
对于VECTOR_TYPE,注意到在其tree_common域,其中的type域是单个数据(元素)本身的类型。而元素类型的细节也被保存入这个向量类型。向量类型所包含的元素个数由其机器模式决定。
参考创建数组类型节点