1 /* Next Runtime (ABI-2) private. 2 Copyright (C) 2011-2013 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 "tm.h" 32 #include "tree.h" 33 34 #ifdef OBJCPLUS 35 #include "cp/cp-tree.h" 36 #else 37 #include "c/c-tree.h" 38 #include "c/c-lang.h" 39 #endif 40 #include "langhooks.h" 41 #include "c-family/c-objc.h" 42 #include "objc-act.h" 43 44 /* When building Objective-C++, we are not linking against the C front-end 45 and so need to replicate the C tree-construction functions in some way. */ 46 #ifdef OBJCPLUS 47 #define OBJCP_REMAP_FUNCTIONS 48 #include "objcp-decl.h" 49 #endif /* OBJCPLUS */ 50 51 #include "ggc.h" 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_alloc_cleared_vec_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 typedef struct GTY(()) ident_data_tuple { 1015 tree ident; 1016 tree data; 1017 } ident_data_tuple ; 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, objc_get_class_decl, v, 0); 1091 vec_free (v); 1092 return t; 1093 } 1094 } 1095 1096 /* Used by build_function_type_for_method. Append the types for 1097 receiver & _cmd at the start of a method argument list to ARGTYPES. 1098 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are 1099 trying to define a method or call one. SUPERFLAG says this is for a 1100 send to super. METH may be NULL, in the case that there is no 1101 prototype. */ 1102 1103 static void 1104 next_runtime_abi_02_get_arg_type_list_base (vec<tree, va_gc> **argtypes, 1105 tree meth, int context, 1106 int superflag) 1107 { 1108 tree receiver_type; 1109 1110 if (superflag) 1111 receiver_type = objc_super_type; 1112 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL) 1113 receiver_type = objc_instance_type; 1114 else 1115 receiver_type = objc_object_type; 1116 1117 vec_safe_push (*argtypes, receiver_type); 1118 /* Selector type - will eventually change to `int'. */ 1119 vec_safe_push (*argtypes, 1120 superflag ? objc_v2_super_selector_type 1121 : objc_v2_selector_type); 1122 } 1123 1124 /* TODO: Merge this with the message refs. */ 1125 static tree 1126 build_selector_reference_decl (tree ident) 1127 { 1128 tree decl; 1129 char *t, buf[BUFSIZE]; 1130 1131 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident)); 1132 t = buf; 1133 while (*t) 1134 { 1135 if (*t==':') 1136 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */ 1137 t++; 1138 } 1139 decl = start_var_decl (objc_selector_type, buf); 1140 OBJCMETA (decl, objc_meta, meta_sel_refs); 1141 return decl; 1142 } 1143 1144 static tree 1145 next_runtime_abi_02_build_selector_reference (location_t loc ATTRIBUTE_UNUSED, 1146 tree ident, 1147 tree proto ATTRIBUTE_UNUSED) 1148 { 1149 tree *chain = &sel_ref_chain; 1150 tree expr; 1151 1152 while (*chain) 1153 { 1154 if (TREE_VALUE (*chain) == ident) 1155 return TREE_PURPOSE (*chain); 1156 1157 chain = &TREE_CHAIN (*chain); 1158 } 1159 1160 expr = build_selector_reference_decl (ident); 1161 *chain = tree_cons (expr, ident, NULL_TREE); 1162 1163 return expr; 1164 } 1165 1166 /* Declare a variable of type 'struct message_ref_t'. */ 1167 /* This will be finished in build_v2_message_ref_translation_table (). 1168 We take an idea from LLVM in making the names a bit more connected 1169 and thus the asm more readable. */ 1170 1171 static tree 1172 build_v2_message_reference_decl (tree sel_name, tree message_func_ident) 1173 { 1174 tree decl; 1175 char buf[BUFSIZE], *t; 1176 int offset = 12; 1177 1178 /* Skip past the objc_msgSend it's the same for all... */ 1179 if (IDENTIFIER_POINTER (message_func_ident)[offset] == '_') 1180 offset++; 1181 1182 snprintf (buf, BUFSIZE, "_OBJC_MsgRef_%s_%s", 1183 &(IDENTIFIER_POINTER (message_func_ident)[offset]), 1184 IDENTIFIER_POINTER (sel_name)); 1185 t = buf; 1186 while (*t) 1187 { 1188 if (*t==':') 1189 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */ 1190 t++; 1191 } 1192 decl = start_var_decl (objc_v2_message_ref_template, buf); 1193 OBJCMETA (decl, objc_meta, meta_mref); 1194 return decl; 1195 } 1196 1197 typedef struct GTY(()) msgref_entry { 1198 tree func; 1199 tree selname; 1200 tree refdecl; 1201 } msgref_entry; 1202 1203 static GTY (()) vec<msgref_entry, va_gc> *msgrefs; 1204 1205 /* Build the list of (objc_msgSend_fixup_xxx, selector name), used 1206 later on to initialize the table of 'struct message_ref_t' 1207 elements. */ 1208 1209 static tree 1210 build_v2_selector_messenger_reference (tree sel_name, tree message_func_decl) 1211 { 1212 tree decl; 1213 msgref_entry e; 1214 if (msgrefs) 1215 { 1216 int count; 1217 msgref_entry *ref; 1218 FOR_EACH_VEC_ELT (*msgrefs, count, ref) 1219 if (ref->func == message_func_decl && ref->selname == sel_name) 1220 return ref->refdecl; 1221 } 1222 else 1223 /* Somewhat arbitrary initial provision. */ 1224 vec_alloc (msgrefs, 32); 1225 1226 /* We come here if we don't find a match or at the start. */ 1227 decl = build_v2_message_reference_decl (sel_name, 1228 DECL_NAME (message_func_decl)); 1229 e.func = message_func_decl; 1230 e.selname = sel_name; 1231 e.refdecl = decl; 1232 vec_safe_push (msgrefs, e); 1233 return decl; 1234 } 1235 1236 static tree 1237 build_v2_protocollist_ref_decl (tree protocol) 1238 { 1239 tree decl; 1240 tree protocol_ident = PROTOCOL_NAME (protocol); 1241 char buf[BUFSIZE]; 1242 1243 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRef_%s", 1244 IDENTIFIER_POINTER (protocol_ident)); 1245 /* TODO: other compiler versions make these hidden & weak. */ 1246 decl = create_global_decl (objc_protocol_type, buf); 1247 /* Let optimizer know that this decl is not removable. */ 1248 DECL_PRESERVE_P (decl) = 1; 1249 OBJCMETA (decl, objc_meta, meta_proto_ref); 1250 return decl; 1251 } 1252 1253 typedef struct GTY(()) prot_list_entry { 1254 tree id; 1255 tree refdecl; 1256 } prot_list_entry; 1257 static GTY (()) vec<prot_list_entry, va_gc> *protrefs; 1258 1259 static tree 1260 objc_v2_get_protocol_reference (tree ident) 1261 { 1262 tree decl; 1263 prot_list_entry e; 1264 if (protrefs) 1265 { 1266 int count; 1267 prot_list_entry *ref; 1268 FOR_EACH_VEC_ELT (*protrefs, count, ref) 1269 { 1270 if (ref->id == ident) 1271 { 1272 if (!ref->refdecl) 1273 ref->refdecl = build_v2_protocollist_ref_decl (ident); 1274 return ref->refdecl; 1275 } 1276 } 1277 } 1278 else 1279 /* Somewhat arbitrary initial provision. */ 1280 vec_alloc (protrefs, 32); 1281 1282 /* We come here if we don't find the entry - or if the table was yet 1283 to be created. */ 1284 decl = build_v2_protocollist_ref_decl (ident); 1285 e.id = ident; 1286 e.refdecl = decl; 1287 vec_safe_push (protrefs, e); 1288 return decl; 1289 } 1290 1291 static tree 1292 next_runtime_abi_02_get_protocol_reference (location_t loc ATTRIBUTE_UNUSED, 1293 tree p) 1294 { 1295 if (!PROTOCOL_FORWARD_DECL (p)) 1296 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_02_protocol_decl (p); 1297 1298 return objc_v2_get_protocol_reference (p); 1299 } 1300 1301 /* This routine returns the ivar declaration, if component is a valid 1302 ivar field; NULL_TREE otherwise. On finding an ivar, it also 1303 returns the class name in CLASS. */ 1304 1305 static tree 1306 objc_is_ivar (tree expr, tree component, tree *klass) 1307 { 1308 tree field = NULL_TREE; 1309 tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); 1310 1311 if (TREE_CODE (basetype) == RECORD_TYPE 1312 && TYPE_HAS_OBJC_INFO (basetype) && TYPE_OBJC_INTERFACE (basetype)) 1313 { 1314 *klass = lookup_interface (OBJC_TYPE_NAME (basetype)); 1315 if (*klass) 1316 { 1317 do 1318 { 1319 tree ivar_chain = CLASS_RAW_IVARS (*klass); 1320 if (ivar_chain) 1321 { 1322 field = is_ivar (ivar_chain, component); 1323 if (field != NULL_TREE) 1324 break; 1325 } 1326 *klass = lookup_interface (CLASS_SUPER_NAME (*klass)); 1327 } 1328 while (*klass); 1329 } 1330 } 1331 return field; 1332 } 1333 1334 static void 1335 create_ivar_offset_name (char *buf, tree class_name, tree field_decl) 1336 { 1337 tree fname = DECL_NAME (field_decl); 1338 1339 sprintf (buf, "OBJC_IVAR_$_%s.%s", IDENTIFIER_POINTER (class_name), 1340 IDENTIFIER_POINTER (fname)); 1341 return; 1342 } 1343 1344 /* This routine generates new abi's ivar reference tree. It amounts 1345 to generating *(TYPE*)((char*)pObj + OFFSET_IVAR) when we normally 1346 generate pObj->IVAR. OFFSET_IVAR is an 'extern' variable holding 1347 the offset for 'IVAR' field. TYPE is type of IVAR field. */ 1348 1349 static tree 1350 objc_v2_build_ivar_ref (tree datum, tree component) 1351 { 1352 tree field, ref, class_name, offset, ftype, expr; 1353 char var_offset_name[512]; 1354 1355 field = objc_is_ivar (datum, component, &class_name); 1356 if (!field) 1357 return NULL_TREE; 1358 1359 /* This routine only handles non-bitfield fields */ 1360 /* DECL_INITIAL macro is set to width of bitfield and can be relied 1361 on to check for bitfield ivars. Note that I cannot rely on 1362 DECL_BIT_FIELD macro because it is only set when the whole struct 1363 is seen (at finish_struct) and not when the ivar chain is 1364 built. */ 1365 if (DECL_INITIAL (field)) 1366 return NULL_TREE; 1367 1368 create_ivar_offset_name (var_offset_name, CLASS_NAME (class_name), field); 1369 1370 offset = create_extern_decl (TREE_TYPE (size_zero_node), var_offset_name); 1371 1372 ftype = TREE_TYPE (field); 1373 1374 /* (char*)datum */ 1375 expr = build_c_cast (input_location, 1376 string_type_node, build_fold_addr_expr (datum)); 1377 1378 /* (char*)datum + offset */ 1379 expr = fold_build_pointer_plus_loc (input_location, expr, offset); 1380 1381 /* (ftype*)((char*)datum + offset) */ 1382 expr = build_c_cast (input_location, build_pointer_type (ftype), expr); 1383 1384 /* Finally: *(ftype*)((char*)datum + offset) */ 1385 ref = build_indirect_ref (input_location, expr, RO_UNARY_STAR); 1386 1387 /* We must set type of the resulting expression to be the same as 1388 the field type. This is because, build_indirect_ref (...) 1389 rebuilds the type which may result in lost information; as in the 1390 case of protocol-qualified types (id <protocol> ). */ 1391 TREE_TYPE (ref) = ftype; 1392 1393 if (TREE_READONLY (datum) || TREE_READONLY (field)) 1394 TREE_READONLY (ref) = 1; 1395 1396 if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field)) 1397 TREE_THIS_VOLATILE (ref) = 1; 1398 1399 if (TREE_DEPRECATED (field)) 1400 warn_deprecated_use (field, NULL_TREE); 1401 1402 return ref; 1403 } 1404 1405 /* IVAR refs are made via an externally referenceable offset and built 1406 on the fly. That is, unless they refer to (private) fields in the 1407 class stucture. */ 1408 static tree 1409 next_runtime_abi_02_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED, 1410 tree base, tree id) 1411 { 1412 tree ivar; 1413 if ((ivar = objc_v2_build_ivar_ref (base, id))) 1414 return ivar; 1415 return objc_build_component_ref (base, id); 1416 } 1417 1418 /* [super ...] references are listed here (and built into a table at 1419 meta -data emit time). */ 1420 static tree 1421 build_v2_superclass_ref_decl (tree ident, bool inst) 1422 { 1423 tree decl; 1424 char buf[BUFSIZE]; 1425 1426 snprintf (buf, BUFSIZE, "_OBJC_%sSuperRef_%s", (inst?"":"Meta"), 1427 IDENTIFIER_POINTER (ident)); 1428 decl = start_var_decl (objc_class_type, buf); 1429 OBJCMETA (decl, objc_meta, meta_superclass_ref); 1430 return decl; 1431 } 1432 1433 static GTY (()) vec<ident_data_tuple, va_gc> *class_super_refs; 1434 static GTY (()) vec<ident_data_tuple, va_gc> *metaclass_super_refs; 1435 1436 static tree 1437 next_runtime_abi_02_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, 1438 struct imp_entry *imp, bool inst_meth) 1439 { 1440 tree decl; 1441 ident_data_tuple e; 1442 tree id = CLASS_NAME (imp->imp_context); 1443 vec<ident_data_tuple, va_gc> *list = inst_meth ? class_super_refs 1444 : metaclass_super_refs; 1445 1446 if (list) 1447 { 1448 int count; 1449 ident_data_tuple *ref; 1450 FOR_EACH_VEC_ELT (*list, count, ref) 1451 { 1452 if (ref->ident == id) 1453 { 1454 if (!ref->data) 1455 ref->data = build_v2_superclass_ref_decl (id, inst_meth); 1456 return ref->data; 1457 } 1458 } 1459 } 1460 else 1461 { 1462 /* Somewhat arbitrary initial provision. */ 1463 if (inst_meth) 1464 { 1465 vec_alloc (class_super_refs, 16); 1466 list = class_super_refs; 1467 } 1468 else 1469 { 1470 vec_alloc (metaclass_super_refs, 16); 1471 list = metaclass_super_refs; 1472 } 1473 } 1474 /* We come here if we don't find the entry - or if the table was yet 1475 to be created. */ 1476 decl = build_v2_superclass_ref_decl (id, inst_meth); 1477 e.ident = id; 1478 e.data = decl; 1479 vec_safe_push (list, e); 1480 return decl; 1481 } 1482 1483 static tree 1484 next_runtime_abi_02_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED, 1485 struct imp_entry *imp, bool inst_meth) 1486 { 1487 /* ??? is this OK when zero-link = true? */ 1488 tree super_name = CLASS_SUPER_NAME (imp->imp_template); 1489 tree super_class; 1490 1491 if (!flag_zero_link) 1492 { 1493 super_class = objc_get_class_reference (CLASS_NAME (imp->imp_template)); 1494 1495 if (!inst_meth) 1496 1497 /* If we are in a class method, we must retrieve the 1498 _metaclass_ for the current class, pointed at by the 1499 class's "isa" pointer. The following assumes that "isa" is 1500 the first ivar in a class (which it must be). */ 1501 super_class = 1502 build_indirect_ref (input_location, 1503 build_c_cast (input_location, 1504 build_pointer_type (objc_class_type), 1505 super_class), 1506 RO_UNARY_STAR); 1507 return super_class; 1508 } 1509 /* ??? Do we need to add the class ref anway for zero-link? */ 1510 /* else do it the slow way. */ 1511 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl); 1512 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1, 1513 IDENTIFIER_POINTER (super_name)); 1514 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */ 1515 return build_function_call (input_location, 1516 super_class, 1517 build_tree_list (NULL_TREE, super_name)); 1518 } 1519 1520 static tree 1521 next_runtime_abi_02_receiver_is_class_object (tree receiver) 1522 { 1523 if (TREE_CODE (receiver) == VAR_DECL 1524 && IS_CLASS (TREE_TYPE (receiver)) 1525 && vec_safe_length (classrefs)) 1526 { 1527 int count; 1528 ident_data_tuple *ref; 1529 /* The receiver is a variable created by build_class_reference_decl. */ 1530 FOR_EACH_VEC_ELT (*classrefs, count, ref) 1531 if (ref->data == receiver) 1532 return ref->ident; 1533 } 1534 return NULL_TREE; 1535 } 1536 1537 /* Assign all arguments in VALUES which have side-effect to a temporary 1538 and replaced that argument in VALUES list with the temporary. The 1539 arguments will be passed to a function with FNTYPE. */ 1540 1541 static tree 1542 objc_copy_to_temp_side_effect_params (tree fntype, tree values) 1543 { 1544 tree valtail; 1545 function_args_iterator iter; 1546 1547 /* Skip over receiver and the &_msf_ref types. */ 1548 function_args_iter_init (&iter, fntype); 1549 function_args_iter_next (&iter); 1550 function_args_iter_next (&iter); 1551 1552 for (valtail = values; valtail; 1553 valtail = TREE_CHAIN (valtail), function_args_iter_next (&iter)) 1554 { 1555 tree value = TREE_VALUE (valtail); 1556 tree type = function_args_iter_cond (&iter); 1557 if (type == NULL_TREE) 1558 break; 1559 if (!TREE_SIDE_EFFECTS (value)) 1560 continue; 1561 /* To prevent re-evaluation. */ 1562 value = save_expr (value); 1563 add_stmt (value); 1564 TREE_VALUE (valtail) = value; 1565 } 1566 return values; 1567 } 1568 1569 /* Build the new abi's messaging library call. It looks like: 1570 (*_msg.messenger) (receiver, &_msg, ...) */ 1571 1572 static tree 1573 build_v2_build_objc_method_call (int super_flag, tree method_prototype, 1574 tree lookup_object, tree selector, 1575 tree method_params, 1576 bool check_for_nil) 1577 { 1578 tree ret_val; 1579 tree sender, rcv_p, t; 1580 tree ret_type 1581 = (method_prototype 1582 ? TREE_VALUE (TREE_TYPE (method_prototype)) 1583 : objc_object_type); 1584 tree ftype = build_function_type_for_method (ret_type, method_prototype, 1585 METHOD_REF, super_flag); 1586 tree sender_cast; 1587 1588 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype)) 1589 ftype = build_type_attribute_variant ( 1590 ftype, METHOD_TYPE_ATTRIBUTES (method_prototype)); 1591 1592 sender_cast = build_pointer_type (ftype); 1593 1594 if (check_for_nil) 1595 method_params = objc_copy_to_temp_side_effect_params (ftype, 1596 method_params); 1597 1598 /* Get &message_ref_t.messenger. */ 1599 sender = build_c_cast (input_location, 1600 build_pointer_type (super_flag 1601 ? objc_v2_super_imp_type 1602 : objc_v2_imp_type), 1603 selector); 1604 1605 sender = build_indirect_ref (input_location, sender, RO_UNARY_STAR); 1606 1607 rcv_p = (super_flag ? objc_super_type : objc_object_type); 1608 1609 lookup_object = build_c_cast (input_location, rcv_p, lookup_object); 1610 1611 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */ 1612 lookup_object = save_expr (lookup_object); 1613 1614 method_params = tree_cons (NULL_TREE, lookup_object, 1615 tree_cons (NULL_TREE, selector, 1616 method_params)); 1617 t = build3 (OBJ_TYPE_REF, sender_cast, sender, lookup_object, size_zero_node); 1618 ret_val = build_function_call (input_location, t, method_params); 1619 if (check_for_nil) 1620 { 1621 /* receiver != nil ? ret_val : 0 */ 1622 tree ftree; 1623 tree ifexp; 1624 1625 if (TREE_CODE (ret_type) == RECORD_TYPE 1626 || TREE_CODE (ret_type) == UNION_TYPE) 1627 { 1628 vec<constructor_elt, va_gc> *rtt = NULL; 1629 /* ??? CHECKME. hmmm..... think we need something more 1630 here. */ 1631 CONSTRUCTOR_APPEND_ELT (rtt, NULL_TREE, NULL_TREE); 1632 ftree = objc_build_constructor (ret_type, rtt); 1633 } 1634 else 1635 ftree = fold_convert (ret_type, integer_zero_node); 1636 1637 ifexp = build_binary_op (input_location, NE_EXPR, 1638 lookup_object, 1639 fold_convert (rcv_p, integer_zero_node), 1); 1640 1641 #ifdef OBJCPLUS 1642 ret_val = build_conditional_expr (ifexp, ret_val, ftree, tf_warning_or_error); 1643 #else 1644 /* ??? CHECKME. */ 1645 ret_val = build_conditional_expr (input_location, 1646 ifexp, 1, 1647 ret_val, NULL_TREE, 1648 ftree, NULL_TREE); 1649 #endif 1650 } 1651 return ret_val; 1652 } 1653 1654 static tree 1655 next_runtime_abi_02_build_objc_method_call (location_t loc, 1656 tree method_prototype, 1657 tree receiver, 1658 tree rtype, 1659 tree sel_name, 1660 tree method_params, 1661 int super) 1662 { 1663 tree ret_type, selector; 1664 tree message_func_decl; 1665 bool check_for_nil = flag_objc_nilcheck; 1666 1667 ret_type = method_prototype 1668 ? TREE_VALUE (TREE_TYPE (method_prototype)) 1669 : objc_object_type; 1670 1671 /* Do we need to check for nil receivers ? */ 1672 /* For now, message sent to classes need no nil check. In the 1673 future, class declaration marked as weak_import must be nil 1674 checked. */ 1675 if (super 1676 || (TREE_CODE (receiver) == VAR_DECL 1677 && TREE_TYPE (receiver) == objc_class_type)) 1678 check_for_nil = false; 1679 1680 if (!targetm.calls.struct_value_rtx (0, 0) 1681 && (TREE_CODE (ret_type) == RECORD_TYPE 1682 || TREE_CODE (ret_type) == UNION_TYPE) 1683 && targetm.calls.return_in_memory (ret_type, 0)) 1684 { 1685 if (super) 1686 message_func_decl = umsg_id_super2_stret_fixup_decl; 1687 else 1688 message_func_decl = objc_is_id (rtype) 1689 ? umsg_id_stret_fixup_decl 1690 : umsg_stret_fixup_decl; 1691 } 1692 else 1693 { 1694 if (super) 1695 message_func_decl = umsg_id_super2_fixup_decl; 1696 else 1697 message_func_decl = objc_is_id (rtype) 1698 ? umsg_id_fixup_decl 1699 : umsg_fixup_decl; 1700 } 1701 1702 selector = build_v2_selector_messenger_reference (sel_name, 1703 message_func_decl); 1704 1705 /* selector = &_msg; */ 1706 selector = build_unary_op (loc, ADDR_EXPR, selector, 0); 1707 1708 selector = build_c_cast (loc, (super ? objc_v2_super_selector_type 1709 : objc_v2_selector_type), 1710 selector); 1711 1712 /* (*_msg.messenger) (receiver, &_msg, ...); */ 1713 return build_v2_build_objc_method_call (super, method_prototype, 1714 receiver, selector, 1715 method_params, check_for_nil); 1716 } 1717 1718 /* NOTE --- Constant String Class Stuff --- */ 1719 1720 static bool 1721 next_runtime_abi_02_setup_const_string_class_decl (void) 1722 { 1723 if (!constant_string_global_id) 1724 { 1725 /* Hopefully, this should not represent a serious limitation. */ 1726 char buf[BUFSIZE]; 1727 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", constant_string_class_name); 1728 constant_string_global_id = get_identifier (buf); 1729 } 1730 1731 string_class_decl = lookup_name (constant_string_global_id); 1732 1733 /* In OBJC2 abi, constant string class reference refers to class 1734 name for NSConstantString class. This declaration may not be 1735 available yet (in fact it is not in most cases). So, declare an 1736 extern OBJC_CLASS_$_NSConstantString in its place. */ 1737 if (!string_class_decl) 1738 string_class_decl = 1739 create_extern_decl (objc_v2_class_template, 1740 IDENTIFIER_POINTER (constant_string_global_id)); 1741 1742 return (string_class_decl != NULL_TREE); 1743 } 1744 1745 static tree 1746 next_runtime_abi_02_build_const_string_constructor (location_t loc, tree string, 1747 int length) 1748 { 1749 tree constructor, fields, var; 1750 vec<constructor_elt, va_gc> *v = NULL; 1751 1752 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */ 1753 fields = TYPE_FIELDS (internal_const_str_type); 1754 CONSTRUCTOR_APPEND_ELT (v, fields, 1755 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0)); 1756 1757 fields = DECL_CHAIN (fields); 1758 CONSTRUCTOR_APPEND_ELT (v, fields, 1759 build_unary_op (loc, ADDR_EXPR, string, 1)); 1760 1761 /* ??? check if this should be long. */ 1762 fields = DECL_CHAIN (fields); 1763 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length)); 1764 constructor = objc_build_constructor (internal_const_str_type, v); 1765 1766 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor)); 1767 DECL_INITIAL (var) = constructor; 1768 TREE_STATIC (var) = 1; 1769 DECL_CONTEXT (var) = NULL; 1770 OBJCMETA (var, objc_meta, meta_const_str); 1771 return var; 1772 } 1773 1774 /* NOTE --- NeXT V2 Metadata templates --- */ 1775 1776 /* This routine builds the following type: 1777 struct _prop_t 1778 { 1779 const char * const name; // property name 1780 const char * const attributes; // comma-delimited, encoded, 1781 // property attributes 1782 }; 1783 */ 1784 1785 static tree 1786 build_v2_property_template (void) 1787 { 1788 tree prop_record; 1789 tree decls, *chain = NULL; 1790 1791 prop_record = objc_start_struct (get_identifier ("_prop_t")); 1792 /* const char * name */ 1793 decls = add_field_decl (string_type_node, "name", &chain); 1794 1795 /* const char * attribute */ 1796 add_field_decl (string_type_node, "attribute", &chain); 1797 1798 objc_finish_struct (prop_record, decls); 1799 return prop_record; 1800 } 1801 1802 /* struct ivar_t 1803 { 1804 unsigned long int *offset; 1805 char *name; 1806 char *type; 1807 uint32_t alignment; 1808 uint32_t size; 1809 }; 1810 */ 1811 1812 static tree 1813 build_v2_ivar_t_template (void) 1814 { 1815 tree objc_ivar_id, objc_ivar_record; 1816 tree decls, *chain = NULL; 1817 1818 objc_ivar_id = get_identifier ("_ivar_t"); 1819 objc_ivar_record = objc_start_struct (objc_ivar_id); 1820 1821 /* unsigned long int *offset; */ 1822 decls = add_field_decl (build_pointer_type 1823 (TREE_TYPE (size_zero_node)), "offset", &chain); 1824 1825 /* char *name; */ 1826 add_field_decl (string_type_node, "name", &chain); 1827 1828 /* char *type; */ 1829 add_field_decl (string_type_node, "type", &chain); 1830 1831 /* uint32_t alignment; */ 1832 add_field_decl (integer_type_node, "alignment", &chain); 1833 1834 /* uint32_t size; */ 1835 add_field_decl (integer_type_node, "size", &chain); 1836 1837 objc_finish_struct (objc_ivar_record, decls); 1838 return objc_ivar_record; 1839 } 1840 1841 static void 1842 build_metadata_templates (void) 1843 { 1844 1845 if (!objc_method_template) 1846 objc_method_template = build_method_template (); 1847 1848 if (!objc_v2_property_template) 1849 objc_v2_property_template = build_v2_property_template (); 1850 1851 if (!objc_v2_ivar_template) 1852 objc_v2_ivar_template = build_v2_ivar_t_template (); 1853 1854 } 1855 1856 /* NOTE --- Output NeXT V2 Metadata --- */ 1857 1858 /* Routine builds name of Interface's main meta-data of type class_t. */ 1859 1860 static char * 1861 objc_build_internal_classname (tree ident, bool metaclass) 1862 { 1863 static char string[512]; 1864 snprintf (string, 512, "%s_%s", metaclass ? "OBJC_METACLASS_$" 1865 : "OBJC_CLASS_$", 1866 IDENTIFIER_POINTER (ident)); 1867 return string; 1868 } 1869 1870 /* Build the name for object of type struct class_ro_t */ 1871 1872 static const char * 1873 newabi_append_ro (const char *name) 1874 { 1875 const char *dollar; 1876 char *p; 1877 static char string[BUFSIZE]; 1878 dollar = strchr (name, '$'); 1879 gcc_assert (dollar); 1880 p = string; 1881 *p = '_'; p++; 1882 strncpy (p, name, (int)(dollar - name)); 1883 p += (int)(dollar - name); 1884 sprintf (p, "RO_%s", dollar); 1885 return string; 1886 } 1887 1888 /* Build the struct message_ref_t msg = 1889 {objc_msgSend_fixup_xxx, @selector(func)} 1890 table. */ 1891 1892 static 1893 void build_v2_message_ref_translation_table (void) 1894 { 1895 int count; 1896 msgref_entry *ref; 1897 1898 if (!vec_safe_length (msgrefs)) 1899 return; 1900 1901 FOR_EACH_VEC_ELT (*msgrefs, count, ref) 1902 { 1903 vec<constructor_elt, va_gc> *initializer; 1904 tree expr, constructor; 1905 tree struct_type = TREE_TYPE (ref->refdecl); 1906 location_t loc = DECL_SOURCE_LOCATION (ref->refdecl); 1907 1908 initializer = NULL; 1909 /* First 'IMP messenger' field... */ 1910 expr = build_unary_op (loc, ADDR_EXPR, ref->func, 0); 1911 expr = convert (objc_v2_imp_type, expr); 1912 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr); 1913 1914 /* ... then 'SEL name' field. */ 1915 expr = build_selector (ref->selname); 1916 CONSTRUCTOR_APPEND_ELT (initializer, NULL_TREE, expr); 1917 constructor = objc_build_constructor (struct_type, initializer); 1918 finish_var_decl (ref->refdecl, constructor); 1919 } 1920 } 1921 1922 /* Build decl = initializer; for each externally visible class 1923 reference. */ 1924 1925 static void 1926 build_v2_classrefs_table (void) 1927 { 1928 int count; 1929 ident_data_tuple *ref; 1930 1931 if (!vec_safe_length (classrefs)) 1932 return; 1933 1934 FOR_EACH_VEC_ELT (*classrefs, count, ref) 1935 { 1936 tree expr = ref->ident; 1937 tree decl = ref->data; 1938 /* Interface with no implementation and yet one of its messages 1939 has been used. Need to generate a full address-of tree for it 1940 here. */ 1941 if (TREE_CODE (expr) == IDENTIFIER_NODE) 1942 { 1943 const char *name = objc_build_internal_classname (expr, false); 1944 expr = create_extern_decl (objc_v2_class_template, name); 1945 expr = convert (objc_class_type, build_fold_addr_expr (expr)); 1946 } 1947 /* The runtime wants this, even if it appears unused, so we must force the 1948 output. 1949 DECL_PRESERVE_P (decl) = 1; */ 1950 finish_var_decl (decl, expr); 1951 } 1952 } 1953 1954 /* Build decl = initializer; for each externally visible super class 1955 reference. */ 1956 1957 static void 1958 build_v2_super_classrefs_table (bool metaclass) 1959 { 1960 int count; 1961 ident_data_tuple *ref; 1962 vec<ident_data_tuple, va_gc> *list = metaclass ? metaclass_super_refs 1963 : class_super_refs; 1964 1965 if (!vec_safe_length (list)) 1966 return; 1967 1968 FOR_EACH_VEC_ELT (*list, count, ref) 1969 { 1970 tree expr = ref->ident; 1971 tree decl = ref->data; 1972 /* Interface with no implementation and yet one of its messages 1973 has been used. Need to generate a full address-of tree for it 1974 here. */ 1975 if (TREE_CODE (expr) == IDENTIFIER_NODE) 1976 { 1977 const char * name = objc_build_internal_classname (expr, metaclass); 1978 expr = create_extern_decl (objc_v2_class_template, name); 1979 expr = convert (objc_class_type, build_fold_addr_expr (expr)); 1980 } 1981 finish_var_decl (decl, expr); 1982 } 1983 } 1984 1985 /* Add the global class meta-data declaration to the list which later 1986 on ends up in the __class_list section. */ 1987 1988 static GTY(()) vec<tree, va_gc> *class_list; 1989 1990 static void 1991 objc_v2_add_to_class_list (tree global_class_decl) 1992 { 1993 vec_safe_push (class_list, global_class_decl); 1994 } 1995 1996 static GTY(()) vec<tree, va_gc> *nonlazy_class_list; 1997 1998 /* Add the global class meta-data declaration to the list which later 1999 on ends up in the __nonlazy_class section. */ 2000 2001 static void 2002 objc_v2_add_to_nonlazy_class_list (tree global_class_decl) 2003 { 2004 vec_safe_push (nonlazy_class_list, global_class_decl); 2005 } 2006 2007 static GTY(()) vec<tree, va_gc> *category_list; 2008 2009 /* Add the category meta-data declaration to the list which later on 2010 ends up in the __nonlazy_category section. */ 2011 2012 static void 2013 objc_v2_add_to_category_list (tree decl) 2014 { 2015 vec_safe_push (category_list, decl); 2016 } 2017 2018 static GTY(()) vec<tree, va_gc> *nonlazy_category_list; 2019 2020 /* Add the category meta-data declaration to the list which later on 2021 ends up in the __category_list section. */ 2022 2023 static void 2024 objc_v2_add_to_nonlazy_category_list (tree decl) 2025 { 2026 vec_safe_push (nonlazy_category_list, decl); 2027 } 2028 2029 static bool 2030 has_load_impl (tree clsmeth) 2031 { 2032 while (clsmeth) 2033 { 2034 tree id = METHOD_SEL_NAME (clsmeth); 2035 if (IDENTIFIER_LENGTH (id) == 4 2036 && strncmp (IDENTIFIER_POINTER (id), "load", 4) == 0) 2037 return true; 2038 clsmeth = DECL_CHAIN (clsmeth); 2039 } 2040 2041 return false; 2042 } 2043 2044 /* Build a __{class,category}_list section table containing address of 2045 all @implemented {class,category} meta-data. */ 2046 2047 static void 2048 build_v2_address_table (vec<tree, va_gc> *src, const char *nam, tree attr) 2049 { 2050 int count=0; 2051 tree type, decl, expr; 2052 vec<constructor_elt, va_gc> *initlist = NULL; 2053 2054 if (!vec_safe_length (src)) 2055 return; 2056 2057 FOR_EACH_VEC_ELT (*src, count, decl) 2058 { 2059 #ifndef OBJCPLUS 2060 tree purpose = build_int_cst (NULL_TREE, count); 2061 #else 2062 tree purpose = NULL_TREE; 2063 #endif 2064 expr = convert (objc_class_type, build_fold_addr_expr (decl)); 2065 CONSTRUCTOR_APPEND_ELT (initlist, purpose, expr); 2066 } 2067 gcc_assert (count > 0); 2068 type = build_array_type (objc_class_type, 2069 build_index_type (build_int_cst (NULL_TREE, count - 1))); 2070 decl = start_var_decl (type, nam); 2071 /* The runtime wants this, even if it appears unused, so we must 2072 force the output. */ 2073 DECL_PRESERVE_P (decl) = 1; 2074 expr = objc_build_constructor (type, initlist); 2075 OBJCMETA (decl, objc_meta, attr); 2076 finish_var_decl (decl, expr); 2077 } 2078 2079 /* Build decl = initializer; for each protocol referenced in 2080 @protocol(MyProt) expression. Refs as built in the entry section 2081 above. */ 2082 2083 static void 2084 build_v2_protocol_list_translation_table (void) 2085 { 2086 int count; 2087 prot_list_entry *ref; 2088 2089 if (!protrefs) 2090 return; 2091 2092 FOR_EACH_VEC_ELT (*protrefs, count, ref) 2093 { 2094 char buf[BUFSIZE]; 2095 tree expr; 2096 gcc_assert (TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE); 2097 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s", 2098 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id))); 2099 expr = start_var_decl (objc_v2_protocol_template, buf); 2100 expr = convert (objc_protocol_type, build_fold_addr_expr (expr)); 2101 finish_var_decl (ref->refdecl, expr); 2102 } 2103 /* TODO: Maybe we could explicitly delete the vec. now? */ 2104 } 2105 2106 static GTY (()) vec<prot_list_entry, va_gc> *protlist; 2107 2108 /* Add the local protocol meta-data declaration to the list which 2109 later on ends up in the __protocol_list section. */ 2110 2111 static void 2112 objc_add_to_protocol_list (tree protocol_interface_decl, tree protocol_decl) 2113 { 2114 prot_list_entry e; 2115 if (!protlist) 2116 /* Arbitrary init count. */ 2117 vec_alloc (protlist, 32); 2118 e.id = protocol_interface_decl; 2119 e.refdecl = protocol_decl; 2120 vec_safe_push (protlist, e); 2121 } 2122 2123 /* Build the __protocol_list section table containing address of all 2124 generate protocol_t meta-data. */ 2125 2126 static void 2127 build_v2_protocol_list_address_table (void) 2128 { 2129 int count; 2130 prot_list_entry *ref; 2131 if (!vec_safe_length (protlist)) 2132 return; 2133 2134 FOR_EACH_VEC_ELT (*protlist, count, ref) 2135 { 2136 tree decl, expr; 2137 char buf[BUFSIZE]; 2138 gcc_assert (ref->id && TREE_CODE (ref->id) == PROTOCOL_INTERFACE_TYPE); 2139 snprintf (buf, BUFSIZE, "_OBJC_LabelProtocol_%s", 2140 IDENTIFIER_POINTER (PROTOCOL_NAME (ref->id))); 2141 decl = create_global_decl (objc_protocol_type, buf); 2142 expr = convert (objc_protocol_type, build_fold_addr_expr (ref->refdecl)); 2143 OBJCMETA (decl, objc_meta, meta_label_protocollist); 2144 finish_var_decl (decl, expr); 2145 } 2146 2147 /* TODO: delete the vec. */ 2148 /* TODO: upgrade to the clang/llvm hidden version. */ 2149 } 2150 2151 /* This routine declares a variable to hold meta data for 'struct 2152 protocol_list_t'. */ 2153 2154 static tree 2155 generate_v2_protocol_list (tree i_or_p, tree klass_ctxt) 2156 { 2157 tree refs_decl, lproto, e, plist, ptempl_p_t; 2158 int size = 0; 2159 vec<constructor_elt, va_gc> *initlist = NULL; 2160 char buf[BUFSIZE]; 2161 2162 if (TREE_CODE (i_or_p) == CLASS_INTERFACE_TYPE 2163 || TREE_CODE (i_or_p) == CATEGORY_INTERFACE_TYPE) 2164 plist = CLASS_PROTOCOL_LIST (i_or_p); 2165 else if (TREE_CODE (i_or_p) == PROTOCOL_INTERFACE_TYPE) 2166 plist = PROTOCOL_LIST (i_or_p); 2167 else 2168 gcc_unreachable (); 2169 2170 /* Compute size. */ 2171 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 2172 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE 2173 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))) 2174 size++; 2175 2176 /* Build initializer. */ 2177 2178 ptempl_p_t = build_pointer_type (objc_v2_protocol_template); 2179 e = build_int_cst (ptempl_p_t, size); 2180 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e); 2181 2182 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 2183 { 2184 tree pval = TREE_VALUE (lproto); 2185 2186 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE 2187 && PROTOCOL_FORWARD_DECL (pval)) 2188 { 2189 tree fwref = PROTOCOL_FORWARD_DECL (pval); 2190 location_t loc = DECL_SOURCE_LOCATION (fwref) ; 2191 e = build_unary_op (loc, ADDR_EXPR, fwref, 0); 2192 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, e); 2193 } 2194 } 2195 2196 /* static struct protocol_list_t *list[size]; */ 2197 2198 switch (TREE_CODE (i_or_p)) 2199 { 2200 case PROTOCOL_INTERFACE_TYPE: 2201 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s", 2202 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p))); 2203 break; 2204 case CLASS_INTERFACE_TYPE: 2205 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s", 2206 IDENTIFIER_POINTER (CLASS_NAME (i_or_p))); 2207 break; 2208 case CATEGORY_INTERFACE_TYPE: 2209 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s", 2210 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)), 2211 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt))); 2212 break; 2213 default: 2214 gcc_unreachable (); 2215 } 2216 2217 refs_decl = start_var_decl (build_sized_array_type (ptempl_p_t, size+1), 2218 buf); 2219 /* ObjC2 puts all these in the base section. */ 2220 OBJCMETA (refs_decl, objc_meta, meta_base); 2221 DECL_PRESERVE_P (refs_decl) = 1; 2222 finish_var_decl (refs_decl, 2223 objc_build_constructor (TREE_TYPE (refs_decl),initlist)); 2224 return refs_decl; 2225 } 2226 2227 /* This routine builds one 'struct method_t' initializer list. Note 2228 that the old ABI is supposed to build 'struct objc_method' which 2229 has 3 fields, but it does not build the initialization expression 2230 for 'method_imp' which for protocols is NULL any way. To be 2231 consistant with declaration of 'struct method_t', in the new ABI we 2232 set the method_t.imp to NULL. */ 2233 2234 static tree 2235 build_v2_descriptor_table_initializer (tree type, tree entries) 2236 { 2237 vec<constructor_elt, va_gc> *initlist = NULL; 2238 do 2239 { 2240 vec<constructor_elt, va_gc> *eltlist = NULL; 2241 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, 2242 build_selector (METHOD_SEL_NAME (entries))); 2243 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, 2244 add_objc_string (METHOD_ENCODING (entries), 2245 meth_var_types)); 2246 CONSTRUCTOR_APPEND_ELT (eltlist, NULL_TREE, null_pointer_node); 2247 2248 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 2249 objc_build_constructor (type, eltlist)); 2250 entries = TREE_CHAIN (entries); 2251 } 2252 while (entries); 2253 2254 return objc_build_constructor (build_array_type (type, 0), initlist); 2255 } 2256 2257 /* struct method_list_t 2258 { 2259 uint32_t entsize; 2260 uint32_t method_count; 2261 struct objc_method method_list[method_count]; 2262 }; */ 2263 2264 static tree 2265 build_v2_method_list_template (tree list_type, int size) 2266 { 2267 tree method_list_t_record; 2268 tree array_type, decls, *chain = NULL; 2269 2270 method_list_t_record = objc_start_struct (NULL_TREE); 2271 2272 /* uint32_t const entsize; */ 2273 decls = add_field_decl (integer_type_node, "entsize", &chain); 2274 2275 /* int method_count; */ 2276 add_field_decl (integer_type_node, "method_count", &chain); 2277 2278 /* struct objc_method method_list[]; */ 2279 array_type = build_sized_array_type (list_type, size); 2280 add_field_decl (array_type, "method_list", &chain); 2281 2282 objc_finish_struct (method_list_t_record, decls); 2283 return method_list_t_record; 2284 } 2285 2286 /* Note, as above that we are building to the objc_method_template 2287 which has the *imp field. ABI0/1 build with 2288 objc_method_prototype_template which is missing this field. */ 2289 static tree 2290 generate_v2_meth_descriptor_table (tree chain, tree protocol, 2291 const char *prefix, tree attr) 2292 { 2293 tree method_list_template, initlist, decl, methods; 2294 int size, entsize; 2295 vec<constructor_elt, va_gc> *v = NULL; 2296 char buf[BUFSIZE]; 2297 2298 if (!chain || !prefix) 2299 return NULL_TREE; 2300 2301 methods = chain; 2302 size = 0; 2303 while (methods) 2304 { 2305 if (! METHOD_ENCODING (methods)) 2306 METHOD_ENCODING (methods) = encode_method_prototype (methods); 2307 methods = TREE_CHAIN (methods); 2308 size++; 2309 } 2310 2311 gcc_assert (size); 2312 method_list_template = build_v2_method_list_template (objc_method_template, 2313 size); 2314 snprintf (buf, BUFSIZE, "%s_%s", prefix, 2315 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol))); 2316 2317 decl = start_var_decl (method_list_template, buf); 2318 2319 entsize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template)); 2320 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, entsize)); 2321 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); 2322 initlist = 2323 build_v2_descriptor_table_initializer (objc_method_template, 2324 chain); 2325 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist); 2326 /* Get into the right section. */ 2327 OBJCMETA (decl, objc_meta, attr); 2328 finish_var_decl (decl, objc_build_constructor (method_list_template, v)); 2329 return decl; 2330 } 2331 2332 /* This routine builds the initializer list to initialize the 'struct 2333 _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */ 2334 2335 static tree 2336 build_v2_property_table_initializer (tree type, tree context) 2337 { 2338 tree x; 2339 vec<constructor_elt, va_gc> *inits = NULL; 2340 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE) 2341 x = CLASS_PROPERTY_DECL (context); 2342 else 2343 x = IMPL_PROPERTY_DECL (context); 2344 2345 for (; x; x = TREE_CHAIN (x)) 2346 { 2347 vec<constructor_elt, va_gc> *elemlist = NULL; 2348 /* NOTE! sections where property name/attribute go MUST change 2349 later. */ 2350 tree attribute, name_ident = PROPERTY_NAME (x); 2351 2352 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE, 2353 add_objc_string (name_ident, prop_names_attr)); 2354 2355 attribute = objc_v2_encode_prop_attr (x); 2356 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE, 2357 add_objc_string (attribute, prop_names_attr)); 2358 2359 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2360 objc_build_constructor (type, elemlist)); 2361 } 2362 2363 return objc_build_constructor (build_array_type (type, 0),inits); 2364 } 2365 2366 /* This routine builds the following type: 2367 struct _prop_list_t 2368 { 2369 uint32_t entsize; // sizeof (struct _prop_t) 2370 uint32_t prop_count; 2371 struct _prop_t prop_list [prop_count]; 2372 } 2373 */ 2374 2375 static tree 2376 build_v2_property_list_template (tree list_type, int size) 2377 { 2378 tree property_list_t_record; 2379 tree array_type, decls, *chain = NULL; 2380 2381 /* anonymous. */ 2382 property_list_t_record = objc_start_struct (NULL_TREE); 2383 2384 /* uint32_t const entsize; */ 2385 decls = add_field_decl (integer_type_node, "entsize", &chain); 2386 2387 /* int prop_count; */ 2388 add_field_decl (integer_type_node, "prop_count", &chain); 2389 2390 /* struct _prop_t prop_list[]; */ 2391 array_type = build_sized_array_type (list_type, size); 2392 add_field_decl (array_type, "prop_list", &chain); 2393 2394 objc_finish_struct (property_list_t_record, decls); 2395 return property_list_t_record; 2396 } 2397 2398 /* Top-level routine to generate property tables for each 2399 implementation. */ 2400 2401 static tree 2402 generate_v2_property_table (tree context, tree klass_ctxt) 2403 { 2404 tree x, decl, initlist, property_list_template; 2405 bool is_proto = false; 2406 vec<constructor_elt, va_gc> *inits = NULL; 2407 int init_val, size = 0; 2408 char buf[BUFSIZE]; 2409 2410 if (context) 2411 { 2412 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE); 2413 x = CLASS_PROPERTY_DECL (context); 2414 is_proto = true; 2415 } 2416 else 2417 x = IMPL_PROPERTY_DECL (klass_ctxt); 2418 2419 for (; x; x = TREE_CHAIN (x)) 2420 size++; 2421 2422 if (size == 0) 2423 return NULL_TREE; 2424 2425 property_list_template = 2426 build_v2_property_list_template (objc_v2_property_template, 2427 size); 2428 2429 initlist = build_v2_property_table_initializer (objc_v2_property_template, 2430 is_proto ? context 2431 : klass_ctxt); 2432 2433 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_property_template)); 2434 if (is_proto) 2435 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s", 2436 IDENTIFIER_POINTER (PROTOCOL_NAME (context))); 2437 else 2438 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s", 2439 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt))); 2440 2441 decl = start_var_decl (property_list_template, buf); 2442 2443 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2444 build_int_cst (NULL_TREE, init_val)); 2445 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2446 build_int_cst (NULL_TREE, size)); 2447 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist); 2448 2449 OBJCMETA (decl, objc_meta, meta_base); 2450 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits)); 2451 return decl; 2452 } 2453 2454 static tree 2455 build_v2_protocol_initializer (tree type, tree protocol_name, tree protocol_list, 2456 tree inst_methods, tree class_methods, 2457 tree opt_ins_meth, tree opt_cls_meth, 2458 tree property_list) 2459 { 2460 tree expr, ttyp; 2461 location_t loc; 2462 vec<constructor_elt, va_gc> *inits = NULL; 2463 2464 /* TODO: find a better representation of location from the inputs. */ 2465 loc = UNKNOWN_LOCATION; 2466 2467 /* This is NULL for the new ABI. */ 2468 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2469 convert (objc_object_type, null_pointer_node)); 2470 2471 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name); 2472 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list); 2473 2474 ttyp = objc_method_proto_list_ptr; 2475 if (inst_methods) 2476 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); 2477 else 2478 expr = convert (ttyp, null_pointer_node); 2479 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2480 2481 if (class_methods) 2482 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); 2483 else 2484 expr = convert (ttyp, null_pointer_node); 2485 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2486 2487 if (opt_ins_meth) 2488 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_ins_meth, 0)); 2489 else 2490 expr = convert (ttyp, null_pointer_node); 2491 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2492 2493 if (opt_cls_meth) 2494 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, opt_cls_meth, 0)); 2495 else 2496 expr = convert (ttyp, null_pointer_node); 2497 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2498 2499 ttyp = objc_prop_list_ptr; 2500 if (property_list) 2501 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); 2502 else 2503 expr = convert (ttyp, null_pointer_node); 2504 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2505 2506 /* const uint32_t size; = sizeof(struct protocol_t) */ 2507 expr = build_int_cst (integer_type_node, 2508 TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_protocol_template))); 2509 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 2510 /* const uint32_t flags; = 0 */ 2511 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, integer_zero_node); 2512 2513 return objc_build_constructor (type, inits); 2514 } 2515 2516 /* Main routine to build all meta data for all protocols used in a 2517 translation unit. */ 2518 2519 static void 2520 generate_v2_protocols (void) 2521 { 2522 tree p ; 2523 bool some = false; 2524 2525 if (!protocol_chain) 2526 return ; 2527 2528 /* If a protocol was directly referenced, pull in indirect 2529 references. */ 2530 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 2531 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p)) 2532 generate_protocol_references (PROTOCOL_LIST (p)); 2533 2534 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 2535 { 2536 location_t loc; 2537 tree inst_meth, class_meth, opt_inst_meth, opt_class_meth, props; 2538 tree decl, initlist, protocol_name_expr, refs_decl, refs_expr; 2539 2540 /* If protocol wasn't referenced, don't generate any code. */ 2541 decl = PROTOCOL_FORWARD_DECL (p); 2542 2543 if (!decl) 2544 continue; 2545 2546 loc = DECL_SOURCE_LOCATION (decl); 2547 some = true; 2548 2549 inst_meth = 2550 generate_v2_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p, 2551 "_OBJC_ProtocolInstanceMethods", 2552 meta_proto_nst_meth); 2553 2554 class_meth = 2555 generate_v2_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p, 2556 "_OBJC_ProtocolClassMethods", 2557 meta_proto_cls_meth); 2558 2559 opt_inst_meth = 2560 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p, 2561 "_OBJC_OptProtocolInstMethods", 2562 meta_proto_nst_meth); 2563 2564 opt_class_meth = 2565 generate_v2_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p, 2566 "_OBJC_OptProtocolClassMethods", 2567 meta_proto_cls_meth); 2568 2569 if (PROTOCOL_LIST (p)) 2570 refs_decl = generate_v2_protocol_list (p, NULL_TREE); 2571 else 2572 refs_decl = 0; 2573 2574 /* static struct objc_protocol _OBJC_Protocol_<mumble>; */ 2575 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names); 2576 2577 if (refs_decl) 2578 refs_expr = convert (build_pointer_type (objc_v2_protocol_template), 2579 build_unary_op (loc, ADDR_EXPR, refs_decl, 0)); 2580 else 2581 refs_expr = build_int_cst (NULL_TREE, 0); 2582 2583 props = generate_v2_property_table (p, NULL_TREE); 2584 2585 initlist = build_v2_protocol_initializer (TREE_TYPE (decl), 2586 protocol_name_expr, refs_expr, 2587 inst_meth, class_meth, 2588 opt_inst_meth, opt_class_meth, 2589 props); 2590 finish_var_decl (decl, initlist); 2591 objc_add_to_protocol_list (p, decl); 2592 } 2593 2594 if (some) 2595 { 2596 /* Make sure we get the Protocol class linked in - reference 2597 it... */ 2598 p = objc_v2_get_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME)); 2599 /* ... but since we don't specifically use the reference... we 2600 need to force it. */ 2601 DECL_PRESERVE_P (p) = 1; 2602 } 2603 } 2604 2605 static tree 2606 generate_v2_dispatch_table (tree chain, const char *name, tree attr) 2607 { 2608 tree decl, method_list_template, initlist; 2609 vec<constructor_elt, va_gc> *v = NULL; 2610 int size, init_val; 2611 2612 if (!chain || !name || !(size = list_length (chain))) 2613 return NULL_TREE; 2614 2615 method_list_template 2616 = build_v2_method_list_template (objc_method_template, size); 2617 initlist 2618 = build_dispatch_table_initializer (objc_method_template, chain); 2619 2620 decl = start_var_decl (method_list_template, name); 2621 2622 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_method_template)); 2623 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2624 build_int_cst (integer_type_node, init_val)); 2625 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2626 build_int_cst (integer_type_node, size)); 2627 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist); 2628 2629 OBJCMETA (decl, objc_meta, attr); 2630 finish_var_decl (decl, 2631 objc_build_constructor (TREE_TYPE (decl), v)); 2632 return decl; 2633 } 2634 2635 /* Init a category. */ 2636 static tree 2637 build_v2_category_initializer (tree type, tree cat_name, tree class_name, 2638 tree inst_methods, tree class_methods, 2639 tree protocol_list, tree property_list, 2640 location_t loc) 2641 { 2642 tree expr, ltyp; 2643 vec<constructor_elt, va_gc> *v = NULL; 2644 2645 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name); 2646 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name); 2647 2648 ltyp = objc_method_list_ptr; 2649 if (inst_methods) 2650 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); 2651 else 2652 expr = convert (ltyp, null_pointer_node); 2653 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2654 2655 if (class_methods) 2656 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); 2657 else 2658 expr = convert (ltyp, null_pointer_node); 2659 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2660 2661 /* protocol_list = */ 2662 ltyp = build_pointer_type (objc_v2_protocol_template); 2663 if (protocol_list) 2664 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0)); 2665 else 2666 expr = convert (ltyp, null_pointer_node); 2667 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2668 2669 ltyp = objc_prop_list_ptr; 2670 if (property_list) 2671 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); 2672 else 2673 expr = convert (ltyp, null_pointer_node); 2674 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2675 2676 return objc_build_constructor (type, v); 2677 } 2678 2679 /* static struct category_t _OBJC_CATEGORY_$_<name> = { ... }; */ 2680 2681 static void 2682 generate_v2_category (struct imp_entry *impent) 2683 { 2684 tree initlist, cat_name_expr, class_name_expr; 2685 tree protocol_decl, category, props, t; 2686 tree inst_methods = NULL_TREE, class_methods = NULL_TREE; 2687 tree cat = impent->imp_context; 2688 tree cat_decl = impent->class_decl; 2689 location_t loc; 2690 char buf[BUFSIZE]; 2691 2692 loc = DECL_SOURCE_LOCATION (cat_decl); 2693 2694 /* ??? not sure this is really necessary, the following references should 2695 force appropriate linkage linkage... 2696 -- but ... ensure a reference to the class... */ 2697 t = objc_v2_get_class_reference (CLASS_NAME (cat)); 2698 /* ... which we ignore so force it out.. */ 2699 DECL_PRESERVE_P (t) = 1; 2700 2701 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", IDENTIFIER_POINTER (CLASS_NAME (cat))); 2702 class_name_expr = create_extern_decl (objc_v2_class_template, buf); 2703 class_name_expr = build_fold_addr_expr (class_name_expr); 2704 2705 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); 2706 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat)); 2707 2708 if (category && CLASS_PROTOCOL_LIST (category)) 2709 { 2710 generate_protocol_references (CLASS_PROTOCOL_LIST (category)); 2711 protocol_decl = generate_v2_protocol_list (category, cat); 2712 } 2713 else 2714 protocol_decl = NULL_TREE; 2715 2716 /* decl = update_var_decl(impent->class_decl); */ 2717 2718 props = generate_v2_property_table (NULL_TREE, cat); 2719 2720 if (CLASS_NST_METHODS (cat)) 2721 { 2722 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s", 2723 IDENTIFIER_POINTER (CLASS_NAME (cat)), 2724 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))); 2725 inst_methods = generate_v2_dispatch_table (CLASS_NST_METHODS (cat), buf, 2726 meta_cati_meth); 2727 } 2728 2729 if (CLASS_CLS_METHODS (cat)) 2730 { 2731 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s", 2732 IDENTIFIER_POINTER (CLASS_NAME (cat)), 2733 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))); 2734 class_methods = generate_v2_dispatch_table (CLASS_CLS_METHODS (cat), buf, 2735 meta_catc_meth); 2736 } 2737 2738 initlist = build_v2_category_initializer (TREE_TYPE (cat_decl), 2739 cat_name_expr, class_name_expr, 2740 inst_methods, class_methods, 2741 protocol_decl, props, loc); 2742 2743 finish_var_decl (cat_decl, initlist); 2744 impent->class_decl = cat_decl; 2745 2746 /* Add to list of pointers in __category_list section. */ 2747 objc_v2_add_to_category_list (cat_decl); 2748 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context))) 2749 objc_v2_add_to_nonlazy_category_list (cat_decl); 2750 } 2751 2752 /* This routine declares a variable to hold the offset for ivar 2753 FIELD_DECL. Variable name is .objc_ivar.ClassName.IvarName. */ 2754 2755 typedef struct GTY(()) ivarref_entry 2756 { 2757 tree decl; 2758 tree offset; 2759 } ivarref_entry; 2760 2761 static GTY (()) vec<ivarref_entry, va_gc> *ivar_offset_refs; 2762 2763 static tree 2764 ivar_offset_ref (tree class_name, tree field_decl) 2765 { 2766 tree decl, field_decl_id; 2767 ivarref_entry e; 2768 bool global_var; 2769 char buf[512]; 2770 2771 create_ivar_offset_name (buf, class_name, field_decl); 2772 field_decl_id = get_identifier (buf); 2773 2774 if (ivar_offset_refs) 2775 { 2776 int count; 2777 ivarref_entry *ref; 2778 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref) 2779 if (DECL_NAME (ref->decl) == field_decl_id) 2780 return ref->decl; 2781 } 2782 else 2783 /* Somewhat arbitrary initial provision. */ 2784 vec_alloc (ivar_offset_refs, 32); 2785 2786 /* We come here if we don't find a match or at the start. */ 2787 global_var = (TREE_PUBLIC (field_decl) || TREE_PROTECTED (field_decl)); 2788 if (global_var) 2789 decl = create_global_decl (TREE_TYPE (size_zero_node), buf); 2790 else 2791 decl = create_hidden_decl (TREE_TYPE (size_zero_node), buf); 2792 2793 /* Make sure it ends up in an ObjC section. */ 2794 OBJCMETA (decl, objc_meta, meta_base); 2795 2796 e.decl = decl; 2797 e.offset = byte_position (field_decl); 2798 vec_safe_push (ivar_offset_refs, e); 2799 return decl; 2800 } 2801 2802 /* This routine builds initializer-list needed to initialize 'struct 2803 ivar_t list[count] of 'struct ivar_list_t' meta data. TYPE is 2804 'struct ivar_t' and FIELD_DECL is list of ivars for the target 2805 class. */ 2806 2807 static tree 2808 build_v2_ivar_list_initializer (tree class_name, tree type, tree field_decl) 2809 { 2810 vec<constructor_elt, va_gc> *inits = NULL; 2811 2812 do 2813 { 2814 vec<constructor_elt, va_gc> *ivar = NULL; 2815 int val; 2816 tree id; 2817 2818 /* Unnamed bitfields are ignored. */ 2819 if (!DECL_NAME (field_decl)) 2820 { 2821 field_decl = DECL_CHAIN (field_decl); 2822 continue; 2823 } 2824 2825 /* Set offset. */ 2826 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, 2827 build_unary_op (input_location, 2828 ADDR_EXPR, 2829 ivar_offset_ref (class_name, 2830 field_decl), 0)); 2831 2832 /* Set name. */ 2833 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, 2834 add_objc_string (DECL_NAME (field_decl), 2835 meth_var_names)); 2836 2837 /* Set type. */ 2838 id = add_objc_string (encode_field_decl (field_decl), 2839 meth_var_types); 2840 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, id); 2841 2842 /* Set alignment. */ 2843 val = DECL_ALIGN_UNIT (field_decl); 2844 val = exact_log2 (val); 2845 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, 2846 build_int_cst (integer_type_node, val)); 2847 2848 /* Set size. */ 2849 val = TREE_INT_CST_LOW (DECL_SIZE_UNIT (field_decl)); 2850 CONSTRUCTOR_APPEND_ELT (ivar, NULL_TREE, 2851 build_int_cst (integer_type_node, val)); 2852 2853 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2854 objc_build_constructor (type, ivar)); 2855 2856 do 2857 field_decl = DECL_CHAIN (field_decl); 2858 while (field_decl && TREE_CODE (field_decl) != FIELD_DECL); 2859 } 2860 while (field_decl); 2861 2862 return objc_build_constructor (build_array_type (type, 0), inits); 2863 } 2864 2865 /* 2866 struct ivar_list_t 2867 { 2868 uint32 entsize; 2869 uint32 count; 2870 struct iver_t list[count]; 2871 }; 2872 */ 2873 2874 static tree 2875 build_v2_ivar_list_t_template (tree list_type, int size) 2876 { 2877 tree objc_ivar_list_record; 2878 tree decls, *chain = NULL; 2879 2880 /* Anonymous. */ 2881 objc_ivar_list_record = objc_start_struct (NULL_TREE); 2882 2883 /* uint32 entsize; */ 2884 decls = add_field_decl (integer_type_node, "entsize", &chain); 2885 2886 /* uint32 count; */ 2887 add_field_decl (integer_type_node, "count", &chain); 2888 2889 /* struct objc_ivar ivar_list[]; */ 2890 add_field_decl (build_sized_array_type (list_type, size), 2891 "list", &chain); 2892 2893 objc_finish_struct (objc_ivar_list_record, decls); 2894 return objc_ivar_list_record; 2895 } 2896 2897 /* This routine declares a static variable of type 'struct 2898 ivar_list_t' and initializes it. chain is the source of the data, 2899 name is the name for the var. attr is the meta-data section tag 2900 attribute. templ is the implementation template for the class. */ 2901 2902 static tree 2903 generate_v2_ivars_list (tree chain, const char *name, tree attr, tree templ) 2904 { 2905 tree decl, initlist, ivar_list_template; 2906 vec<constructor_elt, va_gc> *inits = NULL; 2907 int size, ivar_t_size; 2908 2909 if (!chain || !name || !(size = ivar_list_length (chain))) 2910 return NULL_TREE; 2911 2912 generating_instance_variables = 1; 2913 ivar_list_template = build_v2_ivar_list_t_template (objc_v2_ivar_template, 2914 size); 2915 2916 initlist = build_v2_ivar_list_initializer (CLASS_NAME (templ), 2917 objc_v2_ivar_template, chain); 2918 ivar_t_size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_ivar_template)); 2919 2920 decl = start_var_decl (ivar_list_template, name); 2921 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2922 build_int_cst (integer_type_node, ivar_t_size)); 2923 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 2924 build_int_cst (integer_type_node, size)); 2925 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist); 2926 OBJCMETA (decl, objc_meta, attr); 2927 finish_var_decl (decl, objc_build_constructor (TREE_TYPE (decl), inits)); 2928 generating_instance_variables = 0; 2929 return decl; 2930 } 2931 2932 /* Routine to build initializer list to initialize objects of type 2933 struct class_t; */ 2934 2935 static tree 2936 build_v2_class_t_initializer (tree type, tree isa, tree superclass, 2937 tree ro, tree cache, tree vtable) 2938 { 2939 vec<constructor_elt, va_gc> *initlist = NULL; 2940 2941 /* isa */ 2942 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, isa); 2943 2944 /* superclass */ 2945 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, superclass); 2946 2947 /* cache */ 2948 if (cache) 2949 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cache); 2950 else 2951 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node); 2952 2953 /* vtable */ 2954 if (vtable) 2955 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, vtable); 2956 else 2957 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, null_pointer_node); 2958 2959 /* ro */ 2960 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, ro); 2961 2962 return objc_build_constructor (type, initlist); 2963 } 2964 2965 /* Routine to build object of struct class_ro_t { ... }; */ 2966 2967 static tree 2968 build_v2_class_ro_t_initializer (tree type, tree name, 2969 unsigned int flags, unsigned int instanceStart, 2970 unsigned int instanceSize, 2971 tree ivarLayout, 2972 tree baseMethods, tree baseProtocols, 2973 tree ivars, tree property_list) 2974 { 2975 tree expr, unsigned_char_star, ltyp; 2976 location_t loc; 2977 vec<constructor_elt, va_gc> *initlist = NULL; 2978 2979 /* TODO: fish out the real location from somewhere. */ 2980 loc = UNKNOWN_LOCATION; 2981 2982 /* flags */ 2983 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 2984 build_int_cst (integer_type_node, flags)); 2985 2986 /* instanceStart */ 2987 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 2988 build_int_cst (integer_type_node, instanceStart)); 2989 2990 /* instanceSize */ 2991 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 2992 build_int_cst (integer_type_node, instanceSize)); 2993 2994 /* This ABI is currently only used on m64 NeXT. We always 2995 explicitly declare the alignment padding. */ 2996 /* reserved, pads alignment. */ 2997 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 2998 build_int_cst (integer_type_node, 0)); 2999 3000 /* ivarLayout */ 3001 unsigned_char_star = build_pointer_type (unsigned_char_type_node); 3002 if (ivarLayout) 3003 expr = ivarLayout; 3004 else 3005 expr = convert (unsigned_char_star, null_pointer_node); 3006 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); 3007 3008 /* name */ 3009 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, default_conversion (name)); 3010 3011 /* baseMethods */ 3012 ltyp = objc_method_list_ptr; 3013 if (baseMethods) 3014 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseMethods, 0)); 3015 else 3016 expr = convert (ltyp, null_pointer_node); 3017 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); 3018 3019 /* baseProtocols */ 3020 ltyp = build_pointer_type (xref_tag (RECORD_TYPE, 3021 get_identifier (UTAG_V2_PROTOCOL_LIST))); 3022 if (baseProtocols) 3023 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, baseProtocols, 0)); 3024 else 3025 expr = convert (ltyp, null_pointer_node); 3026 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); 3027 3028 /* ivars */ 3029 ltyp = objc_v2_ivar_list_ptr; 3030 if (ivars) 3031 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivars, 0)); 3032 else 3033 expr = convert (ltyp, null_pointer_node); 3034 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); 3035 3036 /* TODO: We don't yet have the weak/strong stuff... */ 3037 /* weakIvarLayout */ 3038 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, 3039 convert (unsigned_char_star, null_pointer_node)); 3040 3041 /* property list */ 3042 ltyp = objc_prop_list_ptr; 3043 if (property_list) 3044 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); 3045 else 3046 expr = convert (ltyp, null_pointer_node); 3047 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, expr); 3048 return objc_build_constructor (type, initlist); 3049 } 3050 3051 static GTY (()) vec<ident_data_tuple, va_gc> *ehtype_list; 3052 3053 /* Record a name as needing a catcher. */ 3054 static void 3055 objc_v2_add_to_ehtype_list (tree name) 3056 { 3057 ident_data_tuple e; 3058 if (ehtype_list) 3059 { 3060 int count = 0; 3061 ident_data_tuple *ref; 3062 3063 FOR_EACH_VEC_ELT (*ehtype_list, count, ref) 3064 if (ref->ident == name) 3065 return; /* Already entered. */ 3066 } 3067 else 3068 /* Arbitrary initial count. */ 3069 vec_alloc (ehtype_list, 8); 3070 3071 /* Not found, or new list. */ 3072 e.ident = name; 3073 e.data = NULL_TREE; 3074 vec_safe_push (ehtype_list, e); 3075 } 3076 3077 static void 3078 generate_v2_class_structs (struct imp_entry *impent) 3079 { 3080 tree decl, name_expr, initlist, protocol_decl, metaclass_decl, class_decl; 3081 tree field, firstIvar, chain; 3082 tree class_superclass_expr, metaclass_superclass_expr, props; 3083 /* TODO: figure out how to compute this. */ 3084 tree ivarLayout = NULL_TREE; 3085 tree my_super_id = NULL_TREE, root_expr = NULL_TREE; 3086 tree inst_methods = NULL_TREE, class_methods = NULL_TREE; 3087 tree inst_ivars = NULL_TREE, class_ivars = NULL_TREE; 3088 location_t loc; 3089 char buf[BUFSIZE]; 3090 unsigned int instanceStart, instanceSize; 3091 unsigned int flags = 0x01; /* RO_META */ 3092 int cls_flags = impent->has_cxx_cdtors ? OBJC2_CLS_HAS_CXX_STRUCTORS 3093 : 0 ; 3094 3095 class_decl = impent->class_decl; 3096 metaclass_decl = impent->meta_decl; 3097 loc = DECL_SOURCE_LOCATION (class_decl); 3098 3099 DECL_EXTERNAL (class_decl) = DECL_EXTERNAL (metaclass_decl) = 0; 3100 TREE_PUBLIC (class_decl) = TREE_PUBLIC (metaclass_decl) = 1; 3101 #ifdef OBJCPLUS 3102 gcc_assert (!CP_DECL_CONTEXT (class_decl) || CP_DECL_CONTEXT (class_decl) == global_namespace); 3103 gcc_assert (!CP_DECL_CONTEXT (metaclass_decl) || CP_DECL_CONTEXT (metaclass_decl) == global_namespace); 3104 #endif 3105 3106 /* Generation of data for meta class. */ 3107 my_super_id = CLASS_SUPER_NAME (impent->imp_template); 3108 if (my_super_id) 3109 { 3110 /* Compute reference to root's name. For a meta class, "isa" is 3111 a reference to the root class name. */ 3112 tree my_root_id = my_super_id; 3113 tree my_root_int, interface; 3114 do 3115 { 3116 my_root_int = lookup_interface (my_root_id); 3117 3118 if (my_root_int && CLASS_SUPER_NAME (my_root_int)) 3119 my_root_id = CLASS_SUPER_NAME (my_root_int); 3120 else 3121 break; 3122 } 3123 while (1); 3124 3125 /* {extern} struct class_t OBJC_METACLASS_$_<my_root_int> 3126 create extern if not already declared. */ 3127 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s", 3128 IDENTIFIER_POINTER (CLASS_NAME (my_root_int))); 3129 root_expr = create_extern_decl (objc_v2_class_template, buf); 3130 root_expr = build_fold_addr_expr (root_expr); 3131 3132 /* Install class `isa' and `super' pointers at runtime. */ 3133 interface = lookup_interface (my_super_id); 3134 gcc_assert (interface); 3135 /* Similarly, for OBJC_CLASS_$_<interface>... */ 3136 snprintf (buf, BUFSIZE, "OBJC_CLASS_$_%s", 3137 IDENTIFIER_POINTER (CLASS_NAME (interface))); 3138 class_superclass_expr = create_extern_decl (objc_v2_class_template, buf); 3139 class_superclass_expr = build_fold_addr_expr (class_superclass_expr); 3140 /* ... and for OBJC_METACLASS_$_<interface>. */ 3141 snprintf (buf, BUFSIZE, "OBJC_METACLASS_$_%s", 3142 IDENTIFIER_POINTER (CLASS_NAME (interface))); 3143 metaclass_superclass_expr = create_extern_decl (objc_v2_class_template, buf); 3144 metaclass_superclass_expr = build_fold_addr_expr (metaclass_superclass_expr); 3145 } 3146 else 3147 { 3148 /* Root class. */ 3149 root_expr = build_unary_op (loc, ADDR_EXPR, metaclass_decl, 0); 3150 metaclass_superclass_expr = build_unary_op (loc, ADDR_EXPR, class_decl, 0); 3151 class_superclass_expr = build_int_cst (NULL_TREE, 0); 3152 flags |= 0x02; /* RO_ROOT: it is also a root meta class. */ 3153 } 3154 3155 if (CLASS_PROTOCOL_LIST (impent->imp_template)) 3156 { 3157 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template)); 3158 protocol_decl = generate_v2_protocol_list (impent->imp_template, 3159 impent->imp_context); 3160 } 3161 else 3162 protocol_decl = 0; 3163 3164 name_expr = add_objc_string (CLASS_NAME (impent->imp_template), 3165 class_names); 3166 3167 if (CLASS_CLS_METHODS (impent->imp_context)) 3168 { 3169 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s", 3170 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 3171 class_methods = 3172 generate_v2_dispatch_table (CLASS_CLS_METHODS (impent->imp_context), 3173 buf, meta_clac_meth); 3174 } 3175 3176 instanceStart = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template)); 3177 3178 /* Currently there are no class ivars and generation of class 3179 variables for the root of the inheritance has been removed. It 3180 causes multiple defines if there are two root classes in the 3181 link, because each will define its own identically-named offset 3182 variable. */ 3183 3184 class_ivars = NULL_TREE; 3185 /* TODO: Add total size of class variables when implemented. */ 3186 instanceSize = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v2_class_template)); 3187 3188 /* So now build the META CLASS structs. */ 3189 /* static struct class_ro_t _OBJC_METACLASS_Foo = { ... }; */ 3190 3191 decl = start_var_decl (objc_v2_class_ro_template, 3192 newabi_append_ro (IDENTIFIER_POINTER 3193 (DECL_NAME (metaclass_decl)))); 3194 3195 /* TODO: ivarLayout needs t be built. */ 3196 initlist = 3197 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr, 3198 (flags | cls_flags), instanceStart, 3199 instanceSize, ivarLayout, 3200 class_methods, protocol_decl, 3201 class_ivars, NULL_TREE); 3202 /* The ROs sit in the default const section. */ 3203 OBJCMETA (decl, objc_meta, meta_base); 3204 finish_var_decl (decl, initlist); 3205 3206 /* static struct class_t _OBJC_METACLASS_Foo = { ... }; */ 3207 initlist = 3208 build_v2_class_t_initializer (TREE_TYPE (metaclass_decl), 3209 root_expr, 3210 metaclass_superclass_expr, 3211 build_fold_addr_expr (decl), 3212 build_fold_addr_expr (UOBJC_V2_CACHE_decl), 3213 build_fold_addr_expr (UOBJC_V2_VTABLE_decl)); 3214 /* The class section attributes are set when they are created. */ 3215 finish_var_decl (metaclass_decl, initlist); 3216 impent->meta_decl = metaclass_decl; 3217 3218 /* So now build the CLASS structs. */ 3219 3220 flags = 0x0; /* ... */ 3221 if (!my_super_id) 3222 flags |= 0x02; /* RO_ROOT: this is a root class */ 3223 3224 if (DECL_VISIBILITY (class_decl) == VISIBILITY_HIDDEN) 3225 flags |= 0x10; /* RO_HIDDEN, OBJC2_CLS_HIDDEN; */ 3226 3227 if (objc2_objc_exception_attr (impent->imp_template)) 3228 flags |= 0x20; /* RO_EXCEPTION */ 3229 3230 if (CLASS_NST_METHODS (impent->imp_context)) 3231 { 3232 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s", 3233 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 3234 inst_methods = 3235 generate_v2_dispatch_table (CLASS_NST_METHODS (impent->imp_context), 3236 buf, meta_clai_meth); 3237 } 3238 3239 /* Sort out the ivars before we try to compute the class sizes. */ 3240 if ((chain = CLASS_IVARS (impent->imp_template))) 3241 { 3242 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s", 3243 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 3244 inst_ivars = generate_v2_ivars_list (chain, buf, meta_clai_vars, 3245 impent->imp_template); 3246 } 3247 3248 /* Compute instanceStart. */ 3249 gcc_assert (CLASS_STATIC_TEMPLATE (impent->imp_template)); 3250 field = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (impent->imp_template)); 3251 if (my_super_id && field && TREE_CHAIN (field)) 3252 field = TREE_CHAIN (field); 3253 3254 firstIvar = field; 3255 3256 while (firstIvar && TREE_CODE (firstIvar) != FIELD_DECL) 3257 firstIvar = TREE_CHAIN (firstIvar); 3258 3259 gcc_assert (inst_ivars? (firstIvar != NULL_TREE): true); 3260 3261 /* Compute instanceSize. */ 3262 while (field && TREE_CHAIN (field) 3263 && TREE_CODE (TREE_CHAIN (field)) == FIELD_DECL) 3264 field = TREE_CHAIN (field); 3265 3266 if (field && TREE_CODE (field) == FIELD_DECL) 3267 instanceSize = int_byte_position (field) * BITS_PER_UNIT 3268 + tree_low_cst (DECL_SIZE (field), 0); 3269 else 3270 instanceSize = 0; 3271 instanceSize /= BITS_PER_UNIT; 3272 3273 props = generate_v2_property_table (NULL_TREE, impent->imp_context); 3274 3275 /* If the class has no ivars, instanceStart should be set to the 3276 superclass's instanceSize. */ 3277 instanceStart = 3278 (inst_ivars != NULL_TREE) ? (unsigned) int_byte_position (firstIvar) 3279 : instanceSize; 3280 3281 /* static struct class_ro_t _OBJC_CLASS_Foo = { ... }; */ 3282 decl = start_var_decl (objc_v2_class_ro_template, 3283 newabi_append_ro (IDENTIFIER_POINTER 3284 (DECL_NAME (class_decl)))); 3285 3286 initlist = 3287 build_v2_class_ro_t_initializer (TREE_TYPE (decl), name_expr, 3288 (flags | cls_flags), instanceStart, 3289 instanceSize, ivarLayout, 3290 inst_methods, protocol_decl, 3291 inst_ivars, props); 3292 /* The ROs sit in the default const section. */ 3293 OBJCMETA (decl, objc_meta, meta_base); 3294 finish_var_decl (decl, initlist); 3295 3296 /* static struct class_t _OBJC_CLASS_Foo = { ... }; */ 3297 initlist = build_v2_class_t_initializer (TREE_TYPE (class_decl), 3298 build_fold_addr_expr (metaclass_decl), 3299 class_superclass_expr, 3300 build_fold_addr_expr (decl), 3301 build_fold_addr_expr (UOBJC_V2_CACHE_decl), 3302 build_fold_addr_expr (UOBJC_V2_VTABLE_decl)); 3303 3304 /* The class section attributes are set when they are created. */ 3305 finish_var_decl (class_decl, initlist); 3306 impent->class_decl = class_decl; 3307 3308 objc_v2_add_to_class_list (class_decl); 3309 if (has_load_impl (CLASS_CLS_METHODS (impent->imp_context))) 3310 objc_v2_add_to_nonlazy_class_list (class_decl); 3311 3312 if (flags & 0x20) /* RO_EXCEPTION */ 3313 objc_v2_add_to_ehtype_list (CLASS_NAME (impent->imp_template)); 3314 } 3315 3316 /* This routine outputs the (ivar_reference_offset, offset) 3317 tuples. */ 3318 3319 static void 3320 build_v2_ivar_offset_ref_table (void) 3321 { 3322 int count; 3323 ivarref_entry *ref; 3324 3325 if (!vec_safe_length (ivar_offset_refs)) 3326 return; 3327 3328 FOR_EACH_VEC_ELT (*ivar_offset_refs, count, ref) 3329 finish_var_decl (ref->decl, ref->offset); 3330 } 3331 3332 static void 3333 objc_generate_v2_next_metadata (void) 3334 { 3335 struct imp_entry *impent; 3336 3337 /* FIXME: Make sure that we generate no metadata if there is nothing 3338 to put into it. */ 3339 3340 gcc_assert (!objc_static_instances); /* Not for NeXT */ 3341 3342 build_metadata_templates (); 3343 3344 for (impent = imp_list; impent; impent = impent->next) 3345 { 3346 /* If -gen-decls is present, Dump the @interface of each class. 3347 TODO: Dump the classes in the order they were found, rather 3348 than in reverse order as we are doing now. */ 3349 if (flag_gen_declaration) 3350 dump_interface (gen_declaration_file, impent->imp_context); 3351 3352 /* all of the following reference the string pool... */ 3353 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) 3354 generate_v2_class_structs (impent); 3355 else 3356 generate_v2_category (impent); 3357 } 3358 3359 build_next_selector_translation_table (); 3360 build_v2_message_ref_translation_table (); 3361 3362 /* This will add "Protocol" to the class refs. */ 3363 generate_v2_protocols (); 3364 3365 build_v2_classrefs_table (); 3366 build_v2_super_classrefs_table (/*metaclass= */false); 3367 build_v2_super_classrefs_table (/*metaclass= */true); 3368 3369 build_v2_ivar_offset_ref_table (); 3370 3371 build_v2_protocol_list_translation_table (); 3372 build_v2_protocol_list_address_table (); 3373 3374 build_v2_address_table (class_list, "_OBJC_ClassList$", 3375 meta_label_classlist); 3376 build_v2_address_table (category_list, "_OBJC_CategoryList$", 3377 meta_label_categorylist); 3378 build_v2_address_table (nonlazy_class_list, "_OBJC_NonLazyClassList$", 3379 meta_label_nonlazy_classlist); 3380 build_v2_address_table (nonlazy_category_list, "_OBJC_NonLazyCategoryList$", 3381 meta_label_nonlazy_categorylist); 3382 3383 /* Generate catch objects for eh, if any are needed. */ 3384 build_v2_eh_catch_objects (); 3385 3386 /* Emit the string table last. */ 3387 generate_strings (); 3388 } 3389 3390 /* NOTE --- Output NeXT V2 Exceptions --- */ 3391 3392 static GTY(()) tree objc_v2_ehtype_template; 3393 static GTY(()) tree next_v2_ehvtable_decl; 3394 static GTY(()) tree next_v2_EHTYPE_id_decl; 3395 3396 static void 3397 build_v2_ehtype_template (void) 3398 { 3399 tree decls, *chain = NULL; 3400 objc_v2_ehtype_template = objc_start_struct (get_identifier (UTAG_V2_EH_TYPE)); 3401 3402 /* void *_objc_ehtype_vtable; */ 3403 decls = add_field_decl (ptr_type_node, "_objc_ehtype_vtable_ptr", &chain); 3404 3405 /* const char *className; */ 3406 add_field_decl (string_type_node, "className", &chain); 3407 3408 /* struct class_t *const cls; */ 3409 add_field_decl (build_pointer_type (objc_v2_class_template), "cls", &chain); 3410 3411 objc_finish_struct (objc_v2_ehtype_template, decls); 3412 } 3413 3414 /* Template for the Objective-C family typeinfo type for ABI=2. This 3415 starts off the same as the gxx/cxx eh typeinfo. 3416 3417 struct _objc_ehtype_t 3418 { 3419 void *_objc_ehtype_vtable_ptr; - as per c++ 3420 const char *className; - as per c++ 3421 struct class_t *const cls; 3422 } 3423 */ 3424 3425 /* This routine builds initializer list for object of type struct _objc_ehtype_t. 3426 */ 3427 3428 static tree 3429 objc2_build_ehtype_initializer (tree name, tree cls) 3430 { 3431 vec<constructor_elt, va_gc> *initlist = NULL; 3432 tree addr, offs; 3433 3434 /* This is done the same way as c++, missing the two first entries 3435 in the parent vtable. NOTE: there is a fix-me in the Apple/NeXT 3436 runtime source about this so, perhaps, this will change at some 3437 point. */ 3438 /* _objc_ehtype_vtable + 2*sizeof(void*) */ 3439 if (!next_v2_ehvtable_decl) 3440 { 3441 next_v2_ehvtable_decl = 3442 start_var_decl (ptr_type_node, TAG_NEXT_EHVTABLE_NAME); 3443 TREE_STATIC (next_v2_ehvtable_decl) = 0; 3444 DECL_EXTERNAL (next_v2_ehvtable_decl) = 1; 3445 TREE_PUBLIC (next_v2_ehvtable_decl) = 1; 3446 } 3447 addr = build_fold_addr_expr_with_type (next_v2_ehvtable_decl, ptr_type_node); 3448 offs = size_int (2 * int_cst_value (TYPE_SIZE_UNIT (ptr_type_node))); 3449 addr = fold_build_pointer_plus (addr, offs); 3450 3451 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, addr); 3452 3453 /* className */ 3454 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, name); 3455 3456 /* cls */ 3457 CONSTRUCTOR_APPEND_ELT (initlist, NULL_TREE, cls); 3458 3459 return objc_build_constructor (objc_v2_ehtype_template, initlist); 3460 } 3461 3462 static tree 3463 build_ehtype (tree name, const char *eh_name, bool weak) 3464 { 3465 tree name_expr, class_name_expr, ehtype_decl, inits; 3466 3467 name_expr = add_objc_string (name, class_names); 3468 /* Extern ref. for the class. ??? Maybe we can look this up 3469 somewhere. */ 3470 class_name_expr = 3471 create_extern_decl (objc_v2_class_template, 3472 objc_build_internal_classname (name, false)); 3473 class_name_expr = build_fold_addr_expr (class_name_expr); 3474 ehtype_decl = create_global_decl (objc_v2_ehtype_template, eh_name); 3475 if (weak) 3476 DECL_WEAK (ehtype_decl) = 1; 3477 inits = objc2_build_ehtype_initializer (name_expr, class_name_expr); 3478 OBJCMETA (ehtype_decl, objc_meta, meta_ehtype); 3479 finish_var_decl (ehtype_decl, inits); 3480 return ehtype_decl; 3481 } 3482 3483 /* This routine returns TRUE if CLS or any of its super classes has 3484 __attribute__ ((objc_exception)). */ 3485 3486 static bool 3487 objc2_objc_exception_attr (tree cls) 3488 { 3489 while (cls) 3490 { 3491 if (CLASS_HAS_EXCEPTION_ATTR (cls)) 3492 return true; 3493 cls = lookup_interface (CLASS_SUPER_NAME (cls)); 3494 } 3495 3496 return false; 3497 } 3498 3499 static bool 3500 is_implemented (tree name) 3501 { 3502 struct imp_entry *t; 3503 for (t = imp_list; t; t = t->next) 3504 if (TREE_CODE (t->imp_context) == CLASS_IMPLEMENTATION_TYPE 3505 && CLASS_NAME (t->imp_template) == name) 3506 return true; 3507 3508 return false; 3509 } 3510 3511 /* We will build catch objects: 3512 for any type implemented here. 3513 for any type used in a catch that has no exception attribute. */ 3514 static void build_v2_eh_catch_objects (void) 3515 { 3516 int count=0; 3517 ident_data_tuple *ref; 3518 3519 if (!vec_safe_length (ehtype_list)) 3520 return; 3521 3522 FOR_EACH_VEC_ELT (*ehtype_list, count, ref) 3523 { 3524 char buf[BUFSIZE]; 3525 bool impl = is_implemented (ref->ident); 3526 bool excpt = objc2_objc_exception_attr (lookup_interface (ref->ident)); 3527 snprintf (buf, BUFSIZE, "OBJC_EHTYPE_$_%s", IDENTIFIER_POINTER (ref->ident)); 3528 if (!impl && excpt) 3529 /* The User says this class has a catcher already. */ 3530 ref->data = create_extern_decl (objc_v2_ehtype_template, buf); 3531 else 3532 /* Create a catcher, weak if it wasn't marked. */ 3533 ref->data = build_ehtype (ref->ident, buf, !excpt); 3534 } 3535 } 3536 3537 static tree 3538 lookup_ehtype_ref (tree id) 3539 { 3540 int count=0; 3541 ident_data_tuple *ref; 3542 3543 if (!vec_safe_length (ehtype_list)) 3544 return NULL_TREE; 3545 3546 FOR_EACH_VEC_ELT (*ehtype_list, count, ref) 3547 if (ref->ident == id) 3548 return ref->data; 3549 return NULL_TREE; 3550 } 3551 3552 /* This hook, called via lang_eh_runtime_type, generates a runtime 3553 object which is either the address of the 'OBJC_EHTYPE_$_class' 3554 object or address of external OBJC_EHTYPE_id object. */ 3555 static tree 3556 next_runtime_02_eh_type (tree type) 3557 { 3558 tree t; 3559 3560 if (type == error_mark_node 3561 /*|| errorcount || sorrycount*/) 3562 goto err_mark_in; 3563 3564 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type))) 3565 { 3566 if (!next_v2_EHTYPE_id_decl) 3567 { 3568 /* This is provided by the Apple/NeXT libobjc.dylib so we 3569 need only to reference it. */ 3570 next_v2_EHTYPE_id_decl = 3571 start_var_decl (objc_v2_ehtype_template, "OBJC_EHTYPE_id"); 3572 DECL_EXTERNAL (next_v2_EHTYPE_id_decl) = 1; 3573 TREE_PUBLIC (next_v2_EHTYPE_id_decl) = 1; 3574 TREE_STATIC (next_v2_EHTYPE_id_decl) = 0; 3575 } 3576 return build_fold_addr_expr (next_v2_EHTYPE_id_decl); 3577 } 3578 3579 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type))) 3580 { 3581 #ifdef OBJCPLUS 3582 /* This routine is also called for c++'s catch clause; in which 3583 case, we use c++'s typeinfo decl. */ 3584 return build_eh_type_type (type); 3585 #else 3586 error ("non-objective-c type '%T' cannot be caught", type); 3587 goto err_mark_in; 3588 #endif 3589 } 3590 else 3591 t = OBJC_TYPE_NAME (TREE_TYPE (type)); 3592 3593 /* We have to build a reference to the OBJC_EHTYPE_<Class>. */ 3594 t = lookup_ehtype_ref (t); 3595 if (!t) 3596 goto err_mark_in; 3597 3598 return build_fold_addr_expr (t); 3599 3600 err_mark_in: 3601 return error_mark_node; 3602 } 3603 3604 static GTY(()) tree objc_eh_personality_decl; 3605 3606 static tree 3607 objc_eh_personality (void) 3608 { 3609 if (!objc_eh_personality_decl) 3610 objc_eh_personality_decl = build_personality_function ("objc"); 3611 return objc_eh_personality_decl; 3612 } 3613 3614 /* NOTE --- interfaces --- */ 3615 3616 static tree 3617 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown) 3618 { 3619 tree t; 3620 if (rethrown) 3621 /* We have a separate re-throw entry. */ 3622 t = build_function_call_vec (loc, objc_rethrow_exception_decl, NULL, NULL); 3623 else 3624 { 3625 /* Throw like the others... */ 3626 vec<tree, va_gc> *parms; 3627 vec_alloc (parms, 1); 3628 parms->quick_push (throw_expr); 3629 t = build_function_call_vec (loc, objc_exception_throw_decl, parms, 0); 3630 vec_free (parms); 3631 } 3632 return add_stmt (t); 3633 } 3634 3635 /* Build __builtin_eh_pointer. */ 3636 3637 static tree 3638 objc_build_exc_ptr (struct objc_try_context **x ATTRIBUTE_UNUSED) 3639 { 3640 tree t; 3641 t = builtin_decl_explicit (BUILT_IN_EH_POINTER); 3642 t = build_call_expr (t, 1, integer_zero_node); 3643 return fold_convert (objc_object_type, t); 3644 } 3645 3646 static tree begin_catch (struct objc_try_context **cur_try_context, tree type, 3647 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED) 3648 { 3649 tree t; 3650 3651 /* Record the data for the catch in the try context so that we can 3652 finalize it later. Ellipsis is signalled by a NULL entry. */ 3653 if (ellipsis) 3654 t = build_stmt (input_location, CATCH_EXPR, NULL_TREE, compound); 3655 else 3656 t = build_stmt (input_location, CATCH_EXPR, type, compound); 3657 (*cur_try_context)->current_catch = t; 3658 3659 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */ 3660 t = objc_build_exc_ptr (cur_try_context); 3661 t = convert (TREE_TYPE (decl), t); 3662 /* FIXME: location. */ 3663 if (type && type != error_mark_node) 3664 { 3665 t = build1(NOP_EXPR, ptr_type_node, t); 3666 t = build_function_call (input_location, objc2_begin_catch_decl, 3667 tree_cons (NULL_TREE, t, NULL_TREE)); 3668 3669 /* We might want to build a catch object for this (if it's not 3670 id). */ 3671 if (POINTER_TYPE_P (type) 3672 && !objc_is_object_id (TREE_TYPE (type)) 3673 && TYPED_OBJECT (TREE_TYPE (type))) 3674 objc_v2_add_to_ehtype_list (OBJC_TYPE_NAME (TREE_TYPE (type))); 3675 } 3676 return build2 (MODIFY_EXPR, void_type_node, decl, t); 3677 } 3678 3679 /* try { catch-body } finally { objc_end_catch (); } */ 3680 static void 3681 finish_catch (struct objc_try_context **cur_try_context, tree curr_catch) 3682 { 3683 struct objc_try_context *ct; 3684 tree try_exp, func, *l, t ; 3685 location_t loc = (*cur_try_context)->try_locus; 3686 3687 if (!curr_catch || curr_catch == error_mark_node) 3688 return; 3689 3690 t = CATCH_BODY (curr_catch); 3691 if (TREE_CODE (t) == BIND_EXPR) 3692 { 3693 /* Usual case of @catch (objc-expr). */ 3694 objc_begin_try_stmt (loc, BIND_EXPR_BODY (t)); 3695 BIND_EXPR_BODY (t) = NULL_TREE; 3696 l = &BIND_EXPR_BODY (t); 3697 } 3698 else 3699 { 3700 /* NULL entry, meaning @catch (...). */ 3701 objc_begin_try_stmt (loc, t); 3702 CATCH_BODY (curr_catch) = NULL_TREE; 3703 l = &CATCH_BODY (curr_catch); 3704 } 3705 3706 /* Pick up the new context we made in begin_try above... */ 3707 ct = *cur_try_context; 3708 func = build_function_call_vec (loc, objc2_end_catch_decl, NULL, NULL); 3709 append_to_statement_list (func, &ct->finally_body); 3710 try_exp = build_stmt (loc, TRY_FINALLY_EXPR, ct->try_body, ct->finally_body); 3711 *cur_try_context = ct->outer; 3712 free (ct); 3713 append_to_statement_list (try_exp, l); 3714 append_to_statement_list (curr_catch, &((*cur_try_context)->catch_list)); 3715 } 3716 3717 static tree 3718 finish_try_stmt (struct objc_try_context **cur_try_context) 3719 { 3720 struct objc_try_context *c = *cur_try_context; 3721 tree stmt = c->try_body; 3722 if (c->catch_list) 3723 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list); 3724 if (c->finally_body) 3725 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body); 3726 return stmt; 3727 } 3728 3729 #include "gt-objc-objc-next-runtime-abi-02.h" 3730