]> git.ipfire.org Git - thirdparty/gcc.git/blame - libobjc/selector.c
rs6000: Check -+0 and NaN for smax/smin generation
[thirdparty/gcc.git] / libobjc / selector.c
CommitLineData
88e17b57 1/* GNU Objective C Runtime selector related functions
8d9254fc 2 Copyright (C) 1993-2020 Free Software Foundation, Inc.
88e17b57
BE
3 Contributed by Kresten Krab Thorup
4
38709cad 5This file is part of GCC.
88e17b57 6
38709cad 7GCC is free software; you can redistribute it and/or modify it under the
88e17b57 8terms of the GNU General Public License as published by the Free Software
748086b7 9Foundation; either version 3, or (at your option) any later version.
88e17b57 10
38709cad 11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
88e17b57
BE
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14details.
15
748086b7
JJ
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23<http://www.gnu.org/licenses/>. */
88e17b57 24
6dead247 25#include "objc-private/common.h"
9ecfa8de 26#include "objc/runtime.h"
a19fac96 27#include "objc/thr.h"
5be9cdc1 28#include "objc-private/hash.h"
9ecfa8de
NP
29#include "objc-private/objc-list.h"
30#include "objc-private/module-abi-8.h"
a19fac96 31#include "objc-private/runtime.h"
5d3b14bd 32#include "objc-private/sarray.h"
1af5b8f5 33#include "objc-private/selector.h"
5750872c 34#include <stdlib.h> /* For malloc. */
88e17b57 35
d4645ada 36/* Initial selector hash table size. Value doesn't matter much. */
88e17b57
BE
37#define SELECTOR_HASH_SIZE 128
38
d4645ada 39/* Tables mapping selector names to uid and opposite. */
40165636
RB
40static struct sarray *__objc_selector_array = 0; /* uid -> sel !T:MUTEX */
41static struct sarray *__objc_selector_names = 0; /* uid -> name !T:MUTEX */
88e17b57
BE
42static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
43
d4645ada 44/* Number of selectors stored in each of the above tables. */
b62cc13a 45unsigned int __objc_selector_max_index = 0; /* !T:MUTEX */
88e17b57 46
600cbba2
NP
47/* Forward-declare an internal function. */
48static SEL
49__sel_register_typed_name (const char *name, const char *types,
50 struct objc_selector *orig, BOOL is_const);
51
64cbe55e 52void __objc_init_selector_tables (void)
88e17b57
BE
53{
54 __objc_selector_array = sarray_new (SELECTOR_HASH_SIZE, 0);
55 __objc_selector_names = sarray_new (SELECTOR_HASH_SIZE, 0);
56 __objc_selector_hash
270a1283
DA
57 = objc_hash_new (SELECTOR_HASH_SIZE,
58 (hash_func_type) objc_hash_string,
59 (compare_func_type) objc_compare_strings);
88e17b57
BE
60}
61
600cbba2
NP
62/* Register a bunch of selectors from the table of selectors in a
63 module. 'selectors' should not be NULL. The list is terminated by
64 a selectors with a NULL sel_id. The selectors are assumed to
65 contain the 'name' in the sel_id field; this is replaced with the
66 final selector id after they are registered. */
67void
68__objc_register_selectors_from_module (struct objc_selector *selectors)
69{
70 int i;
71
72 for (i = 0; selectors[i].sel_id; ++i)
73 {
74 const char *name, *type;
75 name = (char *) selectors[i].sel_id;
76 type = (char *) selectors[i].sel_types;
77 /* Constructors are constant static data and we can safely store
78 pointers to them in the runtime structures, so we set
79 is_const == YES. */
80 __sel_register_typed_name (name, type, (struct objc_selector *) &(selectors[i]),
81 /* is_const */ YES);
82 }
83}
84
d4645ada
NP
85/* This routine is given a class and records all of the methods in its
86 class structure in the record table. */
88e17b57
BE
87void
88__objc_register_selectors_from_class (Class class)
89{
9ecfa8de 90 struct objc_method_list * method_list;
88e17b57
BE
91
92 method_list = class->methods;
93 while (method_list)
94 {
435317e2 95 __objc_register_selectors_from_list (method_list);
88e17b57
BE
96 method_list = method_list->method_next;
97 }
98}
99
100
d4645ada
NP
101/* This routine is given a list of methods and records each of the
102 methods in the record table. This is the routine that does the
103 actual recording work.
88e17b57 104
435317e2 105 The name and type pointers in the method list must be permanent and
d4645ada 106 immutable. */
435317e2 107void
9ecfa8de 108__objc_register_selectors_from_list (struct objc_method_list *method_list)
88e17b57
BE
109{
110 int i = 0;
435317e2
AP
111
112 objc_mutex_lock (__objc_runtime_mutex);
88e17b57
BE
113 while (i < method_list->method_count)
114 {
9ecfa8de 115 Method method = &method_list->method_list[i];
435317e2
AP
116 if (method->method_name)
117 {
118 method->method_name
119 = __sel_register_typed_name ((const char *) method->method_name,
120 method->method_types, 0, YES);
121 }
88e17b57
BE
122 i += 1;
123 }
435317e2 124 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
125}
126
f7185d47
NP
127/* The same as __objc_register_selectors_from_list, but works on a
128 struct objc_method_description_list* instead of a struct
129 objc_method_list*. This is only used for protocols, which have
d4645ada 130 lists of method descriptions, not methods. */
f7185d47
NP
131void
132__objc_register_selectors_from_description_list
133(struct objc_method_description_list *method_list)
134{
135 int i = 0;
136
137 objc_mutex_lock (__objc_runtime_mutex);
138 while (i < method_list->count)
139 {
140 struct objc_method_description *method = &method_list->list[i];
141 if (method->name)
142 {
143 method->name
144 = __sel_register_typed_name ((const char *) method->name,
145 method->types, 0, YES);
146 }
147 i += 1;
148 }
149 objc_mutex_unlock (__objc_runtime_mutex);
150}
88e17b57 151
d4645ada 152/* Register instance methods as class methods for root classes. */
40165636 153void __objc_register_instance_methods_to_class (Class class)
88e17b57 154{
9ecfa8de
NP
155 struct objc_method_list *method_list;
156 struct objc_method_list *class_method_list;
88e17b57 157 int max_methods_no = 16;
9ecfa8de
NP
158 struct objc_method_list *new_list;
159 Method curr_method;
88e17b57
BE
160
161 /* Only if a root class. */
40165636 162 if (class->super_class)
88e17b57
BE
163 return;
164
d4645ada 165 /* Allocate a method list to hold the new class methods. */
40165636 166 new_list = objc_calloc (sizeof (struct objc_method_list)
d4645ada 167 + sizeof (struct objc_method[max_methods_no]), 1);
88e17b57
BE
168 method_list = class->methods;
169 class_method_list = class->class_pointer->methods;
170 curr_method = &new_list->method_list[0];
d4645ada
NP
171
172 /* Iterate through the method lists for the class. */
88e17b57
BE
173 while (method_list)
174 {
175 int i;
d4645ada
NP
176
177 /* Iterate through the methods from this method list. */
88e17b57
BE
178 for (i = 0; i < method_list->method_count; i++)
179 {
9ecfa8de 180 Method mth = &method_list->method_list[i];
88e17b57 181 if (mth->method_name
40165636 182 && ! search_for_method_in_list (class_method_list,
88e17b57
BE
183 mth->method_name))
184 {
d4645ada
NP
185 /* This instance method isn't a class method. Add it
186 into the new_list. */
88e17b57 187 *curr_method = *mth;
d4645ada
NP
188
189 /* Reallocate the method list if necessary. */
40165636 190 if (++new_list->method_count == max_methods_no)
88e17b57 191 new_list =
40165636
RB
192 objc_realloc (new_list, sizeof (struct objc_method_list)
193 + sizeof (struct
d4645ada 194 objc_method[max_methods_no += 16]));
88e17b57
BE
195 curr_method = &new_list->method_list[new_list->method_count];
196 }
197 }
198
199 method_list = method_list->method_next;
200 }
201
d4645ada
NP
202 /* If we created any new class methods then attach the method list
203 to the class. */
88e17b57
BE
204 if (new_list->method_count)
205 {
206 new_list =
40165636 207 objc_realloc (new_list, sizeof (struct objc_method_list)
d4645ada 208 + sizeof (struct objc_method[new_list->method_count]));
88e17b57
BE
209 new_list->method_next = class->class_pointer->methods;
210 class->class_pointer->methods = new_list;
211 }
5af0e6ae
AF
212 else
213 objc_free(new_list);
d4645ada
NP
214
215 __objc_update_dispatch_table_for_class (class->class_pointer);
88e17b57
BE
216}
217
debfbfee
NP
218BOOL
219sel_isEqual (SEL s1, SEL s2)
220{
221 if (s1 == 0 || s2 == 0)
222 return s1 == s2;
223 else
224 return s1->sel_id == s2->sel_id;
225}
88e17b57 226
d4645ada
NP
227/* Return YES iff t1 and t2 have same method types. Ignore the
228 argframe layout. */
0b0b41a8 229static BOOL
40165636 230sel_types_match (const char *t1, const char *t2)
88e17b57 231{
40165636 232 if (! t1 || ! t2)
88e17b57
BE
233 return NO;
234 while (*t1 && *t2)
235 {
236 if (*t1 == '+') t1++;
237 if (*t2 == '+') t2++;
40165636
RB
238 while (isdigit ((unsigned char) *t1)) t1++;
239 while (isdigit ((unsigned char) *t2)) t2++;
88e17b57 240 /* xxx Remove these next two lines when qualifiers are put in
d4645ada 241 all selectors, not just Protocol selectors. */
40165636
RB
242 t1 = objc_skip_type_qualifiers (t1);
243 t2 = objc_skip_type_qualifiers (t2);
244 if (! *t1 && ! *t2)
88e17b57
BE
245 return YES;
246 if (*t1 != *t2)
247 return NO;
248 t1++;
249 t2++;
250 }
251 return NO;
252}
253
d4645ada 254/* Return selector representing name. */
88e17b57
BE
255SEL
256sel_get_any_uid (const char *name)
257{
258 struct objc_list *l;
259 sidx i;
260
40165636 261 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 262
270a1283 263 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
264 if (soffset_decode (i) == 0)
265 {
40165636 266 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
267 return 0;
268 }
269
40165636
RB
270 l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
271 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
272
273 if (l == 0)
274 return 0;
275
40165636 276 return (SEL) l->head;
88e17b57
BE
277}
278
5750872c
NP
279SEL
280sel_getTypedSelector (const char *name)
281{
282 sidx i;
5750872c 283
9cacfc3e
NP
284 if (name == NULL)
285 return NULL;
286
287 objc_mutex_lock (__objc_runtime_mutex);
288
5750872c
NP
289 /* Look for a typed selector. */
290 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
291 if (i != 0)
292 {
293 struct objc_list *l;
68ade9e4 294 SEL returnValue = NULL;
5750872c
NP
295
296 for (l = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
297 l; l = l->tail)
298 {
299 SEL s = (SEL) l->head;
300 if (s->sel_types)
301 {
68ade9e4
NP
302 if (returnValue == NULL)
303 {
304 /* First typed selector that we find. Keep it in
305 returnValue, but keep checking as we want to
306 detect conflicts. */
307 returnValue = s;
308 }
309 else
310 {
311 /* We had already found a typed selectors, so we
312 have multiple ones. Double-check that they have
313 different types, just in case for some reason we
314 got duplicates with the same types. If so, it's
315 OK, we'll ignore the duplicate. */
316 if (returnValue->sel_types == s->sel_types)
317 continue;
318 else if (sel_types_match (returnValue->sel_types, s->sel_types))
319 continue;
320 else
321 {
322 /* The types of the two selectors are different;
323 it's a conflict. Too bad. Return NULL. */
324 objc_mutex_unlock (__objc_runtime_mutex);
325 return NULL;
326 }
327 }
5750872c
NP
328 }
329 }
68ade9e4
NP
330
331 if (returnValue != NULL)
332 {
333 objc_mutex_unlock (__objc_runtime_mutex);
334 return returnValue;
335 }
5750872c
NP
336 }
337
338 /* No typed selector found. Return NULL. */
339 objc_mutex_unlock (__objc_runtime_mutex);
340 return 0;
341}
342
343SEL *
344sel_copyTypedSelectorList (const char *name, unsigned int *numberOfReturnedSelectors)
345{
346 unsigned int count = 0;
347 SEL *returnValue = NULL;
348 sidx i;
349
350 if (name == NULL)
351 {
352 if (numberOfReturnedSelectors)
353 *numberOfReturnedSelectors = 0;
354 return NULL;
355 }
356
357 objc_mutex_lock (__objc_runtime_mutex);
358
359 /* Count how many selectors we have. */
360 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
361 if (i != 0)
362 {
363 struct objc_list *selector_list = NULL;
364 selector_list = (struct objc_list *) sarray_get_safe (__objc_selector_array, i);
365
366 /* Count how many selectors we have. */
367 {
368 struct objc_list *l;
369 for (l = selector_list; l; l = l->tail)
370 count++;
371 }
372
373 if (count != 0)
374 {
375 /* Allocate enough memory to hold them. */
376 returnValue = (SEL *)(malloc (sizeof (SEL) * (count + 1)));
377
378 /* Copy the selectors. */
379 {
380 unsigned int j;
381 for (j = 0; j < count; j++)
382 {
383 returnValue[j] = (SEL)(selector_list->head);
384 selector_list = selector_list->tail;
385 }
386 returnValue[j] = NULL;
387 }
388 }
389 }
390
391 objc_mutex_unlock (__objc_runtime_mutex);
392
393 if (numberOfReturnedSelectors)
394 *numberOfReturnedSelectors = count;
395
396 return returnValue;
397}
398
d4645ada
NP
399/* Get the name of a selector. If the selector is unknown, the empty
400 string "" is returned. */
bc18535a 401const char *sel_getName (SEL selector)
88e17b57
BE
402{
403 const char *ret;
404
524660d2
NP
405 if (selector == NULL)
406 return "<null selector>";
d4645ada 407
40165636
RB
408 objc_mutex_lock (__objc_runtime_mutex);
409 if ((soffset_decode ((sidx)selector->sel_id) > 0)
410 && (soffset_decode ((sidx)selector->sel_id) <= __objc_selector_max_index))
88e17b57
BE
411 ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
412 else
413 ret = 0;
40165636 414 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
415 return ret;
416}
417
418BOOL
419sel_is_mapped (SEL selector)
420{
421 unsigned int idx = soffset_decode ((sidx)selector->sel_id);
422 return ((idx > 0) && (idx <= __objc_selector_max_index));
423}
424
5750872c 425const char *sel_getTypeEncoding (SEL selector)
88e17b57
BE
426{
427 if (selector)
428 return selector->sel_types;
429 else
430 return 0;
431}
432
d4645ada 433/* The uninstalled dispatch table. */
40165636 434extern struct sarray *__objc_uninstalled_dtable;
88e17b57 435
435317e2 436/* __sel_register_typed_name allocates lots of struct objc_selector:s
d4645ada
NP
437 of 8 (16, if pointers are 64 bits) bytes at startup. To reduce the
438 number of malloc calls and memory lost to malloc overhead, we
439 allocate objc_selector:s in blocks here. This is only called from
440 __sel_register_typed_name, and __sel_register_typed_name may only
441 be called when __objc_runtime_mutex is locked.
442
443 Note that the objc_selector:s allocated from
444 __sel_register_typed_name are never freed.
445
446 62 because 62 * sizeof (struct objc_selector) = 496 (992). This
447 should let malloc add some overhead and use a nice, round 512
448 (1024) byte chunk. */
435317e2
AP
449#define SELECTOR_POOL_SIZE 62
450static struct objc_selector *selector_pool;
451static int selector_pool_left;
452
453static struct objc_selector *
454pool_alloc_selector(void)
455{
456 if (!selector_pool_left)
457 {
458 selector_pool = objc_malloc (sizeof (struct objc_selector)
459 * SELECTOR_POOL_SIZE);
460 selector_pool_left = SELECTOR_POOL_SIZE;
461 }
462 return &selector_pool[--selector_pool_left];
463}
464
d4645ada
NP
465/* Store the passed selector name in the selector record and return
466 its selector value (value returned by sel_get_uid). Assume that
467 the calling function has locked down __objc_runtime_mutex. The
600cbba2 468 'is_const' parameter tells us if the name and types parameters are
d4645ada
NP
469 really constant or not. If YES then they are constant and we can
470 just store the pointers. If NO then we need to copy name and types
600cbba2
NP
471 because the pointers may disappear later on. If the 'orig'
472 parameter is not NULL, then we are registering a selector from a
473 module, and 'orig' is that selector. In this case, we can put the
474 selector in the tables if needed, and orig->sel_id is updated with
475 the selector ID of the registered selector, and 'orig' is
476 returned. */
477static SEL
88e17b57
BE
478__sel_register_typed_name (const char *name, const char *types,
479 struct objc_selector *orig, BOOL is_const)
480{
40165636 481 struct objc_selector *j;
88e17b57
BE
482 sidx i;
483 struct objc_list *l;
484
270a1283 485 i = (sidx) objc_hash_value_for_key (__objc_selector_hash, name);
88e17b57
BE
486 if (soffset_decode (i) != 0)
487 {
c75534d1
NP
488 /* There are already selectors with that name. Examine them to
489 see if the one we're registering already exists. */
490 for (l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
491 l; l = l->tail)
492 {
c75534d1 493 SEL s = (SEL)l->head;
88e17b57
BE
494 if (types == 0 || s->sel_types == 0)
495 {
496 if (s->sel_types == types)
497 {
498 if (orig)
499 {
c75534d1 500 orig->sel_id = (void *)i;
88e17b57
BE
501 return orig;
502 }
503 else
504 return s;
505 }
506 }
85fe6408 507 else if (sel_types_match (s->sel_types, types))
88e17b57
BE
508 {
509 if (orig)
510 {
c75534d1 511 orig->sel_id = (void *)i;
88e17b57
BE
512 return orig;
513 }
514 else
515 return s;
516 }
517 }
c75534d1
NP
518 /* A selector with this specific name/type combination does not
519 exist yet. We need to register it. */
88e17b57
BE
520 if (orig)
521 j = orig;
522 else
435317e2 523 j = pool_alloc_selector ();
d4645ada 524
c75534d1
NP
525 j->sel_id = (void *)i;
526 /* Can we use the pointer or must we copy types ? Don't copy if
d4645ada 527 NULL. */
88e17b57 528 if ((is_const) || (types == 0))
c75534d1 529 j->sel_types = types;
d4645ada
NP
530 else
531 {
c75534d1
NP
532 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
533 strcpy ((char *)j->sel_types, types);
d4645ada 534 }
c75534d1 535 l = (struct objc_list *)sarray_get_safe (__objc_selector_array, i);
88e17b57
BE
536 }
537 else
538 {
c75534d1
NP
539 /* There are no other selectors with this name registered in the
540 runtime tables. */
541 const char *new_name;
542
543 /* Determine i. */
88e17b57 544 __objc_selector_max_index += 1;
40165636 545 i = soffset_encode (__objc_selector_max_index);
c75534d1
NP
546
547 /* Prepare the selector. */
88e17b57
BE
548 if (orig)
549 j = orig;
550 else
435317e2 551 j = pool_alloc_selector ();
d4645ada 552
c75534d1
NP
553 j->sel_id = (void *)i;
554 /* Can we use the pointer or must we copy types ? Don't copy if
d4645ada 555 NULL. */
c75534d1
NP
556 if (is_const || (types == 0))
557 j->sel_types = types;
558 else
559 {
560 j->sel_types = (char *)objc_malloc (strlen (types) + 1);
561 strcpy ((char *)j->sel_types, types);
562 }
563
564 /* Since this is the first selector with this name, we need to
565 register the correspondence between 'i' (the sel_id) and
566 'name' (the actual string) in __objc_selector_names and
567 __objc_selector_hash. */
568
569 /* Can we use the pointer or must we copy name ? Don't copy if
570 NULL. (FIXME: Can the name really be NULL here ?) */
571 if (is_const || (name == 0))
572 new_name = name;
d4645ada
NP
573 else
574 {
c75534d1
NP
575 new_name = (char *)objc_malloc (strlen (name) + 1);
576 strcpy ((char *)new_name, name);
d4645ada 577 }
c75534d1
NP
578
579 /* This maps the sel_id to the name. */
580 sarray_at_put_safe (__objc_selector_names, i, (void *)new_name);
581
582 /* This maps the name to the sel_id. */
583 objc_hash_add (&__objc_selector_hash, (void *)new_name, (void *)i);
584
88e17b57
BE
585 l = 0;
586 }
587
588 DEBUG_PRINTF ("Record selector %s[%s] as: %ld\n", name, types,
c75534d1
NP
589 (long)soffset_decode (i));
590
591 /* Now add the selector to the list of selectors with that id. */
592 l = list_cons ((void *)j, l);
593 sarray_at_put_safe (__objc_selector_array, i, (void *)l);
594
40165636 595 sarray_realloc (__objc_uninstalled_dtable, __objc_selector_max_index + 1);
d4645ada 596
c75534d1 597 return (SEL)j;
88e17b57
BE
598}
599
600SEL
bc18535a 601sel_registerName (const char *name)
88e17b57
BE
602{
603 SEL ret;
9cacfc3e
NP
604
605 if (name == NULL)
606 return NULL;
88e17b57 607
40165636 608 objc_mutex_lock (__objc_runtime_mutex);
88e17b57 609 /* Assume that name is not constant static memory and needs to be
d4645ada 610 copied before put into a runtime structure. is_const == NO. */
88e17b57 611 ret = __sel_register_typed_name (name, 0, 0, NO);
40165636 612 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
613
614 return ret;
615}
616
bc18535a
NP
617SEL
618sel_registerTypedName (const char *name, const char *type)
88e17b57
BE
619{
620 SEL ret;
435317e2 621
9cacfc3e
NP
622 if (name == NULL)
623 return NULL;
624
40165636 625 objc_mutex_lock (__objc_runtime_mutex);
d4645ada
NP
626 /* Assume that name and type are not constant static memory and need
627 to be copied before put into a runtime structure. is_const ==
628 NO. */
88e17b57 629 ret = __sel_register_typed_name (name, type, 0, NO);
40165636 630 objc_mutex_unlock (__objc_runtime_mutex);
88e17b57
BE
631
632 return ret;
633}
bc18535a 634
d4645ada 635/* Return the selector representing name. */
bc18535a
NP
636SEL
637sel_getUid (const char *name)
638{
639 return sel_registerTypedName (name, 0);
640}