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