1 /* Next Runtime (ABI-2) private.
2 Copyright (C) 2011-2022 Free Software Foundation, Inc.
3
4 Contributed by Iain Sandoe and based, in part, on an implementation in
5 'branches/apple/trunk' contributed by Apple Computer Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
22
23 /* The NeXT ABI2 is used for m64 implementations on Darwin/OSX machines.
24
25 This version is intended to match (logically) the output of Apple's
26 4.2.1 compiler. */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tree.h"
32 #include "stringpool.h"
33 #include "attribs.h"
34
35 #ifdef OBJCPLUS
36 #include "cp/cp-tree.h"
37 #else
38 #include "c/c-tree.h"
39 #include "c/c-lang.h"
40 #endif
41 #include "langhooks.h"
42 #include "c-family/c-objc.h"
43 #include "objc-act.h"
44
45 /* When building Objective-C++, we are not linking against the C front-end
46 and so need to replicate the C tree-construction functions in some way. */
47 #ifdef OBJCPLUS
48 #define OBJCP_REMAP_FUNCTIONS
49 #include "objcp-decl.h"
50 #endif /* OBJCPLUS */
51
52 #include "target.h"
53 #include "tree-iterator.h"
54 #include "opts.h"
55
56 #include "objc-runtime-hooks.h"
57 #include "objc-runtime-shared-support.h"
58 #include "objc-next-metadata-tags.h"
59 #include "objc-encoding.h"
60
61 /* ABI 2 Private definitions. */
62 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString"
63
64 #define TAG_GETCLASS "objc_getClass"
65 #define TAG_GETMETACLASS "objc_getMetaClass"
66
67 #define TAG_MSGSEND "objc_msgSend"
68 #define TAG_MSGSENDID "objc_msgSendId"
69 #define TAG_MSGSENDSUPER "objc_msgSendSuper2"
70 #define TAG_MSGSEND_STRET "objc_msgSend_stret"
71 #define TAG_MSGSENDID_STRET "objc_msgSendId_stret"
72 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper2_stret"
73
74 #define USE_FIXUP_BEFORE 100600
75 #define WEAK_PROTOCOLS_AFTER 100700
76 #define TAG_FIXUP "_fixup"
77
78
79 #define TAG_NEXT_EHVTABLE_NAME "objc_ehtype_vtable"
80 #define TAG_V2_EH_TYPE "objc_ehtype_t"
81
82 #define UTAG_V2_CLASS "_class_t"
83 #define UTAG_V2_CLASS_RO "_class_ro_t"
84 #define UTAG_V2_PROTOCOL "_protocol_t"
85 #define UTAG_V2_PROTOCOL_LIST "_protocol_list_t"
86
87 #define UTAG_V2_EH_TYPE "_objc_ehtype_t"
88
89 #define OBJC2_CLS_HAS_CXX_STRUCTORS 0x0004L
90
91 enum objc_v2_tree_index
92 {
93 /* Templates. */
94 OCTI_V2_CLS_TEMPL,
95 OCTI_V2_CAT_TEMPL,
96 OCTI_V2_CLS_RO_TEMPL,
97 OCTI_V2_PROTO_TEMPL,
98 OCTI_V2_IVAR_TEMPL,
99 OCTI_V2_IVAR_LIST_TEMPL,
100 OCTI_V2_MESSAGE_REF_TEMPL,
101 OCTI_V2_SUPER_MESSAGE_REF_TEMPL,
102
103 OCTI_V2_MESSAGE_SELECTOR_TYPE,
104 OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE,
105 OCTI_V2_IMP_TYPE,
106 OCTI_V2_SUPER_IMP_TYPE,
107
108 OCTI_V2_CACHE_DECL,
109 OCTI_V2_VTABLE_DECL,
110
111 OCTI_V2_PROPERTY_TEMPL,
112
113 /* V2 messaging. */
114 OCTI_V2_UMSG_FIXUP_DECL,
115 OCTI_V2_UMSG_STRET_FIXUP_DECL,
116 OCTI_V2_UMSG_ID_FIXUP_DECL,
117 OCTI_V2_UMSG_ID_STRET_FIXUP_DECL,
118 OCTI_V2_UMSG_SUPER2_FIXUP_DECL,
119 OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL,
120
121 /* Exceptions - related. */
122 OCTI_V2_BEGIN_CATCH_DECL,
123 OCTI_V2_END_CATCH_DECL,
124 OCTI_V2_RETHROW_DECL,
125
126 OCTI_V2_MAX
127 };
128
129 #define objc_v2_class_template objc_v2_global_trees[OCTI_V2_CLS_TEMPL]
130 #define objc_v2_class_ro_template \
131 objc_v2_global_trees[OCTI_V2_CLS_RO_TEMPL]
132 #define objc_v2_category_template \
133 objc_v2_global_trees[OCTI_V2_CAT_TEMPL]
134 #define objc_v2_protocol_template \
135 objc_v2_global_trees[OCTI_V2_PROTO_TEMPL]
136
137 /* struct message_ref_t */
138 #define objc_v2_message_ref_template \
139 objc_v2_global_trees[OCTI_V2_MESSAGE_REF_TEMPL]
140
141 #define objc_v2_ivar_list_ptr objc_v2_global_trees[OCTI_V2_IVAR_LIST_TEMPL]
142
143 /* struct super_message_ref_t */
144 #define objc_v2_super_message_ref_template \
145 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_REF_TEMPL]
146
147 /* struct message_ref_t* */
148 #define objc_v2_selector_type objc_v2_global_trees[OCTI_V2_MESSAGE_SELECTOR_TYPE]
149 /* struct super_super_message_ref_t */
150 #define objc_v2_super_selector_type \
151 objc_v2_global_trees[OCTI_V2_SUPER_MESSAGE_SELECTOR_TYPE]
152 #define objc_v2_imp_type objc_v2_global_trees[OCTI_V2_IMP_TYPE]
153 #define objc_v2_super_imp_type objc_v2_global_trees[OCTI_V2_SUPER_IMP_TYPE]
154
155 #define UOBJC_V2_CACHE_decl objc_v2_global_trees[OCTI_V2_CACHE_DECL]
156 #define UOBJC_V2_VTABLE_decl objc_v2_global_trees[OCTI_V2_VTABLE_DECL]
157
158 #define objc_v2_ivar_template objc_v2_global_trees[OCTI_V2_IVAR_TEMPL]
159 #define objc_v2_property_template \
160 objc_v2_global_trees[OCTI_V2_PROPERTY_TEMPL]
161
162 /* V2 Messaging */
163
164 /* objc_msgSend_fixup_rtp */
165 #define umsg_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_FIXUP_DECL]
166 /* objc_msgSend_stret_fixup_rtp */
167 #define umsg_stret_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_STRET_FIXUP_DECL]
168 /* objc_msgSendId_fixup_rtp */
169 #define umsg_id_fixup_decl objc_v2_global_trees[OCTI_V2_UMSG_ID_FIXUP_DECL]
170 /* objc_msgSendId_stret_fixup_rtp */
171 #define umsg_id_stret_fixup_decl \
172 objc_v2_global_trees[OCTI_V2_UMSG_ID_STRET_FIXUP_DECL]
173 /* objc_msgSendSuper2_fixup_rtp */
174 #define umsg_id_super2_fixup_decl \
175 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_FIXUP_DECL]
176 /* objc_msgSendSuper2_stret_fixup_rtp */
177 #define umsg_id_super2_stret_fixup_decl \
178 objc_v2_global_trees[OCTI_V2_UMSG_SUPER2_STRET_FIXUP_DECL]
179
180 #define objc2_begin_catch_decl objc_v2_global_trees[OCTI_V2_BEGIN_CATCH_DECL]
181 #define objc2_end_catch_decl objc_v2_global_trees[OCTI_V2_END_CATCH_DECL]
182 #define objc_rethrow_exception_decl \
183 objc_v2_global_trees[OCTI_V2_RETHROW_DECL]
184
185 /* The OCTI_V2_... enumeration itself is in above. */
186 static GTY(()) tree objc_v2_global_trees[OCTI_V2_MAX];
187
188 static void next_runtime_02_initialize (void);
189
190 static void build_v2_message_ref_templates (void);
191 static void build_v2_class_templates (void);
192 static void build_v2_super_template (void);
193 static void build_v2_category_template (void);
194 static void build_v2_protocol_template (void);
195
196 static tree next_runtime_abi_02_super_superclassfield_id (void);
197
198 static tree next_runtime_abi_02_class_decl (tree);
199 static tree next_runtime_abi_02_metaclass_decl (tree);
200 static tree next_runtime_abi_02_category_decl (tree);
201 static tree next_runtime_abi_02_protocol_decl (tree);
202 static tree next_runtime_abi_02_string_decl (tree, const char *, string_section);
203
204 static tree next_runtime_abi_02_get_class_reference (tree);
205 static tree next_runtime_abi_02_build_selector_reference (location_t, tree, tree);
206 static tree next_runtime_abi_02_get_protocol_reference (location_t, tree);
207 static tree next_runtime_abi_02_build_ivar_ref (location_t, tree, tree);
208 static tree next_runtime_abi_02_get_class_super_ref (location_t, struct imp_entry *, bool);
209 static tree next_runtime_abi_02_get_category_super_ref (location_t, struct imp_entry *, bool);
210
211 static tree next_runtime_abi_02_receiver_is_class_object (tree);
212 static void next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **,
213 tree, int, int);
214 static tree next_runtime_abi_02_build_objc_method_call (location_t, tree, tree,
215 tree, tree, tree, int);
216 static bool next_runtime_abi_02_setup_const_string_class_decl (void);
217 static tree next_runtime_abi_02_build_const_string_constructor (location_t, tree, int);
218
219 static tree create_extern_decl (tree, const char *);
220
221 static void objc_generate_v2_next_metadata (void);
222 static bool objc2_objc_exception_attr (tree);
223
224 /* void build_v2_protocol_reference (tree);*/
225 static void build_v2_ehtype_template (void);
226 static void build_v2_eh_catch_objects (void);
227 static tree next_runtime_02_eh_type (tree);
228 static tree objc_eh_personality (void);
229 static tree build_throw_stmt (location_t, tree, bool);
230 static tree objc_build_exc_ptr (struct objc_try_context **);
231 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
232 static void finish_catch (struct objc_try_context **, tree);
233 static tree finish_try_stmt (struct objc_try_context **);
234
235 /* TODO: Use an objc-map. */
236 static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
237
238 bool
objc_next_runtime_abi_02_init(objc_runtime_hooks * rthooks)239 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
240 {
241 extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
242
243 if (flag_objc_sjlj_exceptions)
244 {
245 inform (UNKNOWN_LOCATION,
246 "%<-fobjc-sjlj-exceptions%> is ignored for "
247 "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
248 "greater than 1");
249 flag_objc_sjlj_exceptions = 0;
250 }
251
252 /* NeXT ABI 2 is intended to default to checking for nil receivers. */
253 if (! OPTION_SET_P (flag_objc_nilcheck))
254 flag_objc_nilcheck = 1;
255
256 rthooks->initialize = next_runtime_02_initialize;
257 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME;
258 rthooks->tag_getclass = TAG_GETCLASS;
259 rthooks->super_superclassfield_ident = next_runtime_abi_02_super_superclassfield_id;
260
261 rthooks->class_decl = next_runtime_abi_02_class_decl;
262 rthooks->metaclass_decl = next_runtime_abi_02_metaclass_decl;
263 rthooks->category_decl = next_runtime_abi_02_category_decl;
264 rthooks->protocol_decl = next_runtime_abi_02_protocol_decl;
265 rthooks->string_decl = next_runtime_abi_02_string_decl;
266
267 rthooks->get_class_reference = next_runtime_abi_02_get_class_reference;
268 rthooks->build_selector_reference = next_runtime_abi_02_build_selector_reference;
269 rthooks->get_protocol_reference = next_runtime_abi_02_get_protocol_reference;
270 rthooks->build_ivar_reference = next_runtime_abi_02_build_ivar_ref;
271 rthooks->get_class_super_ref = next_runtime_abi_02_get_class_super_ref;
272 rthooks->get_category_super_ref = next_runtime_abi_02_get_category_super_ref;
273
274 rthooks->receiver_is_class_object = next_runtime_abi_02_receiver_is_class_object;
275 rthooks->get_arg_type_list_base = next_runtime_abi_02_get_arg_type_list_base;
276 rthooks->build_objc_method_call = next_runtime_abi_02_build_objc_method_call;
277
278 rthooks->setup_const_string_class_decl =
279 next_runtime_abi_02_setup_const_string_class_decl;
280 rthooks->build_const_string_constructor =
281 next_runtime_abi_02_build_const_string_constructor;
282
283 rthooks->build_throw_stmt = build_throw_stmt;
284 rthooks->build_exc_ptr = objc_build_exc_ptr;
285 rthooks->begin_catch = begin_catch;
286 rthooks->finish_catch = finish_catch;
287 rthooks->finish_try_stmt = finish_try_stmt;
288
289 rthooks->generate_metadata = objc_generate_v2_next_metadata;
290 return true;
291 }
292
293 /* We need a way to convey what kind of meta-data are represented by a given
294 variable, since each type is expected (by the runtime) to be found in a
295 specific named section. The solution must be usable with LTO.
296
297 The scheme used for NeXT ABI 0/1 (partial matching of variable names) is not
298 satisfactory when LTO is used with ABI-2. We now tag ObjC meta-data with
299 identification attributes in the front end. The back-end may choose to act
300 on these as it requires. */
301
302 static void
next_runtime_abi_02_init_metadata_attributes(void)303 next_runtime_abi_02_init_metadata_attributes (void)
304 {
305 if (!objc_meta)
306 objc_meta = get_identifier ("OBJC2META");
307
308 if (!meta_base)
309 meta_base = get_identifier ("V2_BASE");
310
311 meta_class = get_identifier ("G2_CLAS");
312 meta_metaclass = get_identifier ("G2_META");
313 meta_category = meta_base;
314 meta_protocol = get_identifier ("V2_PCOL");
315
316 meta_clac_vars =
317 meta_clai_vars = meta_base;
318
319 meta_clac_meth =
320 meta_clai_meth =
321 meta_catc_meth =
322 meta_cati_meth =
323 meta_proto_cls_meth =
324 meta_proto_nst_meth = meta_base;
325
326 meta_clas_prot =
327 meta_catg_prot = meta_base;
328
329 meta_sel_refs = get_identifier ("V2_SRFS");
330
331 meta_class_name = get_identifier ("V2_CNAM");
332 meta_meth_name = get_identifier ("V2_MNAM");
333
334 meta_meth_type = get_identifier ("V2_MTYP");
335 meta_prop_name_attr = get_identifier ("V2_STRG");
336
337 meta_mref = get_identifier ("V2_MREF");
338 meta_class_ref = get_identifier ("V2_CLRF");
339 meta_superclass_ref = get_identifier ("V2_SURF");
340
341 meta_label_classlist = get_identifier ("V2_CLAB");
342 meta_label_nonlazy_classlist = get_identifier ("V2_NLCL");
343 meta_label_categorylist = get_identifier ("V2_CALA");
344 meta_label_nonlazy_categorylist = get_identifier ("V2_NLCA");
345
346 meta_label_protocollist = get_identifier ("V2_PLST");
347 meta_proto_ref = get_identifier ("V2_PRFS");
348
349 meta_info = get_identifier ("V2_INFO");
350
351 meta_ehtype = get_identifier ("V2_EHTY");
352
353 meta_const_str = get_identifier ("V2_CSTR");
354
355 meta_ivar_ref = get_identifier ("V2_IVRF");
356 }
357
next_runtime_02_initialize(void)358 static void next_runtime_02_initialize (void)
359 {
360 tree type;
361 #ifdef OBJCPLUS
362 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by
363 default. */
364 if (!OPTION_SET_P (flag_objc_call_cxx_cdtors))
365 global_options.x_flag_objc_call_cxx_cdtors = 1;
366 #endif
367
368 /* Set up attributes to be attached to the meta-data so that they
369 will be placed in the correct sections. */
370 next_runtime_abi_02_init_metadata_attributes ();
371
372 /* `struct objc_selector *' */
373 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE,
374 get_identifier (TAG_SELECTOR)));
375
376 /* SEL typedef. */
377 type = lang_hooks.decls.pushdecl (build_decl (input_location,
378 TYPE_DECL,
379 objc_selector_name,
380 objc_selector_type));
381 suppress_warning (type);
382
383 /* IMP : id (*) (id, _message_ref_t*, ...)
384 SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)
385 objc_v2_selector_type. */
386 build_v2_message_ref_templates ();
387
388 objc_v2_ivar_list_ptr =
389 build_pointer_type (xref_tag (RECORD_TYPE,
390 get_identifier ("_ivar_list_t")));
391
392 objc_prop_list_ptr =
393 build_pointer_type (xref_tag (RECORD_TYPE,
394 get_identifier ("_prop_list_t")));
395
396 build_v2_class_templates ();
397 build_v2_super_template ();
398 build_v2_protocol_template ();
399 build_v2_category_template ();
400
401 bool fixup_p = flag_next_runtime < USE_FIXUP_BEFORE;
402 if (fixup_p)
403 {
404 /* id objc_msgSend_fixup_rtp (id, struct message_ref_t*, ...); */
405 type = build_varargs_function_type_list (objc_object_type,
406 objc_object_type,
407 objc_v2_selector_type,
408 NULL_TREE);
409 }
410 else
411 {
412 /* id objc_msgSendXXXX (id, SEL, ...); */
413 type = build_varargs_function_type_list (objc_object_type,
414 objc_object_type,
415 objc_selector_type,
416 NULL_TREE);
417 }
418 const char *fnam = fixup_p ? TAG_MSGSEND TAG_FIXUP : TAG_MSGSEND;
419 umsg_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
420 NULL, NULL_TREE);
421 TREE_NOTHROW (umsg_fixup_decl) = 0;
422
423 /* id objc_msgSend_stret_fixup_rtp (id, struct message_ref_t*, ...); */
424 fnam = fixup_p ? TAG_MSGSEND_STRET TAG_FIXUP : TAG_MSGSEND_STRET;
425 umsg_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
426 NULL, NULL_TREE);
427 TREE_NOTHROW (umsg_stret_fixup_decl) = 0;
428
429 /* id objc_msgSendId_fixup_rtp (id, struct message_ref_t*, ...); */
430 fnam = fixup_p ? TAG_MSGSENDID TAG_FIXUP : TAG_MSGSENDID;
431 umsg_id_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
432 NULL, NULL_TREE);
433 TREE_NOTHROW (umsg_id_fixup_decl) = 0;
434
435 /* id objc_msgSendId_stret_fixup_rtp (id, struct message_ref_t*, ...); */
436 fnam = fixup_p ? TAG_MSGSENDID_STRET TAG_FIXUP : TAG_MSGSENDID_STRET;
437 umsg_id_stret_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
438 NULL, NULL_TREE);
439 TREE_NOTHROW (umsg_id_stret_fixup_decl) = 0;
440
441 /* id objc_msgSendSuper2_fixup_rtp
442 (struct objc_super *, struct message_ref_t*, ...); */
443 type = build_varargs_function_type_list (objc_object_type,
444 objc_super_type,
445 objc_v2_super_selector_type,
446 NULL_TREE);
447 fnam = fixup_p ? TAG_MSGSENDSUPER TAG_FIXUP : TAG_MSGSENDSUPER;
448 umsg_id_super2_fixup_decl = add_builtin_function (fnam, type, 0, NOT_BUILT_IN,
449 NULL, NULL_TREE);
450 TREE_NOTHROW (umsg_id_super2_fixup_decl) = 0;
451
452 /* id objc_msgSendSuper2_stret_fixup_rtp
453 (struct objc_super *, struct message_ref_t*, ...); */
454 fnam = fixup_p ? TAG_MSGSENDSUPER_STRET TAG_FIXUP : TAG_MSGSENDSUPER_STRET;
455 umsg_id_super2_stret_fixup_decl = add_builtin_function (fnam, type, 0,
456 NOT_BUILT_IN, NULL,
457 NULL_TREE);
458 TREE_NOTHROW (umsg_id_super2_stret_fixup_decl) = 0;
459
460 /* Present in the library, but unused by the FE. */
461 /* Protocol *objc_getProtocol (const char *)
462 type = build_function_type_list (objc_protocol_type,
463 const_string_type_node,
464 NULL_TREE);
465 objc_v2_getprotocol_decl = add_builtin_function ("objc_getProtocol",
466 type, 0, NOT_BUILT_IN,
467 NULL, NULL_TREE);
468 TREE_NOTHROW (objc_v2_getprotocol_decl) = 0;*/
469
470 UOBJC_V2_CACHE_decl = create_extern_decl (ptr_type_node,
471 "_objc_empty_cache");
472
473 UOBJC_V2_VTABLE_decl = create_extern_decl (objc_v2_imp_type,
474 "_objc_empty_vtable");
475
476 /* id objc_getClass (const char *); */
477 type = build_function_type_list (objc_object_type,
478 const_string_type_node,
479 NULL_TREE);
480 objc_get_class_decl = add_builtin_function (TAG_GETCLASS,
481 type, 0, NOT_BUILT_IN,
482 NULL, NULL_TREE);
483
484 /* id objc_getMetaClass (const char *); */
485 objc_get_meta_class_decl = add_builtin_function (TAG_GETMETACLASS,
486 type, 0, NOT_BUILT_IN,
487 NULL, NULL_TREE);
488
489 /* This is the type of all of the following functions
490 objc_copyStruct(). */
491 type = build_function_type_list (void_type_node,
492 ptr_type_node,
493 const_ptr_type_node,
494 ptrdiff_type_node,
495 boolean_type_node,
496 boolean_type_node,
497 NULL_TREE);
498 /* Declare the following function:
499 void
500 objc_copyStruct (void *destination, const void *source,
501 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */
502 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct",
503 type, 0, NOT_BUILT_IN,
504 NULL, NULL_TREE);
505 TREE_NOTHROW (objc_copyStruct_decl) = 0;
506 objc_getPropertyStruct_decl = NULL_TREE;
507 objc_setPropertyStruct_decl = NULL_TREE;
508
509 gcc_checking_assert (!flag_objc_sjlj_exceptions);
510
511 /* Although we warn that fobjc-exceptions is required for exceptions
512 code, we carry on and create it anyway. */
513
514 /* This can be required, even when exceptions code is not present,
515 when an __attribute__((objc_exception)) is applied to a
516 class. */
517 build_v2_ehtype_template ();
518
519 /* void * objc_begin_catch (void *) */
520 type = build_function_type_list (ptr_type_node,
521 ptr_type_node, NULL_TREE);
522
523 objc2_begin_catch_decl = add_builtin_function ("objc_begin_catch",
524 type, 0, NOT_BUILT_IN,
525 NULL, NULL_TREE);
526 TREE_NOTHROW (objc2_begin_catch_decl) = 0;
527
528 /* void objc_end_catch () */
529 type = build_function_type_list (void_type_node, NULL_TREE);
530 objc2_end_catch_decl = add_builtin_function ("objc_end_catch",
531 type, 0, NOT_BUILT_IN,
532 NULL, NULL_TREE);
533 TREE_NOTHROW (objc2_end_catch_decl) = 0;
534
535 /* void objc_exception_rethrow (void) */
536 objc_rethrow_exception_decl =
537 add_builtin_function ("objc_exception_rethrow",
538 type, 0, NOT_BUILT_IN,
539 NULL, NULL_TREE);
540 TREE_NOTHROW (objc_rethrow_exception_decl) = 0;
541 using_eh_for_cleanups ();
542 lang_hooks.eh_runtime_type = next_runtime_02_eh_type;
543 lang_hooks.eh_personality = objc_eh_personality;
544 }
545
546 /* NOTE --- templates --- */
547
548 /* Set 'objc_v2_message_ref_template' to the data type node for
549 'struct _message_ref_t'. This needs to be done just once per
550 compilation. Also Set 'objc_v2_super_message_ref_template' to data
551 type node for 'struct _super_message_ref_t'. */
552
553 /* struct _message_ref_t
554 {
555 IMP messenger;
556 SEL name;
557 };
558 where IMP is: id (*) (id, _message_ref_t*, ...)
559 */
560
561 /* struct _super_message_ref_t
562 {
563 SUPER_IMP messenger;
564 SEL name;
565 };
566 where SUPER_IMP is: id (*) ( super_t*, _super_message_ref_t*, ...)
567 */
568
569 static void
build_v2_message_ref_templates(void)570 build_v2_message_ref_templates (void)
571 {
572 tree ptr_message_ref_t;
573 tree decls, *chain = NULL;
574
575 /* struct _message_ref_t {...} */
576 objc_v2_message_ref_template =
577 objc_start_struct (get_identifier ("_message_ref_t"));
578
579 /* IMP messenger; */
580 ptr_message_ref_t =
581 build_pointer_type (xref_tag (RECORD_TYPE,
582 get_identifier ("_message_ref_t")));
583
584 objc_v2_imp_type =
585 build_pointer_type (build_function_type_list
586 (objc_object_type,
587 objc_object_type,
588 ptr_message_ref_t,
589 NULL_TREE));
590
591 decls = add_field_decl (objc_v2_imp_type, "messenger", &chain);
592
593 /* SEL name; */
594 add_field_decl (objc_selector_type, "name", &chain);
595
596 objc_finish_struct (objc_v2_message_ref_template, decls);
597
598 objc_v2_selector_type = build_pointer_type (objc_v2_message_ref_template);
599
600 chain = NULL;
601 /* struct _super_message_ref_t {...} */
602 objc_v2_super_message_ref_template =
603 objc_start_struct (get_identifier ("_super_message_ref_t"));
604
605 /* SUPER_IMP messenger; */
606 ptr_message_ref_t = build_pointer_type
607 (xref_tag (RECORD_TYPE,
608 get_identifier ("_super_message_ref_t")));
609
610 objc_v2_super_imp_type =
611 build_pointer_type (build_function_type_list
612 (objc_object_type,
613 objc_super_type,
614 ptr_message_ref_t,
615 NULL_TREE));
616
617 add_field_decl (objc_v2_super_imp_type, "messenger", &chain);
618
619 /* SEL name; */
620 add_field_decl (objc_selector_type, "name", &chain);
621
622 objc_finish_struct (objc_v2_super_message_ref_template, decls);
623 objc_v2_super_selector_type =
624 build_pointer_type (objc_v2_super_message_ref_template);
625 }
626
627 /* Build following types which represent each class implementation.
628
629 struct class_ro_t
630 {
631 uint32_t const flags;
632 uint32_t const instanceStart;
633 uint32_t const instanceSize;
634 #ifdef __LP64__
635 uint32_t const reserved;
636 #endif
637 const uint8_t * const ivarLayout;
638 const char *const name;
639 const struct method_list_t * const baseMethods;
640 const struct objc_protocol_list *const baseProtocols;
641 const struct ivar_list_t *const ivars;
642 const uint8_t * const weakIvarLayout;
643 const struct _prop_list_t * const properties;
644 };
645
646 struct class_t
647 {
648 struct class_t *isa;
649 struct class_t *superclass;
650 void *cache;
651 IMP *vtable;
652
653 ...When this is active - it will point to a rw version, but
654 when we build the meta-data we point it to the ro...
655 struct class_ro_t *data;
656 };
657
658 */
659
660 static void
build_v2_class_templates(void)661 build_v2_class_templates (void)
662 {
663 tree cnst_strg_type;
664 tree decls, *chain = NULL;
665
666 /* struct class_ro_t {...} */
667 objc_v2_class_ro_template =
668 objc_start_struct (get_identifier (UTAG_V2_CLASS_RO));
669
670 /* uint32_t const flags; */
671 decls = add_field_decl (integer_type_node, "flags", &chain);
672
673 /* uint32_t const instanceStart; */
674 add_field_decl (integer_type_node, "instanceStart", &chain);
675
676 /* uint32_t const instanceSize; */
677 add_field_decl (integer_type_node, "instanceSize", &chain);
678
679 /* This ABI is currently only used on m64 NeXT. We always
680 explicitly declare the alignment padding. */
681 /* uint32_t const reserved; */
682 add_field_decl (integer_type_node, "reserved", &chain);
683
684 /* const uint8_t * const ivarLayout; */
685 cnst_strg_type = build_pointer_type (unsigned_char_type_node);
686 add_field_decl (cnst_strg_type, "ivarLayout", &chain);
687
688 /* const char *const name; */
689 add_field_decl (string_type_node, "name", &chain);
690
691 /* const struct method_list_t * const baseMethods; */
692 add_field_decl (objc_method_list_ptr, "baseMethods", &chain);
693
694 /* const struct objc_protocol_list *const baseProtocols; */
695 add_field_decl (build_pointer_type
696 (xref_tag (RECORD_TYPE,
697 get_identifier (UTAG_V2_PROTOCOL_LIST))),
698 "baseProtocols", &chain);
699
700 /* const struct ivar_list_t *const ivars; */
701 add_field_decl (objc_v2_ivar_list_ptr, "ivars", &chain);
702
703 /* const uint8_t * const weakIvarLayout; */
704 add_field_decl (cnst_strg_type, "weakIvarLayout", &chain);
705
706 /* struct _prop_list_t * baseProperties; */
707 add_field_decl (objc_prop_list_ptr, "baseProperties", &chain);
708
709 objc_finish_struct (objc_v2_class_ro_template, decls);
710
711 chain = NULL;
712 /* struct class_t {...} */
713 objc_v2_class_template =
714 objc_start_struct (get_identifier (UTAG_V2_CLASS));
715
716 /* struct class_t *isa; */
717 decls = add_field_decl (build_pointer_type (objc_v2_class_template),
718 "isa", &chain);
719
720 /* struct class_t * const superclass; */
721 add_field_decl (build_pointer_type (objc_v2_class_template),
722 "superclass", &chain);
723
724 /* void *cache; */
725 add_field_decl (build_pointer_type (void_type_node), "cache", &chain);
726
727 /* IMP *vtable; */
728 add_field_decl (build_pointer_type (objc_v2_imp_type), "vtable", &chain);
729
730 /* struct class_ro_t *ro; */
731 add_field_decl (build_pointer_type (objc_v2_class_ro_template), "ro", &chain);
732
733 objc_finish_struct (objc_v2_class_template, decls);
734 }
735
736 /* struct _objc_super
737 {
738 struct _objc_object *self;
739 Class cls;
740 }; */
741 void
build_v2_super_template(void)742 build_v2_super_template (void)
743 {
744 tree decls, *chain = NULL;
745
746 objc_super_template = objc_start_struct (get_identifier (UTAG_SUPER));
747
748 /* struct _objc_object *self; */
749 decls = add_field_decl (objc_object_type, "self", &chain);
750
751 /* Class cls; */
752 add_field_decl (objc_class_type, "cls", &chain);
753
754 objc_finish_struct (objc_super_template, decls);
755 }
756
757 /* struct protocol_t
758 {
759 Class isa;
760 const char * const protocol_name;
761 const struct protocol_list_t * const protocol_list;
762 const struct method_list_t * const instance_methods;
763 const struct method_list_t * const class_methods;
764 const struct method_list_t * optionalInstanceMethods;
765 const struct method_list_t * optionalClassMethod
766 const struct _prop_list_t * const properties;
767 const uint32_t size;
768 const uint32_t flags;
769 const char ** extended_method_types;
770 const char * demangled_name;
771 const struct _prop_list_t * class_properties;
772 }
773 */
774 static void
build_v2_protocol_template(void)775 build_v2_protocol_template (void)
776 {
777 tree decls, *chain = NULL;
778
779 objc_v2_protocol_template =
780 objc_start_struct (get_identifier (UTAG_V2_PROTOCOL));
781
782 /* Class isa; */
783 decls = add_field_decl (objc_object_type, "isa", &chain);
784
785 /* char *protocol_name; */
786 add_field_decl (string_type_node, "protocol_name", &chain);
787
788 /* const struct protocol_list_t * const protocol_list; */
789 add_field_decl (build_pointer_type (objc_v2_protocol_template),
790 "protocol_list", &chain);
791
792 /* const struct method_list_t * const instance_methods; */
793 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain);
794
795 /* const struct method_list_t * const class_methods; */
796 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain);
797
798 /* const struct method_list_t * optionalInstanceMethods; */
799 add_field_decl (objc_method_proto_list_ptr, "optionalInstanceMethods", &chain);
800
801 /* const struct method_list_t * optionalClassMethods; */
802 add_field_decl (objc_method_proto_list_ptr, "optionalClassMethods", &chain);
803
804 /* struct _prop_list_t * properties; */
805 add_field_decl (objc_prop_list_ptr, "properties", &chain);
806
807 /* const uint32_t size; */
808 add_field_decl (integer_type_node, "size", &chain);
809
810 /* const uint32_t flags; */
811 add_field_decl (integer_type_node, "flags", &chain);
812
813 /* const char **extendedMethodTypes; */
814 tree ptr_to_ptr_to_char = build_pointer_type (string_type_node);
815 add_field_decl (ptr_to_ptr_to_char, "extended_method_types", &chain);
816
817 /* const char *demangledName; */
818 add_field_decl (string_type_node, "demangled_name", &chain);
819
820 /* const struct _prop_list_t *class_properties; */
821 add_field_decl (objc_prop_list_ptr, "class_properties", &chain);
822
823 objc_finish_struct (objc_v2_protocol_template, decls);
824 }
825
826 /* Build type for a category:
827 struct category_t
828 {
829 const char * const name;
830 struct class_t *const cls;
831 const struct method_list_t * const instance_methods;
832 const struct method_list_t * const class_methods;
833 const struct protocol_list_t * const protocols;
834 const struct _prop_list_t * const properties;
835 }
836 */
837
838 static void
build_v2_category_template(void)839 build_v2_category_template (void)
840 {
841 tree decls, *chain = NULL;
842
843 objc_v2_category_template =
844 objc_start_struct (get_identifier ("_category_t"));
845
846 /* char *name; */
847 decls = add_field_decl (string_type_node, "name", &chain);
848
849 /* struct class_t *const cls; */
850 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
851
852 /* struct method_list_t *instance_methods; */
853 add_field_decl (objc_method_list_ptr, "instance_methods", &chain);
854
855 /* struct method_list_t *class_methods; */
856 add_field_decl (objc_method_list_ptr, "class_methods", &chain);
857
858 /* struct protocol_list_t *protocol_list; */
859 add_field_decl (build_pointer_type (objc_v2_protocol_template),
860 "protocol_list", &chain );
861
862 /* struct _prop_list_t * properties; */
863 add_field_decl (objc_prop_list_ptr, "properties", &chain);
864
865 objc_finish_struct (objc_v2_category_template, decls);
866 }
867
868 /* NOTE --- Decls, Identifiers, Names etc. --- */
869
870 /* This routine is given a name and returns a matching extern variable
871 if one is found. */
872
873 static tree
hash_name_lookup(hash * hashlist,tree name)874 hash_name_lookup (hash *hashlist, tree name)
875 {
876 hash target;
877
878 target = hashlist[IDENTIFIER_HASH_VALUE (name) % SIZEHASHTABLE];
879
880 while (target)
881 {
882 if (name == DECL_NAME (target->key))
883 return target->key;
884
885 target = target->next;
886 }
887 return 0;
888 }
889
890 /* This routine is given an extern variable and enters it in its hash
891 table. Note that hashing is done on its inner IDENTIFIER_NODE
892 node. */
893
894 static void
hash_name_enter(hash * hashlist,tree id)895 hash_name_enter (hash *hashlist, tree id)
896 {
897 hash obj;
898 int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
899
900 obj = ggc_alloc<hashed_entry> ();
901 obj->list = 0;
902 obj->next = hashlist[slot];
903 obj->key = id;
904
905 hashlist[slot] = obj; /* append to front */
906 }
907
908 /* Create a declaration "extern <type> <name>;"
909 The var will need to be finalized (e.g. by calling finish_var_decl()). */
910
911 static tree
create_extern_decl(tree type,const char * name)912 create_extern_decl (tree type, const char *name)
913 {
914 tree id = get_identifier (name);
915 tree var = hash_name_lookup (extern_names, id);
916 if (var)
917 return var;
918 /* New name. */
919 var = start_var_decl (type, name);
920 TREE_STATIC (var) = 0;
921 DECL_EXTERNAL (var) = 1;
922 TREE_PUBLIC (var) = 1;
923 hash_name_enter (extern_names, var);
924 return var;
925 }
926
927 /* Create a globally visible definition for variable NAME of a given TYPE. The
928 finish_var_decl() routine will need to be called on it afterwards. */
929 static tree
930 create_global_decl (tree type, const char *name, bool is_def = false);
931
932 static tree
create_global_decl(tree type,const char * name,bool is_def)933 create_global_decl (tree type, const char *name, bool is_def)
934 {
935 tree id = get_identifier (name);
936 tree var = hash_name_lookup (extern_names, id);
937 if (var)
938 is_def = true;
939 else
940 {
941 var = start_var_decl (type, name);
942 hash_name_enter (extern_names, var);
943 }
944 if (is_def)
945 {
946 DECL_EXTERNAL (var) = 0;
947 TREE_STATIC (var) = 1;
948 }
949 TREE_PUBLIC (var) = 1;
950 return var;
951 }
952
953 /* Create a symbol with __attribute__ ((visibility ("hidden")))
954 attribute (private extern). */
955 static tree
956 create_hidden_decl (tree type, const char *name, bool is_def = false);
957
958 static tree
create_hidden_decl(tree type,const char * name,bool is_def)959 create_hidden_decl (tree type, const char *name, bool is_def)
960 {
961 tree decl = create_global_decl (type, name, is_def);
962 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
963 DECL_VISIBILITY_SPECIFIED (decl) = 1;
964 return decl;
965 }
966
967 /* Irritatingly, we have a different superclass field name for ABI=2. */
968 /* PS/TODO: The field name does not matter, it is only used internally
969 by the compiler. We can rename it to whatever we want. ;-) */
970
971 static tree
next_runtime_abi_02_super_superclassfield_id(void)972 next_runtime_abi_02_super_superclassfield_id (void)
973 {
974 /* TODO: Simplify. Just always return get_identifier ("cls"), or at
975 most look it once at startup then always return it. */
976 if (!super_superclassfield_id)
977 super_superclassfield_id = get_identifier ("cls");
978 return super_superclassfield_id;
979 }
980
981 static tree
next_runtime_abi_02_class_decl(tree klass)982 next_runtime_abi_02_class_decl (tree klass)
983 {
984 tree decl;
985 char buf[BUFSIZE];
986 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
987 IDENTIFIER_POINTER (CLASS_NAME (klass)));
988 /* ObjC2 classes are extern visible. */
989 decl = create_global_decl (objc_v2_class_template, buf);
990 OBJCMETA (decl, objc_meta, meta_class);
991 return decl;
992 }
993
994 static tree
next_runtime_abi_02_metaclass_decl(tree klass)995 next_runtime_abi_02_metaclass_decl (tree klass)
996 {
997 tree decl;
998 char buf[BUFSIZE];
999 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
1000 IDENTIFIER_POINTER (CLASS_NAME (klass)));
1001 /* ObjC2 classes are extern visible. */
1002 decl = create_global_decl (objc_v2_class_template, buf);
1003 OBJCMETA (decl, objc_meta, meta_metaclass);
1004 return decl;
1005 }
1006
1007 static tree
next_runtime_abi_02_category_decl(tree klass)1008 next_runtime_abi_02_category_decl (tree klass)
1009 {
1010 tree decl;
1011 char buf[BUFSIZE];
1012 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_%s",
1013 IDENTIFIER_POINTER (CLASS_NAME (klass)),
1014 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)));
1015 decl = start_var_decl (objc_v2_category_template, buf);
1016 OBJCMETA (decl, objc_meta, meta_category);
1017 return decl;
1018 }
1019
1020 static tree
next_runtime_abi_02_protocol_decl(tree p)1021 next_runtime_abi_02_protocol_decl (tree p)
1022 {
1023 tree decl;
1024 char buf[BUFSIZE];
1025
1026 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */
1027 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
1028 IDENTIFIER_POINTER (PROTOCOL_NAME (p)));
1029 if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
1030 {
1031 decl = create_hidden_decl (objc_v2_protocol_template, buf);
1032 DECL_WEAK (decl) = true;
1033 }
1034 else
1035 decl = start_var_decl (objc_v2_protocol_template, buf);
1036 OBJCMETA (decl, objc_meta, meta_protocol);
1037 DECL_PRESERVE_P (decl) = 1;
1038 return decl;
1039 }
1040
1041 static tree
next_runtime_abi_02_string_decl(tree type,const char * name,string_section where)1042 next_runtime_abi_02_string_decl (tree type, const char *name, string_section where)
1043 {
1044 tree var = start_var_decl (type, name);
1045 switch (where)
1046 {
1047 case class_names:
1048 OBJCMETA (var, objc_meta, meta_class_name);
1049 break;
1050 case meth_var_names:
1051 OBJCMETA (var, objc_meta, meta_meth_name);
1052 break;
1053 case meth_var_types:
1054 OBJCMETA (var, objc_meta, meta_meth_type);
1055 break;
1056 case prop_names_attr:
1057 OBJCMETA (var, objc_meta, meta_prop_name_attr);
1058 break;
1059 default:
1060 OBJCMETA (var, objc_meta, meta_base);
1061 break;
1062 }
1063 return var;
1064 }
1065
1066 /* NOTE --- entry --- */
1067
1068 struct GTY(()) ident_data_tuple {
1069 tree ident;
1070 tree data;
1071 };
1072
1073 /* This routine creates a file scope static variable of type 'Class'
1074 to hold the address of a class. */
1075
1076 static tree
build_v2_class_reference_decl(tree ident)1077 build_v2_class_reference_decl (tree ident)
1078 {
1079 tree decl;
1080 char buf[BUFSIZE];
1081
1082 snprintf (buf, BUFSIZE, "_OBJC_ClassRef_%s", IDENTIFIER_POINTER (ident));
1083 decl = start_var_decl (objc_class_type, buf);
1084 OBJCMETA (decl, objc_meta, meta_class_ref);
1085 return decl;
1086 }
1087
1088 /* This routine builds a class refs entry for each class name used.
1089 Initially, a (static-ref, IDENT) tuple is added to the list. The
1090 ident is replaced with address of the class metadata (of type
1091 'Class') in the output routine. */
1092
1093 static GTY (()) vec<ident_data_tuple, va_gc> *classrefs;
1094
1095 static tree
objc_v2_get_class_reference(tree ident)1096 objc_v2_get_class_reference (tree ident)
1097 {
1098 tree decl;
1099 ident_data_tuple e;
1100 if (classrefs)
1101 {
1102 int count;
1103 ident_data_tuple *ref;
1104 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1105 {
1106 if (ref->ident == ident)
1107 {
1108 if (!ref->data)
1109 ref->data = build_v2_class_reference_decl (ident);
1110 return ref->data;
1111 }
1112 }
1113 }
1114 else
1115 /* Somewhat arbitrary initial provision. */
1116 vec_alloc (classrefs, 16);
1117
1118 /* We come here if we don't find the entry - or if the table was yet
1119 to be created. */
1120 decl = build_v2_class_reference_decl (ident);
1121 e.ident = ident;
1122 e.data = decl;
1123 vec_safe_push (classrefs, e);
1124 return decl;
1125 }
1126
1127 static tree
next_runtime_abi_02_get_class_reference(tree ident)1128 next_runtime_abi_02_get_class_reference (tree ident)
1129 {
1130 if (!flag_zero_link)
1131 return objc_v2_get_class_reference (ident);
1132 else
1133 {
1134 /* We fall back to using objc_getClass (). */
1135 vec<tree, va_gc> *v;
1136 vec_alloc (v, 1);
1137 tree t;
1138 /* ??? add_class_reference (ident); - is pointless, since the
1139 system lib does not export the equivalent symbols. Maybe we
1140 need to build a class ref anyway. */
1141 t = my_build_string_pointer (IDENTIFIER_LENGTH (ident) + 1,
1142 IDENTIFIER_POINTER (ident));
1143 v->quick_push (t);
1144 t = build_function_call_vec (input_location, vNULL, objc_get_class_decl,
1145 v, 0);
1146 vec_free (v);
1147 return t;
1148 }
1149 }
1150
1151 /* Used by build_function_type_for_method. Append the types for
1152 receiver & _cmd at the start of a method argument list to ARGTYPES.
1153 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are
1154 trying to define a method or call one. SUPERFLAG says this is for a
1155 send to super. METH may be NULL, in the case that there is no
1156 prototype. */
1157
1158 static void
next_runtime_abi_02_get_arg_type_list_base(vec<tree,va_gc> ** argtypes,tree meth,int context,int superflag)1159 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes,
1160 tree meth, int context,
1161 int superflag)
1162 {
1163 tree receiver_type;
1164
1165 if (superflag)
1166 receiver_type = objc_super_type;
1167 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL)
1168 receiver_type = objc_instance_type;
1169 else
1170 receiver_type = objc_object_type;
1171
1172 vec_safe_push (*argtypes, receiver_type);
1173 if (flag_next_runtime < USE_FIXUP_BEFORE)
1174 /* Selector type - will eventually change to `int'. */
1175 vec_safe_push (*argtypes, superflag ? objc_v2_super_selector_type
1176 : objc_v2_selector_type);
1177 else
1178 vec_safe_push (*argtypes, objc_selector_type);
1179 }
1180
1181 /* TODO: Merge this with the message refs. */
1182 static tree
build_selector_reference_decl(tree ident)1183 build_selector_reference_decl (tree ident)
1184 {
1185 tree decl;
1186 char *t, buf[BUFSIZE];
1187
1188 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident));
1189 t = buf;
1190 while (*t)
1191 {
1192 if (*t==':')
1193 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1194 t++;
1195 }
1196 decl = start_var_decl (objc_selector_type, buf);
1197 OBJCMETA (decl, objc_meta, meta_sel_refs);
1198 return decl;
1199 }
1200
1201 static tree
next_runtime_abi_02_build_selector_reference(location_t loc ATTRIBUTE_UNUSED,tree ident,tree proto ATTRIBUTE_UNUSED)1202 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED,
1203 tree ident,
1204 tree proto ATTRIBUTE_UNUSED)
1205 {
1206 tree *chain = &sel_ref_chain;
1207 tree expr;
1208
1209 while (*chain)
1210 {
1211 if (TREE_VALUE (*chain) == ident)
1212 return TREE_PURPOSE (*chain);
1213
1214 chain = &TREE_CHAIN (*chain);
1215 }
1216
1217 expr = build_selector_reference_decl (ident);
1218 *chain = tree_cons (expr, ident, NULL_TREE);
1219
1220 return expr;
1221 }
1222
1223 /* Declare a variable of type 'struct message_ref_t'. */
1224 /* This will be finished in build_v2_message_ref_translation_table ().
1225 We take an idea from LLVM in making the names a bit more connected
1226 and thus the asm more readable. */
1227
1228 static tree
build_v2_message_reference_decl(tree sel_name,tree message_func_ident)1229 build_v2_message_reference_decl (tree sel_name, tree message_func_ident)
1230 {
1231 tree decl;
1232 char buf[BUFSIZE], *t;
1233 int offset = 12;
1234
1235 /* Skip past the objc_msgSend it's the same for all... */
1236 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_')
1237 offset++;
1238
1239 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s",
1240 &(IDENTIFIER_POINTER (message_func_ident)[offset]),
1241 IDENTIFIER_POINTER (sel_name));
1242 t = buf;
1243 while (*t)
1244 {
1245 if (*t==':')
1246 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */
1247 t++;
1248 }
1249 decl = start_var_decl (objc_v2_message_ref_template, buf);
1250 OBJCMETA (decl, objc_meta, meta_mref);
1251 return decl;
1252 }
1253
1254 struct GTY(()) msgref_entry {
1255 tree func;
1256 tree selname;
1257 tree refdecl;
1258 };
1259
1260 static GTY (()) vec<msgref_entry, va_gc> *msgrefs;
1261
1262 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used
1263 later on to initialize the table of 'struct message_ref_t'
1264 elements. */
1265
1266 static tree
build_v2_selector_messenger_reference(tree sel_name,tree message_func_decl)1267 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl)
1268 {
1269 tree decl;
1270 msgref_entry e;
1271 if (msgrefs)
1272 {
1273 int count;
1274 msgref_entry *ref;
1275 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
1276 if (ref->func == message_func_decl && ref->selname == sel_name)
1277 return ref->refdecl;
1278 }
1279 else
1280 /* Somewhat arbitrary initial provision. */
1281 vec_alloc (msgrefs, 32);
1282
1283 /* We come here if we don't find a match or at the start. */
1284 decl = build_v2_message_reference_decl (sel_name,
1285 DECL_NAME (message_func_decl));
1286 e.func = message_func_decl;
1287 e.selname = sel_name;
1288 e.refdecl = decl;
1289 vec_safe_push (msgrefs, e);
1290 return decl;
1291 }
1292
1293 static tree
build_v2_protocollist_ref_decl(tree protocol)1294 build_v2_protocollist_ref_decl (tree protocol)
1295 {
1296 tree decl;
1297 tree protocol_ident = PROTOCOL_NAME (protocol);
1298 char buf[BUFSIZE];
1299
1300 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s",
1301 IDENTIFIER_POINTER (protocol_ident));
1302 /* TODO: other compiler versions make these hidden & weak. */
1303 decl = create_global_decl (objc_protocol_type, buf);
1304 /* Let optimizer know that this decl is not removable. */
1305 DECL_PRESERVE_P (decl) = 1;
1306 OBJCMETA (decl, objc_meta, meta_proto_ref);
1307 return decl;
1308 }
1309
1310 struct GTY(()) prot_list_entry {
1311 tree id;
1312 tree refdecl;
1313 };
1314 static GTY (()) vec<prot_list_entry, va_gc> *protrefs;
1315
1316 static tree
objc_v2_get_protocol_reference(tree ident)1317 objc_v2_get_protocol_reference (tree ident)
1318 {
1319 tree decl;
1320 prot_list_entry e;
1321 if (protrefs)
1322 {
1323 int count;
1324 prot_list_entry *ref;
1325 FOR_EACH_VEC_ELT (*protrefs, count, ref)
1326 {
1327 if (ref->id == ident)
1328 {
1329 if (!ref->refdecl)
1330 ref->refdecl = build_v2_protocollist_ref_decl (ident);
1331 return ref->refdecl;
1332 }
1333 }
1334 }
1335 else
1336 /* Somewhat arbitrary initial provision. */
1337 vec_alloc (protrefs, 32);
1338
1339 /* We come here if we don't find the entry - or if the table was yet
1340 to be created. */
1341 decl = build_v2_protocollist_ref_decl (ident);
1342 e.id = ident;
1343 e.refdecl = decl;
1344 vec_safe_push (protrefs, e);
1345 return decl;
1346 }
1347
1348 static tree
next_runtime_abi_02_get_protocol_reference(location_t loc ATTRIBUTE_UNUSED,tree p)1349 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED,
1350 tree p)
1351 {
1352 if (!PROTOCOL_FORWARD_DECL (p))
1353 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p);
1354
1355 return objc_v2_get_protocol_reference (p);
1356 }
1357
1358 /* This routine returns the ivar declaration, if component is a valid
1359 ivar field; NULL_TREE otherwise. On finding an ivar, it also
1360 returns the class name in CLASS. */
1361
1362 static tree
objc_is_ivar(tree expr,tree component,tree * klass)1363 objc_is_ivar (tree expr, tree component, tree *klass)
1364 {
1365 tree field = NULL_TREE;
1366 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
1367
1368 if (TREE_CODE (basetype) == RECORD_TYPE
1369 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype))
1370 {
1371 *klass = lookup_interface (OBJC_TYPE_NAME (basetype));
1372 if (*klass)
1373 {
1374 do
1375 {
1376 tree ivar_chain = CLASS_RAW_IVARS (*klass);
1377 if (ivar_chain)
1378 {
1379 field = is_ivar (ivar_chain, component);
1380 if (field != NULL_TREE)
1381 break;
1382 }
1383 *klass = lookup_interface (CLASS_SUPER_NAME (*klass));
1384 }
1385 while (*klass);
1386 }
1387 }
1388 return field;
1389 }
1390
1391 static void
create_ivar_offset_name(char * buf,tree class_name,tree field_decl)1392 create_ivar_offset_name (char *buf, tree class_name, tree field_decl)
1393 {
1394 tree fname = DECL_NAME (field_decl);
1395
1396 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name),
1397 IDENTIFIER_POINTER (fname));
1398 return;
1399 }
1400
1401 /* This routine generates new abi's ivar reference tree. It amounts
1402 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally
1403 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding
1404 the offset for 'IVAR' field. TYPE is type of IVAR field. */
1405
1406 static tree
objc_v2_build_ivar_ref(tree datum,tree component)1407 objc_v2_build_ivar_ref (tree datum, tree component)
1408 {
1409 tree field, ref, class_name, offset, ftype, expr;
1410 char var_offset_name[512];
1411
1412 field = objc_is_ivar (datum, component, &class_name);
1413 if (!field)
1414 return NULL_TREE;
1415
1416 /* This routine only handles non-bitfield fields */
1417 if (DECL_C_BIT_FIELD (field))
1418 return NULL_TREE;
1419
1420 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field);
1421
1422 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name);
1423
1424 ftype = TREE_TYPE (field);
1425
1426 /* (char*)datum */
1427 expr = build_c_cast (input_location,
1428 string_type_node, build_fold_addr_expr (datum));
1429
1430 /* (char*)datum + offset */
1431 expr = fold_build_pointer_plus_loc (input_location, expr, offset);
1432
1433 /* (ftype*)((char*)datum + offset) */
1434 expr = build_c_cast (input_location, build_pointer_type (ftype), expr);
1435
1436 /* Finally: *(ftype*)((char*)datum + offset) */
1437 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR);
1438
1439 /* We must set type of the resulting expression to be the same as
1440 the field type. This is because, build_indirect_ref (...)
1441 rebuilds the type which may result in lost information; as in the
1442 case of protocol-qualified types (id <protocol> ). */
1443 TREE_TYPE (ref) = ftype;
1444
1445 if (TREE_READONLY (datum) || TREE_READONLY (field))
1446 TREE_READONLY (ref) = 1;
1447
1448 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
1449 TREE_THIS_VOLATILE (ref) = 1;
1450
1451 if (TREE_DEPRECATED (field))
1452 warn_deprecated_use (field, NULL_TREE);
1453
1454 return ref;
1455 }
1456
1457 /* IVAR refs are made via an externally referenceable offset and built
1458 on the fly. That is, unless they refer to (private) fields in the
1459 class structure. */
1460 static tree
next_runtime_abi_02_build_ivar_ref(location_t loc ATTRIBUTE_UNUSED,tree base,tree id)1461 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED,
1462 tree base, tree id)
1463 {
1464 tree ivar;
1465 if ((ivar = objc_v2_build_ivar_ref (base, id)))
1466 return ivar;
1467 return objc_build_component_ref (base, id);
1468 }
1469
1470 /* [super ...] references are listed here (and built into a table at
1471 meta -data emit time). */
1472 static tree
build_v2_superclass_ref_decl(tree ident,bool inst)1473 build_v2_superclass_ref_decl (tree ident, bool inst)
1474 {
1475 tree decl;
1476 char buf[BUFSIZE];
1477
1478 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"),
1479 IDENTIFIER_POINTER (ident));
1480 decl = start_var_decl (objc_class_type, buf);
1481 OBJCMETA (decl, objc_meta, meta_superclass_ref);
1482 return decl;
1483 }
1484
1485 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs;
1486 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs;
1487
1488 /* Find or build a superclass reference decl for class NAME. */
1489
1490 static tree
objc_get_superclass_ref_decl(tree name,bool inst_meth)1491 objc_get_superclass_ref_decl (tree name, bool inst_meth)
1492 {
1493 tree decl;
1494 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs
1495 : metaclass_super_refs;
1496
1497 if (list)
1498 {
1499 int count;
1500 ident_data_tuple *ref;
1501 FOR_EACH_VEC_ELT (*list, count, ref)
1502 {
1503 if (ref->ident == name)
1504 {
1505 if (!ref->data)
1506 ref->data = build_v2_superclass_ref_decl (name, inst_meth);
1507 return ref->data;
1508 }
1509 }
1510 }
1511 else
1512 {
1513 /* Somewhat arbitrary initial provision. */
1514 if (inst_meth)
1515 {
1516 vec_alloc (class_super_refs, 16);
1517 list = class_super_refs;
1518 }
1519 else
1520 {
1521 vec_alloc (metaclass_super_refs, 16);
1522 list = metaclass_super_refs;
1523 }
1524 }
1525 /* We come here if we don't find the entry - or if the table was yet
1526 to be created. */
1527 decl = build_v2_superclass_ref_decl (name, inst_meth);
1528 ident_data_tuple e;
1529 e.ident = name;
1530 e.data = decl;
1531 vec_safe_push (list, e);
1532 return decl;
1533 }
1534
1535 /* Get a reference to the superclass for IMP. */
1536
1537 static tree
next_runtime_abi_02_get_class_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1538 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED,
1539 struct imp_entry *imp, bool inst_meth)
1540 {
1541 tree name = CLASS_NAME (imp->imp_context);
1542 return objc_get_superclass_ref_decl (name, inst_meth);
1543 }
1544
1545 /* Get a reference to the superclass for category IMP. */
1546
1547 static tree
next_runtime_abi_02_get_category_super_ref(location_t loc ATTRIBUTE_UNUSED,struct imp_entry * imp,bool inst_meth)1548 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED,
1549 struct imp_entry *imp,
1550 bool inst_meth)
1551 {
1552 if (flag_zero_link)
1553 {
1554 /* Do it the slow way. */
1555 tree get_cl_fn = inst_meth ? objc_get_class_decl
1556 : objc_get_meta_class_decl;
1557 tree super_name = CLASS_SUPER_NAME (imp->imp_template);
1558 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1,
1559 IDENTIFIER_POINTER (super_name));
1560 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */
1561 return build_function_call (input_location, get_cl_fn,
1562 build_tree_list (NULL_TREE, super_name));
1563 }
1564
1565 /* This is the 'usual' path. */
1566 tree cls_name = CLASS_NAME (imp->imp_template);
1567 if (!inst_meth)
1568 return objc_get_superclass_ref_decl (cls_name, inst_meth);
1569 return objc_get_class_reference (cls_name);
1570 }
1571
1572 static tree
next_runtime_abi_02_receiver_is_class_object(tree receiver)1573 next_runtime_abi_02_receiver_is_class_object (tree receiver)
1574 {
1575 if (TREE_CODE (receiver) == VAR_DECL
1576 && IS_CLASS (TREE_TYPE (receiver))
1577 && vec_safe_length (classrefs))
1578 {
1579 int count;
1580 ident_data_tuple *ref;
1581 /* The receiver is a variable created by build_class_reference_decl. */
1582 FOR_EACH_VEC_ELT (*classrefs, count, ref)
1583 if (ref->data == receiver)
1584 return ref->ident;
1585 }
1586 return NULL_TREE;
1587 }
1588
1589 /* Assign all arguments in VALUES which have side-effect to a temporary
1590 and replaced that argument in VALUES list with the temporary. The
1591 arguments will be passed to a function with FNTYPE. */
1592
1593 static tree
objc_copy_to_temp_side_effect_params(tree fntype,tree values)1594 objc_copy_to_temp_side_effect_params (tree fntype, tree values)
1595 {
1596 tree valtail;
1597 function_args_iterator iter;
1598
1599 /* Skip over receiver and the &_msf_ref types. */
1600 function_args_iter_init (&iter, fntype);
1601 function_args_iter_next (&iter);
1602 function_args_iter_next (&iter);
1603
1604 for (valtail = values; valtail;
1605 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter))
1606 {
1607 tree value = TREE_VALUE (valtail);
1608 tree type = function_args_iter_cond (&iter);
1609 if (type == NULL_TREE)
1610 break;
1611 if (!TREE_SIDE_EFFECTS (value))
1612 continue;
1613 /* To prevent re-evaluation. */
1614 value = save_expr (value);
1615 add_stmt (value);
1616 TREE_VALUE (valtail) = value;
1617 }
1618 return values;
1619 }
1620
1621 /* Build the new abi's messaging library call. It looks like:
1622 (*_msg.messenger) (receiver, &_msg, ...) */
1623
1624 static tree
build_v2_objc_method_fixup_call(int super_flag,tree method_prototype,tree lookup_object,tree selector,tree method_params,bool check_for_nil)1625 build_v2_objc_method_fixup_call (int super_flag, tree method_prototype,
1626 tree lookup_object, tree selector,
1627 tree method_params, bool check_for_nil)
1628 {
1629 tree ret_val;
1630 tree sender, rcv_p, t;
1631 tree ret_type
1632 = (method_prototype
1633 ? TREE_VALUE (TREE_TYPE (method_prototype))
1634 : objc_object_type);
1635 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1636 METHOD_REF, super_flag);
1637 tree sender_cast;
1638
1639 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1640 ftype = build_type_attribute_variant (
1641 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype));
1642
1643 sender_cast = build_pointer_type (ftype);
1644
1645 if (check_for_nil)
1646 method_params = objc_copy_to_temp_side_effect_params (ftype,
1647 method_params);
1648
1649 /* Get &message_ref_t.messenger. */
1650 sender = build_c_cast (input_location,
1651 build_pointer_type (super_flag
1652 ? objc_v2_super_imp_type
1653 : objc_v2_imp_type),
1654 selector);
1655
1656 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR);
1657
1658 rcv_p = (super_flag ? objc_super_type : objc_object_type);
1659
1660 lookup_object = build_c_cast (input_location, rcv_p, lookup_object);
1661 if (sender == error_mark_node || lookup_object == error_mark_node)
1662 return error_mark_node;
1663
1664 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1665 lookup_object = save_expr (lookup_object);
1666
1667 method_params = tree_cons (NULL_TREE, lookup_object,
1668 tree_cons (NULL_TREE, selector,
1669 method_params));
1670 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object,
1671 build_int_cst (TREE_TYPE (lookup_object), 0));
1672 ret_val = build_function_call (input_location, t, method_params);
1673 if (check_for_nil)
1674 {
1675 /* receiver != nil ? ret_val : 0 */
1676 tree ftree;
1677 tree ifexp;
1678
1679 if (TREE_CODE (ret_type) == RECORD_TYPE
1680 || TREE_CODE (ret_type) == UNION_TYPE)
1681 /* An empty constructor is zero-filled by the middle end. */
1682 ftree = objc_build_constructor (ret_type, NULL);
1683 else
1684 ftree = fold_convert (ret_type, integer_zero_node);
1685
1686 ifexp = build_binary_op (input_location, NE_EXPR,
1687 lookup_object,
1688 fold_convert (rcv_p, integer_zero_node), 1);
1689
1690 #ifdef OBJCPLUS
1691 ret_val = build_conditional_expr (input_location,
1692 ifexp, ret_val, ftree,
1693 tf_warning_or_error);
1694 #else
1695 ret_val = build_conditional_expr (input_location,
1696 ifexp, 0,
1697 ret_val, NULL_TREE, input_location,
1698 ftree, NULL_TREE, input_location);
1699 ret_val = fold_convert (ret_type, ret_val);
1700 #endif
1701 }
1702 return ret_val;
1703 }
1704
1705 static tree
build_v2_build_objc_method_call(int super,tree method_prototype,tree lookup_object,tree selector,tree method_params,location_t loc,bool check_for_nil,bool rx_is_id)1706 build_v2_build_objc_method_call (int super, tree method_prototype,
1707 tree lookup_object, tree selector,
1708 tree method_params, location_t loc,
1709 bool check_for_nil, bool rx_is_id)
1710 {
1711 tree sender, sender_cast, method, t;
1712 tree rcv_p = (super ? objc_super_type : objc_object_type);
1713 vec<tree, va_gc> *parms;
1714 unsigned nparm = (method_params ? list_length (method_params) : 0);
1715
1716 /* If a prototype for the method to be called exists, then cast
1717 the sender's return type and arguments to match that of the method.
1718 Otherwise, leave sender as is. */
1719 tree ret_type
1720 = (method_prototype
1721 ? TREE_VALUE (TREE_TYPE (method_prototype))
1722 : objc_object_type);
1723 tree ftype = build_function_type_for_method (ret_type, method_prototype,
1724 METHOD_REF, super);
1725
1726 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype))
1727 ftype = build_type_attribute_variant (ftype,
1728 METHOD_TYPE_ATTRIBUTES
1729 (method_prototype));
1730
1731 sender_cast = build_pointer_type (ftype);
1732
1733 lookup_object = build_c_cast (loc, rcv_p, lookup_object);
1734
1735 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */
1736 lookup_object = save_expr (lookup_object);
1737
1738 /* Param list + 2 slots for object and selector. */
1739 vec_alloc (parms, nparm + 2);
1740
1741 /* If we are returning an item that must be returned in memory, and the
1742 target ABI does this by an invisible pointer provided as the first arg,
1743 we need to adjust the message signature to include this. The second
1744 part of this excludes targets that provide some alternate scheme for
1745 structure returns. */
1746 if (ret_type && !VOID_TYPE_P (ret_type)
1747 && targetm.calls.return_in_memory (ret_type, 0)
1748 && !(targetm.calls.struct_value_rtx (0, 0)
1749 && (TREE_CODE (ret_type) == RECORD_TYPE
1750 || TREE_CODE (ret_type) == UNION_TYPE)))
1751 {
1752 if (super)
1753 sender = umsg_id_super2_stret_fixup_decl;
1754 else
1755 sender = rx_is_id ? umsg_id_stret_fixup_decl
1756 : umsg_stret_fixup_decl;
1757 }
1758 else
1759 {
1760 if (super)
1761 sender = umsg_id_super2_fixup_decl;
1762 else
1763 sender = rx_is_id ? umsg_id_fixup_decl
1764 : umsg_fixup_decl;
1765 }
1766
1767 method = build_fold_addr_expr_loc (loc, sender);
1768
1769 /* Pass the object to the method. */
1770 parms->quick_push (lookup_object);
1771 /* Pass the selector to the method. */
1772 parms->quick_push (selector);
1773 /* Now append the remainder of the parms. */
1774 if (nparm)
1775 for (; method_params; method_params = TREE_CHAIN (method_params))
1776 parms->quick_push (TREE_VALUE (method_params));
1777
1778 /* Build an obj_type_ref, with the correct cast for the method call. */
1779 t = build3 (OBJ_TYPE_REF, sender_cast, method,
1780 lookup_object, build_int_cst (TREE_TYPE (lookup_object), 0));
1781 tree ret_val = build_function_call_vec (loc, vNULL, t, parms, NULL);
1782 vec_free (parms);
1783 if (check_for_nil)
1784 {
1785 /* receiver != nil ? ret_val : 0 */
1786 tree ftree;
1787 tree ifexp;
1788
1789 if (TREE_CODE (ret_type) == RECORD_TYPE
1790 || TREE_CODE (ret_type) == UNION_TYPE)
1791 {
1792 /* An empty constructor is zero-filled by the middle end. */
1793 ftree = objc_build_constructor (ret_type, NULL);
1794 }
1795 else
1796 ftree = fold_convert (ret_type, integer_zero_node);
1797
1798 ifexp = build_binary_op (loc, NE_EXPR,
1799 lookup_object,
1800 fold_convert (rcv_p, integer_zero_node), 1);
1801
1802 #ifdef OBJCPLUS
1803 ret_val = build_conditional_expr (loc, ifexp, ret_val, ftree,
1804 tf_warning_or_error);
1805 #else
1806 ret_val = build_conditional_expr (loc, ifexp, 1,
1807 ret_val, NULL_TREE, loc,
1808 ftree, NULL_TREE, loc);
1809 ret_val = fold_convert (ret_type, ret_val);
1810 #endif
1811 }
1812 return ret_val;
1813 }
1814
1815 static tree
next_runtime_abi_02_build_objc_method_call(location_t loc,tree method_prototype,tree receiver,tree rtype,tree sel_name,tree method_params,int super)1816 next_runtime_abi_02_build_objc_method_call (location_t loc,
1817 tree method_prototype,
1818 tree receiver,
1819 tree rtype,
1820 tree sel_name,
1821 tree method_params,
1822 int super)
1823 {
1824 /* Do we need to check for nil receivers ? */
1825 /* For now, message sent to classes need no nil check. In the
1826 future, class declaration marked as weak_import must be nil
1827 checked. */
1828 bool check_for_nil = flag_objc_nilcheck;
1829 if (super
1830 || (TREE_CODE (receiver) == VAR_DECL
1831 && TREE_TYPE (receiver) == objc_class_type))
1832 check_for_nil = false;
1833
1834 if (flag_next_runtime >= USE_FIXUP_BEFORE)
1835 {
1836 tree selector
1837 = next_runtime_abi_02_build_selector_reference (loc, sel_name,
1838 method_prototype);
1839 return build_v2_build_objc_method_call (super, method_prototype,
1840 receiver, selector,
1841 method_params, loc,
1842 check_for_nil,
1843 objc_is_id (rtype));
1844 }
1845
1846 /* else we have to build a pair of the function and selector. */
1847 tree message_func_decl;
1848 tree ret_type = method_prototype
1849 ? TREE_VALUE (TREE_TYPE (method_prototype))
1850 : objc_object_type;
1851
1852 /* See comment for the fixup version above. */
1853 if (ret_type && !VOID_TYPE_P (ret_type)
1854 && targetm.calls.return_in_memory (ret_type, 0)
1855 && !(targetm.calls.struct_value_rtx (0, 0)
1856 && (TREE_CODE (ret_type) == RECORD_TYPE
1857 || TREE_CODE (ret_type) == UNION_TYPE)))
1858 {
1859 if (super)
1860 message_func_decl = umsg_id_super2_stret_fixup_decl;
1861 else
1862 message_func_decl = objc_is_id (rtype)
1863 ? umsg_id_stret_fixup_decl
1864 : umsg_stret_fixup_decl;
1865 }
1866 else
1867 {
1868 if (super)
1869 message_func_decl = umsg_id_super2_fixup_decl;
1870 else
1871 message_func_decl = objc_is_id (rtype)
1872 ? umsg_id_fixup_decl
1873 : umsg_fixup_decl;
1874 }
1875
1876 tree selector = build_v2_selector_messenger_reference (sel_name,
1877 message_func_decl);
1878
1879 /* selector = &_msg; */
1880 selector = build_unary_op (loc, ADDR_EXPR, selector, 0);
1881
1882 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type
1883 : objc_v2_selector_type),
1884 selector);
1885
1886 /* (*_msg.messenger) (receiver, &_msg, ...); */
1887 return build_v2_objc_method_fixup_call (super, method_prototype, receiver,
1888 selector, method_params,
1889 check_for_nil);
1890 }
1891
1892 /* NOTE --- Constant String Class Stuff --- */
1893
1894 static bool
next_runtime_abi_02_setup_const_string_class_decl(void)1895 next_runtime_abi_02_setup_const_string_class_decl (void)
1896 {
1897 if (!constant_string_global_id)
1898 {
1899 /* Hopefully, this should not represent a serious limitation. */
1900 char buf[BUFSIZE];
1901 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name);
1902 constant_string_global_id = get_identifier (buf);
1903 }
1904
1905 string_class_decl = lookup_name (constant_string_global_id);
1906
1907 /* In OBJC2 abi, constant string class reference refers to class
1908 name for NSConstantString class. This declaration may not be
1909 available yet (in fact it is not in most cases). So, declare an
1910 extern OBJC_CLASS_$_NSConstantString in its place. */
1911 if (!string_class_decl)
1912 string_class_decl =
1913 create_extern_decl (objc_v2_class_template,
1914 IDENTIFIER_POINTER (constant_string_global_id));
1915
1916 return (string_class_decl != NULL_TREE);
1917 }
1918
1919 static tree
next_runtime_abi_02_build_const_string_constructor(location_t loc,tree string,int length)1920 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string,
1921 int length)
1922 {
1923 tree constructor, fields, var;
1924 vec<constructor_elt, va_gc> *v = NULL;
1925
1926 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */
1927 fields = TYPE_FIELDS (internal_const_str_type);
1928 CONSTRUCTOR_APPEND_ELT (v, fields,
1929 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0));
1930
1931 fields = DECL_CHAIN (fields);
1932 CONSTRUCTOR_APPEND_ELT (v, fields,
1933 build_unary_op (loc, ADDR_EXPR, string, 1));
1934
1935 /* ??? check if this should be long. */
1936 fields = DECL_CHAIN (fields);
1937 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length));
1938 constructor = objc_build_constructor (internal_const_str_type, v);
1939
1940 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor));
1941 DECL_INITIAL (var) = constructor;
1942 TREE_STATIC (var) = 1;
1943 DECL_CONTEXT (var) = NULL;
1944 OBJCMETA (var, objc_meta, meta_const_str);
1945 return var;
1946 }
1947
1948 /* NOTE --- NeXT V2 Metadata templates --- */
1949
1950 /* This routine builds the following type:
1951 struct _prop_t
1952 {
1953 const char * const name; // property name
1954 const char * const attributes; // comma-delimited, encoded,
1955 // property attributes
1956 };
1957 */
1958
1959 static tree
build_v2_property_template(void)1960 build_v2_property_template (void)
1961 {
1962 tree prop_record;
1963 tree decls, *chain = NULL;
1964
1965 prop_record = objc_start_struct (get_identifier ("_prop_t"));
1966 /* const char * name */
1967 decls = add_field_decl (string_type_node, "name", &chain);
1968
1969 /* const char * attribute */
1970 add_field_decl (string_type_node, "attribute", &chain);
1971
1972 objc_finish_struct (prop_record, decls);
1973 return prop_record;
1974 }
1975
1976 /* struct ivar_t
1977 {
1978 unsigned long int *offset;
1979 char *name;
1980 char *type;
1981 uint32_t alignment;
1982 uint32_t size;
1983 };
1984 */
1985
1986 static tree
build_v2_ivar_t_template(void)1987 build_v2_ivar_t_template (void)
1988 {
1989 tree objc_ivar_id, objc_ivar_record;
1990 tree decls, *chain = NULL;
1991
1992 objc_ivar_id = get_identifier ("_ivar_t");
1993 objc_ivar_record = objc_start_struct (objc_ivar_id);
1994
1995 /* unsigned long int *offset; */
1996 decls = add_field_decl (build_pointer_type
1997 (TREE_TYPE (size_zero_node)), "offset", &chain);
1998
1999 /* char *name; */
2000 add_field_decl (string_type_node, "name", &chain);
2001
2002 /* char *type; */
2003 add_field_decl (string_type_node, "type", &chain);
2004
2005 /* uint32_t alignment; */
2006 add_field_decl (integer_type_node, "alignment", &chain);
2007
2008 /* uint32_t size; */
2009 add_field_decl (integer_type_node, "size", &chain);
2010
2011 objc_finish_struct (objc_ivar_record, decls);
2012 return objc_ivar_record;
2013 }
2014
2015 static void
build_metadata_templates(void)2016 build_metadata_templates (void)
2017 {
2018
2019 if (!objc_method_template)
2020 objc_method_template = build_method_template ();
2021
2022 if (!objc_v2_property_template)
2023 objc_v2_property_template = build_v2_property_template ();
2024
2025 if (!objc_v2_ivar_template)
2026 objc_v2_ivar_template = build_v2_ivar_t_template ();
2027
2028 }
2029
2030 /* NOTE --- Output NeXT V2 Metadata --- */
2031
2032 /* Routine builds name of Interface's main meta-data of type class_t. */
2033
2034 static char *
objc_build_internal_classname(tree ident,bool metaclass)2035 objc_build_internal_classname (tree ident, bool metaclass)
2036 {
2037 static char string[512];
2038 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$"
2039 : "OBJC_CLASS_$",
2040 IDENTIFIER_POINTER (ident));
2041 return string;
2042 }
2043
2044 /* Build the name for object of type struct class_ro_t */
2045
2046 static const char *
newabi_append_ro(const char * name)2047 newabi_append_ro (const char *name)
2048 {
2049 const char *dollar;
2050 char *p;
2051 static char string[BUFSIZE];
2052 dollar = strchr (name, '$');
2053 gcc_assert (dollar);
2054 p = string;
2055 *p = '_'; p++;
2056 strncpy (p, name, (int)(dollar - name));
2057 p += (int)(dollar - name);
2058 sprintf (p, "RO_%s", dollar);
2059 return string;
2060 }
2061
2062 /* Build the struct message_ref_t msg =
2063 {objc_msgSend_fixup_xxx, @selector(func)}
2064 table. */
2065
2066 static
build_v2_message_ref_translation_table(void)2067 void build_v2_message_ref_translation_table (void)
2068 {
2069 int count;
2070 msgref_entry *ref;
2071
2072 if (!vec_safe_length (msgrefs))
2073 return;
2074
2075 FOR_EACH_VEC_ELT (*msgrefs, count, ref)
2076 {
2077 vec<constructor_elt, va_gc> *initializer;
2078 tree expr, constructor;
2079 tree struct_type = TREE_TYPE (ref->refdecl);
2080 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl);
2081
2082 initializer = NULL;
2083 /* First 'IMP messenger' field... */
2084 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0);
2085 expr = convert (objc_v2_imp_type, expr);
2086 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2087
2088 /* ... then 'SEL name' field. */
2089 expr = build_selector (ref->selname);
2090 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr);
2091 constructor = objc_build_constructor (struct_type, initializer);
2092 finish_var_decl (ref->refdecl, constructor);
2093 }
2094 }
2095
2096 /* Build decl = initializer; for each externally visible class
2097 reference. */
2098
2099 static void
build_v2_classrefs_table(void)2100 build_v2_classrefs_table (void)
2101 {
2102 int count;
2103 ident_data_tuple *ref;
2104
2105 if (!vec_safe_length (classrefs))
2106 return;
2107
2108 FOR_EACH_VEC_ELT (*classrefs, count, ref)
2109 {
2110 tree expr = ref->ident;
2111 tree decl = ref->data;
2112 /* Interface with no implementation and yet one of its messages
2113 has been used. Need to generate a full address-of tree for it
2114 here. */
2115 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2116 {
2117 const char *name = objc_build_internal_classname (expr, false);
2118 expr = create_extern_decl (objc_v2_class_template, name);
2119 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2120 }
2121 /* The runtime wants this, even if it appears unused, so we must force the
2122 output. */
2123 DECL_PRESERVE_P (decl) = 1;
2124 finish_var_decl (decl, expr);
2125 }
2126 }
2127
2128 /* Build decl = initializer; for each externally visible super class
2129 reference. */
2130
2131 static void
build_v2_super_classrefs_table(bool metaclass)2132 build_v2_super_classrefs_table (bool metaclass)
2133 {
2134 int count;
2135 ident_data_tuple *ref;
2136 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs
2137 : class_super_refs;
2138
2139 if (!vec_safe_length (list))
2140 return;
2141
2142 FOR_EACH_VEC_ELT (*list, count, ref)
2143 {
2144 tree expr = ref->ident;
2145 tree decl = ref->data;
2146 /* Interface with no implementation and yet one of its messages
2147 has been used. Need to generate a full address-of tree for it
2148 here. */
2149 if (TREE_CODE (expr) == IDENTIFIER_NODE)
2150 {
2151 const char * name = objc_build_internal_classname (expr, metaclass);
2152 expr = create_extern_decl (objc_v2_class_template, name);
2153 expr = convert (objc_class_type, build_fold_addr_expr (expr));
2154 }
2155 finish_var_decl (decl, expr);
2156 }
2157 }
2158
2159 /* Add the global class meta-data declaration to the list which later
2160 on ends up in the __class_list section. */
2161
2162 static GTY(()) vec<tree, va_gc> *class_list;
2163
2164 static void
objc_v2_add_to_class_list(tree global_class_decl)2165 objc_v2_add_to_class_list (tree global_class_decl)
2166 {
2167 vec_safe_push (class_list, global_class_decl);
2168 }
2169
2170 static GTY(()) vec<tree, va_gc> *nonlazy_class_list;
2171
2172 /* Add the global class meta-data declaration to the list which later
2173 on ends up in the __nonlazy_class section. */
2174
2175 static void
objc_v2_add_to_nonlazy_class_list(tree global_class_decl)2176 objc_v2_add_to_nonlazy_class_list (tree global_class_decl)
2177 {
2178 vec_safe_push (nonlazy_class_list, global_class_decl);
2179 }
2180
2181 static GTY(()) vec<tree, va_gc> *category_list;
2182
2183 /* Add the category meta-data declaration to the list which later on
2184 ends up in the __nonlazy_category section. */
2185
2186 static void
objc_v2_add_to_category_list(tree decl)2187 objc_v2_add_to_category_list (tree decl)
2188 {
2189 vec_safe_push (category_list, decl);
2190 }
2191
2192 static GTY(()) vec<tree, va_gc> *nonlazy_category_list;
2193
2194 /* Add the category meta-data declaration to the list which later on
2195 ends up in the __category_list section. */
2196
2197 static void
objc_v2_add_to_nonlazy_category_list(tree decl)2198 objc_v2_add_to_nonlazy_category_list (tree decl)
2199 {
2200 vec_safe_push (nonlazy_category_list, decl);
2201 }
2202
2203 static bool
has_load_impl(tree clsmeth)2204 has_load_impl (tree clsmeth)
2205 {
2206 while (clsmeth)
2207 {
2208 tree id = METHOD_SEL_NAME (clsmeth);
2209 if (IDENTIFIER_LENGTH (id) == 4
2210 && startswith (IDENTIFIER_POINTER (id), "load"))
2211 return true;
2212 clsmeth = DECL_CHAIN (clsmeth);
2213 }
2214
2215 return false;
2216 }
2217
2218 /* Build a __{class,category}_list section table containing address of
2219 all @implemented {class,category} meta-data. */
2220
2221 static void
build_v2_address_table(vec<tree,va_gc> * src,const char * nam,tree attr)2222 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr)
2223 {
2224 int count=0;
2225 tree type, decl, expr;
2226 vec<constructor_elt, va_gc> *initlist = NULL;
2227
2228 if (!vec_safe_length (src))
2229 return;
2230
2231 FOR_EACH_VEC_ELT (*src, count, decl)
2232 {
2233 #ifndef OBJCPLUS
2234 tree purpose = build_int_cst (NULL_TREE, count);
2235 #else
2236 tree purpose = NULL_TREE;
2237 #endif
2238 expr = convert (objc_class_type, build_fold_addr_expr (decl));
2239 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr);
2240 }
2241 gcc_assert (count > 0);
2242 type = build_array_type (objc_class_type,
2243 build_index_type (build_int_cst (NULL_TREE, count - 1)));
2244 decl = start_var_decl (type, nam);
2245 /* The runtime wants this, even if it appears unused, so we must
2246 force the output. */
2247 DECL_PRESERVE_P (decl) = 1;
2248 expr = objc_build_constructor (type, initlist);
2249 OBJCMETA (decl, objc_meta, attr);
2250 DECL_USER_ALIGN (decl) = 1;
2251 finish_var_decl (decl, expr);
2252 }
2253
2254 /* Build decl = initializer; for each protocol referenced in
2255 @protocol(MyProt) expression. Refs as built in the entry section
2256 above. */
2257
2258 static void
build_v2_protocol_list_translation_table(void)2259 build_v2_protocol_list_translation_table (void)
2260 {
2261 int count;
2262 prot_list_entry *ref;
2263
2264 if (!protrefs)
2265 return;
2266
2267 FOR_EACH_VEC_ELT (*protrefs, count, ref)
2268 {
2269 char buf[BUFSIZE];
2270 tree expr;
2271 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2272 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s",
2273 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2274 expr = start_var_decl (objc_v2_protocol_template, buf);
2275 expr = convert (objc_protocol_type, build_fold_addr_expr (expr));
2276 finish_var_decl (ref->refdecl, expr);
2277 }
2278 /* TODO: Maybe we could explicitly delete the vec. now? */
2279 }
2280
2281 static GTY (()) vec<prot_list_entry, va_gc> *protlist;
2282
2283 /* Add the local protocol meta-data declaration to the list which
2284 later on ends up in the __protocol_list section. */
2285
2286 static void
objc_add_to_protocol_list(tree protocol_interface_decl,tree protocol_decl)2287 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl)
2288 {
2289 prot_list_entry e;
2290 if (!protlist)
2291 /* Arbitrary init count. */
2292 vec_alloc (protlist, 32);
2293 e.id = protocol_interface_decl;
2294 e.refdecl = protocol_decl;
2295 vec_safe_push (protlist, e);
2296 }
2297
2298 /* Build the __protocol_list section table containing address of all
2299 generate protocol_t meta-data. */
2300
2301 static void
build_v2_protocol_list_address_table(void)2302 build_v2_protocol_list_address_table (void)
2303 {
2304 int count;
2305 prot_list_entry *ref;
2306 if (!vec_safe_length (protlist))
2307 return;
2308
2309 FOR_EACH_VEC_ELT (*protlist, count, ref)
2310 {
2311 tree decl, expr;
2312 char buf[BUFSIZE];
2313 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE);
2314 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s",
2315 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id)));
2316 if (flag_next_runtime >= WEAK_PROTOCOLS_AFTER)
2317 {
2318 decl = create_hidden_decl (objc_protocol_type, buf, /*is def=*/true);
2319 DECL_WEAK (decl) = true;
2320 }
2321 else
2322 decl = create_global_decl (objc_protocol_type, buf, /*is def=*/true);
2323 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl));
2324 OBJCMETA (decl, objc_meta, meta_label_protocollist);
2325 DECL_PRESERVE_P (decl) = 1;
2326 DECL_USER_ALIGN (decl) = 1;
2327 finish_var_decl (decl, expr);
2328 }
2329
2330 /* TODO: delete the vec. */
2331 /* TODO: upgrade to the clang/llvm hidden version. */
2332 }
2333
2334 /* This routine declares a variable to hold meta data for 'struct
2335 protocol_list_t'. */
2336
2337 static tree
generate_v2_protocol_list(tree i_or_p,tree klass_ctxt)2338 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt)
2339 {
2340 tree refs_decl, lproto, e, plist, ptempl_p_t;
2341 int size = 0;
2342 vec<constructor_elt, va_gc> *initlist = NULL;
2343 char buf[BUFSIZE];
2344
2345 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE
2346 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE)
2347 plist = CLASS_PROTOCOL_LIST (i_or_p);
2348 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE)
2349 plist = PROTOCOL_LIST (i_or_p);
2350 else
2351 gcc_unreachable ();
2352
2353 /* Compute size. */
2354 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2355 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE
2356 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto)))
2357 size++;
2358
2359 /* Build initializer. */
2360
2361 ptempl_p_t = build_pointer_type (objc_v2_protocol_template);
2362 e = build_int_cst (ptempl_p_t, size);
2363 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2364
2365 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto))
2366 {
2367 tree pval = TREE_VALUE (lproto);
2368
2369 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE
2370 && PROTOCOL_FORWARD_DECL (pval))
2371 {
2372 tree fwref = PROTOCOL_FORWARD_DECL (pval);
2373 location_t loc = DECL_SOURCE_LOCATION (fwref) ;
2374 e = build_unary_op (loc, ADDR_EXPR, fwref, 0);
2375 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e);
2376 }
2377 }
2378
2379 /* static struct protocol_list_t *list[size]; */
2380
2381 switch (TREE_CODE (i_or_p))
2382 {
2383 case PROTOCOL_INTERFACE_TYPE:
2384 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s",
2385 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p)));
2386 break;
2387 case CLASS_INTERFACE_TYPE:
2388 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s",
2389 IDENTIFIER_POINTER (CLASS_NAME (i_or_p)));
2390 break;
2391 case CATEGORY_INTERFACE_TYPE:
2392 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s",
2393 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)),
2394 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt)));
2395 break;
2396 default:
2397 gcc_unreachable ();
2398 }
2399
2400 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1),
2401 buf);
2402 /* ObjC2 puts all these in the base section. */
2403 OBJCMETA (refs_decl, objc_meta, meta_base);
2404 DECL_PRESERVE_P (refs_decl) = 1;
2405 DECL_USER_ALIGN (refs_decl) = 1;
2406 finish_var_decl (refs_decl,
2407 objc_build_constructor (TREE_TYPE (refs_decl),initlist));
2408 return refs_decl;
2409 }
2410
2411 /* This routine builds one 'struct method_t' initializer list. Note
2412 that the old ABI is supposed to build 'struct objc_method' which
2413 has 3 fields, but it does not build the initialization expression
2414 for 'method_imp' which for protocols is NULL any way. To be
2415 consistent with declaration of 'struct method_t', in the new ABI we
2416 set the method_t.imp to NULL. */
2417
2418 static tree
build_v2_descriptor_table_initializer(tree type,tree entries)2419 build_v2_descriptor_table_initializer (tree type, tree entries)
2420 {
2421 vec<constructor_elt, va_gc> *initlist = NULL;
2422 do
2423 {
2424 vec<constructor_elt, va_gc> *eltlist = NULL;
2425 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2426 build_selector (METHOD_SEL_NAME (entries)));
2427 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE,
2428 add_objc_string (METHOD_ENCODING (entries),
2429 meth_var_types));
2430 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node);
2431
2432 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
2433 objc_build_constructor (type, eltlist));
2434 entries = TREE_CHAIN (entries);
2435 }
2436 while (entries);
2437
2438 return objc_build_constructor (build_array_type (type, 0), initlist);
2439 }
2440
2441 /* struct method_list_t
2442 {
2443 uint32_t entsize;
2444 uint32_t method_count;
2445 struct objc_method method_list[method_count];
2446 }; */
2447
2448 static tree
build_v2_method_list_template(tree list_type,int size)2449 build_v2_method_list_template (tree list_type, int size)
2450 {
2451 tree method_list_t_record;
2452 tree array_type, decls, *chain = NULL;
2453
2454 method_list_t_record = objc_start_struct (NULL_TREE);
2455
2456 /* uint32_t const entsize; */
2457 decls = add_field_decl (integer_type_node, "entsize", &chain);
2458
2459 /* int method_count; */
2460 add_field_decl (integer_type_node, "method_count", &chain);
2461
2462 /* struct objc_method method_list[]; */
2463 array_type = build_sized_array_type (list_type, size);
2464 add_field_decl (array_type, "method_list", &chain);
2465
2466 objc_finish_struct (method_list_t_record, decls);
2467 return method_list_t_record;
2468 }
2469
2470 /* Note, as above that we are building to the objc_method_template
2471 which has the *imp field. ABI0/1 build with
2472 objc_method_prototype_template which is missing this field. */
2473 static tree
generate_v2_meth_descriptor_table(tree chain,tree protocol,const char * prefix,tree attr,vec<tree> & all_meths)2474 generate_v2_meth_descriptor_table (tree chain, tree protocol,
2475 const char *prefix, tree attr,
2476 vec<tree>& all_meths)
2477 {
2478 tree method_list_template, initlist, decl;
2479 int size, entsize;
2480 vec<constructor_elt, va_gc> *v = NULL;
2481 char buf[BUFSIZE];
2482
2483 if (!chain || !prefix)
2484 return NULL_TREE;
2485
2486 tree method = chain;
2487 size = 0;
2488 while (method)
2489 {
2490 if (! METHOD_ENCODING (method))
2491 METHOD_ENCODING (method) = encode_method_prototype (method);
2492 all_meths.safe_push (method);
2493 method = TREE_CHAIN (method);
2494 size++;
2495 }
2496
2497 gcc_assert (size);
2498 method_list_template = build_v2_method_list_template (objc_method_template,
2499 size);
2500 snprintf (buf, BUFSIZE, "%s_%s", prefix,
2501 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2502
2503 decl = start_var_decl (method_list_template, buf);
2504
2505 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2506 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize));
2507 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size));
2508 initlist =
2509 build_v2_descriptor_table_initializer (objc_method_template,
2510 chain);
2511 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2512 /* Get into the right section. */
2513 OBJCMETA (decl, objc_meta, attr);
2514 DECL_USER_ALIGN (decl) = 1;
2515 finish_var_decl (decl, objc_build_constructor (method_list_template, v));
2516 return decl;
2517 }
2518
2519 static tree
generate_v2_meth_type_list(vec<tree> & all_meths,tree protocol,const char * prefix)2520 generate_v2_meth_type_list (vec<tree>& all_meths, tree protocol,
2521 const char *prefix)
2522 {
2523 if (all_meths.is_empty () || !prefix)
2524 return NULL_TREE;
2525
2526 unsigned size = all_meths.length ();
2527 tree list_type = build_sized_array_type (string_type_node, size);
2528 char *nam;
2529 asprintf (&nam, "%s_%s", prefix,
2530 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol)));
2531 tree decl = start_var_decl (list_type, nam);
2532 free (nam);
2533 vec<constructor_elt, va_gc> *v = NULL;
2534
2535 for (unsigned i = 0; i < size; ++i)
2536 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2537 add_objc_string (METHOD_ENCODING (all_meths[i]),
2538 meth_var_types));
2539 OBJCMETA (decl, objc_meta, meta_base);
2540 DECL_USER_ALIGN (decl) = 1;
2541 finish_var_decl (decl, objc_build_constructor (list_type, v));
2542 return decl;
2543 }
2544
2545 /* This routine builds the initializer list to initialize the 'struct
2546 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */
2547
2548 static tree
build_v2_property_table_initializer(tree type,tree context)2549 build_v2_property_table_initializer (tree type, tree context)
2550 {
2551 tree x;
2552 vec<constructor_elt, va_gc> *inits = NULL;
2553 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE)
2554 x = CLASS_PROPERTY_DECL (context);
2555 else
2556 x = IMPL_PROPERTY_DECL (context);
2557
2558 for (; x; x = TREE_CHAIN (x))
2559 {
2560 vec<constructor_elt, va_gc> *elemlist = NULL;
2561 /* NOTE! sections where property name/attribute go MUST change
2562 later. */
2563 tree attribute, name_ident = PROPERTY_NAME (x);
2564
2565 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2566 add_objc_string (name_ident, prop_names_attr));
2567
2568 attribute = objc_v2_encode_prop_attr (x);
2569 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE,
2570 add_objc_string (attribute, prop_names_attr));
2571
2572 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2573 objc_build_constructor (type, elemlist));
2574 }
2575
2576 return objc_build_constructor (build_array_type (type, 0),inits);
2577 }
2578
2579 /* This routine builds the following type:
2580 struct _prop_list_t
2581 {
2582 uint32_t entsize; // sizeof (struct _prop_t)
2583 uint32_t prop_count;
2584 struct _prop_t prop_list [prop_count];
2585 }
2586 */
2587
2588 static tree
build_v2_property_list_template(tree list_type,int size)2589 build_v2_property_list_template (tree list_type, int size)
2590 {
2591 tree property_list_t_record;
2592 tree array_type, decls, *chain = NULL;
2593
2594 /* anonymous. */
2595 property_list_t_record = objc_start_struct (NULL_TREE);
2596
2597 /* uint32_t const entsize; */
2598 decls = add_field_decl (integer_type_node, "entsize", &chain);
2599
2600 /* int prop_count; */
2601 add_field_decl (integer_type_node, "prop_count", &chain);
2602
2603 /* struct _prop_t prop_list[]; */
2604 array_type = build_sized_array_type (list_type, size);
2605 add_field_decl (array_type, "prop_list", &chain);
2606
2607 objc_finish_struct (property_list_t_record, decls);
2608 return property_list_t_record;
2609 }
2610
2611 /* Top-level routine to generate property tables for each
2612 implementation. */
2613
2614 static tree
generate_v2_property_table(tree context,tree klass_ctxt)2615 generate_v2_property_table (tree context, tree klass_ctxt)
2616 {
2617 tree x, decl, initlist, property_list_template;
2618 bool is_proto = false;
2619 vec<constructor_elt, va_gc> *inits = NULL;
2620 int init_val, size = 0;
2621 char buf[BUFSIZE];
2622
2623 if (context)
2624 {
2625 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE);
2626 x = CLASS_PROPERTY_DECL (context);
2627 is_proto = true;
2628 }
2629 else
2630 x = IMPL_PROPERTY_DECL (klass_ctxt);
2631
2632 for (; x; x = TREE_CHAIN (x))
2633 size++;
2634
2635 if (size == 0)
2636 return NULL_TREE;
2637
2638 property_list_template =
2639 build_v2_property_list_template (objc_v2_property_template,
2640 size);
2641
2642 initlist = build_v2_property_table_initializer (objc_v2_property_template,
2643 is_proto ? context
2644 : klass_ctxt);
2645
2646 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template));
2647 if (is_proto)
2648 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s",
2649 IDENTIFIER_POINTER (PROTOCOL_NAME (context)));
2650 else
2651 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s",
2652 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)));
2653
2654 decl = start_var_decl (property_list_template, buf);
2655
2656 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2657 build_int_cst (NULL_TREE, init_val));
2658 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2659 build_int_cst (NULL_TREE, size));
2660 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
2661
2662 OBJCMETA (decl, objc_meta, meta_base);
2663 DECL_USER_ALIGN (decl) = 1;
2664 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
2665 return decl;
2666 }
2667
2668 static tree
build_v2_protocol_initializer(tree type,tree protocol_name,tree protocol_list,tree inst_methods,tree class_methods,tree opt_ins_meth,tree opt_cls_meth,tree property_list,tree ext_meth_types,tree demangled_name,tree class_prop_list)2669 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list,
2670 tree inst_methods, tree class_methods,
2671 tree opt_ins_meth, tree opt_cls_meth,
2672 tree property_list, tree ext_meth_types,
2673 tree demangled_name, tree class_prop_list)
2674 {
2675 tree expr, ttyp;
2676 location_t loc;
2677 vec<constructor_elt, va_gc> *inits = NULL;
2678
2679 /* TODO: find a better representation of location from the inputs. */
2680 loc = UNKNOWN_LOCATION;
2681
2682 /* This is NULL for the new ABI. */
2683 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
2684 convert (objc_object_type, null_pointer_node));
2685
2686 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name);
2687 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list);
2688
2689 ttyp = objc_method_proto_list_ptr;
2690 if (inst_methods)
2691 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2692 else
2693 expr = convert (ttyp, null_pointer_node);
2694 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2695
2696 if (class_methods)
2697 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2698 else
2699 expr = convert (ttyp, null_pointer_node);
2700 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2701
2702 if (opt_ins_meth)
2703 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0));
2704 else
2705 expr = convert (ttyp, null_pointer_node);
2706 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2707
2708 if (opt_cls_meth)
2709 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0));
2710 else
2711 expr = convert (ttyp, null_pointer_node);
2712 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2713
2714 ttyp = objc_prop_list_ptr;
2715 if (property_list)
2716 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2717 else
2718 expr = convert (ttyp, null_pointer_node);
2719 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2720
2721 /* const uint32_t size; = sizeof(struct protocol_t) */
2722 expr = build_int_cst (integer_type_node,
2723 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template)));
2724 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2725 /* const uint32_t flags; = 0 */
2726 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node);
2727
2728 ttyp = build_pointer_type (string_type_node);
2729 if (ext_meth_types)
2730 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, ext_meth_types, 0));
2731 else
2732 expr = convert (ttyp, null_pointer_node);
2733 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2734
2735 ttyp = string_type_node;
2736 if (demangled_name)
2737 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, demangled_name, 0));
2738 else
2739 expr = convert (ttyp, null_pointer_node);
2740 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2741
2742 ttyp = objc_prop_list_ptr;
2743 if (class_prop_list)
2744 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_prop_list, 0));
2745 else
2746 expr = convert (ttyp, null_pointer_node);
2747 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr);
2748
2749 return objc_build_constructor (type, inits);
2750 }
2751
2752 /* Main routine to build all meta data for all protocols used in a
2753 translation unit. */
2754
2755 static void
generate_v2_protocols(void)2756 generate_v2_protocols (void)
2757 {
2758 tree p ;
2759 bool some = false;
2760
2761 if (!protocol_chain)
2762 return ;
2763
2764 /* If a protocol was directly referenced, pull in indirect
2765 references. */
2766 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2767 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p))
2768 generate_protocol_references (PROTOCOL_LIST (p));
2769
2770 for (p = protocol_chain; p; p = TREE_CHAIN (p))
2771 {
2772 location_t loc;
2773 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props;
2774 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr;
2775
2776 /* If protocol wasn't referenced, don't generate any code. */
2777 decl = PROTOCOL_FORWARD_DECL (p);
2778
2779 if (!decl)
2780 continue;
2781
2782 loc = DECL_SOURCE_LOCATION (decl);
2783 some = true;
2784
2785 vec<tree> all_meths = vNULL;
2786 inst_meth =
2787 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p,
2788 "_OBJC_ProtocolInstanceMethods",
2789 meta_proto_nst_meth, all_meths);
2790
2791 class_meth =
2792 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p,
2793 "_OBJC_ProtocolClassMethods",
2794 meta_proto_cls_meth, all_meths);
2795
2796 opt_inst_meth =
2797 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p,
2798 "_OBJC_ProtocolOptInstMethods",
2799 meta_proto_nst_meth, all_meths);
2800
2801 opt_class_meth =
2802 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p,
2803 "_OBJC_ProtocolOptClassMethods",
2804 meta_proto_cls_meth, all_meths);
2805
2806 if (PROTOCOL_LIST (p))
2807 refs_decl = generate_v2_protocol_list (p, NULL_TREE);
2808 else
2809 refs_decl = 0;
2810
2811 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */
2812 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names);
2813
2814 if (refs_decl)
2815 refs_expr = convert (build_pointer_type (objc_v2_protocol_template),
2816 build_unary_op (loc, ADDR_EXPR, refs_decl, 0));
2817 else
2818 refs_expr = build_int_cst (NULL_TREE, 0);
2819
2820 props = generate_v2_property_table (p, NULL_TREE);
2821
2822 tree ext_meth_types
2823 = generate_v2_meth_type_list (all_meths, p,
2824 "_OBJC_ProtocolMethodTypes");
2825 tree demangled_name = NULL_TREE;
2826 tree class_prop_list = NULL_TREE;
2827
2828 initlist = build_v2_protocol_initializer (TREE_TYPE (decl),
2829 protocol_name_expr, refs_expr,
2830 inst_meth, class_meth,
2831 opt_inst_meth, opt_class_meth,
2832 props, ext_meth_types,
2833 demangled_name,class_prop_list);
2834 finish_var_decl (decl, initlist);
2835 objc_add_to_protocol_list (p, decl);
2836 all_meths.truncate (0);
2837 }
2838
2839 if (some)
2840 {
2841 /* Make sure we get the Protocol class linked in - reference
2842 it... */
2843 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME));
2844 /* ... but since we don't specifically use the reference... we
2845 need to force it. */
2846 DECL_PRESERVE_P (p) = 1;
2847 }
2848 }
2849
2850 static tree
generate_v2_dispatch_table(tree chain,const char * name,tree attr)2851 generate_v2_dispatch_table (tree chain, const char *name, tree attr)
2852 {
2853 tree decl, method_list_template, initlist;
2854 vec<constructor_elt, va_gc> *v = NULL;
2855 int size, init_val;
2856
2857 if (!chain || !name || !(size = list_length (chain)))
2858 return NULL_TREE;
2859
2860 method_list_template
2861 = build_v2_method_list_template (objc_method_template, size);
2862 initlist
2863 = build_dispatch_table_initializer (objc_method_template, chain);
2864
2865 decl = start_var_decl (method_list_template, name);
2866
2867 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template));
2868 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2869 build_int_cst (integer_type_node, init_val));
2870 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
2871 build_int_cst (integer_type_node, size));
2872 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist);
2873
2874 OBJCMETA (decl, objc_meta, attr);
2875 DECL_USER_ALIGN (decl) = 1;
2876 finish_var_decl (decl,
2877 objc_build_constructor (TREE_TYPE (decl), v));
2878 return decl;
2879 }
2880
2881 /* Init a category. */
2882 static tree
build_v2_category_initializer(tree type,tree cat_name,tree class_name,tree inst_methods,tree class_methods,tree protocol_list,tree property_list,location_t loc)2883 build_v2_category_initializer (tree type, tree cat_name, tree class_name,
2884 tree inst_methods, tree class_methods,
2885 tree protocol_list, tree property_list,
2886 location_t loc)
2887 {
2888 tree expr, ltyp;
2889 vec<constructor_elt, va_gc> *v = NULL;
2890
2891 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name);
2892 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name);
2893
2894 ltyp = objc_method_list_ptr;
2895 if (inst_methods)
2896 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0));
2897 else
2898 expr = convert (ltyp, null_pointer_node);
2899 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2900
2901 if (class_methods)
2902 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0));
2903 else
2904 expr = convert (ltyp, null_pointer_node);
2905 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2906
2907 /* protocol_list = */
2908 ltyp = build_pointer_type (objc_v2_protocol_template);
2909 if (protocol_list)
2910 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0));
2911 else
2912 expr = convert (ltyp, null_pointer_node);
2913 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2914
2915 ltyp = objc_prop_list_ptr;
2916 if (property_list)
2917 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
2918 else
2919 expr = convert (ltyp, null_pointer_node);
2920 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr);
2921
2922 return objc_build_constructor (type, v);
2923 }
2924
2925 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */
2926
2927 static void
generate_v2_category(struct imp_entry * impent)2928 generate_v2_category (struct imp_entry *impent)
2929 {
2930 tree initlist, cat_name_expr, class_name_expr;
2931 tree protocol_decl, category, props, t;
2932 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
2933 tree cat = impent->imp_context;
2934 tree cat_decl = impent->class_decl;
2935 location_t loc;
2936 char buf[BUFSIZE];
2937
2938 loc = DECL_SOURCE_LOCATION (cat_decl);
2939
2940 /* ??? not sure this is really necessary, the following references should
2941 force appropriate linkage linkage...
2942 -- but ... ensure a reference to the class... */
2943 t = objc_v2_get_class_reference (CLASS_NAME (cat));
2944 /* ... which we ignore so force it out.. */
2945 DECL_PRESERVE_P (t) = 1;
2946
2947 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat)));
2948 class_name_expr = create_extern_decl (objc_v2_class_template, buf);
2949 class_name_expr = build_fold_addr_expr (class_name_expr);
2950
2951 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names);
2952 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat));
2953
2954 if (category && CLASS_PROTOCOL_LIST (category))
2955 {
2956 generate_protocol_references (CLASS_PROTOCOL_LIST (category));
2957 protocol_decl = generate_v2_protocol_list (category, cat);
2958 }
2959 else
2960 protocol_decl = NULL_TREE;
2961
2962 /* decl = update_var_decl(impent->class_decl); */
2963
2964 props = generate_v2_property_table (NULL_TREE, cat);
2965
2966 if (CLASS_NST_METHODS (cat))
2967 {
2968 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s",
2969 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2970 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2971 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf,
2972 meta_cati_meth);
2973 }
2974
2975 if (CLASS_CLS_METHODS (cat))
2976 {
2977 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s",
2978 IDENTIFIER_POINTER (CLASS_NAME (cat)),
2979 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat)));
2980 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf,
2981 meta_catc_meth);
2982 }
2983
2984 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl),
2985 cat_name_expr, class_name_expr,
2986 inst_methods, class_methods,
2987 protocol_decl, props, loc);
2988
2989 finish_var_decl (cat_decl, initlist);
2990 impent->class_decl = cat_decl;
2991
2992 /* Add to list of pointers in __category_list section. */
2993 objc_v2_add_to_category_list (cat_decl);
2994 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
2995 objc_v2_add_to_nonlazy_category_list (cat_decl);
2996 }
2997
2998 /* This routine declares a variable to hold the offset for ivar
2999 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */
3000
3001 struct GTY(()) ivarref_entry
3002 {
3003 tree decl;
3004 tree offset;
3005 };
3006
3007 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs;
3008
3009 static tree
ivar_offset_ref(tree class_name,tree field_decl)3010 ivar_offset_ref (tree class_name, tree field_decl)
3011 {
3012 tree decl, field_decl_id;
3013 ivarref_entry e;
3014 bool global_var;
3015 char buf[512];
3016
3017 create_ivar_offset_name (buf, class_name, field_decl);
3018 field_decl_id = get_identifier (buf);
3019
3020 if (ivar_offset_refs)
3021 {
3022 int count;
3023 ivarref_entry *ref;
3024 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3025 if (DECL_NAME (ref->decl) == field_decl_id)
3026 return ref->decl;
3027 }
3028 else
3029 /* Somewhat arbitrary initial provision. */
3030 vec_alloc (ivar_offset_refs, 32);
3031
3032 /* We come here if we don't find a match or at the start. */
3033 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl));
3034 if (global_var)
3035 decl = create_global_decl (TREE_TYPE (size_zero_node), buf);
3036 else
3037 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf);
3038
3039 /* Identify so that we can indirect these where the ABI requires. */
3040 OBJCMETA (decl, objc_meta, meta_ivar_ref);
3041
3042 e.decl = decl;
3043 e.offset = byte_position (field_decl);
3044 vec_safe_push (ivar_offset_refs, e);
3045 return decl;
3046 }
3047
3048 /* This routine builds initializer-list needed to initialize 'struct
3049 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is
3050 'struct ivar_t' and FIELD_DECL is list of ivars for the target
3051 class. */
3052
3053 static tree
build_v2_ivar_list_initializer(tree class_name,tree type,tree field_decl)3054 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl)
3055 {
3056 vec<constructor_elt, va_gc> *inits = NULL;
3057
3058 do
3059 {
3060 vec<constructor_elt, va_gc> *ivar = NULL;
3061 int val;
3062 tree id;
3063
3064 /* Unnamed bitfields are ignored. */
3065 if (!DECL_NAME (field_decl))
3066 {
3067 field_decl = DECL_CHAIN (field_decl);
3068 continue;
3069 }
3070
3071 /* Set offset. */
3072 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3073 build_unary_op (input_location,
3074 ADDR_EXPR,
3075 ivar_offset_ref (class_name,
3076 field_decl), 0));
3077
3078 /* Set name. */
3079 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3080 add_objc_string (DECL_NAME (field_decl),
3081 meth_var_names));
3082
3083 /* Set type. */
3084 id = add_objc_string (encode_field_decl (field_decl),
3085 meth_var_types);
3086 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id);
3087
3088 /* Set alignment. */
3089 val = DECL_ALIGN_UNIT (field_decl);
3090 val = exact_log2 (val);
3091 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3092 build_int_cst (integer_type_node, val));
3093
3094 /* Set size. */
3095 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl));
3096 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE,
3097 build_int_cst (integer_type_node, val));
3098
3099 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3100 objc_build_constructor (type, ivar));
3101
3102 do
3103 field_decl = DECL_CHAIN (field_decl);
3104 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL);
3105 }
3106 while (field_decl);
3107
3108 return objc_build_constructor (build_array_type (type, 0), inits);
3109 }
3110
3111 /*
3112 struct ivar_list_t
3113 {
3114 uint32 entsize;
3115 uint32 count;
3116 struct iver_t list[count];
3117 };
3118 */
3119
3120 static tree
build_v2_ivar_list_t_template(tree list_type,int size)3121 build_v2_ivar_list_t_template (tree list_type, int size)
3122 {
3123 tree objc_ivar_list_record;
3124 tree decls, *chain = NULL;
3125
3126 /* Anonymous. */
3127 objc_ivar_list_record = objc_start_struct (NULL_TREE);
3128
3129 /* uint32 entsize; */
3130 decls = add_field_decl (integer_type_node, "entsize", &chain);
3131
3132 /* uint32 count; */
3133 add_field_decl (integer_type_node, "count", &chain);
3134
3135 /* struct objc_ivar ivar_list[]; */
3136 add_field_decl (build_sized_array_type (list_type, size),
3137 "list", &chain);
3138
3139 objc_finish_struct (objc_ivar_list_record, decls);
3140 return objc_ivar_list_record;
3141 }
3142
3143 /* This routine declares a static variable of type 'struct
3144 ivar_list_t' and initializes it. chain is the source of the data,
3145 name is the name for the var. attr is the meta-data section tag
3146 attribute. templ is the implementation template for the class. */
3147
3148 static tree
generate_v2_ivars_list(tree chain,const char * name,tree attr,tree templ)3149 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ)
3150 {
3151 tree decl, initlist, ivar_list_template;
3152 vec<constructor_elt, va_gc> *inits = NULL;
3153 int size, ivar_t_size;
3154
3155 if (!chain || !name || !(size = ivar_list_length (chain)))
3156 return NULL_TREE;
3157
3158 generating_instance_variables = 1;
3159 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template,
3160 size);
3161
3162 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ),
3163 objc_v2_ivar_template, chain);
3164 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template));
3165
3166 decl = start_var_decl (ivar_list_template, name);
3167 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3168 build_int_cst (integer_type_node, ivar_t_size));
3169 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE,
3170 build_int_cst (integer_type_node, size));
3171 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist);
3172 OBJCMETA (decl, objc_meta, attr);
3173 DECL_USER_ALIGN (decl) = 1;
3174 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits));
3175 generating_instance_variables = 0;
3176 return decl;
3177 }
3178
3179 /* Routine to build initializer list to initialize objects of type
3180 struct class_t; */
3181
3182 static tree
build_v2_class_t_initializer(tree type,tree isa,tree superclass,tree ro,tree cache,tree vtable)3183 build_v2_class_t_initializer (tree type, tree isa, tree superclass,
3184 tree ro, tree cache, tree vtable)
3185 {
3186 vec<constructor_elt, va_gc> *initlist = NULL;
3187
3188 /* isa */
3189 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa);
3190
3191 /* superclass */
3192 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass);
3193
3194 /* cache */
3195 if (cache)
3196 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache);
3197 else
3198 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3199
3200 /* vtable */
3201 if (vtable)
3202 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable);
3203 else
3204 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node);
3205
3206 /* ro */
3207 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro);
3208
3209 return objc_build_constructor (type, initlist);
3210 }
3211
3212 /* Routine to build object of struct class_ro_t { ... }; */
3213
3214 static tree
build_v2_class_ro_t_initializer(tree type,tree name,unsigned int flags,unsigned int instanceStart,unsigned int instanceSize,tree ivarLayout,tree baseMethods,tree baseProtocols,tree ivars,tree property_list)3215 build_v2_class_ro_t_initializer (tree type, tree name,
3216 unsigned int flags, unsigned int instanceStart,
3217 unsigned int instanceSize,
3218 tree ivarLayout,
3219 tree baseMethods, tree baseProtocols,
3220 tree ivars, tree property_list)
3221 {
3222 tree expr, unsigned_char_star, ltyp;
3223 location_t loc;
3224 vec<constructor_elt, va_gc> *initlist = NULL;
3225
3226 /* TODO: fish out the real location from somewhere. */
3227 loc = UNKNOWN_LOCATION;
3228
3229 /* flags */
3230 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3231 build_int_cst (integer_type_node, flags));
3232
3233 /* instanceStart */
3234 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3235 build_int_cst (integer_type_node, instanceStart));
3236
3237 /* instanceSize */
3238 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3239 build_int_cst (integer_type_node, instanceSize));
3240
3241 /* This ABI is currently only used on m64 NeXT. We always
3242 explicitly declare the alignment padding. */
3243 /* reserved, pads alignment. */
3244 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3245 build_int_cst (integer_type_node, 0));
3246
3247 /* ivarLayout */
3248 unsigned_char_star = build_pointer_type (unsigned_char_type_node);
3249 if (ivarLayout)
3250 expr = ivarLayout;
3251 else
3252 expr = convert (unsigned_char_star, null_pointer_node);
3253 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3254
3255 /* name */
3256 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name));
3257
3258 /* baseMethods */
3259 ltyp = objc_method_list_ptr;
3260 if (baseMethods)
3261 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0));
3262 else
3263 expr = convert (ltyp, null_pointer_node);
3264 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3265
3266 /* baseProtocols */
3267 ltyp = build_pointer_type (xref_tag (RECORD_TYPE,
3268 get_identifier (UTAG_V2_PROTOCOL_LIST)));
3269 if (baseProtocols)
3270 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0));
3271 else
3272 expr = convert (ltyp, null_pointer_node);
3273 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3274
3275 /* ivars */
3276 ltyp = objc_v2_ivar_list_ptr;
3277 if (ivars)
3278 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0));
3279 else
3280 expr = convert (ltyp, null_pointer_node);
3281 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3282
3283 /* TODO: We don't yet have the weak/strong stuff... */
3284 /* weakIvarLayout */
3285 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE,
3286 convert (unsigned_char_star, null_pointer_node));
3287
3288 /* property list */
3289 ltyp = objc_prop_list_ptr;
3290 if (property_list)
3291 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0));
3292 else
3293 expr = convert (ltyp, null_pointer_node);
3294 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr);
3295 return objc_build_constructor (type, initlist);
3296 }
3297
3298 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list;
3299
3300 /* Record a name as needing a catcher. */
3301 static void
objc_v2_add_to_ehtype_list(tree name)3302 objc_v2_add_to_ehtype_list (tree name)
3303 {
3304 ident_data_tuple e;
3305 if (ehtype_list)
3306 {
3307 int count = 0;
3308 ident_data_tuple *ref;
3309
3310 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3311 if (ref->ident == name)
3312 return; /* Already entered. */
3313 }
3314 else
3315 /* Arbitrary initial count. */
3316 vec_alloc (ehtype_list, 8);
3317
3318 /* Not found, or new list. */
3319 e.ident = name;
3320 e.data = NULL_TREE;
3321 vec_safe_push (ehtype_list, e);
3322 }
3323
3324 static void
generate_v2_class_structs(struct imp_entry * impent)3325 generate_v2_class_structs (struct imp_entry *impent)
3326 {
3327 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl;
3328 tree field, firstIvar, chain;
3329 tree class_superclass_expr, metaclass_superclass_expr, props;
3330 /* TODO: figure out how to compute this. */
3331 tree ivarLayout = NULL_TREE;
3332 tree my_super_id = NULL_TREE, root_expr = NULL_TREE;
3333 tree inst_methods = NULL_TREE, class_methods = NULL_TREE;
3334 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE;
3335 location_t loc;
3336 char buf[BUFSIZE];
3337 unsigned int instanceStart, instanceSize;
3338 unsigned int flags = 0x01; /* RO_META */
3339 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS
3340 : 0 ;
3341
3342 class_decl = impent->class_decl;
3343 metaclass_decl = impent->meta_decl;
3344 loc = DECL_SOURCE_LOCATION (class_decl);
3345
3346 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0;
3347 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1;
3348 #ifdef OBJCPLUS
3349 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace);
3350 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace);
3351 #endif
3352
3353 /* Generation of data for meta class. */
3354 my_super_id = CLASS_SUPER_NAME (impent->imp_template);
3355 if (my_super_id)
3356 {
3357 /* Compute reference to root's name. For a meta class, "isa" is
3358 a reference to the root class name. */
3359 tree my_root_id = my_super_id;
3360 tree my_root_int, interface;
3361 do
3362 {
3363 my_root_int = lookup_interface (my_root_id);
3364
3365 if (my_root_int && CLASS_SUPER_NAME (my_root_int))
3366 my_root_id = CLASS_SUPER_NAME (my_root_int);
3367 else
3368 break;
3369 }
3370 while (1);
3371
3372 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int>
3373 create extern if not already declared. */
3374 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3375 IDENTIFIER_POINTER (CLASS_NAME (my_root_int)));
3376 root_expr = create_extern_decl (objc_v2_class_template, buf);
3377 root_expr = build_fold_addr_expr (root_expr);
3378
3379 /* Install class `isa' and `super' pointers at runtime. */
3380 interface = lookup_interface (my_super_id);
3381 gcc_assert (interface);
3382 /* Similarly, for OBJC_CLASS_$_<interface>... */
3383 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s",
3384 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3385 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3386 class_superclass_expr = build_fold_addr_expr (class_superclass_expr);
3387 /* ... and for OBJC_METACLASS_$_<interface>. */
3388 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s",
3389 IDENTIFIER_POINTER (CLASS_NAME (interface)));
3390 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf);
3391 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr);
3392 }
3393 else
3394 {
3395 /* Root class. */
3396 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0);
3397 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0);
3398 class_superclass_expr = build_int_cst (NULL_TREE, 0);
3399 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */
3400 }
3401
3402 if (CLASS_PROTOCOL_LIST (impent->imp_template))
3403 {
3404 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template));
3405 protocol_decl = generate_v2_protocol_list (impent->imp_template,
3406 impent->imp_context);
3407 }
3408 else
3409 protocol_decl = 0;
3410
3411 name_expr = add_objc_string (CLASS_NAME (impent->imp_template),
3412 class_names);
3413
3414 if (CLASS_CLS_METHODS (impent->imp_context))
3415 {
3416 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s",
3417 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3418 class_methods =
3419 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context),
3420 buf, meta_clac_meth);
3421 }
3422
3423 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3424
3425 /* Currently there are no class ivars and generation of class
3426 variables for the root of the inheritance has been removed. It
3427 causes multiple defines if there are two root classes in the
3428 link, because each will define its own identically-named offset
3429 variable. */
3430
3431 class_ivars = NULL_TREE;
3432 /* TODO: Add total size of class variables when implemented. */
3433 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template));
3434
3435 /* So now build the META CLASS structs. */
3436 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */
3437
3438 decl = start_var_decl (objc_v2_class_ro_template,
3439 newabi_append_ro (IDENTIFIER_POINTER
3440 (DECL_NAME (metaclass_decl))));
3441 /* TODO: ivarLayout needs t be built. */
3442 initlist =
3443 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3444 (flags | cls_flags), instanceStart,
3445 instanceSize, ivarLayout,
3446 class_methods, protocol_decl,
3447 class_ivars, NULL_TREE);
3448 /* The ROs sit in the default const section. */
3449 OBJCMETA (decl, objc_meta, meta_base);
3450 DECL_USER_ALIGN (decl) = 1;
3451 finish_var_decl (decl, initlist);
3452
3453 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */
3454 initlist =
3455 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl),
3456 root_expr,
3457 metaclass_superclass_expr,
3458 build_fold_addr_expr (decl),
3459 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3460 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3461 /* The class section attributes are set when they are created. */
3462 DECL_USER_ALIGN (metaclass_decl) = 1;
3463 finish_var_decl (metaclass_decl, initlist);
3464 impent->meta_decl = metaclass_decl;
3465
3466 /* So now build the CLASS structs. */
3467
3468 flags = 0x0; /* ... */
3469 if (!my_super_id)
3470 flags |= 0x02; /* RO_ROOT: this is a root class */
3471
3472 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN)
3473 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */
3474
3475 if (objc2_objc_exception_attr (impent->imp_template))
3476 flags |= 0x20; /* RO_EXCEPTION */
3477
3478 if (CLASS_NST_METHODS (impent->imp_context))
3479 {
3480 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s",
3481 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3482 inst_methods =
3483 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context),
3484 buf, meta_clai_meth);
3485 }
3486
3487 /* Sort out the ivars before we try to compute the class sizes. */
3488 if ((chain = CLASS_IVARS (impent->imp_template)))
3489 {
3490 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s",
3491 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
3492 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars,
3493 impent->imp_template);
3494 }
3495
3496 /* Compute instanceStart. */
3497 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template));
3498 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template));
3499 if (my_super_id && field && TREE_CHAIN (field))
3500 field = TREE_CHAIN (field);
3501
3502 firstIvar = field;
3503
3504 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL)
3505 firstIvar = TREE_CHAIN (firstIvar);
3506
3507 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true);
3508
3509 /* Compute instanceSize. */
3510 while (field && TREE_CHAIN (field)
3511 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL)
3512 field = TREE_CHAIN (field);
3513
3514 if (field && TREE_CODE (field) == FIELD_DECL)
3515 instanceSize = int_byte_position (field) * BITS_PER_UNIT
3516 + tree_to_shwi (DECL_SIZE (field));
3517 else
3518 instanceSize = 0;
3519 instanceSize /= BITS_PER_UNIT;
3520
3521 props = generate_v2_property_table (NULL_TREE, impent->imp_context);
3522
3523 /* If the class has no ivars, instanceStart should be set to the
3524 superclass's instanceSize. */
3525 instanceStart =
3526 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar)
3527 : instanceSize;
3528
3529 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */
3530 decl = start_var_decl (objc_v2_class_ro_template,
3531 newabi_append_ro (IDENTIFIER_POINTER
3532 (DECL_NAME (class_decl))));
3533
3534 initlist =
3535 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr,
3536 (flags | cls_flags), instanceStart,
3537 instanceSize, ivarLayout,
3538 inst_methods, protocol_decl,
3539 inst_ivars, props);
3540 /* The ROs sit in the default const section. */
3541 OBJCMETA (decl, objc_meta, meta_base);
3542 DECL_USER_ALIGN (decl) = 1;
3543 finish_var_decl (decl, initlist);
3544
3545 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */
3546 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl),
3547 build_fold_addr_expr (metaclass_decl),
3548 class_superclass_expr,
3549 build_fold_addr_expr (decl),
3550 build_fold_addr_expr (UOBJC_V2_CACHE_decl),
3551 build_fold_addr_expr (UOBJC_V2_VTABLE_decl));
3552
3553 /* The class section attributes are set when they are created. */
3554 DECL_USER_ALIGN (class_decl) = 1;
3555 finish_var_decl (class_decl, initlist);
3556 impent->class_decl = class_decl;
3557
3558 objc_v2_add_to_class_list (class_decl);
3559 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context)))
3560 objc_v2_add_to_nonlazy_class_list (class_decl);
3561
3562 if (flags & 0x20) /* RO_EXCEPTION */
3563 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template));
3564 }
3565
3566 /* This routine outputs the (ivar_reference_offset, offset)
3567 tuples. */
3568
3569 static void
build_v2_ivar_offset_ref_table(void)3570 build_v2_ivar_offset_ref_table (void)
3571 {
3572 int count;
3573 ivarref_entry *ref;
3574
3575 if (!vec_safe_length (ivar_offset_refs))
3576 return;
3577
3578 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref)
3579 finish_var_decl (ref->decl, ref->offset);
3580 }
3581
3582 static void
objc_generate_v2_next_metadata(void)3583 objc_generate_v2_next_metadata (void)
3584 {
3585 struct imp_entry *impent;
3586
3587 /* FIXME: Make sure that we generate no metadata if there is nothing
3588 to put into it. */
3589
3590 gcc_assert (!objc_static_instances); /* Not for NeXT */
3591
3592 build_metadata_templates ();
3593
3594 for (impent = imp_list; impent; impent = impent->next)
3595 {
3596 /* If -gen-decls is present, Dump the @interface of each class.
3597 TODO: Dump the classes in the order they were found, rather
3598 than in reverse order as we are doing now. */
3599 if (flag_gen_declaration)
3600 dump_interface (gen_declaration_file, impent->imp_context);
3601
3602 /* all of the following reference the string pool... */
3603 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE)
3604 generate_v2_class_structs (impent);
3605 else
3606 generate_v2_category (impent);
3607 }
3608
3609 build_next_selector_translation_table ();
3610 build_v2_message_ref_translation_table ();
3611
3612 /* This will add "Protocol" to the class refs. */
3613 generate_v2_protocols ();
3614
3615 build_v2_classrefs_table ();
3616 build_v2_super_classrefs_table (/*metaclass= */false);
3617 build_v2_super_classrefs_table (/*metaclass= */true);
3618
3619 build_v2_ivar_offset_ref_table ();
3620
3621 build_v2_protocol_list_translation_table ();
3622 build_v2_protocol_list_address_table ();
3623
3624 build_v2_address_table (class_list, "_OBJC_ClassList$",
3625 meta_label_classlist);
3626 build_v2_address_table (category_list, "_OBJC_CategoryList$",
3627 meta_label_categorylist);
3628 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$",
3629 meta_label_nonlazy_classlist);
3630 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$",
3631 meta_label_nonlazy_categorylist);
3632
3633 /* Generate catch objects for eh, if any are needed. */
3634 build_v2_eh_catch_objects ();
3635
3636 /* Emit the string table last. */
3637 generate_strings ();
3638 }
3639
3640 /* NOTE --- Output NeXT V2 Exceptions --- */
3641
3642 static GTY(()) tree objc_v2_ehtype_template;
3643 static GTY(()) tree next_v2_ehvtable_decl;
3644 static GTY(()) tree next_v2_EHTYPE_id_decl;
3645
3646 static void
build_v2_ehtype_template(void)3647 build_v2_ehtype_template (void)
3648 {
3649 tree decls, *chain = NULL;
3650 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE));
3651
3652 /* void *_objc_ehtype_vtable; */
3653 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain);
3654
3655 /* const char *className; */
3656 add_field_decl (string_type_node, "className", &chain);
3657
3658 /* struct class_t *const cls; */
3659 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain);
3660
3661 objc_finish_struct (objc_v2_ehtype_template, decls);
3662 }
3663
3664 /* Template for the Objective-C family typeinfo type for ABI=2. This
3665 starts off the same as the gxx/cxx eh typeinfo.
3666
3667 struct _objc_ehtype_t
3668 {
3669 void *_objc_ehtype_vtable_ptr; - as per c++
3670 const char *className; - as per c++
3671 struct class_t *const cls;
3672 }
3673 */
3674
3675 /* This routine builds initializer list for object of type struct _objc_ehtype_t.
3676 */
3677
3678 static tree
objc2_build_ehtype_initializer(tree name,tree cls)3679 objc2_build_ehtype_initializer (tree name, tree cls)
3680 {
3681 vec<constructor_elt, va_gc> *initlist = NULL;
3682 tree addr, offs;
3683
3684 /* This is done the same way as c++, missing the two first entries
3685 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT
3686 runtime source about this so, perhaps, this will change at some
3687 point. */
3688 /* _objc_ehtype_vtable + 2*sizeof(void*) */
3689 if (!next_v2_ehvtable_decl)
3690 {
3691 next_v2_ehvtable_decl =
3692 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME);
3693 TREE_STATIC (next_v2_ehvtable_decl) = 0;
3694 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1;
3695 TREE_PUBLIC (next_v2_ehvtable_decl) = 1;
3696 }
3697 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node);
3698 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node)));
3699 addr = fold_build_pointer_plus (addr, offs);
3700
3701 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr);
3702
3703 /* className */
3704 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name);
3705
3706 /* cls */
3707 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls);
3708
3709 return objc_build_constructor (objc_v2_ehtype_template, initlist);
3710 }
3711
3712 static tree
build_ehtype(tree name,const char * eh_name,bool weak)3713 build_ehtype (tree name, const char *eh_name, bool weak)
3714 {
3715 tree name_expr, class_name_expr, ehtype_decl, inits;
3716
3717 name_expr = add_objc_string (name, class_names);
3718 /* Extern ref. for the class. ??? Maybe we can look this up
3719 somewhere. */
3720 class_name_expr =
3721 create_extern_decl (objc_v2_class_template,
3722 objc_build_internal_classname (name, false));
3723 class_name_expr = build_fold_addr_expr (class_name_expr);
3724 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name);
3725 if (weak)
3726 DECL_WEAK (ehtype_decl) = 1;
3727 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr);
3728 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype);
3729 DECL_USER_ALIGN (ehtype_decl) = 1;
3730 finish_var_decl (ehtype_decl, inits);
3731 return ehtype_decl;
3732 }
3733
3734 /* This routine returns TRUE if CLS or any of its super classes has
3735 __attribute__ ((objc_exception)). */
3736
3737 static bool
objc2_objc_exception_attr(tree cls)3738 objc2_objc_exception_attr (tree cls)
3739 {
3740 while (cls)
3741 {
3742 if (CLASS_HAS_EXCEPTION_ATTR (cls))
3743 return true;
3744 cls = lookup_interface (CLASS_SUPER_NAME (cls));
3745 }
3746
3747 return false;
3748 }
3749
3750 static bool
is_implemented(tree name)3751 is_implemented (tree name)
3752 {
3753 struct imp_entry *t;
3754 for (t = imp_list; t; t = t->next)
3755 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE
3756 && CLASS_NAME (t->imp_template) == name)
3757 return true;
3758
3759 return false;
3760 }
3761
3762 /* We will build catch objects:
3763 for any type implemented here.
3764 for any type used in a catch that has no exception attribute. */
build_v2_eh_catch_objects(void)3765 static void build_v2_eh_catch_objects (void)
3766 {
3767 int count=0;
3768 ident_data_tuple *ref;
3769
3770 if (!vec_safe_length (ehtype_list))
3771 return;
3772
3773 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3774 {
3775 char buf[BUFSIZE];
3776 bool impl = is_implemented (ref->ident);
3777 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident));
3778 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident));
3779 if (!impl && excpt)
3780 /* The User says this class has a catcher already. */
3781 ref->data = create_extern_decl (objc_v2_ehtype_template, buf);
3782 else
3783 /* Create a catcher, weak if it wasn't marked. */
3784 ref->data = build_ehtype (ref->ident, buf, !excpt);
3785 }
3786 }
3787
3788 static tree
lookup_ehtype_ref(tree id)3789 lookup_ehtype_ref (tree id)
3790 {
3791 int count=0;
3792 ident_data_tuple *ref;
3793
3794 if (!vec_safe_length (ehtype_list))
3795 return NULL_TREE;
3796
3797 FOR_EACH_VEC_ELT (*ehtype_list, count, ref)
3798 if (ref->ident == id)
3799 return ref->data;
3800 return NULL_TREE;
3801 }
3802
3803 /* This hook, called via lang_eh_runtime_type, generates a runtime
3804 object which is either the address of the 'OBJC_EHTYPE_$_class'
3805 object or address of external OBJC_EHTYPE_id object. */
3806 static tree
next_runtime_02_eh_type(tree type)3807 next_runtime_02_eh_type (tree type)
3808 {
3809 tree t;
3810
3811 if (type == error_mark_node
3812 /*|| errorcount || sorrycount*/)
3813 goto err_mark_in;
3814
3815 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
3816 {
3817 if (!next_v2_EHTYPE_id_decl)
3818 {
3819 /* This is provided by the Apple/NeXT libobjc.dylib so we
3820 need only to reference it. */
3821 next_v2_EHTYPE_id_decl =
3822 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id");
3823 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1;
3824 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1;
3825 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0;
3826 }
3827 return build_fold_addr_expr (next_v2_EHTYPE_id_decl);
3828 }
3829
3830 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type)))
3831 {
3832 #ifdef OBJCPLUS
3833 /* This routine is also called for c++'s catch clause; in which
3834 case, we use c++'s typeinfo decl. */
3835 return build_eh_type_type (type);
3836 #else
3837 error ("non-objective-c type %qT cannot be caught", type);
3838 goto err_mark_in;
3839 #endif
3840 }
3841 else
3842 t = OBJC_TYPE_NAME (TREE_TYPE (type));
3843
3844 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */
3845 t = lookup_ehtype_ref (t);
3846 if (!t)
3847 goto err_mark_in;
3848
3849 return build_fold_addr_expr (t);
3850
3851 err_mark_in:
3852 return error_mark_node;
3853 }
3854
3855 static GTY(()) tree objc_eh_personality_decl;
3856
3857 static tree
objc_eh_personality(void)3858 objc_eh_personality (void)
3859 {
3860 if (!objc_eh_personality_decl)
3861 objc_eh_personality_decl = build_personality_function ("objc");
3862 return objc_eh_personality_decl;
3863 }
3864
3865 /* NOTE --- interfaces --- */
3866
3867 static tree
build_throw_stmt(location_t loc,tree throw_expr,bool rethrown)3868 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown)
3869 {
3870 tree t;
3871 if (rethrown)
3872 /* We have a separate re-throw entry. */
3873 t = build_function_call_vec (loc, vNULL, objc_rethrow_exception_decl,
3874 NULL, NULL);
3875 else
3876 {
3877 /* Throw like the others... */
3878 vec<tree, va_gc> *parms;
3879 vec_alloc (parms, 1);
3880 parms->quick_push (throw_expr);
3881 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl,
3882 parms, 0);
3883 vec_free (parms);
3884 }
3885 return add_stmt (t);
3886 }
3887
3888 /* Build __builtin_eh_pointer. */
3889
3890 static tree
objc_build_exc_ptr(struct objc_try_context ** x ATTRIBUTE_UNUSED)3891 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED)
3892 {
3893 tree t;
3894 t = builtin_decl_explicit (BUILT_IN_EH_POINTER);
3895 t = build_call_expr (t, 1, integer_zero_node);
3896 return fold_convert (objc_object_type, t);
3897 }
3898
begin_catch(struct objc_try_context ** cur_try_context,tree type,tree decl,tree compound,bool ellipsis ATTRIBUTE_UNUSED)3899 static tree begin_catch (struct objc_try_context **cur_try_context, tree type,
3900 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED)
3901 {
3902 tree t;
3903
3904 /* Record the data for the catch in the try context so that we can
3905 finalize it later. Ellipsis is signalled by a NULL entry. */
3906 if (ellipsis)
3907 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound);
3908 else
3909 t = build_stmt (input_location, CATCH_EXPR, type, compound);
3910 (*cur_try_context)->current_catch = t;
3911
3912 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */
3913 t = objc_build_exc_ptr (cur_try_context);
3914 t = convert (TREE_TYPE (decl), t);
3915 /* FIXME: location. */
3916 if (type && type != error_mark_node)
3917 {
3918 t = build1(NOP_EXPR, ptr_type_node, t);
3919 t = build_function_call (input_location, objc2_begin_catch_decl,
3920 tree_cons (NULL_TREE, t, NULL_TREE));
3921
3922 /* We might want to build a catch object for this (if it's not
3923 id). */
3924 if (POINTER_TYPE_P (type)
3925 && !objc_is_object_id (TREE_TYPE (type))
3926 && TYPED_OBJECT (TREE_TYPE (type)))
3927 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type)));
3928 }
3929 return build2 (MODIFY_EXPR, void_type_node, decl, t);
3930 }
3931
3932 /* try { catch-body } finally { objc_end_catch (); } */
3933 static void
finish_catch(struct objc_try_context ** cur_try_context,tree curr_catch)3934 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch)
3935 {
3936 struct objc_try_context *ct;
3937 tree try_exp, func, *l, t ;
3938 location_t loc = (*cur_try_context)->try_locus;
3939
3940 if (!curr_catch || curr_catch == error_mark_node)
3941 return;
3942
3943 t = CATCH_BODY (curr_catch);
3944 if (TREE_CODE (t) == BIND_EXPR)
3945 {
3946 /* Usual case of @catch (objc-expr). */
3947 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t));
3948 BIND_EXPR_BODY (t) = NULL_TREE;
3949 l = &BIND_EXPR_BODY (t);
3950 }
3951 else
3952 {
3953 /* NULL entry, meaning @catch (...). */
3954 objc_begin_try_stmt (loc, t);
3955 CATCH_BODY (curr_catch) = NULL_TREE;
3956 l = &CATCH_BODY (curr_catch);
3957 }
3958
3959 /* Pick up the new context we made in begin_try above... */
3960 ct = *cur_try_context;
3961 func = build_function_call_vec (loc, vNULL, objc2_end_catch_decl, NULL,
3962 NULL);
3963 append_to_statement_list (func, &ct->finally_body);
3964 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body);
3965 *cur_try_context = ct->outer;
3966 free (ct);
3967 append_to_statement_list (try_exp, l);
3968 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list));
3969 }
3970
3971 static tree
finish_try_stmt(struct objc_try_context ** cur_try_context)3972 finish_try_stmt (struct objc_try_context **cur_try_context)
3973 {
3974 struct objc_try_context *c = *cur_try_context;
3975 tree stmt = c->try_body;
3976 if (c->catch_list)
3977 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list);
3978 if (c->finally_body)
3979 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body);
3980 return stmt;
3981 }
3982
3983 #include "gt-objc-objc-next-runtime-abi-02.h"
3984