]> gcc.gnu.org Git - gcc.git/blame - gcc/objc/init.c
(objc_sizeof_type, objc_alignof_type): Replace call to abort function with call to...
[gcc.git] / gcc / objc / init.c
CommitLineData
c72fc2d9 1/* GNU Objective C Runtime initialization
aef85e6a 2 Copyright (C) 1993, 1995, 1996 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) */
4426bf3f 30#define OBJC_VERSION 7
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. */
43_objc_mutex_t __objc_runtime_mutex;
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
4426bf3f
RK
70/* Run through the statics list, removing modules as soon as all its statics
71 have been initialized. */
72static void
73objc_init_statics ()
74{
75 struct objc_list **cell = &uninitialized_statics;
76 struct objc_static_instances **statics_in_module;
77
aef85e6a
RK
78 objc_mutex_lock(__objc_runtime_mutex);
79
4426bf3f
RK
80 while (*cell)
81 {
82 int module_initialized = 1;
83
84 for (statics_in_module = (*cell)->head;
85 *statics_in_module; statics_in_module++)
86 {
87 struct objc_static_instances *statics = *statics_in_module;
df27f225 88 Class class = objc_lookup_class (statics->class_name);
4426bf3f
RK
89
90 if (!class)
91 module_initialized = 0;
92 /* Actually, the static's class_pointer will be NULL when we
93 haven't been here before. However, the comparison is to be
94 reminded of taking into account class posing and to think about
95 possible semantics... */
96 else if (class != statics->instances[0]->class_pointer)
97 {
98 id *inst;
99
100 for (inst = &statics->instances[0]; *inst; inst++)
101 {
102 (*inst)->class_pointer = class;
103
104 /* ??? Make sure the object will not be freed. With
105 refcounting, invoke `-retain'. Without refcounting, do
106 nothing and hope that `-free' will never be invoked. */
107
108 /* ??? Send the object an `-initStatic' or something to
109 that effect now or later on? What are the semantics of
110 statically allocated instances, besides the trivial
111 NXConstantString, anyway? */
112 }
113 }
114 }
115 if (module_initialized)
116 {
117 /* Remove this module from the uninitialized list. */
118 struct objc_list *this = *cell;
119 *cell = this->tail;
9d46282b 120 objc_free(this);
4426bf3f
RK
121 }
122 else
123 cell = &(*cell)->tail;
124 }
aef85e6a
RK
125
126 objc_mutex_unlock(__objc_runtime_mutex);
4426bf3f 127} /* objc_init_statics */
a39d31bc 128
c72fc2d9
TW
129/* This function is called by constructor functions generated for each
130 module compiled. (_GLOBAL_$I$...) The purpose of this function is to
131 gather the module pointers so that they may be processed by the
132 initialization routines as soon as possible */
133
134void
135__objc_exec_class (Module_t module)
136{
4426bf3f
RK
137 /* Have we processed any constructors previously? This flag is used to
138 indicate that some global data structures need to be built. */
c72fc2d9
TW
139 static BOOL previous_constructors = 0;
140
141 static struct objc_list* unclaimed_categories = 0;
142
4426bf3f 143 /* The symbol table (defined in objc-api.h) generated by gcc */
c72fc2d9
TW
144 Symtab_t symtab = module->symtab;
145
c72fc2d9
TW
146 /* Entry used to traverse hash lists */
147 struct objc_list** cell;
148
149 /* The table of selector references for this module */
a39d31bc 150 SEL selectors = symtab->refs;
c72fc2d9
TW
151
152 /* dummy counter */
153 int i;
154
155 DEBUG_PRINTF ("received module: %s\n", module->name);
4426bf3f 156
c72fc2d9
TW
157 /* check gcc version */
158 init_check_module_version(module);
159
160 /* On the first call of this routine, initialize some data structures. */
161 if (!previous_constructors)
162 {
aef85e6a
RK
163 /* Initialize thread-safe system */
164 __objc_init_thread_system();
165 __objc_runtime_threads_alive = 1;
166 __objc_runtime_mutex = objc_mutex_allocate();
167
c72fc2d9
TW
168 __objc_init_selector_tables();
169 __objc_init_class_tables();
170 __objc_init_dispatch_tables();
171 previous_constructors = 1;
172 }
173
174 /* Save the module pointer for later processing. (not currently used) */
aef85e6a 175 objc_mutex_lock(__objc_runtime_mutex);
c72fc2d9
TW
176 __objc_module_list = list_cons(module, __objc_module_list);
177
a39d31bc
KKT
178 /* Replace referenced selectors from names to SEL's. */
179 if (selectors)
180 {
181 for (i = 0; selectors[i].sel_id; ++i)
182 {
183 const char *name, *type;
184 name = (char*)selectors[i].sel_id;
185 type = (char*)selectors[i].sel_types;
018086d1
RK
186 /* Constructors are constant static data so we can safely store
187 pointers to them in the runtime structures. is_const == YES */
a39d31bc 188 __sel_register_typed_name (name, type,
018086d1
RK
189 (struct objc_selector*)&(selectors[i]),
190 YES);
a39d31bc
KKT
191 }
192 }
193
c72fc2d9
TW
194 /* Parse the classes in the load module and gather selector information. */
195 DEBUG_PRINTF ("gathering selectors from module: %s\n", module->name);
196 for (i = 0; i < symtab->cls_def_cnt; ++i)
197 {
4426bf3f 198 Class class = (Class) symtab->defs[i];
c72fc2d9
TW
199
200 /* Make sure we have what we think. */
201 assert (CLS_ISCLASS(class));
202 assert (CLS_ISMETA(class->class_pointer));
203 DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
204
205 /* Store the class in the class table and assign class numbers. */
206 __objc_add_class_to_hash (class);
207
208 /* Register all of the selectors in the class and meta class. */
209 __objc_register_selectors_from_class (class);
4426bf3f 210 __objc_register_selectors_from_class ((Class) class->class_pointer);
c72fc2d9
TW
211
212 /* Install the fake dispatch tables */
213 __objc_install_premature_dtable(class);
214 __objc_install_premature_dtable(class->class_pointer);
215
216 if (class->protocols)
217 __objc_init_protocols (class->protocols);
d8a55d09
RK
218
219 if (_objc_load_callback)
220 _objc_load_callback(class, 0);
c72fc2d9
TW
221 }
222
c72fc2d9
TW
223 /* Process category information from the module. */
224 for (i = 0; i < symtab->cat_def_cnt; ++i)
225 {
226 Category_t category = symtab->defs[i + symtab->cls_def_cnt];
4426bf3f 227 Class class = objc_lookup_class (category->class_name);
c72fc2d9
TW
228
229 /* If the class for the category exists then append its methods. */
230 if (class)
231 {
232
233 DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
234 module->name,
235 class->name);
236
237 /* Do instance methods. */
238 if (category->instance_methods)
239 class_add_method_list (class, category->instance_methods);
240
241 /* Do class methods. */
242 if (category->class_methods)
4426bf3f 243 class_add_method_list ((Class) class->class_pointer,
c72fc2d9
TW
244 category->class_methods);
245
246 if (category->protocols)
247 {
248 __objc_init_protocols (category->protocols);
249 __objc_class_add_protocols (class, category->protocols);
250 }
251
d8a55d09
RK
252 if (_objc_load_callback)
253 _objc_load_callback(class, category);
c72fc2d9
TW
254 }
255 else
256 {
257 /* The object to which the category methods belong can't be found.
258 Save the information. */
259 unclaimed_categories = list_cons(category, unclaimed_categories);
260 }
261 }
262
4426bf3f
RK
263 if (module->statics)
264 uninitialized_statics = list_cons (module->statics, uninitialized_statics);
265 if (uninitialized_statics)
266 objc_init_statics ();
267
c72fc2d9
TW
268 /* Scan the unclaimed category hash. Attempt to attach any unclaimed
269 categories to objects. */
270 for (cell = &unclaimed_categories;
271 *cell;
a39d31bc 272 ({ if (*cell) cell = &(*cell)->tail; }))
c72fc2d9
TW
273 {
274 Category_t category = (*cell)->head;
4426bf3f 275 Class class = objc_lookup_class (category->class_name);
c72fc2d9
TW
276
277 if (class)
278 {
279 DEBUG_PRINTF ("attaching stored categories to object: %s\n",
280 class->name);
281
282 list_remove_head (cell);
283
284 if (category->instance_methods)
285 class_add_method_list (class, category->instance_methods);
286
287 if (category->class_methods)
4426bf3f 288 class_add_method_list ((Class) class->class_pointer,
c72fc2d9
TW
289 category->class_methods);
290
291 if (category->protocols)
292 {
293 __objc_init_protocols (category->protocols);
294 __objc_class_add_protocols (class, category->protocols);
295 }
296
d8a55d09
RK
297 if (_objc_load_callback)
298 _objc_load_callback(class, category);
c72fc2d9
TW
299 }
300 }
301
302 if (unclaimed_proto_list && objc_lookup_class ("Protocol"))
303 {
304 list_mapcar (unclaimed_proto_list,(void(*)(void*))__objc_init_protocols);
305 list_free (unclaimed_proto_list);
306 unclaimed_proto_list = 0;
307 }
308
aef85e6a 309 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
310}
311
312/* Sanity check the version of gcc used to compile `module'*/
313static void init_check_module_version(Module_t module)
314{
315 if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
316 {
317 fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
a39d31bc 318 module->name, (int)module->version, OBJC_VERSION);
c72fc2d9
TW
319 if(module->version > OBJC_VERSION)
320 fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
321 else if (module->version < OBJC_VERSION)
322 fprintf (stderr, "Compiler (gcc) is out of date\n");
323 else
324 fprintf (stderr, "Objective C internal error -- bad Module size\n");
325 abort ();
326 }
327}
328
329static void
330__objc_init_protocols (struct objc_protocol_list* protos)
331{
332 int i;
4426bf3f 333 static Class proto_class = 0;
c72fc2d9
TW
334
335 if (! protos)
336 return;
337
aef85e6a
RK
338 objc_mutex_lock(__objc_runtime_mutex);
339
eba92c95
RS
340 if (!proto_class)
341 proto_class = objc_lookup_class("Protocol");
c72fc2d9 342
eba92c95 343 if (!proto_class)
c72fc2d9
TW
344 {
345 unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
8c55cd78 346 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
347 return;
348 }
349
2acb0388 350#if 0
c72fc2d9 351 assert (protos->next == 0); /* only single ones allowed */
2acb0388 352#endif
c72fc2d9
TW
353
354 for(i = 0; i < protos->count; i++)
355 {
eba92c95
RS
356 struct objc_protocol* aProto = protos->list[i];
357 if (((size_t)aProto->class_pointer) == PROTOCOL_VERSION)
358 {
359 /* assign class pointer */
360 aProto->class_pointer = proto_class;
361
362 /* init super protocols */
363 __objc_init_protocols (aProto->protocol_list);
364 }
365 else if (protos->list[i]->class_pointer != proto_class)
c72fc2d9
TW
366 {
367 fprintf (stderr,
0046ffa3 368 "Version %d doesn't match runtime protocol version %d\n",
a39d31bc 369 (int)((char*)protos->list[i]->class_pointer-(char*)0),
c72fc2d9
TW
370 PROTOCOL_VERSION);
371 abort ();
372 }
373 }
aef85e6a
RK
374
375 objc_mutex_unlock(__objc_runtime_mutex);
c72fc2d9
TW
376}
377
4426bf3f 378static void __objc_class_add_protocols (Class class,
c72fc2d9
TW
379 struct objc_protocol_list* protos)
380{
c72fc2d9
TW
381 /* Well... */
382 if (! protos)
383 return;
384
385 /* Add it... */
386 protos->next = class->protocols;
387 class->protocols = protos;
388}
This page took 0.309489 seconds and 5 git commands to generate.