]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/objc/objc-next-runtime-abi-01.c
* output.h (__gcc_host_wide_int__): Move to hwint.h.
[thirdparty/gcc.git] / gcc / objc / objc-next-runtime-abi-01.c
1 /* Next Runtime (ABI-0/1) private.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Iain Sandoe (split from objc-act.c)
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 /* This implements the original NeXT ABI (0) used for m32 code and
22 indicated by module version 6. It also implements the small number
23 of additions made for properties and optional protocol methods as
24 ABI=1 (module version 7). */
25
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "tm.h"
30 #include "tree.h"
31
32 #ifdef OBJCPLUS
33 #include "cp-tree.h"
34 #else
35 #include "c-tree.h"
36 #include "c-lang.h"
37 #endif
38 #include "langhooks.h"
39 #include "c-family/c-objc.h"
40 #include "objc-act.h"
41
42 /* When building Objective-C++, we are not linking against the C
43 front-end and so need to replicate the C tree-construction
44 functions in some way. */
45 #ifdef OBJCPLUS
46 #define OBJCP_REMAP_FUNCTIONS
47 #include "objcp-decl.h"
48 #endif /* OBJCPLUS */
49
50 #include "ggc.h"
51 #include "target.h"
52 #include "output.h" /* for asm_out_file */
53 #include "tree-iterator.h"
54
55 #include "objc-runtime-hooks.h"
56 #include "objc-runtime-shared-support.h"
57 #include "objc-encoding.h"
58
59 /* NeXT ABI 0 and 1 private definitions. */
60 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
61
62 #define TAG_GETCLASS "objc_getClass"
63 #define TAG_GETMETACLASS "objc_getMetaClass"
64
65 #define TAG_MSGSEND "objc_msgSend"
66 #define TAG_MSGSENDSUPER "objc_msgSendSuper"
67 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
68 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret"
69
70 /* NeXT-specific tags. */
71
72 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil"
73 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret"
74 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract"
75 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter"
76 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit"
77 #define TAG_EXCEPTIONMATCH "objc_exception_match"
78 #define TAG_SETJMP "_setjmp"
79
80 #define TAG_ASSIGNIVAR "objc_assign_ivar"
81 #define TAG_ASSIGNGLOBAL "objc_assign_global"
82 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast"
83
84 /* Branch entry points. All that matters here are the addresses;
85 functions with these names do not really exist in libobjc. */
86
87 #define TAG_MSGSEND_FAST "objc_msgSend_Fast"
88 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast"
89
90 /* The version identifies which language generation and runtime the
91 module (file) was compiled for, and is recorded in the module
92 descriptor. */
93 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6)
94
95 #define UTAG_CLASS_EXT "_objc_class_ext"
96 #define UTAG_PROPERTY_LIST "_prop_list_t"
97 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension"
98
99 #define CLS_HAS_CXX_STRUCTORS 0x2000L
100
101 /* rt_trees identifiers - shared between NeXT implementations. These
102 allow the FE to tag meta-data in a manner that survives LTO and can
103 be used when the runtime requires that certain meta-data items
104 appear in particular named sections. */
105
106 #include "objc-next-metadata-tags.h"
107 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX];
108
109 static void next_runtime_01_initialize (void);
110
111 static tree next_runtime_abi_01_super_superclassfield_id (void);
112
113 static tree next_runtime_abi_01_class_decl (tree);
114 static tree next_runtime_abi_01_metaclass_decl (tree);
115 static tree next_runtime_abi_01_category_decl (tree);
116 static tree next_runtime_abi_01_protocol_decl (tree);
117 static tree next_runtime_abi_01_string_decl (tree, const char *, string_section);
118
119 static tree next_runtime_abi_01_get_class_reference (tree);
120 static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree);
121 static tree next_runtime_abi_01_get_protocol_reference (location_t, tree);
122 static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree);
123 static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool);
124 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool);
125
126 static tree next_runtime_abi_01_receiver_is_class_object (tree);
127 static void next_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **, tree,
128 int, int);
129 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree,
130 tree, tree, tree, int);
131 static bool next_runtime_abi_01_setup_const_string_class_decl (void);
132 static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int);
133
134 static void objc_generate_v1_next_metadata (void);
135
136 static void build_next_objc_exception_stuff (void);
137 static tree objc_eh_runtime_type (tree type);
138 static tree objc_eh_personality (void);
139 static tree build_throw_stmt (location_t, tree, bool);
140 static tree objc_build_exc_ptr (struct objc_try_context **);
141 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
142 static void finish_catch (struct objc_try_context **, tree);
143 static tree finish_try_stmt (struct objc_try_context **);
144
145 bool
146 objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
147 {
148 if (flag_objc_exceptions
149 && !flag_objc_sjlj_exceptions)
150 {
151 warning_at (UNKNOWN_LOCATION, OPT_Wall,
152 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
153 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
154 }
155
156 rthooks->initialize = next_runtime_01_initialize;
157 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
158 rthooks->tag_getclass = TAG_GETCLASS;
159 rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id;
160
161 rthooks->class_decl = next_runtime_abi_01_class_decl;
162 rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl;
163 rthooks->category_decl = next_runtime_abi_01_category_decl;
164 rthooks->protocol_decl = next_runtime_abi_01_protocol_decl;
165 rthooks->string_decl = next_runtime_abi_01_string_decl;
166
167 rthooks->get_class_reference = next_runtime_abi_01_get_class_reference;
168 rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference;
169 rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference;
170 rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref;
171 rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref;
172 rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref;
173
174 rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object;
175 rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base;
176 rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call;
177
178 rthooks->setup_const_string_class_decl =
179 next_runtime_abi_01_setup_const_string_class_decl;
180 rthooks->build_const_string_constructor =
181 next_runtime_abi_01_build_const_string_constructor;
182
183 rthooks->build_throw_stmt = build_throw_stmt;
184 rthooks->build_exc_ptr = objc_build_exc_ptr;
185 rthooks->begin_catch = begin_catch;
186 rthooks->finish_catch = finish_catch;
187 rthooks->finish_try_stmt = finish_try_stmt;
188
189 rthooks->generate_metadata = objc_generate_v1_next_metadata;
190 return true;
191 }
192
193 /* We need a way to convey what kind of meta-data are represented by a
194 given variable, since each type is expected (by the runtime) to be
195 found in a specific named section. The solution must be usable
196 with LTO.
197
198 The scheme used for NeXT ABI 0/1 (partial matching of variable
199 names) is not satisfactory for LTO & ABI-2. We now tag ObjC
200 meta-data with identification attributes in the front end. The
201 back-end may choose to act on these as it requires. */
202
203 static void
204 next_runtime_abi_01_init_metadata_attributes (void)
205 {
206 if (!objc_meta)
207 objc_meta = get_identifier ("OBJC1META");
208
209 if (!meta_base)
210 meta_base = get_identifier ("V1_BASE");
211
212 meta_class = get_identifier ("V1_CLAS");
213 meta_metaclass = get_identifier ("V1_META");
214 meta_category = get_identifier ("V1_CATG");
215 meta_protocol = get_identifier ("V1_PROT");
216
217 meta_clac_vars = get_identifier ("V1_CLCV");
218 meta_clai_vars = get_identifier ("V1_CLIV");
219
220 meta_clac_meth = get_identifier ("V1_CLCM");
221 meta_clai_meth = get_identifier ("V1_CLIM");
222 meta_catc_meth = get_identifier ("V1_CACM");
223 meta_cati_meth = get_identifier ("V1_CAIM");
224 meta_proto_cls_meth = get_identifier ("V1_PCLM");
225 meta_proto_nst_meth = get_identifier ("V1_PNSM");
226
227 meta_clas_prot = get_identifier ("V1_CLPR");
228 meta_catg_prot = get_identifier ("V1_CAPR");
229
230 meta_class_reference = get_identifier ("V1_CLRF");
231 meta_proto_ref = get_identifier ("V1_PRFS");
232 meta_sel_refs = get_identifier ("V1_SRFS");
233
234 meta_class_name = get_identifier ("V1_CLSN");
235 meta_meth_name = get_identifier ("V1_METN");
236 meta_meth_type = get_identifier ("V1_METT");
237 meta_prop_name_attr = get_identifier ("V1_STRG");
238
239 meta_modules = get_identifier ("V1_MODU");
240 meta_symtab = get_identifier ("V1_SYMT");
241 meta_info = get_identifier ("V1_INFO");
242
243 meta_proplist = get_identifier ("V1_PLST");
244 meta_protocol_extension = get_identifier ("V1_PEXT");
245 meta_class_extension = get_identifier ("V1_CEXT");
246
247 meta_const_str = get_identifier ("V1_CSTR");
248 }
249
250 static void build_v1_class_template (void);
251 static void build_v1_category_template (void);
252 static void build_v1_protocol_template (void);
253
254 static void next_runtime_01_initialize (void)
255 {
256 tree type;
257
258 #ifdef OBJCPLUS
259 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
260 default. */
261 if (!global_options_set.x_flag_objc_call_cxx_cdtors)
262 global_options.x_flag_objc_call_cxx_cdtors = 1;
263 #endif
264
265 /* Set up attributes to be attached to the meta-data so that they
266 will be placed in the correct sections. */
267 next_runtime_abi_01_init_metadata_attributes ();
268
269 if (flag_objc_abi >= 1)
270 objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE,
271 get_identifier ("_prop_list_t")));
272
273 /* Declare type of selector-objects that represent an operation
274 name. */
275 /* `struct objc_selector *' */
276 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
277 get_identifier (TAG_SELECTOR)));
278
279 build_v1_class_template ();
280 build_super_template ();
281 build_v1_protocol_template ();
282 build_v1_category_template ();
283
284 /* NB: In order to call one of the ..._stret (struct-returning)
285 functions, the function *MUST* first be cast to a signature that
286 corresponds to the actual ObjC method being invoked. This is
287 what is done by the build_objc_method_call() routine below. */
288
289 /* id objc_msgSend (id, SEL, ...); */
290 /* id objc_msgSendNonNil (id, SEL, ...); */
291 /* id objc_msgSend_stret (id, SEL, ...); */
292 /* id objc_msgSendNonNil_stret (id, SEL, ...); */
293 type = build_varargs_function_type_list (objc_object_type,
294 objc_object_type,
295 objc_selector_type,
296 NULL_TREE);
297
298 umsg_decl = add_builtin_function (TAG_MSGSEND,
299 type, 0, NOT_BUILT_IN,
300 NULL, NULL_TREE);
301
302 umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL,
303 type, 0, NOT_BUILT_IN,
304 NULL, NULL_TREE);
305
306 umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET,
307 type, 0, NOT_BUILT_IN,
308 NULL, NULL_TREE);
309
310 umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET,
311 type, 0, NOT_BUILT_IN,
312 NULL, NULL_TREE);
313
314 /* These can throw, because the function that gets called can throw
315 in Obj-C++, or could itself call something that can throw even in
316 Obj-C. */
317 TREE_NOTHROW (umsg_decl) = 0;
318 TREE_NOTHROW (umsg_nonnil_decl) = 0;
319 TREE_NOTHROW (umsg_stret_decl) = 0;
320 TREE_NOTHROW (umsg_nonnil_stret_decl) = 0;
321
322 /* id objc_msgSend_Fast (id, SEL, ...)
323 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */
324 #ifdef OFFS_MSGSEND_FAST
325 umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST,
326 type, 0, NOT_BUILT_IN,
327 NULL, NULL_TREE);
328 TREE_NOTHROW (umsg_fast_decl) = 0;
329 DECL_ATTRIBUTES (umsg_fast_decl)
330 = tree_cons (get_identifier ("hard_coded_address"),
331 build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST),
332 NULL_TREE);
333 #else
334 /* No direct dispatch available. */
335 umsg_fast_decl = umsg_decl;
336 #endif
337
338 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */
339 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */
340 type = build_varargs_function_type_list (objc_object_type,
341 objc_super_type,
342 objc_selector_type,
343 NULL_TREE);
344 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER,
345 type, 0, NOT_BUILT_IN,
346 NULL, NULL_TREE);
347 umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET,
348 type, 0, NOT_BUILT_IN, 0,
349 NULL_TREE);
350 TREE_NOTHROW (umsg_super_decl) = 0;
351 TREE_NOTHROW (umsg_super_stret_decl) = 0;
352
353 type = build_function_type_list (objc_object_type,
354 const_string_type_node,
355 NULL_TREE);
356
357 /* id objc_getClass (const char *); */
358 objc_get_class_decl
359 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN,
360 NULL, NULL_TREE);
361
362 /* id objc_getMetaClass (const char *); */
363 objc_get_meta_class_decl
364 = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
365
366 /* This is the type of all of the following functions
367 objc_copyStruct(). */
368 type = build_function_type_list (void_type_node,
369 ptr_type_node,
370 const_ptr_type_node,
371 ptrdiff_type_node,
372 boolean_type_node,
373 boolean_type_node,
374 NULL_TREE);
375 /* Declare the following function:
376 void
377 objc_copyStruct (void *destination, const void *source,
378 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
379 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
380 type, 0, NOT_BUILT_IN,
381 NULL, NULL_TREE);
382 TREE_NOTHROW (objc_copyStruct_decl) = 0;
383 objc_getPropertyStruct_decl = NULL_TREE;
384 objc_setPropertyStruct_decl = NULL_TREE;
385
386 build_next_objc_exception_stuff ();
387 if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
388 using_eh_for_cleanups ();
389 lang_hooks.eh_runtime_type = objc_eh_runtime_type;
390 lang_hooks.eh_personality = objc_eh_personality;
391 }
392
393 /* --- templates --- */
394
395 /* struct _objc_class
396 {
397 struct _objc_class *isa;
398 struct _objc_class *super_class;
399 char *name;
400 long version;
401 long info;
402 long instance_size;
403 struct _objc_ivar_list *ivars;
404 struct _objc_method_list *methods;
405 struct objc_cache *cache;
406 struct _objc_protocol_list *protocols;
407 #if ABI=1
408 const char *ivar_layout;
409 struct _objc_class_ext *ext;
410 #else
411 void *sel_id;
412 void *gc_object_type;
413 #endif
414 }; */
415
416 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT
417 runtime. We generate them for ABI==0 to maintain backward binary
418 compatibility. */
419
420 static void
421 build_v1_class_template (void)
422 {
423 tree ptype, decls, *chain = NULL;
424
425 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS));
426
427 /* struct _objc_class *isa; */
428 decls = add_field_decl (build_pointer_type (objc_class_template),
429 "isa", &chain);
430
431 /* struct _objc_class *super_class; */
432 add_field_decl (build_pointer_type (objc_class_template),
433 "super_class", &chain);
434
435 /* char *name; */
436 add_field_decl (string_type_node, "name", &chain);
437
438 /* long version; */
439 add_field_decl (long_integer_type_node, "version", &chain);
440
441 /* long info; */
442 add_field_decl (long_integer_type_node, "info", &chain);
443
444 /* long instance_size; */
445 add_field_decl (long_integer_type_node, "instance_size", &chain);
446
447 /* struct _objc_ivar_list *ivars; */
448 add_field_decl (objc_ivar_list_ptr,"ivars", &chain);
449
450 /* struct _objc_method_list *methods; */
451 add_field_decl (objc_method_list_ptr, "methods", &chain);
452
453 /* struct objc_cache *cache; */
454 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
455 get_identifier ("objc_cache")));
456 add_field_decl (ptype, "cache", &chain);
457
458 /* struct _objc_protocol **protocol_list; */
459 ptype = build_pointer_type (build_pointer_type
460 (xref_tag (RECORD_TYPE,
461 get_identifier (UTAG_PROTOCOL))));
462 add_field_decl (ptype, "protocol_list", &chain);
463
464 if (flag_objc_abi >= 1)
465 {
466 /* const char *ivar_layout; */
467 add_field_decl (const_string_type_node, "ivar_layout", &chain);
468
469 /* struct _objc_class_ext *ext; */
470 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
471 get_identifier (UTAG_CLASS_EXT)));
472 add_field_decl (ptype, "ext", &chain);
473 }
474 else
475 {
476 /* void *sel_id; */
477 add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain);
478 /* void *gc_object_type; */
479 add_field_decl (build_pointer_type (void_type_node), "gc_object_type",
480 &chain);
481 }
482
483 objc_finish_struct (objc_class_template, decls);
484 }
485
486 /* struct _objc_category
487 {
488 char *category_name;
489 char *class_name;
490 struct _objc_method_list *instance_methods;
491 struct _objc_method_list *class_methods;
492 struct _objc_protocol_list *protocols;
493 #if ABI=1
494 uint32_t size; // sizeof (struct _objc_category)
495 struct _objc_property_list *instance_properties; // category's own @property decl.
496 #endif
497 }; */
498
499 static void
500 build_v1_category_template (void)
501 {
502 tree ptype, decls, *chain = NULL;
503
504 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY));
505
506 /* char *category_name; */
507 decls = add_field_decl (string_type_node, "category_name", &chain);
508
509 /* char *class_name; */
510 add_field_decl (string_type_node, "class_name", &chain);
511
512 /* struct _objc_method_list *instance_methods; */
513 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
514
515 /* struct _objc_method_list *class_methods; */
516 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
517
518 /* struct _objc_protocol **protocol_list; */
519 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
520 add_field_decl (ptype, "protocol_list", &chain);
521
522 if (flag_objc_abi >= 1)
523 {
524 add_field_decl (integer_type_node, "size", &chain);
525
526 /* struct _objc_property_list *instance_properties;
527 This field describes a category's @property declarations.
528 Properties from inherited protocols are not included. */
529 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
530 get_identifier (UTAG_PROPERTY_LIST)));
531 add_field_decl (ptype, "instance_properties", &chain);
532 }
533 objc_finish_struct (objc_category_template, decls);
534 }
535
536 /* Begin code generation for protocols...
537 Modified for ObjC #1 extensions. */
538
539 /* struct _objc_protocol
540 {
541 #if ABI=1
542 struct _objc_protocol_extension *isa;
543 #else
544 struct _objc_class *isa;
545 #endif
546
547 char *protocol_name;
548 struct _objc_protocol **protocol_list;
549 struct _objc__method_prototype_list *instance_methods;
550 struct _objc__method_prototype_list *class_methods;
551 }; */
552
553 static void
554 build_v1_protocol_template (void)
555 {
556 tree ptype, decls, *chain = NULL;
557
558 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL));
559
560 if (flag_objc_abi >= 1)
561 /* struct _objc_protocol_extension *isa; */
562 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
563 get_identifier (UTAG_PROTOCOL_EXT)));
564 else
565 /* struct _objc_class *isa; */
566 ptype = build_pointer_type (xref_tag (RECORD_TYPE,
567 get_identifier (UTAG_CLASS)));
568
569 decls = add_field_decl (ptype, "isa", &chain);
570
571 /* char *protocol_name; */
572 add_field_decl (string_type_node, "protocol_name", &chain);
573
574 /* struct _objc_protocol **protocol_list; */
575 ptype = build_pointer_type (build_pointer_type (objc_protocol_template));
576 add_field_decl (ptype, "protocol_list", &chain);
577
578 /* struct _objc__method_prototype_list *instance_methods; */
579 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
580
581 /* struct _objc__method_prototype_list *class_methods; */
582 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
583
584 objc_finish_struct (objc_protocol_template, decls);
585 }
586
587 /* --- names, decls identifers --- */
588
589 static tree
590 next_runtime_abi_01_super_superclassfield_id (void)
591 {
592 if (!super_superclassfield_id)
593 super_superclassfield_id = get_identifier ("super_class");
594 return super_superclassfield_id;
595 }
596
597 static tree
598 next_runtime_abi_01_class_decl (tree klass)
599 {
600 tree decl;
601 char buf[BUFSIZE];
602 snprintf (buf, BUFSIZE, "_OBJC_Class_%s",
603 IDENTIFIER_POINTER (CLASS_NAME (klass)));
604 decl = start_var_decl (objc_class_template, buf);
605 OBJCMETA (decl, objc_meta, meta_class);
606 return decl;
607 }
608
609 static tree
610 next_runtime_abi_01_metaclass_decl (tree klass)
611 {
612 tree decl;
613 char buf[BUFSIZE];
614 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s",
615 IDENTIFIER_POINTER (CLASS_NAME (klass)));
616 decl = start_var_decl (objc_class_template, buf);
617 OBJCMETA (decl, objc_meta, meta_metaclass);
618 return decl;
619 }
620
621 static tree
622 next_runtime_abi_01_category_decl (tree klass)
623 {
624 tree decl;
625 char buf[BUFSIZE];
626 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s",
627 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)),
628 IDENTIFIER_POINTER (CLASS_NAME (klass)));
629 decl = start_var_decl (objc_category_template, buf);
630 OBJCMETA (decl, objc_meta, meta_category);
631 return decl;
632 }
633
634 static tree
635 next_runtime_abi_01_protocol_decl (tree p)
636 {
637 tree decl;
638 char buf[BUFSIZE];
639
640 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
641
642 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
643 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
644 decl = start_var_decl (objc_protocol_template, buf);
645 OBJCMETA (decl, objc_meta, meta_protocol);
646 return decl;
647 }
648
649 static tree
650 next_runtime_abi_01_string_decl (tree type, const char *name, string_section where)
651 {
652 tree var = start_var_decl (type, name);
653 switch (where)
654 {
655 case class_names:
656 OBJCMETA (var, objc_meta, meta_class_name);
657 break;
658 case meth_var_names:
659 OBJCMETA (var, objc_meta, meta_meth_name);
660 break;
661 case meth_var_types:
662 OBJCMETA (var, objc_meta, meta_meth_type);
663 break;
664 case prop_names_attr:
665 OBJCMETA (var, objc_meta, meta_prop_name_attr);
666 break;
667 default:
668 OBJCMETA (var, objc_meta, meta_base);
669 break;
670 }
671 return var;
672 }
673
674 /* --- entry --- */
675
676 static GTY(()) int class_reference_idx;
677
678 static tree
679 build_class_reference_decl (void)
680 {
681 tree decl;
682 char buf[BUFSIZE];
683
684 sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++);
685 decl = start_var_decl (objc_class_type, buf);
686
687 return decl;
688 }
689
690 static tree
691 next_runtime_abi_01_get_class_reference (tree ident)
692 {
693 if (!flag_zero_link)
694 {
695 tree *chain;
696 tree decl;
697
698 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain))
699 if (TREE_VALUE (*chain) == ident)
700 {
701 if (! TREE_PURPOSE (*chain))
702 TREE_PURPOSE (*chain) = build_class_reference_decl ();
703
704 return TREE_PURPOSE (*chain);
705 }
706
707 decl = build_class_reference_decl ();
708 *chain = tree_cons (decl, ident, NULL_TREE);
709 return decl;
710 }
711 else
712 {
713 tree params;
714
715 add_class_reference (ident);
716
717 params = build_tree_list (NULL_TREE,
718 my_build_string_pointer
719 (IDENTIFIER_LENGTH (ident) + 1,
720 IDENTIFIER_POINTER (ident)));
721
722 return build_function_call (input_location, objc_get_class_decl, params);
723 }
724 }
725
726 /* Used by build_function_type_for_method. Append the types for
727 receiver & _cmd at the start of a method argument list to ARGTYPES.
728 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
729 trying to define a method or call one. SUPERFLAG says this is for a
730 send to super. METH may be NULL, in the case that there is no
731 prototype. */
732
733 static void
734 next_runtime_abi_01_get_arg_type_list_base (VEC(tree,gc) **argtypes, tree meth,
735 int context, int superflag)
736 {
737 tree receiver_type;
738
739 if (superflag)
740 receiver_type = objc_super_type;
741 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
742 receiver_type = objc_instance_type;
743 else
744 receiver_type = objc_object_type;
745
746 VEC_safe_push (tree, gc, *argtypes, receiver_type);
747 /* Selector type - will eventually change to `int'. */
748 VEC_safe_push (tree, gc, *argtypes, objc_selector_type);
749 }
750
751 static tree
752 next_runtime_abi_01_receiver_is_class_object (tree receiver)
753 {
754 if (TREE_CODE (receiver) == VAR_DECL
755 && IS_CLASS (TREE_TYPE (receiver)))
756 {
757 /* The receiver is a variable created by build_class_reference_decl. */
758 tree chain = cls_ref_chain ;
759 /* Look up the identifier in the relevant chain. */
760 for (; chain; chain = TREE_CHAIN (chain))
761 if (TREE_PURPOSE (chain) == receiver)
762 return TREE_VALUE (chain);
763 }
764 return NULL_TREE;
765 }
766
767 static tree
768 build_selector_reference_decl (tree ident)
769 {
770 tree decl;
771 char *t, buf[BUFSIZE];
772
773 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
774 t = buf;
775 while (*t)
776 {
777 if (*t==':')
778 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
779 t++;
780 }
781 decl = start_var_decl (objc_selector_type, buf);
782 OBJCMETA (decl, objc_meta, meta_sel_refs);
783 return decl;
784 }
785
786 static tree
787 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
788 tree ident,
789 tree proto ATTRIBUTE_UNUSED)
790 {
791 tree *chain = &sel_ref_chain;
792 tree expr;
793
794 while (*chain)
795 {
796 if (TREE_VALUE (*chain) == ident)
797 return TREE_PURPOSE (*chain);
798
799 chain = &TREE_CHAIN (*chain);
800 }
801
802 expr = build_selector_reference_decl (ident);
803
804 *chain = tree_cons (expr, ident, NULL_TREE);
805
806 return expr;
807 }
808
809 /* Build a tree expression to send OBJECT the operation SELECTOR,
810 looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
811 assuming the method has prototype METHOD_PROTOTYPE.
812 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
813 LOC is the location of the expression to build.
814 Use METHOD_PARAMS as list of args to pass to the method.
815 If SUPER_FLAG is nonzero, we look up the superclass's method. */
816
817 static tree
818 build_objc_method_call (location_t loc, int super_flag, tree method_prototype,
819 tree lookup_object, tree selector,
820 tree method_params)
821 {
822 tree sender, sender_cast, method, t;
823 tree rcv_p = (super_flag ? objc_super_type : objc_object_type);
824 VEC(tree, gc) *parms;
825 unsigned nparm = (method_params ? list_length (method_params) : 0);
826
827 /* If a prototype for the method to be called exists, then cast
828 the sender's return type and arguments to match that of the method.
829 Otherwise, leave sender as is. */
830 tree ret_type
831 = (method_prototype
832 ? TREE_VALUE (TREE_TYPE (method_prototype))
833 : objc_object_type);
834 tree ftype = build_function_type_for_method (ret_type, method_prototype,
835 METHOD_REF, super_flag);
836
837 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
838 ftype = build_type_attribute_variant (ftype,
839 METHOD_TYPE_ATTRIBUTES
840 (method_prototype));
841
842 sender_cast = build_pointer_type (ftype);
843
844 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
845
846 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
847 lookup_object = save_expr (lookup_object);
848
849 /* Param list + 2 slots for object and selector. */
850 parms = VEC_alloc (tree, gc, nparm + 2);
851
852 /* If we are returning a struct in memory, and the address
853 of that memory location is passed as a hidden first
854 argument, then change which messenger entry point this
855 expr will call. NB: Note that sender_cast remains
856 unchanged (it already has a struct return type). */
857 if (!targetm.calls.struct_value_rtx (0, 0)
858 && (TREE_CODE (ret_type) == RECORD_TYPE
859 || TREE_CODE (ret_type) == UNION_TYPE)
860 && targetm.calls.return_in_memory (ret_type, 0))
861 sender = (super_flag ? umsg_super_stret_decl
862 : flag_nil_receivers ? umsg_stret_decl
863 : umsg_nonnil_stret_decl);
864 else
865 sender = (super_flag ? umsg_super_decl
866 : (flag_nil_receivers ? (flag_objc_direct_dispatch
867 ? umsg_fast_decl
868 : umsg_decl)
869 : umsg_nonnil_decl));
870 method = build_fold_addr_expr_loc (loc, sender);
871
872 /* Pass the object to the method. */
873 VEC_quick_push (tree, parms, lookup_object);
874 /* Pass the selector to the method. */
875 VEC_quick_push (tree, parms, selector);
876 /* Now append the remainder of the parms. */
877 if (nparm)
878 for (; method_params; method_params = TREE_CHAIN (method_params))
879 VEC_quick_push (tree, parms, TREE_VALUE (method_params));
880
881 /* Build an obj_type_ref, with the correct cast for the method call. */
882 t = build3 (OBJ_TYPE_REF, sender_cast, method,
883 lookup_object, size_zero_node);
884 t = build_function_call_vec (loc, t, parms, NULL);
885 VEC_free (tree, gc, parms);
886 return t;
887 }
888
889 static tree
890 next_runtime_abi_01_build_objc_method_call (location_t loc,
891 tree method_prototype,
892 tree receiver,
893 tree rtype ATTRIBUTE_UNUSED,
894 tree sel_name,
895 tree method_params,
896 int super)
897 {
898 tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name,
899 NULL_TREE);
900
901 return build_objc_method_call (loc, super, method_prototype,
902 receiver, selector, method_params);
903 }
904
905 static tree
906 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p)
907 {
908 tree expr;
909
910 if (!PROTOCOL_FORWARD_DECL (p))
911 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p);
912
913 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0);
914 return convert (objc_protocol_type, expr);
915 }
916
917 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */
918
919 static tree
920 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
921 tree base, tree id)
922 {
923 return objc_build_component_ref (base, id);
924 }
925
926 /* We build super class references as we need them (but keep them once
927 built for the sake of efficiency). */
928
929 static tree
930 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
931 struct imp_entry *imp, bool inst_meth)
932 {
933 if (inst_meth)
934 {
935 if (!ucls_super_ref)
936 ucls_super_ref =
937 objc_build_component_ref (imp->class_decl,
938 get_identifier ("super_class"));
939 return ucls_super_ref;
940 }
941 else
942 {
943 if (!uucls_super_ref)
944 uucls_super_ref =
945 objc_build_component_ref (imp->meta_decl,
946 get_identifier ("super_class"));
947 return uucls_super_ref;
948 }
949 }
950
951 static tree
952 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
953 struct imp_entry *imp, bool inst_meth)
954 {
955 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
956 tree super_class;
957
958 if (!flag_zero_link)
959 {
960 super_class = objc_get_class_reference (super_name);
961
962 if (!inst_meth)
963
964 /* If we are in a class method, we must retrieve the
965 _metaclass_ for the current class, pointed at by
966 the class's "isa" pointer. The following assumes that
967 "isa" is the first ivar in a class (which it must be). */
968 super_class =
969 build_indirect_ref (input_location,
970 build_c_cast (input_location,
971 build_pointer_type (objc_class_type),
972 super_class),
973 RO_UNARY_STAR);
974 return super_class;
975 }
976
977 /* else do it the slow way. */
978 add_class_reference (super_name);
979 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl);
980 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
981 IDENTIFIER_POINTER (super_name));
982 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
983 return build_function_call (input_location,
984 super_class,
985 build_tree_list (NULL_TREE, super_name));
986 }
987
988 static bool
989 next_runtime_abi_01_setup_const_string_class_decl (void)
990 {
991 if (!constant_string_global_id)
992 {
993 /* Hopefully, this should not represent a serious limitation. */
994 char buf[BUFSIZE];
995 snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name);
996 constant_string_global_id = get_identifier (buf);
997 }
998
999 string_class_decl = lookup_name (constant_string_global_id);
1000
1001 return (string_class_decl != NULL_TREE);
1002 }
1003
1004 static tree
1005 next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string,
1006 int length)
1007 {
1008 tree constructor, fields, var;
1009 VEC(constructor_elt,gc) *v = NULL;
1010
1011 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1012 fields = TYPE_FIELDS (internal_const_str_type);
1013 CONSTRUCTOR_APPEND_ELT (v, fields,
1014 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1015
1016 fields = DECL_CHAIN (fields);
1017 CONSTRUCTOR_APPEND_ELT (v, fields,
1018 build_unary_op (loc, ADDR_EXPR, string, 1));
1019
1020 /* ??? check if this should be long. */
1021 fields = DECL_CHAIN (fields);
1022 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1023 constructor = objc_build_constructor (internal_const_str_type, v);
1024
1025 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1026 DECL_INITIAL (var) = constructor;
1027 TREE_STATIC (var) = 1;
1028 DECL_CONTEXT (var) = NULL;
1029 OBJCMETA (var, objc_meta, meta_const_str);
1030 return var;
1031 }
1032
1033 /* --- metadata templates --- */
1034
1035 /* This routine builds the following type:
1036 struct _prop_t {
1037 const char * const name; // property name
1038 const char * const attributes; // comma-delimited, encoded,
1039 // property attributes
1040 };
1041 */
1042
1043 static GTY(()) tree objc_v1_property_template;
1044
1045 static tree
1046 build_v1_property_template (void)
1047 {
1048 tree prop_record;
1049 tree decls, *chain = NULL;
1050
1051 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1052 /* const char * name */
1053 decls = add_field_decl (string_type_node, "name", &chain);
1054
1055 /* const char * attribute */
1056 add_field_decl (string_type_node, "attribute", &chain);
1057
1058 objc_finish_struct (prop_record, decls);
1059 return prop_record;
1060 }
1061
1062 /* Build the following type:
1063
1064 struct _objc_protocol_extension
1065 {
1066 uint32_t size; // sizeof (struct _objc_protocol_extension)
1067 struct objc_method_list *optional_instance_methods;
1068 struct objc_method_list *optional_class_methods;
1069 struct objc_prop_list *instance_properties;
1070 }
1071 */
1072
1073 static GTY(()) tree objc_protocol_extension_template;
1074
1075 static void
1076 build_v1_objc_protocol_extension_template (void)
1077 {
1078 tree decls, *chain = NULL;
1079
1080 objc_protocol_extension_template =
1081 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT));
1082
1083 /* uint32_t size; */
1084 decls = add_field_decl (integer_type_node, "size", &chain);
1085
1086 /* struct objc_method_list *optional_instance_methods; */
1087 add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain);
1088
1089 /* struct objc_method_list *optional_class_methods; */
1090 add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain);
1091
1092 /* struct objc_prop_list *instance_properties; */
1093 add_field_decl (objc_prop_list_ptr, "instance_properties", &chain);
1094
1095 objc_finish_struct (objc_protocol_extension_template, decls);
1096 }
1097
1098 /* This routine build following struct type:
1099 struct _objc_class_ext
1100 {
1101 uint32_t size; // sizeof(struct _objc_class_ext)
1102 const char *weak_ivar_layout;
1103 struct _prop_list_t *properties;
1104 }
1105 */
1106
1107 static GTY(()) tree objc_class_ext_template;
1108
1109 static void
1110 build_objc_class_ext_template (void)
1111 {
1112 tree ptrt, decls, *chain = NULL;
1113
1114 objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT));
1115
1116 /* uint32_t size; */
1117 decls = add_field_decl (integer_type_node, "size", &chain);
1118
1119 /* const char *weak_ivar_layout; */
1120 add_field_decl (const_string_type_node, "weak_ivar_layout", &chain);
1121
1122 /* struct _prop_list_t *properties; */
1123 ptrt = build_pointer_type (xref_tag (RECORD_TYPE,
1124 get_identifier(UTAG_PROPERTY_LIST)));
1125 add_field_decl (ptrt, "properties", &chain);
1126
1127 objc_finish_struct (objc_class_ext_template, decls);
1128 }
1129
1130 static void
1131 build_metadata_templates (void)
1132 {
1133
1134 if (!objc_method_template)
1135 objc_method_template = build_method_template ();
1136
1137
1138
1139 }
1140
1141 /* --- emit metadata --- */
1142
1143 static tree
1144 generate_v1_meth_descriptor_table (tree chain, tree protocol,
1145 const char *prefix, tree attr)
1146 {
1147 tree method_list_template, initlist, decl;
1148 int size;
1149 VEC(constructor_elt,gc) *v = NULL;
1150 char buf[BUFSIZE];
1151
1152 if (!chain || !prefix)
1153 return NULL_TREE;
1154
1155 if (!objc_method_prototype_template)
1156 objc_method_prototype_template = build_method_prototype_template ();
1157
1158 size = list_length (chain);
1159 method_list_template =
1160 build_method_prototype_list_template (objc_method_prototype_template,
1161 size);
1162 snprintf (buf, BUFSIZE, "%s_%s", prefix,
1163 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
1164
1165 decl = start_var_decl (method_list_template, buf);
1166
1167 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1168 initlist =
1169 build_descriptor_table_initializer (objc_method_prototype_template,
1170 chain);
1171 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1172 /* Get into the right section. */
1173 OBJCMETA (decl, objc_meta, attr);
1174 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
1175 return decl;
1176 }
1177
1178 /* Build protocol ext =
1179 {size, opt_instance_meth, opt_class_meth, instance_props};
1180 or NULL_TREE if none are present. */
1181
1182 static tree
1183 generate_v1_objc_protocol_extension (tree proto_interface,
1184 tree opt_instance_meth,
1185 tree opt_class_meth,
1186 tree instance_props)
1187 {
1188 int size;
1189 location_t loc;
1190 VEC(constructor_elt,gc) *v = NULL;
1191 tree decl, expr;
1192 char buf[BUFSIZE];
1193
1194 /* If there are no extensions, then don't bother... */
1195 if (!opt_instance_meth && !opt_class_meth && !instance_props)
1196 return NULL_TREE;
1197
1198 if (!objc_protocol_extension_template)
1199 build_v1_objc_protocol_extension_template ();
1200
1201 /* uint32_t size */
1202 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template));
1203 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1204
1205 /* Try for meaningful diagnostics. */
1206 loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface));
1207
1208 /* struct objc_method_list *optional_instance_methods; */
1209 if (opt_instance_meth)
1210 expr = convert (objc_method_list_ptr,
1211 build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0));
1212 else
1213 expr = convert (objc_method_list_ptr, null_pointer_node);
1214
1215 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1216
1217 /* struct objc_method_list *optional_class_methods; */
1218 if (opt_class_meth)
1219 expr = convert (objc_method_list_ptr,
1220 build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0));
1221 else
1222 expr = convert (objc_method_list_ptr, null_pointer_node);
1223
1224 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1225 /* struct objc_prop_list *instance_properties; */
1226 if (instance_props)
1227 expr = convert (objc_prop_list_ptr,
1228 build_unary_op (loc, ADDR_EXPR, instance_props, 0));
1229 else
1230 expr = convert (objc_prop_list_ptr, null_pointer_node);
1231
1232 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1233 snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s",
1234 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface)));
1235
1236 decl = start_var_decl (objc_protocol_extension_template, buf);
1237 expr = objc_build_constructor (TREE_TYPE (decl), v);
1238 OBJCMETA (decl, objc_meta, meta_protocol_extension);
1239 finish_var_decl (decl, expr);
1240 return decl;
1241 }
1242
1243 /* This routine builds the following type:
1244 struct _prop_list_t {
1245 uint32_t entsize; // sizeof (struct _prop_t)
1246 uint32_t prop_count;
1247 struct _prop_t prop_list [prop_count];
1248 }
1249 */
1250
1251 static tree
1252 build_v1_property_list_template (tree list_type, int size)
1253 {
1254 tree property_list_t_record;
1255 tree array_type, decls, *chain = NULL;
1256
1257 /* anonymous. */
1258 property_list_t_record = objc_start_struct (NULL_TREE);
1259
1260 /* uint32_t const entsize */
1261 decls = add_field_decl (integer_type_node, "entsize", &chain);
1262
1263 /* int prop_count */
1264 add_field_decl (integer_type_node, "prop_count", &chain);
1265
1266 /* struct _prop_t prop_list[]; */
1267 array_type = build_sized_array_type (list_type, size);
1268 add_field_decl (array_type, "prop_list", &chain);
1269
1270 objc_finish_struct (property_list_t_record, decls);
1271 return property_list_t_record;
1272 }
1273
1274 /* This routine builds the initializer list to initialize the
1275 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
1276
1277 static tree
1278 build_v1_property_table_initializer (tree type, tree context)
1279 {
1280 tree x;
1281 VEC(constructor_elt,gc) *inits = NULL;
1282
1283 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
1284 x = CLASS_PROPERTY_DECL (context);
1285 else
1286 x = IMPL_PROPERTY_DECL (context);
1287
1288 for (; x; x = TREE_CHAIN (x))
1289 {
1290 VEC(constructor_elt,gc) *elemlist = NULL;
1291 tree attribute, name_ident = PROPERTY_NAME (x);
1292
1293 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1294 add_objc_string (name_ident, prop_names_attr));
1295
1296 attribute = objc_v2_encode_prop_attr (x);
1297 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
1298 add_objc_string (attribute, prop_names_attr));
1299
1300 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
1301 objc_build_constructor (type, elemlist));
1302 }
1303
1304 return objc_build_constructor (build_array_type (type, 0),inits);
1305 }
1306
1307 /* This routine builds the 'struct _prop_list_t' variable declaration and
1308 initializes it with its initializer list. TYPE is 'struct _prop_list_t',
1309 NAME is the internal name of this variable, SIZE is number of properties
1310 for this class and LIST is the initializer list for its 'prop_list' field. */
1311
1312 static tree
1313 generate_v1_property_table (tree context, tree klass_ctxt)
1314 {
1315 tree x, decl, initlist, property_list_template;
1316 bool is_proto = false;
1317 VEC(constructor_elt,gc) *inits = NULL;
1318 int init_val, size = 0;
1319 char buf[BUFSIZE];
1320
1321 if (context)
1322 {
1323 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
1324 x = CLASS_PROPERTY_DECL (context);
1325 is_proto = true;
1326 }
1327 else
1328 x = IMPL_PROPERTY_DECL (klass_ctxt);
1329
1330 for (; x; x = TREE_CHAIN (x))
1331 size++;
1332
1333 if (size == 0)
1334 return NULL_TREE;
1335
1336 if (!objc_v1_property_template)
1337 objc_v1_property_template = build_v1_property_template ();
1338
1339 property_list_template =
1340 build_v1_property_list_template (objc_v1_property_template,
1341 size);
1342 initlist = build_v1_property_table_initializer (objc_v1_property_template,
1343 is_proto ? context
1344 : klass_ctxt);
1345
1346 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template));
1347 if (is_proto)
1348 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
1349 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
1350 else
1351 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
1352 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
1353
1354 decl = start_var_decl (property_list_template, buf);
1355 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val));
1356 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1357 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1358 x = objc_build_constructor (TREE_TYPE (decl), inits);
1359 OBJCMETA (decl, objc_meta, meta_proplist);
1360 finish_var_decl (decl, x);
1361 return decl;
1362 }
1363
1364 static tree
1365 generate_v1_protocol_list (tree i_or_p, tree klass_ctxt)
1366 {
1367 tree array_type, ptype, refs_decl, lproto, e, plist, attr;
1368 int size = 0;
1369 VEC(constructor_elt,gc) *v = NULL;
1370 char buf[BUFSIZE];
1371
1372 switch (TREE_CODE (i_or_p))
1373 {
1374 case CLASS_INTERFACE_TYPE:
1375 case CATEGORY_INTERFACE_TYPE:
1376 plist = CLASS_PROTOCOL_LIST (i_or_p);
1377 break;
1378 case PROTOCOL_INTERFACE_TYPE:
1379 plist = PROTOCOL_LIST (i_or_p);
1380 break;
1381 default:
1382 gcc_unreachable ();
1383 }
1384
1385 /* Compute size. */
1386 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1387 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
1388 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
1389 size++;
1390
1391 /* Build initializer. */
1392 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0));
1393 e = build_int_cst (build_pointer_type (objc_protocol_template), size);
1394 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1395
1396 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
1397 {
1398 tree pval = TREE_VALUE (lproto);
1399
1400 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
1401 && PROTOCOL_FORWARD_DECL (pval))
1402 {
1403 tree fwref = PROTOCOL_FORWARD_DECL (pval);
1404 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
1405 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
1406 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e);
1407 }
1408 }
1409
1410 /* static struct objc_protocol *refs[n]; */
1411 switch (TREE_CODE (i_or_p))
1412 {
1413 case PROTOCOL_INTERFACE_TYPE:
1414 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
1415 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
1416 attr = meta_proto_ref;
1417 break;
1418 case CLASS_INTERFACE_TYPE:
1419 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
1420 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
1421 attr = meta_clas_prot;
1422 break;
1423 case CATEGORY_INTERFACE_TYPE:
1424 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
1425 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
1426 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
1427 attr = meta_catg_prot;
1428 break;
1429 default:
1430 gcc_unreachable ();
1431 }
1432
1433 ptype = build_pointer_type (objc_protocol_template);
1434 array_type = build_sized_array_type (ptype, size + 3);
1435 refs_decl = start_var_decl (array_type, buf);
1436
1437 OBJCMETA (refs_decl, objc_meta, attr);
1438 finish_var_decl (refs_decl,
1439 objc_build_constructor (TREE_TYPE (refs_decl), v));
1440
1441 return refs_decl;
1442 }
1443
1444 static tree
1445 build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
1446 tree inst_methods, tree class_methods,
1447 tree protocol_ext)
1448 {
1449 tree expr, ttyp;
1450 location_t loc;
1451 VEC(constructor_elt,gc) *inits = NULL;
1452
1453 if (!objc_protocol_extension_template)
1454 build_v1_objc_protocol_extension_template ();
1455
1456 /* TODO: find a better representation of location from the inputs. */
1457 loc = UNKNOWN_LOCATION;
1458 ttyp = build_pointer_type (objc_protocol_extension_template);
1459 /* Instead of jamming the protocol version number into the isa, we pass
1460 either a pointer to the protocol extension - or NULL. */
1461 if (protocol_ext)
1462 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0));
1463 else
1464 expr = convert (ttyp, null_pointer_node);
1465
1466 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1467 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
1468 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
1469
1470 ttyp = objc_method_proto_list_ptr;
1471 if (inst_methods)
1472 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1473 else
1474 expr = convert (ttyp, null_pointer_node);
1475 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1476
1477 if (class_methods)
1478 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1479 else
1480 expr = convert (ttyp, null_pointer_node);
1481 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
1482
1483 return objc_build_constructor (type, inits);
1484 }
1485
1486 /* An updated version of generate_protocols () that emit the protocol
1487 extension for ABI=1. */
1488
1489 /* For each protocol which was referenced either from a @protocol()
1490 expression, or because a class/category implements it (then a
1491 pointer to the protocol is stored in the struct describing the
1492 class/category), we create a statically allocated instance of the
1493 Protocol class. The code is written in such a way as to generate
1494 as few Protocol objects as possible; we generate a unique Protocol
1495 instance for each protocol, and we don't generate a Protocol
1496 instance if the protocol is never referenced (either from a
1497 @protocol() or from a class/category implementation). These
1498 statically allocated objects can be referred to via the static
1499 (that is, private to this module) symbols _OBJC_PROTOCOL_n.
1500
1501 The statically allocated Protocol objects that we generate here
1502 need to be fixed up at runtime in order to be used: the 'isa'
1503 pointer of the objects need to be set up to point to the 'Protocol'
1504 class, as known at runtime.
1505
1506 The NeXT runtime fixes up all protocols at program startup time,
1507 before main() is entered. It uses a low-level trick to look up all
1508 those symbols, then loops on them and fixes them up. */
1509
1510 /* TODO: finish getting rid of passing stuff around in globals. */
1511
1512 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl;
1513 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl;
1514 static GTY(()) tree V1_ProtocolExt_decl;
1515 static GTY(()) tree V1_Property_decl;
1516
1517 static void
1518 generate_v1_protocols (void)
1519 {
1520 tree p;
1521
1522 /* If a protocol was directly referenced, pull in indirect references. */
1523 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1524 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
1525 generate_protocol_references (PROTOCOL_LIST (p));
1526
1527 for (p = protocol_chain; p; p = TREE_CHAIN (p))
1528 {
1529 tree decl, encoding, initlist, protocol_name_expr;
1530 tree refs_type, refs_decl, refs_expr;
1531 location_t loc;
1532 tree nst_methods = PROTOCOL_NST_METHODS (p);
1533 tree cls_methods = PROTOCOL_CLS_METHODS (p);
1534
1535 /* If protocol wasn't referenced, don't generate any code. */
1536 decl = PROTOCOL_FORWARD_DECL (p);
1537
1538 if (!decl)
1539 continue;
1540
1541 /* Make sure we link in the Protocol class. */
1542 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
1543
1544 while (nst_methods)
1545 {
1546 if (! METHOD_ENCODING (nst_methods))
1547 {
1548 encoding = encode_method_prototype (nst_methods);
1549 METHOD_ENCODING (nst_methods) = encoding;
1550 }
1551 nst_methods = TREE_CHAIN (nst_methods);
1552 }
1553
1554 UOBJC_INSTANCE_METHODS_decl =
1555 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
1556 "_OBJC_ProtocolInstanceMethods",
1557 meta_proto_nst_meth);
1558
1559 while (cls_methods)
1560 {
1561 if (! METHOD_ENCODING (cls_methods))
1562 {
1563 encoding = encode_method_prototype (cls_methods);
1564 METHOD_ENCODING (cls_methods) = encoding;
1565 }
1566
1567 cls_methods = TREE_CHAIN (cls_methods);
1568 }
1569
1570 UOBJC_CLASS_METHODS_decl =
1571 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
1572 "_OBJC_ProtocolClassMethods",
1573 meta_proto_cls_meth);
1574
1575 /* There should be no optional methods for ABI-0 - but we need to
1576 check all this here before the lists are made. */
1577 nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p);
1578 while (nst_methods)
1579 {
1580 if (! METHOD_ENCODING (nst_methods))
1581 {
1582 encoding = encode_method_prototype (nst_methods);
1583 METHOD_ENCODING (nst_methods) = encoding;
1584 }
1585 nst_methods = TREE_CHAIN (nst_methods);
1586 }
1587
1588 V1_Protocol_OPT_NST_METHODS_decl =
1589 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
1590 "_OBJC_OptionalProtocolInstanceMethods",
1591 meta_proto_nst_meth);
1592
1593 cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p);
1594 while (cls_methods)
1595 {
1596 if (! METHOD_ENCODING (cls_methods))
1597 {
1598 encoding = encode_method_prototype (cls_methods);
1599 METHOD_ENCODING (cls_methods) = encoding;
1600 }
1601
1602 cls_methods = TREE_CHAIN (cls_methods);
1603 }
1604
1605 V1_Protocol_OPT_CLS_METHODS_decl =
1606 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
1607 "_OBJC_OptionalProtocolClassMethods",
1608 meta_proto_cls_meth);
1609
1610 if (PROTOCOL_LIST (p))
1611 refs_decl = generate_v1_protocol_list (p, objc_implementation_context);
1612 else
1613 refs_decl = 0;
1614
1615 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */
1616 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
1617 /* TODO: more locations to be fixed up... */
1618 loc = UNKNOWN_LOCATION;
1619 refs_type =
1620 build_pointer_type (build_pointer_type (objc_protocol_template));
1621 if (refs_decl)
1622 refs_expr = convert (refs_type,
1623 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
1624 else
1625 refs_expr = convert (refs_type, null_pointer_node);
1626
1627 if (flag_objc_abi < 1)
1628 {
1629 /* Original ABI. */
1630 initlist =
1631 build_protocol_initializer (TREE_TYPE (decl),
1632 protocol_name_expr, refs_expr,
1633 UOBJC_INSTANCE_METHODS_decl,
1634 UOBJC_CLASS_METHODS_decl);
1635 finish_var_decl (decl, initlist);
1636 continue;
1637 }
1638
1639 /* else - V1 extensions. */
1640
1641 V1_Property_decl =
1642 generate_v1_property_table (p, NULL_TREE);
1643
1644 V1_ProtocolExt_decl =
1645 generate_v1_objc_protocol_extension (p,
1646 V1_Protocol_OPT_NST_METHODS_decl,
1647 V1_Protocol_OPT_CLS_METHODS_decl,
1648 V1_Property_decl);
1649
1650 initlist = build_v1_protocol_initializer (TREE_TYPE (decl),
1651 protocol_name_expr, refs_expr,
1652 UOBJC_INSTANCE_METHODS_decl,
1653 UOBJC_CLASS_METHODS_decl,
1654 V1_ProtocolExt_decl);
1655 finish_var_decl (decl, initlist);
1656 }
1657 }
1658
1659 static tree
1660 generate_dispatch_table (tree chain, const char *name, tree attr)
1661 {
1662 tree decl, method_list_template, initlist;
1663 VEC(constructor_elt,gc) *v = NULL;
1664 int size;;
1665
1666 if (!chain || !name || !(size = list_length (chain)))
1667 return NULL_TREE;
1668
1669 if (!objc_method_template)
1670 objc_method_template = build_method_template ();
1671
1672 method_list_template = build_method_list_template (objc_method_template,
1673 size);
1674 initlist = build_dispatch_table_initializer (objc_method_template, chain);
1675
1676 decl = start_var_decl (method_list_template, name);
1677
1678 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
1679 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1680 build_int_cst (integer_type_node, size));
1681 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
1682
1683 OBJCMETA (decl, objc_meta, attr);
1684 finish_var_decl (decl,
1685 objc_build_constructor (TREE_TYPE (decl), v));
1686
1687 return decl;
1688 }
1689
1690 /* Init a category. */
1691 static tree
1692 build_v1_category_initializer (tree type, tree cat_name, tree class_name,
1693 tree inst_methods, tree class_methods,
1694 tree protocol_list, tree property_list,
1695 location_t loc)
1696 {
1697 tree expr, ltyp;
1698 VEC(constructor_elt,gc) *v = NULL;
1699
1700 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
1701 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
1702
1703 ltyp = objc_method_list_ptr;
1704 if (inst_methods)
1705 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
1706 else
1707 expr = convert (ltyp, null_pointer_node);
1708 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1709
1710 if (class_methods)
1711 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
1712 else
1713 expr = convert (ltyp, null_pointer_node);
1714 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1715
1716 /* protocol_list = */
1717 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1718 if (protocol_list)
1719 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1720 else
1721 expr = convert (ltyp, null_pointer_node);
1722 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1723
1724 if (flag_objc_abi >= 1)
1725 {
1726 int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template));
1727 expr = build_int_cst (NULL_TREE, val);
1728 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1729 ltyp = objc_prop_list_ptr;
1730 if (property_list)
1731 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1732 else
1733 expr = convert (ltyp, null_pointer_node);
1734 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1735 }
1736
1737 return objc_build_constructor (type, v);
1738 }
1739
1740 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */
1741 /* TODO: get rid of passing stuff around in globals. */
1742 static void
1743 generate_v1_category (struct imp_entry *impent)
1744 {
1745 tree initlist, cat_name_expr, class_name_expr;
1746 tree protocol_decl, category, cat_decl;
1747 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
1748 tree cat = impent->imp_context;
1749 location_t loc;
1750 char buf[BUFSIZE];
1751
1752 cat_decl = impent->class_decl;
1753 loc = DECL_SOURCE_LOCATION (cat_decl);
1754
1755 add_class_reference (CLASS_NAME (cat));
1756 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
1757 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names);
1758
1759 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
1760
1761 if (category && CLASS_PROTOCOL_LIST (category))
1762 {
1763 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
1764 protocol_decl = generate_v1_protocol_list (category, cat);
1765 }
1766 else
1767 protocol_decl = 0;
1768
1769 if (flag_objc_abi >= 1)
1770 V1_Property_decl = generate_v1_property_table (NULL_TREE, cat);
1771 else
1772 V1_Property_decl = NULL_TREE;
1773
1774 if (CLASS_NST_METHODS (cat))
1775 {
1776 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
1777 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1778 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1779 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf,
1780 meta_cati_meth);
1781 }
1782
1783 if (CLASS_CLS_METHODS (cat))
1784 {
1785 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
1786 IDENTIFIER_POINTER (CLASS_NAME (cat)),
1787 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
1788 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf,
1789 meta_catc_meth);
1790 }
1791
1792 initlist = build_v1_category_initializer (TREE_TYPE (cat_decl),
1793 cat_name_expr, class_name_expr,
1794 inst_methods, class_methods,
1795 protocol_decl, V1_Property_decl,
1796 loc);
1797
1798 finish_var_decl (cat_decl, initlist);
1799 impent->class_decl = cat_decl;
1800 }
1801
1802 /* This routine builds the class extension used by v1 NeXT. */
1803
1804 static tree
1805 generate_objc_class_ext (tree property_list, tree context)
1806 {
1807 tree decl, expr, ltyp;
1808 tree weak_ivar_layout_tree;
1809 int size;
1810 location_t loc;
1811 VEC(constructor_elt,gc) *v = NULL;
1812 char buf[BUFSIZE];
1813
1814 /* TODO: pass the loc in or find it from args. */
1815 loc = UNKNOWN_LOCATION;
1816
1817 /* const char *weak_ivar_layout
1818 TODO: Figure the ivar layouts out... */
1819 weak_ivar_layout_tree = NULL_TREE;
1820
1821 if (!property_list && !weak_ivar_layout_tree)
1822 return NULL_TREE;
1823
1824 if (!objc_class_ext_template)
1825 build_objc_class_ext_template ();
1826
1827 /* uint32_t size */
1828 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template));
1829 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
1830
1831 ltyp = const_string_type_node;
1832 if (weak_ivar_layout_tree)
1833 expr = convert (ltyp, weak_ivar_layout_tree);
1834 else
1835 expr = convert (ltyp, null_pointer_node);
1836 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1837
1838 /* struct _prop_list_t *properties; */
1839 ltyp = objc_prop_list_ptr;
1840 if (property_list)
1841 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
1842 else
1843 expr = convert (ltyp, null_pointer_node);
1844 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1845
1846 snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s",
1847 IDENTIFIER_POINTER (CLASS_NAME (context)));
1848 decl = start_var_decl (objc_class_ext_template, buf);
1849 expr = objc_build_constructor (TREE_TYPE (decl), v);
1850 OBJCMETA (decl, objc_meta, meta_class_extension);
1851 finish_var_decl (decl, expr);
1852 return decl;
1853 }
1854
1855 /* struct _objc_class {
1856 struct objc_class *isa;
1857 struct objc_class *super_class;
1858 char *name;
1859 long version;
1860 long info;
1861 long instance_size;
1862 struct objc_ivar_list *ivars;
1863 struct objc_method_list *methods;
1864 struct objc_cache *cache;
1865 struct objc_protocol_list *protocols;
1866 #if ABI >= 1
1867 const char *ivar_layout;
1868 struct _objc_class_ext *ext;
1869 #else
1870 void *sel_id;
1871 void *gc_object_type;
1872 #endif
1873 }; */
1874
1875 static tree
1876 build_v1_shared_structure_initializer (tree type, tree isa, tree super,
1877 tree name, tree size, int status,
1878 tree dispatch_table, tree ivar_list,
1879 tree protocol_list, tree class_ext)
1880 {
1881 tree expr, ltyp;
1882 location_t loc;
1883 VEC(constructor_elt,gc) *v = NULL;
1884
1885 /* TODO: fish the location out of the input data. */
1886 loc = UNKNOWN_LOCATION;
1887
1888 /* isa = */
1889 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa);
1890
1891 /* super_class = */
1892 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super);
1893
1894 /* name = */
1895 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name));
1896
1897 /* version = */
1898 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1899 build_int_cst (long_integer_type_node, 0));
1900
1901 /* info = */
1902 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1903 build_int_cst (long_integer_type_node, status));
1904
1905 /* instance_size = */
1906 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
1907 convert (long_integer_type_node, size));
1908
1909 /* objc_ivar_list = */
1910 ltyp = objc_ivar_list_ptr;
1911 if (ivar_list)
1912 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0));
1913 else
1914 expr = convert (ltyp, null_pointer_node);
1915 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1916
1917 /* objc_method_list = */
1918 ltyp = objc_method_list_ptr;
1919 if (dispatch_table)
1920 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0));
1921 else
1922 expr = convert (ltyp, null_pointer_node);
1923 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1924
1925 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
1926 get_identifier ("objc_cache")));
1927 /* method_cache = */
1928 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node));
1929
1930 /* protocol_list = */
1931 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template));
1932 if (protocol_list)
1933 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
1934 else
1935 expr = convert (ltyp, null_pointer_node);
1936 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1937
1938 if (flag_objc_abi >= 1)
1939 {
1940 /* TODO: figure out the ivar_layout stuff. */
1941 expr = convert (const_string_type_node, null_pointer_node);
1942 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1943 if (!objc_class_ext_template)
1944 build_objc_class_ext_template ();
1945 ltyp = build_pointer_type (objc_class_ext_template);
1946 if (class_ext)
1947 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0));
1948 else
1949 expr = convert (ltyp, null_pointer_node);
1950 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
1951 }
1952 else
1953 {
1954 /* sel_id = NULL */
1955 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1956
1957 /* gc_object_type = NULL */
1958 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node);
1959 }
1960 return objc_build_constructor (type, v);
1961 }
1962
1963 static tree
1964 generate_ivars_list (tree chain, const char *name, tree attr)
1965 {
1966 tree initlist, ivar_list_template, decl;
1967 int size;
1968 VEC(constructor_elt,gc) *inits = NULL;
1969
1970 if (!chain)
1971 return NULL_TREE;
1972
1973 if (!objc_ivar_template)
1974 objc_ivar_template = build_ivar_template ();
1975
1976 size = ivar_list_length (chain);
1977
1978 generating_instance_variables = 1;
1979 ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
1980 initlist = build_ivar_list_initializer (objc_ivar_template, chain);
1981 generating_instance_variables = 0;
1982
1983 decl = start_var_decl (ivar_list_template, name);
1984
1985 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size));
1986 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
1987
1988 OBJCMETA (decl, objc_meta, attr);
1989 finish_var_decl (decl,
1990 objc_build_constructor (TREE_TYPE (decl), inits));
1991
1992 return decl;
1993 }
1994
1995 /* static struct objc_class _OBJC_METACLASS_Foo={ ... };
1996 static struct objc_class _OBJC_CLASS_Foo={ ... }; */
1997
1998 static void
1999 generate_v1_class_structs (struct imp_entry *impent)
2000 {
2001 tree name_expr, super_expr, root_expr, class_decl, meta_decl;
2002 tree my_root_id, my_super_id;
2003 tree cast_type, initlist, protocol_decl;
2004 tree class_ext_decl = NULL_TREE, props = NULL_TREE;
2005 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2006 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
2007 int cls_flags;
2008 location_t loc;
2009 char buf[BUFSIZE];
2010
2011 /* objc_implementation_context = impent->imp_context;
2012 implementation_template = impent->imp_template;*/
2013 class_decl = impent->class_decl;
2014 meta_decl = impent->meta_decl;
2015 cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ;
2016
2017 loc = DECL_SOURCE_LOCATION (impent->class_decl);
2018
2019 if (flag_objc_abi >= 1)
2020 {
2021 /* ABI=1 additions. */
2022 props = generate_v1_property_table (NULL_TREE, impent->imp_context);
2023 class_ext_decl = generate_objc_class_ext (props, impent->imp_context);
2024 }
2025
2026 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
2027 if (my_super_id)
2028 {
2029 add_class_reference (my_super_id);
2030
2031 /* Compute "my_root_id" - this is required for code generation.
2032 the "isa" for all meta class structures points to the root of
2033 the inheritance hierarchy (e.g. "__Object")... */
2034 my_root_id = my_super_id;
2035 do
2036 {
2037 tree my_root_int = lookup_interface (my_root_id);
2038
2039 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
2040 my_root_id = CLASS_SUPER_NAME (my_root_int);
2041 else
2042 break;
2043 }
2044 while (1);
2045 super_expr = add_objc_string (my_super_id, class_names);
2046 }
2047 else
2048 {
2049 /* No super class. */
2050 my_root_id = CLASS_NAME (impent->imp_template);
2051 super_expr = null_pointer_node;
2052 }
2053
2054 /* Install class `isa' and `super' pointers at runtime. */
2055 cast_type = build_pointer_type (objc_class_template);
2056 super_expr = build_c_cast (loc, cast_type, super_expr);
2057
2058 root_expr = add_objc_string (my_root_id, class_names);
2059 root_expr = build_c_cast (loc, cast_type, root_expr);
2060
2061 if (CLASS_PROTOCOL_LIST (impent->imp_template))
2062 {
2063 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
2064 protocol_decl = generate_v1_protocol_list (impent->imp_template,
2065 impent->imp_context);
2066 }
2067 else
2068 protocol_decl = NULL_TREE;
2069
2070 if (CLASS_CLS_METHODS (impent->imp_context))
2071 {
2072 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
2073 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2074 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
2075 buf, meta_clac_meth);
2076 }
2077
2078 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE
2079 && (chain = TYPE_FIELDS (objc_class_template)))
2080 {
2081 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s",
2082 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2083 class_ivars = generate_ivars_list (chain, buf, meta_clac_vars);
2084 }
2085 /* TODO: get rid of hidden passing of stuff in globals. */
2086 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */
2087
2088 name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names);
2089
2090 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
2091
2092 initlist = build_v1_shared_structure_initializer
2093 (TREE_TYPE (meta_decl),
2094 root_expr, super_expr, name_expr,
2095 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)),
2096 CLS_META, class_methods, class_ivars,
2097 protocol_decl, NULL_TREE);
2098
2099 finish_var_decl (meta_decl, initlist);
2100 impent->meta_decl = meta_decl;
2101
2102 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
2103 if (CLASS_NST_METHODS (impent->imp_context))
2104 {
2105 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
2106 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2107 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
2108 buf, meta_clai_meth);
2109 }
2110
2111 if ((chain = CLASS_IVARS (impent->imp_template)))
2112 {
2113 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
2114 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2115 inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars);
2116 }
2117
2118 initlist = build_v1_shared_structure_initializer
2119 (TREE_TYPE (class_decl),
2120 build_unary_op (loc, ADDR_EXPR, meta_decl, 0),
2121 super_expr, name_expr,
2122 convert (integer_type_node,
2123 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))),
2124 CLS_FACTORY | cls_flags, inst_methods, inst_ivars,
2125 protocol_decl, class_ext_decl);
2126
2127 finish_var_decl (class_decl, initlist);
2128 impent->class_decl = class_decl;
2129 }
2130
2131 /* --- Output NeXT V1 Metadata --- */
2132
2133 /* Create the initial value for the `defs' field of _objc_symtab.
2134 This is a CONSTRUCTOR. */
2135
2136 static tree
2137 init_def_list (tree type)
2138 {
2139 tree expr;
2140 location_t loc;
2141 struct imp_entry *impent;
2142 VEC(constructor_elt,gc) *v = NULL;
2143
2144 if (imp_count)
2145 for (impent = imp_list; impent; impent = impent->next)
2146 {
2147 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2148 {
2149 loc = DECL_SOURCE_LOCATION (impent->class_decl);
2150 expr = build_unary_op (loc,
2151 ADDR_EXPR, impent->class_decl, 0);
2152 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2153 }
2154 }
2155
2156 if (cat_count)
2157 for (impent = imp_list; impent; impent = impent->next)
2158 {
2159 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE)
2160 {
2161 loc = DECL_SOURCE_LOCATION (impent->class_decl);
2162 expr = build_unary_op (loc,
2163 ADDR_EXPR, impent->class_decl, 0);
2164 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2165 }
2166 }
2167
2168 return objc_build_constructor (type, v);
2169 }
2170
2171 /* Take care of defining and initializing _OBJC_SYMBOLS. */
2172
2173 /* Predefine the following data type:
2174
2175 struct _objc_symtab
2176 {
2177 long sel_ref_cnt;
2178 SEL *refs;
2179 short cls_def_cnt;
2180 short cat_def_cnt;
2181 void *defs[cls_def_cnt + cat_def_cnt];
2182 }; */
2183
2184 static void
2185 build_objc_symtab_template (void)
2186 {
2187 tree fields, *chain = NULL;
2188
2189 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB));
2190
2191 /* long sel_ref_cnt; */
2192 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain);
2193
2194 /* SEL *refs; */
2195 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain);
2196
2197 /* short cls_def_cnt; */
2198 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain);
2199
2200 /* short cat_def_cnt; */
2201 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain);
2202
2203 if (imp_count || cat_count)
2204 {
2205 /* void *defs[imp_count + cat_count (+ 1)]; */
2206 /* NB: The index is one less than the size of the array. */
2207 int index = imp_count + cat_count;
2208 tree array_type = build_sized_array_type (ptr_type_node, index);
2209 add_field_decl (array_type, "defs", &chain);
2210 }
2211
2212 objc_finish_struct (objc_symtab_template, fields);
2213 }
2214 /* Construct the initial value for all of _objc_symtab. */
2215
2216 static tree
2217 init_objc_symtab (tree type)
2218 {
2219 VEC(constructor_elt,gc) *v = NULL;
2220
2221 /* sel_ref_cnt = { ..., 5, ... } */
2222
2223 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2224 build_int_cst (long_integer_type_node, 0));
2225
2226 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */
2227
2228 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2229 convert (build_pointer_type (objc_selector_type),
2230 integer_zero_node));
2231
2232 /* cls_def_cnt = { ..., 5, ... } */
2233
2234 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2235 build_int_cst (short_integer_type_node, imp_count));
2236
2237 /* cat_def_cnt = { ..., 5, ... } */
2238
2239 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2240 build_int_cst (short_integer_type_node, cat_count));
2241
2242 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
2243
2244 if (imp_count || cat_count)
2245 {
2246 tree field = TYPE_FIELDS (type);
2247 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field))));
2248
2249 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field)));
2250 }
2251
2252 return objc_build_constructor (type, v);
2253 }
2254
2255 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab'
2256 and initialized appropriately. */
2257
2258 static void
2259 generate_objc_symtab_decl (void)
2260 {
2261 build_objc_symtab_template ();
2262 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols");
2263 /* Allow the runtime to mark meta-data such that it can be assigned to target
2264 specific sections by the back-end. */
2265 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab);
2266 finish_var_decl (UOBJC_SYMBOLS_decl,
2267 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));
2268 }
2269
2270
2271 static void
2272 handle_next_class_ref (tree chain)
2273 {
2274 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain));
2275 char *string = (char *) alloca (strlen (name) + 30);
2276
2277 sprintf (string, ".objc_class_name_%s", name);
2278
2279 #ifdef ASM_DECLARE_UNRESOLVED_REFERENCE
2280 ASM_DECLARE_UNRESOLVED_REFERENCE (asm_out_file, string);
2281 #else
2282 return ; /* NULL build for targets other than Darwin. */
2283 #endif
2284 }
2285
2286 static void
2287 handle_next_impent (struct imp_entry *impent)
2288 {
2289 char buf[BUFSIZE];
2290
2291 switch (TREE_CODE (impent->imp_context))
2292 {
2293 case CLASS_IMPLEMENTATION_TYPE:
2294 snprintf (buf, BUFSIZE, ".objc_class_name_%s",
2295 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
2296 break;
2297 case CATEGORY_IMPLEMENTATION_TYPE:
2298 snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s",
2299 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
2300 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
2301 break;
2302 default:
2303 return;
2304 }
2305
2306 #ifdef ASM_DECLARE_CLASS_REFERENCE
2307 ASM_DECLARE_CLASS_REFERENCE (asm_out_file, buf);
2308 #else
2309 return ; /* NULL build for targets other than Darwin. */
2310 #endif
2311 }
2312
2313 static void
2314 generate_classref_translation_entry (tree chain)
2315 {
2316 tree expr, decl, type;
2317
2318 decl = TREE_PURPOSE (chain);
2319 type = TREE_TYPE (decl);
2320
2321 expr = add_objc_string (TREE_VALUE (chain), class_names);
2322 expr = convert (type, expr); /* cast! */
2323
2324 /* This is a class reference. It is re-written by the runtime,
2325 but will be optimized away unless we force it. */
2326 DECL_PRESERVE_P (decl) = 1;
2327 OBJCMETA (decl, objc_meta, meta_class_reference);
2328 finish_var_decl (decl, expr);
2329 return;
2330 }
2331
2332
2333 /* The Fix-and-Continue functionality available in Mac OS X 10.3 and
2334 later requires that ObjC translation units participating in F&C be
2335 specially marked. The following routine accomplishes this. */
2336
2337 /* static int _OBJC_IMAGE_INFO[2] = { 0, 1 }; */
2338
2339 static void
2340 generate_objc_image_info (void)
2341 {
2342 tree decl;
2343 int flags
2344 = ((flag_replace_objc_classes && imp_count ? 1 : 0)
2345 | (flag_objc_gc ? 2 : 0));
2346 VEC(constructor_elt,gc) *v = NULL;
2347 tree array_type;
2348
2349 array_type = build_sized_array_type (integer_type_node, 2);
2350
2351 decl = start_var_decl (array_type, "_OBJC_ImageInfo");
2352
2353 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node);
2354 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (integer_type_node, flags));
2355 /* The runtime wants this and refers to it in a manner hidden from the compiler.
2356 So we must force the output. */
2357 DECL_PRESERVE_P (decl) = 1;
2358 OBJCMETA (decl, objc_meta, meta_info);
2359 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), v));
2360 }
2361
2362 static void
2363 objc_generate_v1_next_metadata (void)
2364 {
2365 struct imp_entry *impent;
2366 tree chain, attr;
2367 long vers;
2368
2369 /* FIXME: Make sure that we generate no metadata if there is nothing
2370 to put into it. */
2371
2372 if (objc_static_instances)
2373 gcc_unreachable (); /* Not for NeXT */
2374
2375 build_metadata_templates ();
2376 objc_implementation_context =
2377 implementation_template =
2378 UOBJC_CLASS_decl =
2379 UOBJC_METACLASS_decl = NULL_TREE;
2380
2381 for (impent = imp_list; impent; impent = impent->next)
2382 {
2383
2384 /* If -gen-decls is present, Dump the @interface of each class.
2385 TODO: Dump the classes in the order they were found, rather than in
2386 reverse order as we are doing now. */
2387 if (flag_gen_declaration)
2388 dump_interface (gen_declaration_file, impent->imp_context);
2389
2390 /* all of the following reference the string pool... */
2391 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
2392 generate_v1_class_structs (impent);
2393 else
2394 generate_v1_category (impent);
2395 }
2396
2397 /* If we are using an array of selectors, we must always
2398 finish up the array decl even if no selectors were used. */
2399 build_next_selector_translation_table ();
2400
2401 if (protocol_chain)
2402 generate_v1_protocols ();
2403
2404 /* Pass summary information to the runtime. */
2405 if (imp_count || cat_count)
2406 generate_objc_symtab_decl ();
2407
2408 vers = OBJC_VERSION;
2409 attr = build_tree_list (objc_meta, meta_modules);
2410 build_module_descriptor (vers, attr);
2411
2412 /* This conveys information on GC usage and zero-link. */
2413 generate_objc_image_info ();
2414
2415 /* Dump the class references. This forces the appropriate classes
2416 to be linked into the executable image, preserving unix archive
2417 semantics. This can be removed when we move to a more dynamically
2418 linked environment. */
2419
2420 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
2421 {
2422 handle_next_class_ref (chain);
2423 if (TREE_PURPOSE (chain))
2424 generate_classref_translation_entry (chain);
2425 }
2426
2427 for (impent = imp_list; impent; impent = impent->next)
2428 handle_next_impent (impent);
2429
2430 /* Emit the strings tables. */
2431 generate_strings ();
2432 }
2433
2434 /* --- exceptions stuff --- */
2435
2436 /* Predefine the following data type:
2437
2438 struct _objc_exception_data
2439 {
2440 int buf[OBJC_JBLEN];
2441 void *pointers[4];
2442 }; */
2443
2444 /* The following yuckiness should prevent users from having to #include
2445 <setjmp.h> in their code... */
2446
2447 /* Define to a harmless positive value so the below code doesn't die. */
2448 #ifndef OBJC_JBLEN
2449 #define OBJC_JBLEN 18
2450 #endif
2451
2452 static void
2453 build_next_objc_exception_stuff (void)
2454 {
2455 tree decls, temp_type, *chain = NULL;
2456
2457 objc_exception_data_template
2458 = objc_start_struct (get_identifier (UTAG_EXCDATA));
2459
2460 /* int buf[OBJC_JBLEN]; */
2461
2462 temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN);
2463 decls = add_field_decl (temp_type, "buf", &chain);
2464
2465 /* void *pointers[4]; */
2466
2467 temp_type = build_sized_array_type (ptr_type_node, 4);
2468 add_field_decl (temp_type, "pointers", &chain);
2469
2470 objc_finish_struct (objc_exception_data_template, decls);
2471
2472 /* int _setjmp(...); */
2473 /* If the user includes <setjmp.h>, this shall be superseded by
2474 'int _setjmp(jmp_buf);' */
2475 temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE);
2476 objc_setjmp_decl
2477 = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE);
2478
2479 /* id objc_exception_extract(struct _objc_exception_data *); */
2480 temp_type
2481 = build_function_type_list (objc_object_type,
2482 build_pointer_type (objc_exception_data_template),
2483 NULL_TREE);
2484 objc_exception_extract_decl
2485 = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL,
2486 NULL_TREE);
2487 /* void objc_exception_try_enter(struct _objc_exception_data *); */
2488 /* void objc_exception_try_exit(struct _objc_exception_data *); */
2489 temp_type
2490 = build_function_type_list (void_type_node,
2491 build_pointer_type (objc_exception_data_template),
2492 NULL_TREE);
2493 objc_exception_try_enter_decl
2494 = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL,
2495 NULL_TREE);
2496 objc_exception_try_exit_decl
2497 = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL,
2498 NULL_TREE);
2499
2500 /* int objc_exception_match(id, id); */
2501 temp_type
2502 = build_function_type_list (integer_type_node,
2503 objc_object_type, objc_object_type, NULL_TREE);
2504 objc_exception_match_decl
2505 = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL,
2506 NULL_TREE);
2507
2508 /* id objc_assign_ivar (id, id, unsigned int); */
2509 /* id objc_assign_ivar_Fast (id, id, unsigned int)
2510 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */
2511 temp_type
2512 = build_function_type_list (objc_object_type,
2513 objc_object_type,
2514 objc_object_type,
2515 unsigned_type_node,
2516 NULL_TREE);
2517 objc_assign_ivar_decl
2518 = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN,
2519 NULL, NULL_TREE);
2520 #ifdef OFFS_ASSIGNIVAR_FAST
2521 objc_assign_ivar_fast_decl
2522 = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0,
2523 NOT_BUILT_IN, NULL, NULL_TREE);
2524 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl)
2525 = tree_cons (get_identifier ("hard_coded_address"),
2526 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST),
2527 NULL_TREE);
2528 #else
2529 /* Default to slower ivar method. */
2530 objc_assign_ivar_fast_decl = objc_assign_ivar_decl;
2531 #endif
2532
2533 /* id objc_assign_global (id, id *); */
2534 /* id objc_assign_strongCast (id, id *); */
2535 temp_type = build_function_type_list (objc_object_type,
2536 objc_object_type,
2537 build_pointer_type (objc_object_type),
2538 NULL_TREE);
2539 objc_assign_global_decl
2540 = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL,
2541 NULL_TREE);
2542 objc_assign_strong_cast_decl
2543 = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL,
2544 NULL_TREE);
2545 }
2546
2547 /* --- NeXT V1 SJLJ Exceptions --- */
2548
2549 /* Build "objc_exception_try_exit(&_stack)". */
2550
2551 static tree
2552 next_sjlj_build_try_exit (struct objc_try_context **ctcp)
2553 {
2554 tree t;
2555 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2556 t = tree_cons (NULL, t, NULL);
2557 t = build_function_call (input_location,
2558 objc_exception_try_exit_decl, t);
2559 return t;
2560 }
2561
2562 /* Build
2563 objc_exception_try_enter (&_stack);
2564 if (_setjmp(&_stack.buf))
2565 ;
2566 else
2567 ;
2568 Return the COND_EXPR. Note that the THEN and ELSE fields are left
2569 empty, ready for the caller to fill them in. */
2570
2571 static tree
2572 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp)
2573 {
2574 tree t, enter, sj, cond;
2575
2576 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2577 t = tree_cons (NULL, t, NULL);
2578 enter = build_function_call (input_location,
2579 objc_exception_try_enter_decl, t);
2580
2581 t = objc_build_component_ref ((*ctcp)->stack_decl,
2582 get_identifier ("buf"));
2583 t = build_fold_addr_expr_loc (input_location, t);
2584 #ifdef OBJCPLUS
2585 /* Convert _setjmp argument to type that is expected. */
2586 if (prototype_p (TREE_TYPE (objc_setjmp_decl)))
2587 t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t);
2588 else
2589 t = convert (ptr_type_node, t);
2590 #else
2591 t = convert (ptr_type_node, t);
2592 #endif
2593 t = tree_cons (NULL, t, NULL);
2594 sj = build_function_call (input_location,
2595 objc_setjmp_decl, t);
2596
2597 cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj);
2598 cond = c_common_truthvalue_conversion (input_location, cond);
2599
2600 return build3 (COND_EXPR, void_type_node, cond, NULL, NULL);
2601 }
2602
2603 /* Build:
2604
2605 DECL = objc_exception_extract(&_stack); */
2606
2607 static tree
2608 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl)
2609 {
2610 tree t;
2611
2612 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl);
2613 t = tree_cons (NULL, t, NULL);
2614 t = build_function_call (input_location,
2615 objc_exception_extract_decl, t);
2616 t = convert (TREE_TYPE (decl), t);
2617 t = build2 (MODIFY_EXPR, void_type_node, decl, t);
2618
2619 return t;
2620 }
2621
2622 /* Build
2623 if (objc_exception_match(obj_get_class(TYPE), _caught)
2624 BODY
2625 else if (...)
2626 ...
2627 else
2628 {
2629 _rethrow = _caught;
2630 objc_exception_try_exit(&_stack);
2631 }
2632 from the sequence of CATCH_EXPRs in the current try context. */
2633
2634 static tree
2635 next_sjlj_build_catch_list (struct objc_try_context **ctcp)
2636 {
2637 tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list);
2638 tree catch_seq, t;
2639 tree *last = &catch_seq;
2640 bool saw_id = false;
2641
2642 for (; !tsi_end_p (i); tsi_next (&i))
2643 {
2644 tree stmt = tsi_stmt (i);
2645 tree type = CATCH_TYPES (stmt);
2646 tree body = CATCH_BODY (stmt);
2647
2648 if (type != error_mark_node
2649 && objc_is_object_id (TREE_TYPE (type)))
2650 {
2651 *last = body;
2652 saw_id = true;
2653 break;
2654 }
2655 else
2656 {
2657 tree args, cond;
2658
2659 if (type == error_mark_node)
2660 cond = error_mark_node;
2661 else
2662 {
2663 args = tree_cons (NULL, (*ctcp)->caught_decl, NULL);
2664 t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type)));
2665 args = tree_cons (NULL, t, args);
2666 t = build_function_call (input_location,
2667 objc_exception_match_decl, args);
2668 cond = c_common_truthvalue_conversion (input_location, t);
2669 }
2670 t = build3 (COND_EXPR, void_type_node, cond, body, NULL);
2671 SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt));
2672
2673 *last = t;
2674 last = &COND_EXPR_ELSE (t);
2675 }
2676 }
2677
2678 if (!saw_id)
2679 {
2680 t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl,
2681 (*ctcp)->caught_decl);
2682 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2683 append_to_statement_list (t, last);
2684
2685 t = next_sjlj_build_try_exit (ctcp);
2686 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus);
2687 append_to_statement_list (t, last);
2688 }
2689
2690 return catch_seq;
2691 }
2692
2693 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp
2694 exception handling. We aim to build:
2695
2696 {
2697 struct _objc_exception_data _stack;
2698 id _rethrow = 0;
2699 try
2700 {
2701 objc_exception_try_enter (&_stack);
2702 if (_setjmp(&_stack.buf))
2703 {
2704 id _caught = objc_exception_extract(&_stack);
2705 objc_exception_try_enter (&_stack);
2706 if (_setjmp(&_stack.buf))
2707 _rethrow = objc_exception_extract(&_stack);
2708 else
2709 CATCH-LIST
2710 }
2711 else
2712 TRY-BLOCK
2713 }
2714 finally
2715 {
2716 if (!_rethrow)
2717 objc_exception_try_exit(&_stack);
2718 FINALLY-BLOCK
2719 if (_rethrow)
2720 objc_exception_throw(_rethrow);
2721 }
2722 }
2723
2724 If CATCH-LIST is empty, we can omit all of the block containing
2725 "_caught" except for the setting of _rethrow. Note the use of
2726 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se,
2727 but handles goto and other exits from the block. */
2728
2729 static tree
2730 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp)
2731 {
2732 tree rethrow_decl, stack_decl, t;
2733 tree catch_seq, try_fin, bind;
2734 struct objc_try_context *cur_try_context = *ctcp;
2735
2736 /* Create the declarations involved. */
2737 t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA));
2738 stack_decl = objc_create_temporary_var (t, NULL);
2739 cur_try_context->stack_decl = stack_decl;
2740
2741 rethrow_decl = objc_create_temporary_var (objc_object_type, NULL);
2742 cur_try_context->rethrow_decl = rethrow_decl;
2743 TREE_CHAIN (rethrow_decl) = stack_decl;
2744
2745 /* Build the outermost variable binding level. */
2746 bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL);
2747 SET_EXPR_LOCATION (bind, cur_try_context->try_locus);
2748 TREE_SIDE_EFFECTS (bind) = 1;
2749
2750 /* Initialize rethrow_decl. */
2751 t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl,
2752 convert (objc_object_type, null_pointer_node));
2753 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2754 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
2755
2756 /* Build the outermost TRY_FINALLY_EXPR. */
2757 try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL);
2758 SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus);
2759 TREE_SIDE_EFFECTS (try_fin) = 1;
2760 append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind));
2761
2762 /* Create the complete catch sequence. */
2763 if (cur_try_context->catch_list)
2764 {
2765 tree caught_decl = objc_build_exc_ptr (ctcp);
2766 catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL);
2767 TREE_SIDE_EFFECTS (catch_seq) = 1;
2768
2769 t = next_sjlj_build_exc_extract (ctcp, caught_decl);
2770 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2771
2772 t = next_sjlj_build_enter_and_setjmp (ctcp);
2773 COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2774 COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp);
2775 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq));
2776 }
2777 else
2778 catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl);
2779 SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus);
2780
2781 /* Build the main register-and-try if statement. */
2782 t = next_sjlj_build_enter_and_setjmp (ctcp);
2783 SET_EXPR_LOCATION (t, cur_try_context->try_locus);
2784 COND_EXPR_THEN (t) = catch_seq;
2785 COND_EXPR_ELSE (t) = cur_try_context->try_body;
2786 TREE_OPERAND (try_fin, 0) = t;
2787
2788 /* Build the complete FINALLY statement list. */
2789 t = next_sjlj_build_try_exit (ctcp);
2790 t = build_stmt (input_location, COND_EXPR,
2791 c_common_truthvalue_conversion
2792 (input_location, rethrow_decl),
2793 NULL, t);
2794 SET_EXPR_LOCATION (t, cur_try_context->finally_locus);
2795 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2796
2797 append_to_statement_list (cur_try_context->finally_body,
2798 &TREE_OPERAND (try_fin, 1));
2799
2800 t = tree_cons (NULL, rethrow_decl, NULL);
2801 t = build_function_call (input_location,
2802 objc_exception_throw_decl, t);
2803 t = build_stmt (input_location, COND_EXPR,
2804 c_common_truthvalue_conversion (input_location,
2805 rethrow_decl),
2806 t, NULL);
2807 SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus);
2808 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1));
2809
2810 return bind;
2811 }
2812
2813 /* We do not expect this to be used at the moment.
2814 If (a) it is possible to implement unwinder exceptions.
2815 (b) we do it... then it might be possibly useful.
2816 */
2817 static GTY(()) tree objc_eh_personality_decl;
2818
2819 static tree
2820 objc_eh_runtime_type (tree type)
2821 {
2822 tree ident, eh_id, decl, str;
2823
2824 gcc_unreachable ();
2825 if (type == error_mark_node)
2826 {
2827 /* Use 'ErrorMarkNode' as class name when error_mark_node is found
2828 to prevent an ICE. Note that we know that the compiler will
2829 terminate with an error and this 'ErrorMarkNode' class name will
2830 never be actually used. */
2831 ident = get_identifier ("ErrorMarkNode");
2832 goto make_err_class;
2833 }
2834
2835 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
2836 {
2837 ident = get_identifier ("id");
2838 goto make_err_class;
2839 }
2840
2841 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
2842 {
2843 #ifdef OBJCPLUS
2844 /* This routine is also called for c++'s catch clause; in which case,
2845 we use c++'s typeinfo decl. */
2846 return build_eh_type_type (type);
2847 #else
2848 error ("non-objective-c type '%T' cannot be caught", type);
2849 ident = get_identifier ("ErrorMarkNode");
2850 goto make_err_class;
2851 #endif
2852 }
2853 else
2854 ident = OBJC_TYPE_NAME (TREE_TYPE (type));
2855
2856 make_err_class:
2857 /* If this class was already referenced, then it will be output during
2858 meta-data emission, so we don't need to do it here. */
2859 decl = get_objc_string_decl (ident, class_names);
2860 eh_id = add_objc_string (ident, class_names);
2861 if (!decl)
2862 {
2863 /* Not found ... so we need to build it - from the freshly-entered id. */
2864 decl = get_objc_string_decl (ident, class_names);
2865 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1,
2866 IDENTIFIER_POINTER (ident));
2867 /* We have to finalize this var here, because this might be called after
2868 all the other metadata strings have been emitted. */
2869 finish_var_decl (decl, str);
2870 }
2871 return eh_id;
2872 }
2873
2874 /* For NeXT ABI 0 and 1, the personality routines are just those of the
2875 underlying language. */
2876
2877 static tree
2878 objc_eh_personality (void)
2879 {
2880 if (!objc_eh_personality_decl)
2881 #ifndef OBJCPLUS
2882 objc_eh_personality_decl = build_personality_function ("gcc");
2883 #else
2884 objc_eh_personality_decl = build_personality_function ("gxx");
2885 #endif
2886 return objc_eh_personality_decl;
2887 }
2888
2889 /* --- interfaces --- */
2890
2891 static tree
2892 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED)
2893 {
2894 tree t;
2895 VEC(tree, gc) *parms = VEC_alloc (tree, gc, 1);
2896 /* A throw is just a call to the runtime throw function with the
2897 object as a parameter. */
2898 VEC_quick_push (tree, parms, throw_expr);
2899 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, NULL);
2900 VEC_free (tree, gc, parms);
2901 return add_stmt (t);
2902 }
2903
2904 /* Build __builtin_eh_pointer, or the moral equivalent. In the case
2905 of Darwin, we'll arrange for it to be initialized (and associated
2906 with a binding) later. */
2907
2908 static tree
2909 objc_build_exc_ptr (struct objc_try_context **cur_try_context)
2910 {
2911 if (flag_objc_sjlj_exceptions)
2912 {
2913 tree var = (*cur_try_context)->caught_decl;
2914 if (!var)
2915 {
2916 var = objc_create_temporary_var (objc_object_type, NULL);
2917 (*cur_try_context)->caught_decl = var;
2918 }
2919 return var;
2920 }
2921 else
2922 {
2923 tree t;
2924 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
2925 t = build_call_expr (t, 1, integer_zero_node);
2926 return fold_convert (objc_object_type, t);
2927 }
2928 }
2929
2930 static tree
2931 begin_catch (struct objc_try_context **cur_try_context, tree type,
2932 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
2933 {
2934 tree t;
2935 /* Record the data for the catch in the try context so that we can
2936 finalize it later. We treat ellipsis the same way as catching
2937 with 'id xyz'. */
2938 t = build_stmt (input_location, CATCH_EXPR, type, compound);
2939 (*cur_try_context)->current_catch = t;
2940
2941 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
2942 t = objc_build_exc_ptr (cur_try_context);
2943 t = convert (TREE_TYPE (decl), t);
2944 return build2 (MODIFY_EXPR, void_type_node, decl, t);
2945 }
2946
2947 static void
2948 finish_catch (struct objc_try_context **cur_try_context, tree current_catch)
2949 {
2950 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list));
2951 }
2952
2953 static tree
2954 finish_try_stmt (struct objc_try_context **cur_try_context)
2955 {
2956 tree stmt;
2957 struct objc_try_context *c = *cur_try_context;
2958 /* If we're doing Darwin setjmp exceptions, build the big nasty. */
2959 if (flag_objc_sjlj_exceptions)
2960 {
2961 bool save = in_late_binary_op;
2962 in_late_binary_op = true;
2963 if (!c->finally_body)
2964 {
2965 c->finally_locus = input_location;
2966 c->end_finally_locus = input_location;
2967 }
2968 stmt = next_sjlj_build_try_catch_finally (cur_try_context);
2969 in_late_binary_op = save;
2970 }
2971 else
2972 /* This doesn't happen at the moment... but maybe one day... */
2973 {
2974 /* Otherwise, nest the CATCH inside a FINALLY. */
2975 stmt = c->try_body;
2976 if (c->catch_list)
2977 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
2978 if (c->finally_body)
2979 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
2980 }
2981 return stmt;
2982 }
2983
2984 #include "gt-objc-objc-next-runtime-abi-01.h"