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