OSDN Git Service

* jump.c (jump_optimize, follow_jumps, mark_jump_label): Disable some
[pf3gnuchains/gcc-fork.git] / gcc / objc / init.c
1 /* GNU Objective C Runtime initialization 
2    Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Kresten Krab Thorup
4
5 This file is part of GNU CC.
6
7 GNU CC 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 2, or (at your option) any later version.
10
11 GNU CC 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 You should have received a copy of the GNU General Public License along with
17 GNU CC; see the file COPYING.  If not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
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) */
30 #define OBJC_VERSION 8
31 #define PROTOCOL_VERSION 2
32
33 /* This list contains all modules currently loaded into the runtime */
34 static struct objc_list* __objc_module_list = 0;        /* !T:MUTEX */
35
36 /* This list contains all proto_list's not yet assigned class links */
37 static struct objc_list* unclaimed_proto_list = 0;      /* !T:MUTEX */
38
39 /* List of unresolved static instances.  */
40 static struct objc_list *uninitialized_statics = 0;     /* !T:MUTEX */
41
42 /* Global runtime "write" mutex. */
43 objc_mutex_t __objc_runtime_mutex;
44
45 /* Number of threads that are alive. */
46 int __objc_runtime_threads_alive = 1;                   /* !T:MUTEX */
47
48 /* Check compiler vs runtime version */
49 static void init_check_module_version (Module_t);
50
51 /* Assign isa links to protos */
52 static void __objc_init_protocols (struct objc_protocol_list* protos);
53
54 /* Add protocol to class */
55 static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
56
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 */
61 void (*_objc_load_callback)(Class class, Category* category) = 0; /* !T:SAFE */
62
63 /* Is all categories/classes resolved? */
64 BOOL __objc_dangling_categories = NO;           /* !T:UNUSED */
65
66 extern SEL
67 __sel_register_typed_name (const char *name, const char *types, 
68                            struct objc_selector *orig, BOOL is_const);
69
70 /* Send +load to all classes and categories from a module that implement
71    this method */
72 static 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. */
76 static struct objc_list* unresolved_classes = 0;
77
78 /* Static function used to references the Object and NXConstantString classes. */
79 static 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
89 /* Run through the statics list, removing modules as soon as all its statics
90    have been initialized.  */
91 static void
92 objc_init_statics ()
93 {
94   struct objc_list **cell = &uninitialized_statics;
95   struct objc_static_instances **statics_in_module;
96
97   objc_mutex_lock(__objc_runtime_mutex);
98
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;
107           Class class = objc_lookup_class (statics->class_name);
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;
139           objc_free(this);
140         }
141       else
142         cell = &(*cell)->tail;
143     }
144
145   objc_mutex_unlock(__objc_runtime_mutex);
146 } /* objc_init_statics */
147
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
153 void
154 __objc_exec_class (Module_t module)
155 {
156   /* Have we processed any constructors previously?  This flag is used to
157      indicate that some global data structures need to be built.  */
158   static BOOL previous_constructors = 0;
159
160   static struct objc_list* unclaimed_categories = 0;
161
162   /* The symbol table (defined in objc-api.h) generated by gcc */
163   Symtab_t symtab = module->symtab;
164
165   /* The statics in this module */
166   struct objc_static_instances **statics
167     = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
168
169   /* Entry used to traverse hash lists */
170   struct objc_list** cell;
171
172   /* The table of selector references for this module */
173   SEL selectors = symtab->refs; 
174
175   /* dummy counter */
176   int i;
177
178   DEBUG_PRINTF ("received module: %s\n", module->name);
179
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     {
186         /* Initialize thread-safe system */
187       __objc_init_thread_system();
188       __objc_runtime_threads_alive = 1;
189       __objc_runtime_mutex = objc_mutex_allocate();
190
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) */
198   objc_mutex_lock(__objc_runtime_mutex);
199   __objc_module_list = list_cons(module, __objc_module_list);
200
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;
209           /* Constructors are constant static data so we can safely store
210              pointers to them in the runtime structures. is_const == YES */
211           __sel_register_typed_name (name, type, 
212                                      (struct objc_selector*)&(selectors[i]),
213                                      YES);
214         }
215     }
216
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     {
221       Class class = (Class) symtab->defs[i];
222       const char* superclass = (char*)class->super_class;
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);
234       __objc_register_selectors_from_class ((Class) class->class_pointer);
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);
242
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);
247    }
248
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];
253       Class class = objc_lookup_class (category->class_name);
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)
269             class_add_method_list ((Class) class->class_pointer, 
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
278           if (_objc_load_callback)
279             _objc_load_callback(class, category);
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
289   if (statics)
290     uninitialized_statics = list_cons (statics, uninitialized_statics);
291   if (uninitialized_statics)
292     objc_init_statics ();
293
294   /* Scan the unclaimed category hash.  Attempt to attach any unclaimed
295      categories to objects.  */
296   for (cell = &unclaimed_categories;
297        *cell;
298        ({ if (*cell) cell = &(*cell)->tail; }))
299     {
300       Category_t category = (*cell)->head;
301       Class class = objc_lookup_class (category->class_name);
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)
314             class_add_method_list ((Class) class->class_pointer,
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           
323           if (_objc_load_callback)
324             _objc_load_callback(class, category);
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
335   objc_send_load ();
336
337   objc_mutex_unlock(__objc_runtime_mutex);
338 }
339
340 void 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
383 static 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
406 static 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
447 /* Sanity check the version of gcc used to compile `module'*/
448 static void init_check_module_version(Module_t module)
449 {
450   if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
451     {
452       int code;
453
454       if(module->version > OBJC_VERSION)
455         code = OBJC_ERR_OBJC_VERSION;
456       else if (module->version < OBJC_VERSION)
457         code = OBJC_ERR_GCC_VERSION;
458       else
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);
463     }
464 }
465
466 static void
467 __objc_init_protocols (struct objc_protocol_list* protos)
468 {
469   int i;
470   static Class proto_class = 0;
471
472   if (! protos)
473     return;
474
475   objc_mutex_lock(__objc_runtime_mutex);
476
477   if (!proto_class)
478     proto_class = objc_lookup_class("Protocol");
479
480   if (!proto_class)
481     {
482       unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
483       objc_mutex_unlock(__objc_runtime_mutex);
484       return;
485     }
486
487 #if 0
488   assert (protos->next == 0);   /* only single ones allowed */
489 #endif
490
491   for(i = 0; i < protos->count; i++)
492     {
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)
503         {
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);
508         }
509     }
510
511   objc_mutex_unlock(__objc_runtime_mutex);
512 }
513
514 static void __objc_class_add_protocols (Class class,
515                                         struct objc_protocol_list* protos)
516 {
517   /* Well... */
518   if (! protos)
519     return;
520
521   /* Add it... */
522   protos->next = class->protocols;
523   class->protocols = protos;
524 }