fix bug in method type hashing
[cparser] / type_hash.c
1 #include <config.h>
2
3 #include "type_hash.h"
4
5 #include "adt/error.h"
6 #include "type_t.h"
7
8 #include <assert.h>
9
10 #define HashSet         type_hash_t
11 #define HashSetIterator type_hash_iterator_t
12 #define ValueType       type_t*
13 #include "adt/hashset.h"
14 #undef ValueType
15 #undef HashSetIterator
16 #undef HashSet
17
18 /* TODO: ^= is a bad way of combining hashes since most addresses are very
19  * similar */
20
21 static
22 unsigned hash_ptr(const void *ptr)
23 {
24         unsigned ptr_int = ((char*) ptr - (char*) NULL);
25         return ptr_int >> 3;
26 }
27
28 static
29 unsigned hash_atomic_type(const atomic_type_t *type)
30 {
31         unsigned some_prime = 27644437;
32
33         return type->atype * some_prime;
34 }
35
36 static
37 unsigned hash_pointer_type(const pointer_type_t *type)
38 {
39         return hash_ptr(type->points_to);
40 }
41
42 static
43 unsigned hash_compound_type(const compound_type_t *type)
44 {
45         unsigned result = hash_ptr(type->symbol);
46
47         return result;
48 }
49
50 static
51 unsigned hash_type(const type_t *type);
52
53 static
54 unsigned hash_method_type(const method_type_t *type)
55 {
56         unsigned result = hash_ptr(type->result_type);
57
58         method_parameter_t *parameter = type->parameters;
59         while(parameter != NULL) {
60                 result   ^= hash_ptr(parameter->type);
61                 parameter = parameter->next;
62         }
63
64         return result;
65 }
66
67 static
68 unsigned hash_enum_type(const enum_type_t *type)
69 {
70         unsigned result = hash_ptr(type->symbol);
71
72         /* TODO */
73
74         return result;
75 }
76
77 static
78 unsigned hash_type(const type_t *type)
79 {
80         unsigned hash;
81
82         switch(type->type) {
83         case TYPE_INVALID:
84                 panic("internalizing void or invalid types not possible");
85                 return 0;
86         case TYPE_ATOMIC:
87                 hash = hash_atomic_type((const atomic_type_t*) type);
88                 break;
89         case TYPE_ENUM:
90                 hash = hash_enum_type((const enum_type_t*) type);
91                 break;
92         case TYPE_COMPOUND_STRUCT:
93         case TYPE_COMPOUND_UNION:
94                 hash = hash_compound_type((const compound_type_t*) type);
95                 break;
96         case TYPE_METHOD:
97                 hash = hash_method_type((const method_type_t*) type);
98                 break;
99         case TYPE_POINTER:
100                 hash = hash_pointer_type((const pointer_type_t*) type);
101                 break;
102         case TYPE_BUILTIN:
103                 hash = hash_ptr(((const builtin_type_t*) type)->symbol);
104                 break;
105         }
106
107         unsigned some_prime = 99991;
108         hash ^= some_prime * type->qualifiers;
109
110         return hash;
111 }
112
113 static
114 int atomic_types_equal(const atomic_type_t *type1, const atomic_type_t *type2)
115 {
116         return type1->atype == type2->atype;
117 }
118
119 static
120 int compound_types_equal(const compound_type_t *type1,
121                          const compound_type_t *type2)
122 {
123         if(type1->type.type != type2->type.type)
124                 return 0;
125         if(type1->symbol != type2->symbol)
126                 return 0;
127
128         if(type1->symbol == NULL) {
129                 /* previous tests should already have checked for this */
130                 assert(type1 != type2);
131                 /* anonymous types are only equal if they are the very same type */
132                 return 0;
133         } else {
134                 /* non-anonymous types are equal if they have the same symbol */
135                 /* TODO: is this correct */
136                 return 1;
137         }
138
139 #if 0
140         declaration_t *entry1 = type1->context.declarations;
141         declaration_t *entry2 = type2->context.declarations;
142
143         while(entry1 != NULL && entry2 != NULL) {
144                 if(entry1->type != entry2->type)
145                         return 0;
146                 if(entry1->symbol != entry2->symbol)
147                         return 0;
148                 entry1 = entry1->next;
149                 entry2 = entry2->next;
150         }
151         if(entry1 != NULL || entry2 != NULL)
152                 return 0;
153 #endif
154
155         return 1;
156 }
157
158 static
159 int method_types_equal(const method_type_t *type1, const method_type_t *type2)
160 {
161         if(type1->result_type != type2->result_type)
162                 return 0;
163         if(type1->variadic != type2->variadic)
164                 return 0;
165         if(type1->unspecified_parameters != type2->unspecified_parameters)
166                 return 0;
167
168         method_parameter_t *param1 = type1->parameters;
169         method_parameter_t *param2 = type2->parameters;
170         while(param1 != NULL && param2 != NULL) {
171                 if(param1->type != param2->type)
172                         return 0;
173                 param1 = param1->next;
174                 param2 = param2->next;
175         }
176         if(param1 != NULL || param2 != NULL)
177                 return 0;
178
179         return 1;
180 }
181
182 static
183 int pointer_types_equal(const pointer_type_t *type1,
184                         const pointer_type_t *type2)
185 {
186         return type1->points_to == type2->points_to;
187 }
188
189 static
190 int enum_types_equal(const enum_type_t *type1, const enum_type_t *type2)
191 {
192         if(type1->symbol != NULL && type1->symbol == type2->symbol)
193                 return 1;
194
195         enum_entry_t *entry1 = type1->entries;
196         enum_entry_t *entry2 = type2->entries;
197         while(entry1 != NULL && entry2 != NULL) {
198                 if(entry1->symbol != entry2->symbol)
199                         return 0;
200                 /* TODO: compare expressions */
201                 entry1 = entry1->next;
202                 entry2 = entry2->next;
203         }
204         if(entry1 != NULL || entry2 != NULL)
205                 return 0;
206
207         return 1;
208 }
209
210 static
211 int builtin_types_equal(const builtin_type_t *type1,
212                         const builtin_type_t *type2)
213 {
214         return type1->symbol == type2->symbol;
215 }
216
217 static
218 int types_equal(const type_t *type1, const type_t *type2)
219 {
220         if(type1 == type2)
221                 return 1;
222         if(type1->type != type2->type)
223                 return 0;
224         if(type1->qualifiers != type2->qualifiers)
225                 return 0;
226
227         switch(type1->type) {
228         case TYPE_INVALID:
229                 return 0;
230         case TYPE_ATOMIC:
231                 return atomic_types_equal((const atomic_type_t*) type1,
232                                           (const atomic_type_t*) type2);
233         case TYPE_COMPOUND_STRUCT:
234         case TYPE_COMPOUND_UNION:
235                 return compound_types_equal((const compound_type_t*) type1,
236                                             (const compound_type_t*) type2);
237         case TYPE_ENUM:
238                 return enum_types_equal((const enum_type_t*) type1,
239                                         (const enum_type_t*) type2);
240         case TYPE_METHOD:
241                 return method_types_equal((const method_type_t*) type1,
242                                           (const method_type_t*) type2);
243         case TYPE_POINTER:
244                 return pointer_types_equal((const pointer_type_t*) type1,
245                                            (const pointer_type_t*) type2);
246         case TYPE_BUILTIN:
247                 return builtin_types_equal((const builtin_type_t*) type1,
248                                            (const builtin_type_t*) type2);
249         }
250
251         abort();
252 }
253
254 #define HashSet                    type_hash_t
255 #define HashSetIterator            type_hash_iterator_t
256 #define ValueType                  type_t*
257 #define NullValue                  NULL
258 #define DeletedValue               ((type_t*)-1)
259 #define Hash(this, key)            hash_type(key)
260 #define KeysEqual(this,key1,key2)  types_equal(key1, key2)
261 #define SetRangeEmpty(ptr,size)    memset(ptr, 0, (size) * sizeof(*(ptr)))
262
263 #define hashset_init             _typehash_init
264 #define hashset_init_size        _typehash_init_size
265 #define hashset_destroy          _typehash_destroy
266 #define hashset_insert           _typehash_insert
267 #define hashset_remove           typehash_remove
268 #define hashset_find             typehash_find
269 #define hashset_size             typehash_size
270 #define hashset_iterator_init    typehash_iterator_init
271 #define hashset_iterator_next    typehash_iterator_next
272 #define hashset_remove_iterator  typehash_remove_iterator
273
274 #include "adt/hashset.c"
275
276 static type_hash_t typehash;
277
278 void init_typehash(void)
279 {
280         _typehash_init(&typehash);
281 }
282
283 void exit_typehash(void)
284 {
285         _typehash_destroy(&typehash);
286 }
287
288 type_t *typehash_insert(type_t *type)
289 {
290         return _typehash_insert(&typehash, type);
291 }