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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 2193 objc_v2_add_to_nonlazy_category_list (tree decl) 2194 { 2195 vec_safe_push (nonlazy_category_list, decl); 2196 } 2197 2198 static bool 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. */ 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 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 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 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 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 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 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 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 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