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