]> gcc.gnu.org Git - gcc.git/blame - gcc/objc/init.c
(configure): Target is $(srcdir)/configure.
[gcc.git] / gcc / objc / init.c
CommitLineData
c72fc2d9 1/* GNU Objective C Runtime initialization
241365d3 2 Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
4426bf3f 3 Contributed by Kresten Krab Thorup
c72fc2d9
TW
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify it under the
4426bf3f
RK
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 2, or (at your option) any later version.
c72fc2d9
TW
10
11GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
4426bf3f
RK
12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14details.
c72fc2d9
TW
15
16You should have received a copy of the GNU General Public License along with
4426bf3f 17GNU CC; see the file COPYING. If not, write to the Free Software
84c09f78 18Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
c72fc2d9
TW
19
20/* As a special exception, if you link this library with files compiled with
21 GCC to produce an executable, this does not cause the resulting executable
22 to be covered by the GNU General Public License. This exception does not
23 however invalidate any other reasons why the executable file might be
24 covered by the GNU General Public License. */
25
26#include "runtime.h"
27
28/* The version number of this runtime. This must match the number
29 defined in gcc (objc-act.c) */
f0a52291 30#define OBJC_VERSION 8
c72fc2d9
TW
31#define PROTOCOL_VERSION 2
32
33/* This list contains all modules currently loaded into the runtime */
aef85e6a 34static struct objc_list* __objc_module_list = 0; /* !T:MUTEX */
c72fc2d9
TW
35
36/* This list contains all proto_list's not yet assigned class links */
aef85e6a 37static struct objc_list* unclaimed_proto_list = 0; /* !T:MUTEX */
c72fc2d9 38
4426bf3f 39/* List of unresolved static instances. */
aef85e6a
RK
40static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
41
42/* Global runtime "write" mutex. */
e0d0c8a1 43objc_mutex_t __objc_runtime_mutex;
aef85e6a
RK
44
45/* Number of threads that are alive. */
46int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
4426bf3f 47
c72fc2d9 48/* Check compiler vs runtime version */
4426bf3f 49static void init_check_module_version (Module_t);
c72fc2d9
TW
50
51/* Assign isa links to protos */
52static void __objc_init_protocols (struct objc_protocol_list* protos);
53
54/* Add protocol to class */
4426bf3f 55static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
c72fc2d9 56
d8a55d09
RK
57/* This is a hook which is called by __objc_exec_class every time a class
58 or a category is loaded into the runtime. This may e.g. help a
59 dynamic loader determine the classes that have been loaded when
60 an object file is dynamically linked in */
aef85e6a 61void (*_objc_load_callback)(Class class, Category* category) = 0; /* !T:SAFE */
d8a55d09 62
c72fc2d9 63/* Is all categories/classes resolved? */
aef85e6a 64BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
c72fc2d9 65
a39d31bc
KKT
66extern SEL
67__sel_register_typed_name (const char *name, const char *types,
018086d1 68 struct objc_selector *orig, BOOL is_const);
a39d31bc 69
f0a52291
RK
70/* Send +load to all classes and categories from a module that implement
71 this method */
72static void __objc_send_load(Module_t module);
73
74/* This list contains all the classes in the runtime system for whom their
75 superclasses are not yet know to the runtime. */
76static struct objc_list* unresolved_classes = 0;
77
78/* Static function used to references the Object and NXConstantString classes. */
79static void
80__objc_force_linking (void)
81{
82 extern void __objc_linking (void);
83 __objc_linking ();
84
85 /* Call the function to avoid compiler warning */
86 __objc_force_linking ();
87}
88
4426bf3f
RK
89/* Run through the statics list, removing modules as soon as all its statics
90 have been initialized. */
91static void
92objc_init_statics ()
93{
94 struct objc_list **cell = &uninitialized_statics;
95 struct objc_static_instances **statics_in_module;
96
aef85e6a
RK
97 objc_mutex_lock(__objc_runtime_mutex);
98
4426bf3f
RK
99 while (*cell)
100 {
101 int module_initialized = 1;
102
103 for (statics_in_module = (*cell)->head;
104 *statics_in_module; statics_in_module++)
105 {
106 struct objc_static_instances *statics = *statics_in_module;
df27f225 107 Class class = objc_lookup_class (statics->class_name);
4426bf3f
RK
108
109 if (!class)
110 module_initialized = 0;
111 /* Actually, the static's class_pointer will be NULL when we
112 haven't been here before. However, the comparison is to be
113 reminded of taking into account class posing and to think about
114 possible semantics... */
115 else if (class != statics->instances[0]->class_pointer)
116 {
117 id *inst;
118
119 for (inst = &statics->instances[0]; *inst; inst++)
120 {
121 (*inst)->class_pointer = class;
122
123 /* ??? Make sure the object will not be freed. With
124 refcounting, invoke `-retain'. Without refcounting, do
125 nothing and hope that `-free' will never be invoked. */
126
127 /* ??? Send the object an `-initStatic' or something to
128 that effect now or later on? What are the semantics of
129 statically allocated instances, besides the trivial
130 NXConstantString, anyway? */
131 }
132 }
133 }
134 if (module_initialized)
135 {
136 /* Remove this module from the uninitialized list. */
137 struct objc_list *this = *cell;
138 *cell = this->tail;
9d46282b 139 objc_free(this);
4426bf3f
RK
140 }
141 else
142 cell = &(*cell)->tail;
143 }
aef85e6a
RK
144
145 objc_mutex_unlock(__objc_runtime_mutex);
4426bf3f 146} /* objc_init_statics */
a39d31bc 147
c72fc2d9
TW
148/* This function is called by constructor functions generated for each
149 module compiled. (_GLOBAL_$I$...) The purpose of this function is to
150 gather the module pointers so that they may be processed by the
151 initialization routines as soon as possible */
152
153void
154__objc_exec_class (Module_t module)
155{
4426bf3f
RK
156 /* Have we processed any constructors previously? This flag is used to
157 indicate that some global data structures need to be built. */
c72fc2d9
TW
158 static BOOL previous_constructors = 0;
159
160 static struct objc_list* unclaimed_categories = 0;
161
4426bf3f 162 /* The symbol table (defined in objc-api.h) generated by gcc */
c72fc2d9
TW
163 Symtab_t symtab = module->symtab;
164
f0a52291
RK
165 /* The statics in this module */
166 struct objc_static_instances **statics
167 = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
168
c72fc2d9
TW
169 /* Entry used to traverse hash lists */
170 struct objc_list** cell;
171
172 /* The table of selector references for this module */
a39d31bc 173 SEL selectors = symtab->refs;
c72fc2d9
TW
174
175 /* dummy counter */
176 int i;
177
178 DEBUG_PRINTF ("received module: %s\n", module->name);
4426bf3f 179
c72fc2d9
TW
180 /* check gcc version */
181 init_check_module_version(module);
182
183 /* On the first call of this routine, initialize some data structures. */
184 if (!previous_constructors)
185 {
aef85e6a
RK
186 /* Initialize thread-safe system */
187 __objc_init_thread_system();
188 __objc_runtime_threads_alive = 1;
189 __objc_runtime_mutex = objc_mutex_allocate();
190
c72fc2d9
TW
191 __objc_init_selector_tables();
192 __objc_init_class_tables();
193 __objc_init_dispatch_tables();
194 previous_constructors = 1;
195 }
196
197 /* Save the module pointer for later processing. (not currently used) */
aef85e6a 198 objc_mutex_lock(__objc_runtime_mutex);
c72fc2d9
TW
199 __objc_module_list = list_cons(module, __objc_module_list);
200
a39d31bc
KKT
201 /* Replace referenced selectors from names to SEL's. */
202 if (selectors)
203 {
204 for (i = 0; selectors[i].sel_id; ++i)
205 {
206 const char *name, *type;
207 name = (char*)selectors[i].sel_id;
208 type = (char*)selectors[i].sel_types;
018086d1
RK
209 /* Constructors are constant static data so we can safely store
210 pointers to them in the runtime structures. is_const == YES */
a39d31bc 211 __sel_register_typed_name (name, type,
018086d1
RK
212 (struct objc_selector*)&(selectors[i]),
213 YES);
a39d31bc
KKT
214 }
215 }
216
c72fc2d9
TW
217 /* Parse the classes in the load module and gather selector information. */
218 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
219 for (i = 0; i < symtab->cls_def_cnt; ++i)
220 {
4426bf3f 221 Class class = (Class) symtab->defs[i];
f0a52291 222 const char* superclass = (char*)class->super_class;
c72fc2d9
TW
223
224 /* Make sure we have what we think. */
225 assert (CLS_ISCLASS(class));
226 assert (CLS_ISMETA(class->class_pointer));
227 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
228
229 /* Store the class in the class table and assign class numbers. */
230 __objc_add_class_to_hash (class);
231
232 /* Register all of the selectors in the class and meta class. */
233 __objc_register_selectors_from_class (class);
4426bf3f 234 __objc_register_selectors_from_class ((Class) class->class_pointer);
c72fc2d9
TW
235
236 /* Install the fake dispatch tables */
237 __objc_install_premature_dtable(class);
238 __objc_install_premature_dtable(class->class_pointer);
239
240 if (class->protocols)
241 __objc_init_protocols (class->protocols);
d8a55d09 242
f0a52291
RK
243 /* Check to see if the superclass is known in this point. If it's not
244 add the class to the unresolved_classes list. */
245 if (superclass && !objc_lookup_class (superclass))
246 unresolved_classes = list_cons (class, unresolved_classes);
c72fc2d9
TW
247 }
248
c72fc2d9
TW
249 /* Process category information from the module. */
250 for (i = 0; i < symtab->cat_def_cnt; ++i)
251 {
252 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
4426bf3f 253 Class class = objc_lookup_class (category->class_name);
c72fc2d9
TW
254
255 /* If the class for the category exists then append its methods. */
256 if (class)
257 {
258
259 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
260 module->name,
261 class->name);
262
263 /* Do instance methods. */
264 if (category->instance_methods)
265 class_add_method_list (class, category->instance_methods);
266
267 /* Do class methods. */
268 if (category->class_methods)
4426bf3f 269 class_add_method_list ((Class) class->class_pointer,
c72fc2d9
TW
270 category->class_methods);
271
272 if (category->protocols)
273 {
274 __objc_init_protocols (category->protocols);
275 __objc_class_add_protocols (class, category->protocols);
276 }
277
d8a55d09
RK
278 if (_objc_load_callback)
279 _objc_load_callback(class, category);
c72fc2d9
TW
280 }
281 else
282 {
283 /* The object to which the category methods belong can't be found.
284 Save the information. */
285 unclaimed_categories = list_cons(category, unclaimed_categories);
286 }
287 }
288
f0a52291
RK
289 if (statics)
290 uninitialized_statics = list_cons (statics, uninitialized_statics);
4426bf3f
RK
291 if (uninitialized_statics)
292 objc_init_statics ();
293
c72fc2d9
TW
294 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
295 categories to objects. */
296 for (cell = &unclaimed_categories;
297 *cell;
a39d31bc 298 ({ if (*cell) cell = &(*cell)->tail; }))
c72fc2d9
TW
299 {
300 Category_t category = (*cell)->head;
4426bf3f 301 Class class = objc_lookup_class (category->class_name);
c72fc2d9
TW
302
303 if (class)
304 {
305 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
306 class->name);
307
308 list_remove_head (cell);
309
310 if (category->instance_methods)
311 class_add_method_list (class, category->instance_methods);
312
313 if (category->class_methods)
4426bf3f 314 class_add_method_list ((Class) class->class_pointer,
c72fc2d9
TW
315 category->class_methods);
316
317 if (category->protocols)
318 {
319 __objc_init_protocols (category->protocols);
320 __objc_class_add_protocols (class, category->protocols);
321 }
322
d8a55d09
RK
323 if (_objc_load_callback)
324 _objc_load_callback(class, category);
c72fc2d9
TW
325 }
326 }
327
328 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
329 {
330 list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
331 list_free (unclaimed_proto_list);
332 unclaimed_proto_list = 0;
333 }
334
f0a52291
RK
335 objc_send_load ();
336
aef85e6a 337 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
338}
339
f0a52291
RK
340void objc_send_load (void)
341{
342 if (!__objc_module_list)
343 return;
344
345 /* Try to find out if all the classes loaded so far also have their
346 superclasses known to the runtime. We suppose that the objects that are
347 allocated in the +load method are in general of a class declared in the
348 same module. */
349 if (unresolved_classes)
350 {
351 Class class = unresolved_classes->head;
352
353 while (objc_lookup_class ((char*)class->super_class))
354 {
355 list_remove_head (&unresolved_classes);
356 if (unresolved_classes)
357 class = unresolved_classes->head;
358 else
359 break;
360 }
361
362 /*
363 * If we still have classes for which we don't have yet their super
364 * classes known to the runtime we don't send the +load messages.
365 */
366 if (unresolved_classes)
367 return;
368 }
369
370 /* Special check to allow sending messages to constant strings in +load
371 methods. If the class is not yet known, even if all the classes are known,
372 delay sending of +load. */
373 if (!objc_lookup_class ("NXConstantString"))
374 return;
375
376 /* Iterate over all modules in the __objc_module_list and call on them the
377 __objc_send_load function that sends the +load message. */
378 list_mapcar (__objc_module_list, (void(*)(void*))__objc_send_load);
379 list_free (__objc_module_list);
380 __objc_module_list = NULL;
381}
382
383static void
384__objc_send_message_in_list (MethodList_t method_list, id object, SEL op)
385{
386 while (method_list)
387 {
388 int i;
389
390 /* Search the method list. */
391 for (i = 0; i < method_list->method_count; i++)
392 {
393 Method_t mth = &method_list->method_list[i];
394
395 if (mth->method_name && sel_eq (mth->method_name, op))
396 {
397 /* The method was found. */
398 (*mth->method_imp) (object, mth->method_name);
399 break;
400 }
401 }
402 method_list = method_list->method_next;
403 }
404}
405
406static void
407__objc_send_load(Module_t module)
408{
409 /* The runtime mutex is locked in this point */
410
411 Symtab_t symtab = module->symtab;
412 static SEL load_sel = 0;
413 int i;
414
415 if (!load_sel)
416 load_sel = sel_register_name ("load");
417
418 /* Iterate thru classes defined in this module and send them the +load
419 message if they implement it. At this point all methods defined in
420 categories were added to the corresponding class, so all the +load
421 methods of categories are in their corresponding classes. */
422 for (i = 0; i < symtab->cls_def_cnt; i++)
423 {
424 Class class = (Class) symtab->defs[i];
425 MethodList_t method_list = class->class_pointer->methods;
426
427 __objc_send_message_in_list (method_list, (id)class, load_sel);
428
429 /* Call the _objc_load_callback for this class. */
430 if (_objc_load_callback)
431 _objc_load_callback(class, 0);
432 }
433
434 /* Call the _objc_load_callback for categories. Don't register the instance
435 methods as class methods for categories to root classes since they were
436 already added in the class. */
437 for (i = 0; i < symtab->cat_def_cnt; i++)
438 {
439 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
440 Class class = objc_lookup_class (category->class_name);
441
442 if (_objc_load_callback)
443 _objc_load_callback(class, category);
444 }
445}
446
c72fc2d9
TW
447/* Sanity check the version of gcc used to compile `module'*/
448static void init_check_module_version(Module_t module)
449{
450 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
451 {
241365d3
RK
452 int code;
453
c72fc2d9 454 if(module->version > OBJC_VERSION)
241365d3 455 code = OBJC_ERR_OBJC_VERSION;
c72fc2d9 456 else if (module->version < OBJC_VERSION)
241365d3 457 code = OBJC_ERR_GCC_VERSION;
c72fc2d9 458 else
241365d3
RK
459 code = OBJC_ERR_MODULE_SIZE;
460
461 objc_error(nil, code, "Module %s version %d doesn't match runtime %d\n",
462 module->name, (int)module->version, OBJC_VERSION);
c72fc2d9
TW
463 }
464}
465
466static void
467__objc_init_protocols (struct objc_protocol_list* protos)
468{
469 int i;
4426bf3f 470 static Class proto_class = 0;
c72fc2d9
TW
471
472 if (! protos)
473 return;
474
aef85e6a
RK
475 objc_mutex_lock(__objc_runtime_mutex);
476
eba92c95
RS
477 if (!proto_class)
478 proto_class = objc_lookup_class("Protocol");
c72fc2d9 479
eba92c95 480 if (!proto_class)
c72fc2d9
TW
481 {
482 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
8c55cd78 483 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
484 return;
485 }
486
2acb0388 487#if 0
c72fc2d9 488 assert (protos->next == 0); /* only single ones allowed */
2acb0388 489#endif
c72fc2d9
TW
490
491 for(i = 0; i < protos->count; i++)
492 {
eba92c95
RS
493 struct objc_protocol* aProto = protos->list[i];
494 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
495 {
496 /* assign class pointer */
497 aProto->class_pointer = proto_class;
498
499 /* init super protocols */
500 __objc_init_protocols (aProto->protocol_list);
501 }
502 else if (protos->list[i]->class_pointer != proto_class)
c72fc2d9 503 {
241365d3
RK
504 objc_error(nil, OBJC_ERR_PROTOCOL_VERSION,
505 "Version %d doesn't match runtime protocol version %d\n",
506 (int)((char*)protos->list[i]->class_pointer-(char*)0),
507 PROTOCOL_VERSION);
c72fc2d9
TW
508 }
509 }
aef85e6a
RK
510
511 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
512}
513
4426bf3f 514static void __objc_class_add_protocols (Class class,
c72fc2d9
TW
515 struct objc_protocol_list* protos)
516{
c72fc2d9
TW
517 /* Well... */
518 if (! protos)
519 return;
520
521 /* Add it... */
522 protos->next = class->protocols;
523 class->protocols = protos;
524}
This page took 0.386569 seconds and 5 git commands to generate.