arm.h (REG_CLASS_CONTENTS): Remove soft frame pointer from CORE_REGS and GENERAL_REGS...
[gcc.git] / libobjc / protocols.c
1 /* GNU Objective C Runtime protocol related functions.
2 Copyright (C) 2010 Free Software Foundation, Inc.
3 Contributed by Nicola Pero
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 #include "objc-private/common.h"
26 #include "objc/runtime.h"
27 #include "objc-private/module-abi-8.h" /* For runtime structures */
28 #include "objc/thr.h"
29 #include "objc-private/runtime.h" /* the kitchen sink */
30 #include "objc-private/hash.h" /* For the hash table of protocols. */
31 #include "objc-private/protocols.h" /* For __objc_protocols_init() and __objc_protocols_add_protocol() */
32
33 /* This is a table that maps a name to a Protocol instance with that
34 name. Because there may be multiple Protocol instances with the
35 same name (no harm in that) the table records only one
36 instance. */
37 static cache_ptr __protocols_hashtable;
38
39 /* A mutex protecting the protocol_hashtable. */
40 static objc_mutex_t __protocols_hashtable_lock = NULL;
41
42 /* Called at startup by init.c. */
43 void
44 __objc_protocols_init (void)
45 {
46 __protocols_hashtable_lock = objc_mutex_allocate ();
47
48 /* The keys in the table are strings, and the values are Protocol
49 objects. */
50 __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
51 (compare_func_type) objc_compare_strings);
52 }
53
54 /* Add a protocol to the hashtable. */
55 void
56 __objc_protocols_add_protocol (const char *name, Protocol *object)
57 {
58 objc_mutex_lock (__protocols_hashtable_lock);
59
60 /* If we find a protocol with the same name already in the
61 hashtable, we do not need to add the new one, because it will be
62 identical to it. This in the reasonable assumption that two
63 protocols with the same name are identical, which is expected in
64 any sane program. If we are really paranoid, we would compare
65 the protocols and abort if they are not identical.
66 Unfortunately, this would slow down the startup of all
67 Objective-C programs while trying to catch a problem that has
68 never been seen in practice, so we don't do it. */
69 if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
70 {
71 objc_hash_add (&__protocols_hashtable, name, object);
72 }
73
74 objc_mutex_unlock (__protocols_hashtable_lock);
75 }
76
77 Protocol *
78 objc_getProtocol (const char *name)
79 {
80 Protocol *protocol;
81
82 if (name == NULL)
83 return NULL;
84
85 objc_mutex_lock (__protocols_hashtable_lock);
86 protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
87 objc_mutex_unlock (__protocols_hashtable_lock);
88
89 return protocol;
90 }
91
92 Protocol **
93 objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
94 {
95 unsigned int count = 0;
96 Protocol **returnValue = NULL;
97 node_ptr node;
98
99 objc_mutex_lock (__protocols_hashtable_lock);
100
101 /* Count how many protocols we have. */
102 node = objc_hash_next (__protocols_hashtable, NULL);
103 while (node)
104 {
105 count++;
106 node = objc_hash_next (__protocols_hashtable, node);
107 }
108
109 if (count != 0)
110 {
111 unsigned int i = 0;
112
113 /* Allocate enough memory to hold them. */
114 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
115
116 /* Copy the protocols. */
117 node = objc_hash_next (__protocols_hashtable, NULL);
118 while (node)
119 {
120 returnValue[i] = node->value;
121 i++;
122 node = objc_hash_next (__protocols_hashtable, node);
123 }
124
125 returnValue[i] = NULL;
126 }
127 objc_mutex_unlock (__protocols_hashtable_lock);
128
129 if (numberOfReturnedProtocols)
130 *numberOfReturnedProtocols = count;
131
132 return returnValue;
133 }
134
135 BOOL
136 class_addProtocol (Class class_, Protocol *protocol)
137 {
138 struct objc_protocol_list *protocols;
139
140 if (class_ == Nil || protocol == NULL)
141 return NO;
142
143 if (class_conformsToProtocol (class_, protocol))
144 return NO;
145
146 /* Check that it is a Protocol object before casting it to (struct
147 objc_protocol *). */
148 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
149 return NO;
150
151 objc_mutex_lock (__objc_runtime_mutex);
152
153 /* Create the objc_protocol_list. */
154 protocols = malloc (sizeof (struct objc_protocol_list));
155 protocols->count = 1;
156 protocols->list[0] = protocol;
157
158 /* Attach it to the list of class protocols. */
159 protocols->next = class_->protocols;
160 class_->protocols = protocols;
161
162 objc_mutex_unlock (__objc_runtime_mutex);
163
164 return YES;
165 }
166
167 BOOL
168 class_conformsToProtocol (Class class_, Protocol *protocol)
169 {
170 struct objc_protocol_list* proto_list;
171
172 if (class_ == Nil || protocol == NULL)
173 return NO;
174
175 /* Check that it is a Protocol object before casting it to (struct
176 objc_protocol *). */
177 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
178 return NO;
179
180 /* Acquire the runtime lock because the list of protocols for a
181 class may be modified concurrently, for example if another thread
182 calls class_addProtocol(), or dynamically loads from a file a
183 category of the class. */
184 objc_mutex_lock (__objc_runtime_mutex);
185 proto_list = class_->protocols;
186
187 while (proto_list)
188 {
189 size_t i;
190 for (i = 0; i < proto_list->count; i++)
191 {
192 if (proto_list->list[i] == protocol
193 || protocol_conformsToProtocol (proto_list->list[i],
194 protocol))
195 {
196 objc_mutex_unlock (__objc_runtime_mutex);
197 return YES;
198 }
199 }
200 proto_list = proto_list->next;
201 }
202
203 objc_mutex_unlock (__objc_runtime_mutex);
204 return NO;
205 }
206
207 Protocol **
208 class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
209 {
210 unsigned int count = 0;
211 Protocol **returnValue = NULL;
212 struct objc_protocol_list* proto_list;
213
214 if (class_ == Nil)
215 {
216 if (numberOfReturnedProtocols)
217 *numberOfReturnedProtocols = 0;
218 return NULL;
219 }
220
221 /* Lock the runtime mutex because the class protocols may be
222 concurrently modified. */
223 objc_mutex_lock (__objc_runtime_mutex);
224
225 /* Count how many protocols we have. */
226 proto_list = class_->protocols;
227
228 while (proto_list)
229 {
230 count = count + proto_list->count;
231 proto_list = proto_list->next;
232 }
233
234 if (count != 0)
235 {
236 unsigned int i = 0;
237
238 /* Allocate enough memory to hold them. */
239 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
240
241 /* Copy the protocols. */
242 proto_list = class_->protocols;
243
244 while (proto_list)
245 {
246 size_t j;
247 for (j = 0; j < proto_list->count; j++)
248 {
249 returnValue[i] = proto_list->list[j];
250 i++;
251 }
252 proto_list = proto_list->next;
253 }
254
255 returnValue[i] = NULL;
256 }
257 objc_mutex_unlock (__objc_runtime_mutex);
258
259 if (numberOfReturnedProtocols)
260 *numberOfReturnedProtocols = count;
261
262 return returnValue;
263 }
264
265 BOOL
266 protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
267 {
268 struct objc_protocol_list* proto_list;
269
270 if (protocol == NULL || anotherProtocol == NULL)
271 return NO;
272
273 if (protocol == anotherProtocol)
274 return YES;
275
276 /* Check that the objects are Protocol objects before casting them
277 to (struct objc_protocol *). */
278 if (protocol->class_pointer != anotherProtocol->class_pointer)
279 return NO;
280
281 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
282 return NO;
283
284 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
285 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
286 return YES;
287
288 /* We do not acquire any lock because protocols are currently
289 immutable. We can freely iterate over a protocol structure. */
290 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
291 while (proto_list)
292 {
293 size_t i;
294
295 for (i = 0; i < proto_list->count; i++)
296 {
297 if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol))
298 return YES;
299 }
300 proto_list = proto_list->next;
301 }
302
303 return NO;
304 }
305
306 BOOL
307 protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
308 {
309 if (protocol == anotherProtocol)
310 return YES;
311
312 if (protocol == NULL || anotherProtocol == NULL)
313 return NO;
314
315 /* Check that the objects are Protocol objects before casting them
316 to (struct objc_protocol *). */
317 if (protocol->class_pointer != anotherProtocol->class_pointer)
318 return NO;
319
320 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
321 return NO;
322
323 /* Equality between formal protocols is only formal (nothing to do
324 with actually checking the list of methods they have!). Two
325 formal Protocols are equal if and only if they have the same
326 name.
327
328 Please note (for comparisons with other implementations) that
329 checking the names is equivalent to checking that Protocol A
330 conforms to Protocol B and Protocol B conforms to Protocol A,
331 because this happens iff they have the same name. If they have
332 different names, A conforms to B if and only if A includes B, but
333 the situation where A includes B and B includes A is a circular
334 dependency between Protocols which is forbidden by the compiler,
335 so A conforms to B and B conforms to A with A and B having
336 different names is an impossible case. */
337 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
338 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
339 return YES;
340
341 return NO;
342 }
343
344 const char *
345 protocol_getName (Protocol *protocol)
346 {
347 /* Check that it is a Protocol object before casting it to (struct
348 objc_protocol *). */
349 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
350 return NULL;
351
352 return ((struct objc_protocol *)protocol)->protocol_name;
353 }
354
355 struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
356 SEL selector,
357 BOOL requiredMethod,
358 BOOL instanceMethod)
359 {
360 struct objc_method_description no_result = { NULL, NULL };
361 const char* selector_name;
362 struct objc_method_description_list *methods;
363 int i;
364
365 /* TODO: New ABI. */
366 /* The current ABI does not have any information on optional protocol methods. */
367 if (! requiredMethod)
368 return no_result;
369
370 /* Check that it is a Protocol object before casting it to (struct
371 objc_protocol *). */
372 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
373 return no_result;
374
375 selector_name = sel_getName (selector);
376
377 if (instanceMethod)
378 methods = ((struct objc_protocol *)protocol)->instance_methods;
379 else
380 methods = ((struct objc_protocol *)protocol)->class_methods;
381
382 if (methods)
383 {
384 for (i = 0; i < methods->count; i++)
385 {
386 if (strcmp ((char*)(methods->list[i].name), selector_name) == 0)
387 return methods->list[i];
388 }
389 }
390
391 return no_result;
392 }
393
394 struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
395 BOOL requiredMethod,
396 BOOL instanceMethod,
397 unsigned int *numberOfReturnedMethods)
398 {
399 struct objc_method_description_list *methods;
400 unsigned int count = 0;
401 struct objc_method_description *returnValue = NULL;
402
403 /* TODO: New ABI */
404 /* The current ABI does not have any information on optional protocol methods. */
405 if (! requiredMethod)
406 {
407 if (numberOfReturnedMethods)
408 *numberOfReturnedMethods = 0;
409
410 return NULL;
411 }
412
413 /* Check that it is a Protocol object before casting it to (struct
414 objc_protocol *). */
415 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
416 {
417 if (numberOfReturnedMethods)
418 *numberOfReturnedMethods = 0;
419
420 return NULL;
421 }
422
423 /* We do not acquire any lock because protocols are currently
424 immutable. We can freely iterate over a protocol structure. */
425
426 if (instanceMethod)
427 methods = ((struct objc_protocol *)protocol)->instance_methods;
428 else
429 methods = ((struct objc_protocol *)protocol)->class_methods;
430
431 if (methods)
432 {
433 unsigned int i;
434 count = methods->count;
435
436 /* Allocate enough memory to hold them. */
437 returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
438
439 /* Copy them. */
440 for (i = 0; i < count; i++)
441 {
442 returnValue[i].name = methods->list[i].name;
443 returnValue[i].types = methods->list[i].types;
444 }
445 returnValue[i].name = NULL;
446 returnValue[i].types = NULL;
447 }
448
449 if (numberOfReturnedMethods)
450 *numberOfReturnedMethods = count;
451
452 return returnValue;
453 }
454
455 Property protocol_getProperty (Protocol *protocol, const char *propertyName,
456 BOOL requiredProperty, BOOL instanceProperty)
457 {
458 if (protocol == NULL || propertyName == NULL)
459 return NULL;
460
461 if (!requiredProperty || !instanceProperty)
462 return NULL;
463
464 /* Check that it is a Protocol object before casting it to (struct
465 objc_protocol *). */
466 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
467 return NULL;
468
469 /* TODO: New ABI. */
470 /* The current ABI does not have any information on protocol properties. */
471 return NULL;
472 }
473
474 Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
475 {
476 unsigned int count = 0;
477 Property *returnValue = NULL;
478
479 /* Check that it is a Protocol object before casting it to (struct
480 objc_protocol *). */
481 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
482 {
483 if (numberOfReturnedProperties)
484 *numberOfReturnedProperties = 0;
485
486 return NULL;
487 }
488
489 /* We do not acquire any lock because protocols are currently
490 immutable. We can freely iterate over a protocol structure. */
491
492 /* TODO: New ABI. */
493 /* The current ABI does not have any information on protocol properties. */
494 if (numberOfReturnedProperties)
495 *numberOfReturnedProperties = count;
496
497 return returnValue;
498 }
499
500 Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
501 {
502 unsigned int count = 0;
503 Protocol **returnValue = NULL;
504 struct objc_protocol_list* proto_list;
505
506 /* Check that it is a Protocol object before casting it to (struct
507 objc_protocol *). */
508 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
509 {
510 if (numberOfReturnedProtocols)
511 *numberOfReturnedProtocols = 0;
512
513 return NULL;
514 }
515
516 /* We do not acquire any lock because protocols are currently
517 immutable. We can freely iterate over a protocol structure. */
518
519 /* Count how many protocols we have. */
520 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
521
522 while (proto_list)
523 {
524 count = count + proto_list->count;
525 proto_list = proto_list->next;
526 }
527
528 if (count != 0)
529 {
530 unsigned int i = 0;
531
532 /* Allocate enough memory to hold them. */
533 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
534
535 /* Copy the protocols. */
536 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
537
538 while (proto_list)
539 {
540 size_t j;
541 for (j = 0; j < proto_list->count; j++)
542 {
543 returnValue[i] = proto_list->list[j];
544 i++;
545 }
546 proto_list = proto_list->next;
547 }
548
549 returnValue[i] = NULL;
550 }
551
552 if (numberOfReturnedProtocols)
553 *numberOfReturnedProtocols = count;
554
555 return returnValue;
556 }