1 /* Next Runtime (ABI-0/1) private. 2 Copyright (C) 2011-2017 Free Software Foundation, Inc. 3 Contributed by Iain Sandoe (split from objc-act.c) 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 /* This implements the original NeXT ABI (0) used for m32 code and 22 indicated by module version 6. It also implements the small number 23 of additions made for properties and optional protocol methods as 24 ABI=1 (module version 7). */ 25 26 #include "config.h" 27 #include "system.h" 28 #include "coretypes.h" 29 #include "stringpool.h" 30 31 #ifdef OBJCPLUS 32 #include "cp/cp-tree.h" 33 #else 34 #include "c/c-tree.h" 35 #include "c/c-lang.h" 36 #endif 37 #include "langhooks.h" 38 #include "c-family/c-objc.h" 39 #include "objc-act.h" 40 41 /* When building Objective-C++, we are not linking against the C 42 front-end and so need to replicate the C tree-construction 43 functions in some way. */ 44 #ifdef OBJCPLUS 45 #define OBJCP_REMAP_FUNCTIONS 46 #include "objcp-decl.h" 47 #endif /* OBJCPLUS */ 48 49 #include "target.h" 50 #include "c-family/c-target.h" 51 #include "tree-iterator.h" 52 53 #include "objc-runtime-hooks.h" 54 #include "objc-runtime-shared-support.h" 55 #include "objc-encoding.h" 56 57 /* NeXT ABI 0 and 1 private definitions. */ 58 #define DEF_CONSTANT_STRING_CLASS_NAME "NSConstantString" 59 60 #define TAG_GETCLASS "objc_getClass" 61 #define TAG_GETMETACLASS "objc_getMetaClass" 62 63 #define TAG_MSGSEND "objc_msgSend" 64 #define TAG_MSGSENDSUPER "objc_msgSendSuper" 65 #define TAG_MSGSEND_STRET "objc_msgSend_stret" 66 #define TAG_MSGSENDSUPER_STRET "objc_msgSendSuper_stret" 67 68 /* NeXT-specific tags. */ 69 70 #define TAG_MSGSEND_NONNIL "objc_msgSendNonNil" 71 #define TAG_MSGSEND_NONNIL_STRET "objc_msgSendNonNil_stret" 72 #define TAG_EXCEPTIONEXTRACT "objc_exception_extract" 73 #define TAG_EXCEPTIONTRYENTER "objc_exception_try_enter" 74 #define TAG_EXCEPTIONTRYEXIT "objc_exception_try_exit" 75 #define TAG_EXCEPTIONMATCH "objc_exception_match" 76 #define TAG_SETJMP "_setjmp" 77 78 #define TAG_ASSIGNIVAR "objc_assign_ivar" 79 #define TAG_ASSIGNGLOBAL "objc_assign_global" 80 #define TAG_ASSIGNSTRONGCAST "objc_assign_strongCast" 81 82 /* Branch entry points. All that matters here are the addresses; 83 functions with these names do not really exist in libobjc. */ 84 85 #define TAG_MSGSEND_FAST "objc_msgSend_Fast" 86 #define TAG_ASSIGNIVAR_FAST "objc_assign_ivar_Fast" 87 88 /* The version identifies which language generation and runtime the 89 module (file) was compiled for, and is recorded in the module 90 descriptor. */ 91 #define OBJC_VERSION (flag_objc_abi >= 1 ? 7 : 6) 92 93 #define UTAG_CLASS_EXT "_objc_class_ext" 94 #define UTAG_PROPERTY_LIST "_prop_list_t" 95 #define UTAG_PROTOCOL_EXT "_objc_protocol_extension" 96 97 #define CLS_HAS_CXX_STRUCTORS 0x2000L 98 99 /* rt_trees identifiers - shared between NeXT implementations. These 100 allow the FE to tag meta-data in a manner that survives LTO and can 101 be used when the runtime requires that certain meta-data items 102 appear in particular named sections. */ 103 104 #include "objc-next-metadata-tags.h" 105 extern GTY(()) tree objc_rt_trees[OCTI_RT_META_MAX]; 106 107 static void next_runtime_01_initialize (void); 108 109 static tree next_runtime_abi_01_super_superclassfield_id (void); 110 111 static tree next_runtime_abi_01_class_decl (tree); 112 static tree next_runtime_abi_01_metaclass_decl (tree); 113 static tree next_runtime_abi_01_category_decl (tree); 114 static tree next_runtime_abi_01_protocol_decl (tree); 115 static tree next_runtime_abi_01_string_decl (tree, const char *, string_section); 116 117 static tree next_runtime_abi_01_get_class_reference (tree); 118 static tree next_runtime_abi_01_build_selector_reference (location_t, tree, tree); 119 static tree next_runtime_abi_01_get_protocol_reference (location_t, tree); 120 static tree next_runtime_abi_01_build_ivar_ref (location_t, tree, tree); 121 static tree next_runtime_abi_01_get_class_super_ref (location_t, struct imp_entry *, bool); 122 static tree next_runtime_abi_01_get_category_super_ref (location_t, struct imp_entry *, bool); 123 124 static tree next_runtime_abi_01_receiver_is_class_object (tree); 125 static void next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **, 126 tree, int, int); 127 static tree next_runtime_abi_01_build_objc_method_call (location_t, tree, tree, 128 tree, tree, tree, int); 129 static bool next_runtime_abi_01_setup_const_string_class_decl (void); 130 static tree next_runtime_abi_01_build_const_string_constructor (location_t, tree, int); 131 132 static void objc_generate_v1_next_metadata (void); 133 134 static void build_next_objc_exception_stuff (void); 135 static tree objc_eh_runtime_type (tree type); 136 static tree objc_eh_personality (void); 137 static tree build_throw_stmt (location_t, tree, bool); 138 static tree objc_build_exc_ptr (struct objc_try_context **); 139 static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool); 140 static void finish_catch (struct objc_try_context **, tree); 141 static tree finish_try_stmt (struct objc_try_context **); 142 143 bool 144 objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks) 145 { 146 if (flag_objc_exceptions 147 && !flag_objc_sjlj_exceptions) 148 { 149 warning_at (UNKNOWN_LOCATION, OPT_Wall, 150 "%<-fobjc-sjlj-exceptions%> is the only supported exceptions " 151 "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2"); 152 } 153 154 rthooks->initialize = next_runtime_01_initialize; 155 rthooks->default_constant_string_class_name = DEF_CONSTANT_STRING_CLASS_NAME; 156 rthooks->tag_getclass = TAG_GETCLASS; 157 rthooks->super_superclassfield_ident = next_runtime_abi_01_super_superclassfield_id; 158 159 rthooks->class_decl = next_runtime_abi_01_class_decl; 160 rthooks->metaclass_decl = next_runtime_abi_01_metaclass_decl; 161 rthooks->category_decl = next_runtime_abi_01_category_decl; 162 rthooks->protocol_decl = next_runtime_abi_01_protocol_decl; 163 rthooks->string_decl = next_runtime_abi_01_string_decl; 164 165 rthooks->get_class_reference = next_runtime_abi_01_get_class_reference; 166 rthooks->build_selector_reference = next_runtime_abi_01_build_selector_reference; 167 rthooks->get_protocol_reference = next_runtime_abi_01_get_protocol_reference; 168 rthooks->build_ivar_reference = next_runtime_abi_01_build_ivar_ref; 169 rthooks->get_class_super_ref = next_runtime_abi_01_get_class_super_ref; 170 rthooks->get_category_super_ref = next_runtime_abi_01_get_category_super_ref; 171 172 rthooks->receiver_is_class_object = next_runtime_abi_01_receiver_is_class_object; 173 rthooks->get_arg_type_list_base = next_runtime_abi_01_get_arg_type_list_base; 174 rthooks->build_objc_method_call = next_runtime_abi_01_build_objc_method_call; 175 176 rthooks->setup_const_string_class_decl = 177 next_runtime_abi_01_setup_const_string_class_decl; 178 rthooks->build_const_string_constructor = 179 next_runtime_abi_01_build_const_string_constructor; 180 181 rthooks->build_throw_stmt = build_throw_stmt; 182 rthooks->build_exc_ptr = objc_build_exc_ptr; 183 rthooks->begin_catch = begin_catch; 184 rthooks->finish_catch = finish_catch; 185 rthooks->finish_try_stmt = finish_try_stmt; 186 187 rthooks->generate_metadata = objc_generate_v1_next_metadata; 188 return true; 189 } 190 191 /* We need a way to convey what kind of meta-data are represented by a 192 given variable, since each type is expected (by the runtime) to be 193 found in a specific named section. The solution must be usable 194 with LTO. 195 196 The scheme used for NeXT ABI 0/1 (partial matching of variable 197 names) is not satisfactory for LTO & ABI-2. We now tag ObjC 198 meta-data with identification attributes in the front end. The 199 back-end may choose to act on these as it requires. */ 200 201 static void 202 next_runtime_abi_01_init_metadata_attributes (void) 203 { 204 if (!objc_meta) 205 objc_meta = get_identifier ("OBJC1META"); 206 207 if (!meta_base) 208 meta_base = get_identifier ("V1_BASE"); 209 210 meta_class = get_identifier ("V1_CLAS"); 211 meta_metaclass = get_identifier ("V1_META"); 212 meta_category = get_identifier ("V1_CATG"); 213 meta_protocol = get_identifier ("V1_PROT"); 214 215 meta_clac_vars = get_identifier ("V1_CLCV"); 216 meta_clai_vars = get_identifier ("V1_CLIV"); 217 218 meta_clac_meth = get_identifier ("V1_CLCM"); 219 meta_clai_meth = get_identifier ("V1_CLIM"); 220 meta_catc_meth = get_identifier ("V1_CACM"); 221 meta_cati_meth = get_identifier ("V1_CAIM"); 222 meta_proto_cls_meth = get_identifier ("V1_PCLM"); 223 meta_proto_nst_meth = get_identifier ("V1_PNSM"); 224 225 meta_clas_prot = get_identifier ("V1_CLPR"); 226 meta_catg_prot = get_identifier ("V1_CAPR"); 227 228 meta_class_reference = get_identifier ("V1_CLRF"); 229 meta_proto_ref = get_identifier ("V1_PRFS"); 230 meta_sel_refs = get_identifier ("V1_SRFS"); 231 232 meta_class_name = get_identifier ("V1_CLSN"); 233 meta_meth_name = get_identifier ("V1_METN"); 234 meta_meth_type = get_identifier ("V1_METT"); 235 meta_prop_name_attr = get_identifier ("V1_STRG"); 236 237 meta_modules = get_identifier ("V1_MODU"); 238 meta_symtab = get_identifier ("V1_SYMT"); 239 meta_info = get_identifier ("V1_INFO"); 240 241 meta_proplist = get_identifier ("V1_PLST"); 242 meta_protocol_extension = get_identifier ("V1_PEXT"); 243 meta_class_extension = get_identifier ("V1_CEXT"); 244 245 meta_const_str = get_identifier ("V1_CSTR"); 246 } 247 248 static void build_v1_class_template (void); 249 static void build_v1_category_template (void); 250 static void build_v1_protocol_template (void); 251 252 static void next_runtime_01_initialize (void) 253 { 254 tree type; 255 256 #ifdef OBJCPLUS 257 /* For all NeXT objc ABIs -fobjc-call-cxx-cdtors is on by 258 default. */ 259 if (!global_options_set.x_flag_objc_call_cxx_cdtors) 260 global_options.x_flag_objc_call_cxx_cdtors = 1; 261 #endif 262 263 /* Set up attributes to be attached to the meta-data so that they 264 will be placed in the correct sections. */ 265 next_runtime_abi_01_init_metadata_attributes (); 266 267 if (flag_objc_abi >= 1) 268 objc_prop_list_ptr = build_pointer_type (xref_tag (RECORD_TYPE, 269 get_identifier ("_prop_list_t"))); 270 271 /* Declare type of selector-objects that represent an operation 272 name. */ 273 /* `struct objc_selector *' */ 274 objc_selector_type = build_pointer_type (xref_tag (RECORD_TYPE, 275 get_identifier (TAG_SELECTOR))); 276 277 build_v1_class_template (); 278 build_super_template (); 279 build_v1_protocol_template (); 280 build_v1_category_template (); 281 282 /* NB: In order to call one of the ..._stret (struct-returning) 283 functions, the function *MUST* first be cast to a signature that 284 corresponds to the actual ObjC method being invoked. This is 285 what is done by the build_objc_method_call() routine below. */ 286 287 /* id objc_msgSend (id, SEL, ...); */ 288 /* id objc_msgSendNonNil (id, SEL, ...); */ 289 /* id objc_msgSend_stret (id, SEL, ...); */ 290 /* id objc_msgSendNonNil_stret (id, SEL, ...); */ 291 type = build_varargs_function_type_list (objc_object_type, 292 objc_object_type, 293 objc_selector_type, 294 NULL_TREE); 295 296 umsg_decl = add_builtin_function (TAG_MSGSEND, 297 type, 0, NOT_BUILT_IN, 298 NULL, NULL_TREE); 299 300 umsg_nonnil_decl = add_builtin_function (TAG_MSGSEND_NONNIL, 301 type, 0, NOT_BUILT_IN, 302 NULL, NULL_TREE); 303 304 umsg_stret_decl = add_builtin_function (TAG_MSGSEND_STRET, 305 type, 0, NOT_BUILT_IN, 306 NULL, NULL_TREE); 307 308 umsg_nonnil_stret_decl = add_builtin_function (TAG_MSGSEND_NONNIL_STRET, 309 type, 0, NOT_BUILT_IN, 310 NULL, NULL_TREE); 311 312 /* These can throw, because the function that gets called can throw 313 in Obj-C++, or could itself call something that can throw even in 314 Obj-C. */ 315 TREE_NOTHROW (umsg_decl) = 0; 316 TREE_NOTHROW (umsg_nonnil_decl) = 0; 317 TREE_NOTHROW (umsg_stret_decl) = 0; 318 TREE_NOTHROW (umsg_nonnil_stret_decl) = 0; 319 320 /* id objc_msgSend_Fast (id, SEL, ...) 321 __attribute__ ((hard_coded_address (OFFS_MSGSEND_FAST))); */ 322 #ifdef OFFS_MSGSEND_FAST 323 umsg_fast_decl = add_builtin_function (TAG_MSGSEND_FAST, 324 type, 0, NOT_BUILT_IN, 325 NULL, NULL_TREE); 326 TREE_NOTHROW (umsg_fast_decl) = 0; 327 DECL_ATTRIBUTES (umsg_fast_decl) 328 = tree_cons (get_identifier ("hard_coded_address"), 329 build_int_cst (NULL_TREE, OFFS_MSGSEND_FAST), 330 NULL_TREE); 331 #else 332 /* No direct dispatch available. */ 333 umsg_fast_decl = umsg_decl; 334 #endif 335 336 /* id objc_msgSendSuper (struct objc_super *, SEL, ...); */ 337 /* id objc_msgSendSuper_stret (struct objc_super *, SEL, ...); */ 338 type = build_varargs_function_type_list (objc_object_type, 339 objc_super_type, 340 objc_selector_type, 341 NULL_TREE); 342 umsg_super_decl = add_builtin_function (TAG_MSGSENDSUPER, 343 type, 0, NOT_BUILT_IN, 344 NULL, NULL_TREE); 345 umsg_super_stret_decl = add_builtin_function (TAG_MSGSENDSUPER_STRET, 346 type, 0, NOT_BUILT_IN, 0, 347 NULL_TREE); 348 TREE_NOTHROW (umsg_super_decl) = 0; 349 TREE_NOTHROW (umsg_super_stret_decl) = 0; 350 351 type = build_function_type_list (objc_object_type, 352 const_string_type_node, 353 NULL_TREE); 354 355 /* id objc_getClass (const char *); */ 356 objc_get_class_decl 357 = add_builtin_function (TAG_GETCLASS, type, 0, NOT_BUILT_IN, 358 NULL, NULL_TREE); 359 360 /* id objc_getMetaClass (const char *); */ 361 objc_get_meta_class_decl 362 = add_builtin_function (TAG_GETMETACLASS, type, 0, NOT_BUILT_IN, NULL, NULL_TREE); 363 364 /* This is the type of all of the following functions 365 objc_copyStruct(). */ 366 type = build_function_type_list (void_type_node, 367 ptr_type_node, 368 const_ptr_type_node, 369 ptrdiff_type_node, 370 boolean_type_node, 371 boolean_type_node, 372 NULL_TREE); 373 /* Declare the following function: 374 void 375 objc_copyStruct (void *destination, const void *source, 376 ptrdiff_t size, BOOL is_atomic, BOOL has_strong); */ 377 objc_copyStruct_decl = add_builtin_function ("objc_copyStruct", 378 type, 0, NOT_BUILT_IN, 379 NULL, NULL_TREE); 380 TREE_NOTHROW (objc_copyStruct_decl) = 0; 381 objc_getPropertyStruct_decl = NULL_TREE; 382 objc_setPropertyStruct_decl = NULL_TREE; 383 384 build_next_objc_exception_stuff (); 385 if (flag_objc_exceptions && !flag_objc_sjlj_exceptions) 386 using_eh_for_cleanups (); 387 lang_hooks.eh_runtime_type = objc_eh_runtime_type; 388 lang_hooks.eh_personality = objc_eh_personality; 389 } 390 391 /* --- templates --- */ 392 393 /* struct _objc_class 394 { 395 struct _objc_class *isa; 396 struct _objc_class *super_class; 397 char *name; 398 long version; 399 long info; 400 long instance_size; 401 struct _objc_ivar_list *ivars; 402 struct _objc_method_list *methods; 403 struct objc_cache *cache; 404 struct _objc_protocol_list *protocols; 405 #if ABI=1 406 const char *ivar_layout; 407 struct _objc_class_ext *ext; 408 #else 409 void *sel_id; 410 void *gc_object_type; 411 #endif 412 }; */ 413 414 /* The 'sel_id' & 'gc_object_type' fields are not used by the NeXT 415 runtime. We generate them for ABI==0 to maintain backward binary 416 compatibility. */ 417 418 static void 419 build_v1_class_template (void) 420 { 421 tree ptype, decls, *chain = NULL; 422 423 objc_class_template = objc_start_struct (get_identifier (UTAG_CLASS)); 424 425 /* struct _objc_class *isa; */ 426 decls = add_field_decl (build_pointer_type (objc_class_template), 427 "isa", &chain); 428 429 /* struct _objc_class *super_class; */ 430 add_field_decl (build_pointer_type (objc_class_template), 431 "super_class", &chain); 432 433 /* char *name; */ 434 add_field_decl (string_type_node, "name", &chain); 435 436 /* long version; */ 437 add_field_decl (long_integer_type_node, "version", &chain); 438 439 /* long info; */ 440 add_field_decl (long_integer_type_node, "info", &chain); 441 442 /* long instance_size; */ 443 add_field_decl (long_integer_type_node, "instance_size", &chain); 444 445 /* struct _objc_ivar_list *ivars; */ 446 add_field_decl (objc_ivar_list_ptr,"ivars", &chain); 447 448 /* struct _objc_method_list *methods; */ 449 add_field_decl (objc_method_list_ptr, "methods", &chain); 450 451 /* struct objc_cache *cache; */ 452 ptype = build_pointer_type (xref_tag (RECORD_TYPE, 453 get_identifier ("objc_cache"))); 454 add_field_decl (ptype, "cache", &chain); 455 456 /* struct _objc_protocol **protocol_list; */ 457 ptype = build_pointer_type (build_pointer_type 458 (xref_tag (RECORD_TYPE, 459 get_identifier (UTAG_PROTOCOL)))); 460 add_field_decl (ptype, "protocol_list", &chain); 461 462 if (flag_objc_abi >= 1) 463 { 464 /* const char *ivar_layout; */ 465 add_field_decl (const_string_type_node, "ivar_layout", &chain); 466 467 /* struct _objc_class_ext *ext; */ 468 ptype = build_pointer_type (xref_tag (RECORD_TYPE, 469 get_identifier (UTAG_CLASS_EXT))); 470 add_field_decl (ptype, "ext", &chain); 471 } 472 else 473 { 474 /* void *sel_id; */ 475 add_field_decl (build_pointer_type (void_type_node), "sel_id", &chain); 476 /* void *gc_object_type; */ 477 add_field_decl (build_pointer_type (void_type_node), "gc_object_type", 478 &chain); 479 } 480 481 objc_finish_struct (objc_class_template, decls); 482 } 483 484 /* struct _objc_category 485 { 486 char *category_name; 487 char *class_name; 488 struct _objc_method_list *instance_methods; 489 struct _objc_method_list *class_methods; 490 struct _objc_protocol_list *protocols; 491 #if ABI=1 492 uint32_t size; // sizeof (struct _objc_category) 493 struct _objc_property_list *instance_properties; // category's own @property decl. 494 #endif 495 }; */ 496 497 static void 498 build_v1_category_template (void) 499 { 500 tree ptype, decls, *chain = NULL; 501 502 objc_category_template = objc_start_struct (get_identifier (UTAG_CATEGORY)); 503 504 /* char *category_name; */ 505 decls = add_field_decl (string_type_node, "category_name", &chain); 506 507 /* char *class_name; */ 508 add_field_decl (string_type_node, "class_name", &chain); 509 510 /* struct _objc_method_list *instance_methods; */ 511 add_field_decl (objc_method_list_ptr, "instance_methods", &chain); 512 513 /* struct _objc_method_list *class_methods; */ 514 add_field_decl (objc_method_list_ptr, "class_methods", &chain); 515 516 /* struct _objc_protocol **protocol_list; */ 517 ptype = build_pointer_type (build_pointer_type (objc_protocol_template)); 518 add_field_decl (ptype, "protocol_list", &chain); 519 520 if (flag_objc_abi >= 1) 521 { 522 add_field_decl (integer_type_node, "size", &chain); 523 524 /* struct _objc_property_list *instance_properties; 525 This field describes a category's @property declarations. 526 Properties from inherited protocols are not included. */ 527 ptype = build_pointer_type (xref_tag (RECORD_TYPE, 528 get_identifier (UTAG_PROPERTY_LIST))); 529 add_field_decl (ptype, "instance_properties", &chain); 530 } 531 objc_finish_struct (objc_category_template, decls); 532 } 533 534 /* Begin code generation for protocols... 535 Modified for ObjC #1 extensions. */ 536 537 /* struct _objc_protocol 538 { 539 #if ABI=1 540 struct _objc_protocol_extension *isa; 541 #else 542 struct _objc_class *isa; 543 #endif 544 545 char *protocol_name; 546 struct _objc_protocol **protocol_list; 547 struct _objc__method_prototype_list *instance_methods; 548 struct _objc__method_prototype_list *class_methods; 549 }; */ 550 551 static void 552 build_v1_protocol_template (void) 553 { 554 tree ptype, decls, *chain = NULL; 555 556 objc_protocol_template = objc_start_struct (get_identifier (UTAG_PROTOCOL)); 557 558 if (flag_objc_abi >= 1) 559 /* struct _objc_protocol_extension *isa; */ 560 ptype = build_pointer_type (xref_tag (RECORD_TYPE, 561 get_identifier (UTAG_PROTOCOL_EXT))); 562 else 563 /* struct _objc_class *isa; */ 564 ptype = build_pointer_type (xref_tag (RECORD_TYPE, 565 get_identifier (UTAG_CLASS))); 566 567 decls = add_field_decl (ptype, "isa", &chain); 568 569 /* char *protocol_name; */ 570 add_field_decl (string_type_node, "protocol_name", &chain); 571 572 /* struct _objc_protocol **protocol_list; */ 573 ptype = build_pointer_type (build_pointer_type (objc_protocol_template)); 574 add_field_decl (ptype, "protocol_list", &chain); 575 576 /* struct _objc__method_prototype_list *instance_methods; */ 577 add_field_decl (objc_method_proto_list_ptr, "instance_methods", &chain); 578 579 /* struct _objc__method_prototype_list *class_methods; */ 580 add_field_decl (objc_method_proto_list_ptr, "class_methods", &chain); 581 582 objc_finish_struct (objc_protocol_template, decls); 583 } 584 585 /* --- names, decls identifiers --- */ 586 587 static tree 588 next_runtime_abi_01_super_superclassfield_id (void) 589 { 590 if (!super_superclassfield_id) 591 super_superclassfield_id = get_identifier ("super_class"); 592 return super_superclassfield_id; 593 } 594 595 static tree 596 next_runtime_abi_01_class_decl (tree klass) 597 { 598 tree decl; 599 char buf[BUFSIZE]; 600 snprintf (buf, BUFSIZE, "_OBJC_Class_%s", 601 IDENTIFIER_POINTER (CLASS_NAME (klass))); 602 decl = start_var_decl (objc_class_template, buf); 603 OBJCMETA (decl, objc_meta, meta_class); 604 return decl; 605 } 606 607 static tree 608 next_runtime_abi_01_metaclass_decl (tree klass) 609 { 610 tree decl; 611 char buf[BUFSIZE]; 612 snprintf (buf, BUFSIZE, "_OBJC_MetaClass_%s", 613 IDENTIFIER_POINTER (CLASS_NAME (klass))); 614 decl = start_var_decl (objc_class_template, buf); 615 OBJCMETA (decl, objc_meta, meta_metaclass); 616 return decl; 617 } 618 619 static tree 620 next_runtime_abi_01_category_decl (tree klass) 621 { 622 tree decl; 623 char buf[BUFSIZE]; 624 snprintf (buf, BUFSIZE, "_OBJC_Category_%s_on_%s", 625 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass)), 626 IDENTIFIER_POINTER (CLASS_NAME (klass))); 627 decl = start_var_decl (objc_category_template, buf); 628 OBJCMETA (decl, objc_meta, meta_category); 629 return decl; 630 } 631 632 static tree 633 next_runtime_abi_01_protocol_decl (tree p) 634 { 635 tree decl; 636 char buf[BUFSIZE]; 637 638 /* static struct _objc_protocol _OBJC_Protocol_<mumble>; */ 639 640 snprintf (buf, BUFSIZE, "_OBJC_Protocol_%s", 641 IDENTIFIER_POINTER (PROTOCOL_NAME (p))); 642 decl = start_var_decl (objc_protocol_template, buf); 643 OBJCMETA (decl, objc_meta, meta_protocol); 644 return decl; 645 } 646 647 static tree 648 next_runtime_abi_01_string_decl (tree type, const char *name, string_section where) 649 { 650 tree var = start_var_decl (type, name); 651 switch (where) 652 { 653 case class_names: 654 OBJCMETA (var, objc_meta, meta_class_name); 655 break; 656 case meth_var_names: 657 OBJCMETA (var, objc_meta, meta_meth_name); 658 break; 659 case meth_var_types: 660 OBJCMETA (var, objc_meta, meta_meth_type); 661 break; 662 case prop_names_attr: 663 OBJCMETA (var, objc_meta, meta_prop_name_attr); 664 break; 665 default: 666 OBJCMETA (var, objc_meta, meta_base); 667 break; 668 } 669 return var; 670 } 671 672 /* --- entry --- */ 673 674 static GTY(()) int class_reference_idx; 675 676 static tree 677 build_class_reference_decl (void) 678 { 679 tree decl; 680 char buf[BUFSIZE]; 681 682 sprintf (buf, "_OBJC_ClassRefs_%d", class_reference_idx++); 683 decl = start_var_decl (objc_class_type, buf); 684 685 return decl; 686 } 687 688 static tree 689 next_runtime_abi_01_get_class_reference (tree ident) 690 { 691 if (!flag_zero_link) 692 { 693 tree *chain; 694 tree decl; 695 696 for (chain = &cls_ref_chain; *chain; chain = &TREE_CHAIN (*chain)) 697 if (TREE_VALUE (*chain) == ident) 698 { 699 if (! TREE_PURPOSE (*chain)) 700 TREE_PURPOSE (*chain) = build_class_reference_decl (); 701 702 return TREE_PURPOSE (*chain); 703 } 704 705 decl = build_class_reference_decl (); 706 *chain = tree_cons (decl, ident, NULL_TREE); 707 return decl; 708 } 709 else 710 { 711 tree params; 712 713 add_class_reference (ident); 714 715 params = build_tree_list (NULL_TREE, 716 my_build_string_pointer 717 (IDENTIFIER_LENGTH (ident) + 1, 718 IDENTIFIER_POINTER (ident))); 719 720 return build_function_call (input_location, objc_get_class_decl, params); 721 } 722 } 723 724 /* Used by build_function_type_for_method. Append the types for 725 receiver & _cmd at the start of a method argument list to ARGTYPES. 726 CONTEXT is either METHOD_DEF or METHOD_REF, saying whether we are 727 trying to define a method or call one. SUPERFLAG says this is for a 728 send to super. METH may be NULL, in the case that there is no 729 prototype. */ 730 731 static void 732 next_runtime_abi_01_get_arg_type_list_base (vec<tree, va_gc> **argtypes, 733 tree meth, int context, 734 int superflag) 735 { 736 tree receiver_type; 737 738 if (superflag) 739 receiver_type = objc_super_type; 740 else if (context == METHOD_DEF && TREE_CODE (meth) == INSTANCE_METHOD_DECL) 741 receiver_type = objc_instance_type; 742 else 743 receiver_type = objc_object_type; 744 745 vec_safe_push (*argtypes, receiver_type); 746 /* Selector type - will eventually change to `int'. */ 747 vec_safe_push (*argtypes, objc_selector_type); 748 } 749 750 static tree 751 next_runtime_abi_01_receiver_is_class_object (tree receiver) 752 { 753 if (TREE_CODE (receiver) == VAR_DECL 754 && IS_CLASS (TREE_TYPE (receiver))) 755 { 756 /* The receiver is a variable created by build_class_reference_decl. */ 757 tree chain = cls_ref_chain ; 758 /* Look up the identifier in the relevant chain. */ 759 for (; chain; chain = TREE_CHAIN (chain)) 760 if (TREE_PURPOSE (chain) == receiver) 761 return TREE_VALUE (chain); 762 } 763 return NULL_TREE; 764 } 765 766 static tree 767 build_selector_reference_decl (tree ident) 768 { 769 tree decl; 770 char *t, buf[BUFSIZE]; 771 772 snprintf (buf, BUFSIZE, "_OBJC_SelRef_%s", IDENTIFIER_POINTER (ident)); 773 t = buf; 774 while (*t) 775 { 776 if (*t==':') 777 *t = '$'; /* Underscore would clash between foo:bar and foo_bar. */ 778 t++; 779 } 780 decl = start_var_decl (objc_selector_type, buf); 781 OBJCMETA (decl, objc_meta, meta_sel_refs); 782 return decl; 783 } 784 785 static tree 786 next_runtime_abi_01_build_selector_reference (location_t loc ATTRIBUTE_UNUSED, 787 tree ident, 788 tree proto ATTRIBUTE_UNUSED) 789 { 790 tree *chain = &sel_ref_chain; 791 tree expr; 792 793 while (*chain) 794 { 795 if (TREE_VALUE (*chain) == ident) 796 return TREE_PURPOSE (*chain); 797 798 chain = &TREE_CHAIN (*chain); 799 } 800 801 expr = build_selector_reference_decl (ident); 802 803 *chain = tree_cons (expr, ident, NULL_TREE); 804 805 return expr; 806 } 807 808 /* Build a tree expression to send OBJECT the operation SELECTOR, 809 looking up the method on object LOOKUP_OBJECT (often same as OBJECT), 810 assuming the method has prototype METHOD_PROTOTYPE. 811 (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.) 812 LOC is the location of the expression to build. 813 Use METHOD_PARAMS as list of args to pass to the method. 814 If SUPER_FLAG is nonzero, we look up the superclass's method. */ 815 816 static tree 817 build_objc_method_call (location_t loc, int super_flag, tree method_prototype, 818 tree lookup_object, tree selector, 819 tree method_params) 820 { 821 tree sender, sender_cast, method, t; 822 tree rcv_p = (super_flag ? objc_super_type : objc_object_type); 823 vec<tree, va_gc> *parms; 824 unsigned nparm = (method_params ? list_length (method_params) : 0); 825 826 /* If a prototype for the method to be called exists, then cast 827 the sender's return type and arguments to match that of the method. 828 Otherwise, leave sender as is. */ 829 tree ret_type 830 = (method_prototype 831 ? TREE_VALUE (TREE_TYPE (method_prototype)) 832 : objc_object_type); 833 tree ftype = build_function_type_for_method (ret_type, method_prototype, 834 METHOD_REF, super_flag); 835 836 if (method_prototype && METHOD_TYPE_ATTRIBUTES (method_prototype)) 837 ftype = build_type_attribute_variant (ftype, 838 METHOD_TYPE_ATTRIBUTES 839 (method_prototype)); 840 841 sender_cast = build_pointer_type (ftype); 842 843 lookup_object = build_c_cast (loc, rcv_p, lookup_object); 844 845 /* Use SAVE_EXPR to avoid evaluating the receiver twice. */ 846 lookup_object = save_expr (lookup_object); 847 848 /* Param list + 2 slots for object and selector. */ 849 vec_alloc (parms, nparm + 2); 850 851 /* If we are returning a struct in memory, and the address 852 of that memory location is passed as a hidden first 853 argument, then change which messenger entry point this 854 expr will call. NB: Note that sender_cast remains 855 unchanged (it already has a struct return type). */ 856 if (!targetm.calls.struct_value_rtx (0, 0) 857 && (TREE_CODE (ret_type) == RECORD_TYPE 858 || TREE_CODE (ret_type) == UNION_TYPE) 859 && targetm.calls.return_in_memory (ret_type, 0)) 860 sender = (super_flag ? umsg_super_stret_decl 861 : flag_nil_receivers ? umsg_stret_decl 862 : umsg_nonnil_stret_decl); 863 else 864 sender = (super_flag ? umsg_super_decl 865 : (flag_nil_receivers ? (flag_objc_direct_dispatch 866 ? umsg_fast_decl 867 : umsg_decl) 868 : umsg_nonnil_decl)); 869 method = build_fold_addr_expr_loc (loc, sender); 870 871 /* Pass the object to the method. */ 872 parms->quick_push (lookup_object); 873 /* Pass the selector to the method. */ 874 parms->quick_push (selector); 875 /* Now append the remainder of the parms. */ 876 if (nparm) 877 for (; method_params; method_params = TREE_CHAIN (method_params)) 878 parms->quick_push (TREE_VALUE (method_params)); 879 880 /* Build an obj_type_ref, with the correct cast for the method call. */ 881 t = build3 (OBJ_TYPE_REF, sender_cast, method, 882 lookup_object, size_zero_node); 883 t = build_function_call_vec (loc, vNULL, t, parms, NULL); 884 vec_free (parms); 885 return t; 886 } 887 888 static tree 889 next_runtime_abi_01_build_objc_method_call (location_t loc, 890 tree method_prototype, 891 tree receiver, 892 tree rtype ATTRIBUTE_UNUSED, 893 tree sel_name, 894 tree method_params, 895 int super) 896 { 897 tree selector = next_runtime_abi_01_build_selector_reference (loc, sel_name, 898 NULL_TREE); 899 900 return build_objc_method_call (loc, super, method_prototype, 901 receiver, selector, method_params); 902 } 903 904 static tree 905 next_runtime_abi_01_get_protocol_reference (location_t loc, tree p) 906 { 907 tree expr; 908 909 if (!PROTOCOL_FORWARD_DECL (p)) 910 PROTOCOL_FORWARD_DECL (p) = next_runtime_abi_01_protocol_decl (p); 911 912 expr = build_unary_op (loc, ADDR_EXPR, PROTOCOL_FORWARD_DECL (p), 0); 913 return convert (objc_protocol_type, expr); 914 } 915 916 /* For ABI 0/1 and IVAR is just a fixed offset in the class struct. */ 917 918 static tree 919 next_runtime_abi_01_build_ivar_ref (location_t loc ATTRIBUTE_UNUSED, 920 tree base, tree id) 921 { 922 return objc_build_component_ref (base, id); 923 } 924 925 /* We build super class references as we need them (but keep them once 926 built for the sake of efficiency). */ 927 928 static tree 929 next_runtime_abi_01_get_class_super_ref (location_t loc ATTRIBUTE_UNUSED, 930 struct imp_entry *imp, bool inst_meth) 931 { 932 if (inst_meth) 933 { 934 if (!ucls_super_ref) 935 ucls_super_ref = 936 objc_build_component_ref (imp->class_decl, 937 get_identifier ("super_class")); 938 return ucls_super_ref; 939 } 940 else 941 { 942 if (!uucls_super_ref) 943 uucls_super_ref = 944 objc_build_component_ref (imp->meta_decl, 945 get_identifier ("super_class")); 946 return uucls_super_ref; 947 } 948 } 949 950 static tree 951 next_runtime_abi_01_get_category_super_ref (location_t loc ATTRIBUTE_UNUSED, 952 struct imp_entry *imp, bool inst_meth) 953 { 954 tree super_name = CLASS_SUPER_NAME (imp->imp_template); 955 tree super_class; 956 957 if (!flag_zero_link) 958 { 959 super_class = objc_get_class_reference (super_name); 960 961 if (!inst_meth) 962 963 /* If we are in a class method, we must retrieve the 964 _metaclass_ for the current class, pointed at by 965 the class's "isa" pointer. The following assumes that 966 "isa" is the first ivar in a class (which it must be). */ 967 super_class = 968 build_indirect_ref (input_location, 969 build_c_cast (input_location, 970 build_pointer_type (objc_class_type), 971 super_class), 972 RO_UNARY_STAR); 973 return super_class; 974 } 975 976 /* else do it the slow way. */ 977 add_class_reference (super_name); 978 super_class = (inst_meth ? objc_get_class_decl : objc_get_meta_class_decl); 979 super_name = my_build_string_pointer (IDENTIFIER_LENGTH (super_name) + 1, 980 IDENTIFIER_POINTER (super_name)); 981 /* super_class = objc_get{Meta}Class("CLASS_SUPER_NAME"); */ 982 return build_function_call (input_location, 983 super_class, 984 build_tree_list (NULL_TREE, super_name)); 985 } 986 987 static bool 988 next_runtime_abi_01_setup_const_string_class_decl (void) 989 { 990 if (!constant_string_global_id) 991 { 992 /* Hopefully, this should not represent a serious limitation. */ 993 char buf[BUFSIZE]; 994 snprintf (buf, BUFSIZE, "_%sClassReference", constant_string_class_name); 995 constant_string_global_id = get_identifier (buf); 996 } 997 998 string_class_decl = lookup_name (constant_string_global_id); 999 1000 return (string_class_decl != NULL_TREE); 1001 } 1002 1003 static tree 1004 next_runtime_abi_01_build_const_string_constructor (location_t loc, tree string, 1005 int length) 1006 { 1007 tree constructor, fields, var; 1008 vec<constructor_elt, va_gc> *v = NULL; 1009 1010 /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */ 1011 fields = TYPE_FIELDS (internal_const_str_type); 1012 CONSTRUCTOR_APPEND_ELT (v, fields, 1013 build_unary_op (loc, ADDR_EXPR, string_class_decl, 0)); 1014 1015 fields = DECL_CHAIN (fields); 1016 CONSTRUCTOR_APPEND_ELT (v, fields, 1017 build_unary_op (loc, ADDR_EXPR, string, 1)); 1018 1019 /* ??? check if this should be long. */ 1020 fields = DECL_CHAIN (fields); 1021 CONSTRUCTOR_APPEND_ELT (v, fields, build_int_cst (NULL_TREE, length)); 1022 constructor = objc_build_constructor (internal_const_str_type, v); 1023 1024 var = build_decl (input_location, CONST_DECL, NULL, TREE_TYPE (constructor)); 1025 DECL_INITIAL (var) = constructor; 1026 TREE_STATIC (var) = 1; 1027 DECL_CONTEXT (var) = NULL; 1028 OBJCMETA (var, objc_meta, meta_const_str); 1029 return var; 1030 } 1031 1032 /* --- metadata templates --- */ 1033 1034 /* This routine builds the following type: 1035 struct _prop_t { 1036 const char * const name; // property name 1037 const char * const attributes; // comma-delimited, encoded, 1038 // property attributes 1039 }; 1040 */ 1041 1042 static GTY(()) tree objc_v1_property_template; 1043 1044 static tree 1045 build_v1_property_template (void) 1046 { 1047 tree prop_record; 1048 tree decls, *chain = NULL; 1049 1050 prop_record = objc_start_struct (get_identifier ("_prop_t")); 1051 /* const char * name */ 1052 decls = add_field_decl (string_type_node, "name", &chain); 1053 1054 /* const char * attribute */ 1055 add_field_decl (string_type_node, "attribute", &chain); 1056 1057 objc_finish_struct (prop_record, decls); 1058 return prop_record; 1059 } 1060 1061 /* Build the following type: 1062 1063 struct _objc_protocol_extension 1064 { 1065 uint32_t size; // sizeof (struct _objc_protocol_extension) 1066 struct objc_method_list *optional_instance_methods; 1067 struct objc_method_list *optional_class_methods; 1068 struct objc_prop_list *instance_properties; 1069 } 1070 */ 1071 1072 static GTY(()) tree objc_protocol_extension_template; 1073 1074 static void 1075 build_v1_objc_protocol_extension_template (void) 1076 { 1077 tree decls, *chain = NULL; 1078 1079 objc_protocol_extension_template = 1080 objc_start_struct (get_identifier (UTAG_PROTOCOL_EXT)); 1081 1082 /* uint32_t size; */ 1083 decls = add_field_decl (integer_type_node, "size", &chain); 1084 1085 /* struct objc_method_list *optional_instance_methods; */ 1086 add_field_decl (objc_method_list_ptr, "optional_instance_methods", &chain); 1087 1088 /* struct objc_method_list *optional_class_methods; */ 1089 add_field_decl (objc_method_list_ptr, "optional_class_methods", &chain); 1090 1091 /* struct objc_prop_list *instance_properties; */ 1092 add_field_decl (objc_prop_list_ptr, "instance_properties", &chain); 1093 1094 objc_finish_struct (objc_protocol_extension_template, decls); 1095 } 1096 1097 /* This routine build following struct type: 1098 struct _objc_class_ext 1099 { 1100 uint32_t size; // sizeof(struct _objc_class_ext) 1101 const char *weak_ivar_layout; 1102 struct _prop_list_t *properties; 1103 } 1104 */ 1105 1106 static GTY(()) tree objc_class_ext_template; 1107 1108 static void 1109 build_objc_class_ext_template (void) 1110 { 1111 tree ptrt, decls, *chain = NULL; 1112 1113 objc_class_ext_template = objc_start_struct (get_identifier (UTAG_CLASS_EXT)); 1114 1115 /* uint32_t size; */ 1116 decls = add_field_decl (integer_type_node, "size", &chain); 1117 1118 /* const char *weak_ivar_layout; */ 1119 add_field_decl (const_string_type_node, "weak_ivar_layout", &chain); 1120 1121 /* struct _prop_list_t *properties; */ 1122 ptrt = build_pointer_type (xref_tag (RECORD_TYPE, 1123 get_identifier(UTAG_PROPERTY_LIST))); 1124 add_field_decl (ptrt, "properties", &chain); 1125 1126 objc_finish_struct (objc_class_ext_template, decls); 1127 } 1128 1129 static void 1130 build_metadata_templates (void) 1131 { 1132 1133 if (!objc_method_template) 1134 objc_method_template = build_method_template (); 1135 1136 1137 1138 } 1139 1140 /* --- emit metadata --- */ 1141 1142 static tree 1143 generate_v1_meth_descriptor_table (tree chain, tree protocol, 1144 const char *prefix, tree attr) 1145 { 1146 tree method_list_template, initlist, decl; 1147 int size; 1148 vec<constructor_elt, va_gc> *v = NULL; 1149 char buf[BUFSIZE]; 1150 1151 if (!chain || !prefix) 1152 return NULL_TREE; 1153 1154 if (!objc_method_prototype_template) 1155 objc_method_prototype_template = build_method_prototype_template (); 1156 1157 size = list_length (chain); 1158 method_list_template = 1159 build_method_prototype_list_template (objc_method_prototype_template, 1160 size); 1161 snprintf (buf, BUFSIZE, "%s_%s", prefix, 1162 IDENTIFIER_POINTER (PROTOCOL_NAME (protocol))); 1163 1164 decl = start_var_decl (method_list_template, buf); 1165 1166 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); 1167 initlist = 1168 build_descriptor_table_initializer (objc_method_prototype_template, 1169 chain); 1170 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist); 1171 /* Get into the right section. */ 1172 OBJCMETA (decl, objc_meta, attr); 1173 finish_var_decl (decl, objc_build_constructor (method_list_template, v)); 1174 return decl; 1175 } 1176 1177 /* Build protocol ext = 1178 {size, opt_instance_meth, opt_class_meth, instance_props}; 1179 or NULL_TREE if none are present. */ 1180 1181 static tree 1182 generate_v1_objc_protocol_extension (tree proto_interface, 1183 tree opt_instance_meth, 1184 tree opt_class_meth, 1185 tree instance_props) 1186 { 1187 int size; 1188 location_t loc; 1189 vec<constructor_elt, va_gc> *v = NULL; 1190 tree decl, expr; 1191 char buf[BUFSIZE]; 1192 1193 /* If there are no extensions, then don't bother... */ 1194 if (!opt_instance_meth && !opt_class_meth && !instance_props) 1195 return NULL_TREE; 1196 1197 if (!objc_protocol_extension_template) 1198 build_v1_objc_protocol_extension_template (); 1199 1200 /* uint32_t size */ 1201 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_protocol_extension_template)); 1202 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); 1203 1204 /* Try for meaningful diagnostics. */ 1205 loc = DECL_SOURCE_LOCATION (PROTOCOL_FORWARD_DECL (proto_interface)); 1206 1207 /* struct objc_method_list *optional_instance_methods; */ 1208 if (opt_instance_meth) 1209 expr = convert (objc_method_list_ptr, 1210 build_unary_op (loc, ADDR_EXPR, opt_instance_meth, 0)); 1211 else 1212 expr = convert (objc_method_list_ptr, null_pointer_node); 1213 1214 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1215 1216 /* struct objc_method_list *optional_class_methods; */ 1217 if (opt_class_meth) 1218 expr = convert (objc_method_list_ptr, 1219 build_unary_op (loc, ADDR_EXPR, opt_class_meth, 0)); 1220 else 1221 expr = convert (objc_method_list_ptr, null_pointer_node); 1222 1223 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1224 /* struct objc_prop_list *instance_properties; */ 1225 if (instance_props) 1226 expr = convert (objc_prop_list_ptr, 1227 build_unary_op (loc, ADDR_EXPR, instance_props, 0)); 1228 else 1229 expr = convert (objc_prop_list_ptr, null_pointer_node); 1230 1231 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1232 snprintf (buf, BUFSIZE, "_OBJC_ProtocolExt_%s", 1233 IDENTIFIER_POINTER (PROTOCOL_NAME (proto_interface))); 1234 1235 decl = start_var_decl (objc_protocol_extension_template, buf); 1236 expr = objc_build_constructor (TREE_TYPE (decl), v); 1237 OBJCMETA (decl, objc_meta, meta_protocol_extension); 1238 finish_var_decl (decl, expr); 1239 return decl; 1240 } 1241 1242 /* This routine builds the following type: 1243 struct _prop_list_t { 1244 uint32_t entsize; // sizeof (struct _prop_t) 1245 uint32_t prop_count; 1246 struct _prop_t prop_list [prop_count]; 1247 } 1248 */ 1249 1250 static tree 1251 build_v1_property_list_template (tree list_type, int size) 1252 { 1253 tree property_list_t_record; 1254 tree array_type, decls, *chain = NULL; 1255 1256 /* anonymous. */ 1257 property_list_t_record = objc_start_struct (NULL_TREE); 1258 1259 /* uint32_t const entsize */ 1260 decls = add_field_decl (integer_type_node, "entsize", &chain); 1261 1262 /* int prop_count */ 1263 add_field_decl (integer_type_node, "prop_count", &chain); 1264 1265 /* struct _prop_t prop_list[]; */ 1266 array_type = build_sized_array_type (list_type, size); 1267 add_field_decl (array_type, "prop_list", &chain); 1268 1269 objc_finish_struct (property_list_t_record, decls); 1270 return property_list_t_record; 1271 } 1272 1273 /* This routine builds the initializer list to initialize the 1274 'struct _prop_t prop_list[]' field of 'struct _prop_list_t' meta-data. */ 1275 1276 static tree 1277 build_v1_property_table_initializer (tree type, tree context) 1278 { 1279 tree x; 1280 vec<constructor_elt, va_gc> *inits = NULL; 1281 1282 if (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE) 1283 x = CLASS_PROPERTY_DECL (context); 1284 else 1285 x = IMPL_PROPERTY_DECL (context); 1286 1287 for (; x; x = TREE_CHAIN (x)) 1288 { 1289 vec<constructor_elt, va_gc> *elemlist = NULL; 1290 tree attribute, name_ident = PROPERTY_NAME (x); 1291 1292 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE, 1293 add_objc_string (name_ident, prop_names_attr)); 1294 1295 attribute = objc_v2_encode_prop_attr (x); 1296 CONSTRUCTOR_APPEND_ELT (elemlist, NULL_TREE, 1297 add_objc_string (attribute, prop_names_attr)); 1298 1299 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, 1300 objc_build_constructor (type, elemlist)); 1301 } 1302 1303 return objc_build_constructor (build_array_type (type, 0),inits); 1304 } 1305 1306 /* This routine builds the 'struct _prop_list_t' variable declaration and 1307 initializes it with its initializer list. TYPE is 'struct _prop_list_t', 1308 NAME is the internal name of this variable, SIZE is number of properties 1309 for this class and LIST is the initializer list for its 'prop_list' field. */ 1310 1311 static tree 1312 generate_v1_property_table (tree context, tree klass_ctxt) 1313 { 1314 tree x, decl, initlist, property_list_template; 1315 bool is_proto = false; 1316 vec<constructor_elt, va_gc> *inits = NULL; 1317 int init_val, size = 0; 1318 char buf[BUFSIZE]; 1319 1320 if (context) 1321 { 1322 gcc_assert (TREE_CODE (context) == PROTOCOL_INTERFACE_TYPE); 1323 x = CLASS_PROPERTY_DECL (context); 1324 is_proto = true; 1325 } 1326 else 1327 x = IMPL_PROPERTY_DECL (klass_ctxt); 1328 1329 for (; x; x = TREE_CHAIN (x)) 1330 size++; 1331 1332 if (size == 0) 1333 return NULL_TREE; 1334 1335 if (!objc_v1_property_template) 1336 objc_v1_property_template = build_v1_property_template (); 1337 1338 property_list_template = 1339 build_v1_property_list_template (objc_v1_property_template, 1340 size); 1341 initlist = build_v1_property_table_initializer (objc_v1_property_template, 1342 is_proto ? context 1343 : klass_ctxt); 1344 1345 init_val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_v1_property_template)); 1346 if (is_proto) 1347 snprintf (buf, BUFSIZE, "_OBJC_ProtocolPropList_%s", 1348 IDENTIFIER_POINTER (PROTOCOL_NAME (context))); 1349 else 1350 snprintf (buf, BUFSIZE, "_OBJC_ClassPropList_%s", 1351 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt))); 1352 1353 decl = start_var_decl (property_list_template, buf); 1354 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, init_val)); 1355 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size)); 1356 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist); 1357 x = objc_build_constructor (TREE_TYPE (decl), inits); 1358 OBJCMETA (decl, objc_meta, meta_proplist); 1359 finish_var_decl (decl, x); 1360 return decl; 1361 } 1362 1363 static tree 1364 generate_v1_protocol_list (tree i_or_p, tree klass_ctxt) 1365 { 1366 tree array_type, ptype, refs_decl, lproto, e, plist, attr; 1367 int size = 0; 1368 vec<constructor_elt, va_gc> *v = NULL; 1369 char buf[BUFSIZE]; 1370 1371 switch (TREE_CODE (i_or_p)) 1372 { 1373 case CLASS_INTERFACE_TYPE: 1374 case CATEGORY_INTERFACE_TYPE: 1375 plist = CLASS_PROTOCOL_LIST (i_or_p); 1376 break; 1377 case PROTOCOL_INTERFACE_TYPE: 1378 plist = PROTOCOL_LIST (i_or_p); 1379 break; 1380 default: 1381 gcc_unreachable (); 1382 } 1383 1384 /* Compute size. */ 1385 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 1386 if (TREE_CODE (TREE_VALUE (lproto)) == PROTOCOL_INTERFACE_TYPE 1387 && PROTOCOL_FORWARD_DECL (TREE_VALUE (lproto))) 1388 size++; 1389 1390 /* Build initializer. */ 1391 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, 0)); 1392 e = build_int_cst (build_pointer_type (objc_protocol_template), size); 1393 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e); 1394 1395 for (lproto = plist; lproto; lproto = TREE_CHAIN (lproto)) 1396 { 1397 tree pval = TREE_VALUE (lproto); 1398 1399 if (TREE_CODE (pval) == PROTOCOL_INTERFACE_TYPE 1400 && PROTOCOL_FORWARD_DECL (pval)) 1401 { 1402 tree fwref = PROTOCOL_FORWARD_DECL (pval); 1403 location_t loc = DECL_SOURCE_LOCATION (fwref) ; 1404 e = build_unary_op (loc, ADDR_EXPR, fwref, 0); 1405 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, e); 1406 } 1407 } 1408 1409 /* static struct objc_protocol *refs[n]; */ 1410 switch (TREE_CODE (i_or_p)) 1411 { 1412 case PROTOCOL_INTERFACE_TYPE: 1413 snprintf (buf, BUFSIZE, "_OBJC_ProtocolRefs_%s", 1414 IDENTIFIER_POINTER (PROTOCOL_NAME (i_or_p))); 1415 attr = meta_proto_ref; 1416 break; 1417 case CLASS_INTERFACE_TYPE: 1418 snprintf (buf, BUFSIZE, "_OBJC_ClassProtocols_%s", 1419 IDENTIFIER_POINTER (CLASS_NAME (i_or_p))); 1420 attr = meta_clas_prot; 1421 break; 1422 case CATEGORY_INTERFACE_TYPE: 1423 snprintf (buf, BUFSIZE, "_OBJC_CategoryProtocols_%s_%s", 1424 IDENTIFIER_POINTER (CLASS_NAME (klass_ctxt)), 1425 IDENTIFIER_POINTER (CLASS_SUPER_NAME (klass_ctxt))); 1426 attr = meta_catg_prot; 1427 break; 1428 default: 1429 gcc_unreachable (); 1430 } 1431 1432 ptype = build_pointer_type (objc_protocol_template); 1433 array_type = build_sized_array_type (ptype, size + 3); 1434 refs_decl = start_var_decl (array_type, buf); 1435 1436 OBJCMETA (refs_decl, objc_meta, attr); 1437 finish_var_decl (refs_decl, 1438 objc_build_constructor (TREE_TYPE (refs_decl), v)); 1439 1440 return refs_decl; 1441 } 1442 1443 static tree 1444 build_v1_protocol_initializer (tree type, tree protocol_name, tree protocol_list, 1445 tree inst_methods, tree class_methods, 1446 tree protocol_ext) 1447 { 1448 tree expr, ttyp; 1449 location_t loc; 1450 vec<constructor_elt, va_gc> *inits = NULL; 1451 1452 if (!objc_protocol_extension_template) 1453 build_v1_objc_protocol_extension_template (); 1454 1455 /* TODO: find a better representation of location from the inputs. */ 1456 loc = UNKNOWN_LOCATION; 1457 ttyp = build_pointer_type (objc_protocol_extension_template); 1458 /* Instead of jamming the protocol version number into the isa, we pass 1459 either a pointer to the protocol extension - or NULL. */ 1460 if (protocol_ext) 1461 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, protocol_ext, 0)); 1462 else 1463 expr = convert (ttyp, null_pointer_node); 1464 1465 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 1466 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_name); 1467 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, protocol_list); 1468 1469 ttyp = objc_method_proto_list_ptr; 1470 if (inst_methods) 1471 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); 1472 else 1473 expr = convert (ttyp, null_pointer_node); 1474 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 1475 1476 if (class_methods) 1477 expr = convert (ttyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); 1478 else 1479 expr = convert (ttyp, null_pointer_node); 1480 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, expr); 1481 1482 return objc_build_constructor (type, inits); 1483 } 1484 1485 /* An updated version of generate_protocols () that emit the protocol 1486 extension for ABI=1. */ 1487 1488 /* For each protocol which was referenced either from a @protocol() 1489 expression, or because a class/category implements it (then a 1490 pointer to the protocol is stored in the struct describing the 1491 class/category), we create a statically allocated instance of the 1492 Protocol class. The code is written in such a way as to generate 1493 as few Protocol objects as possible; we generate a unique Protocol 1494 instance for each protocol, and we don't generate a Protocol 1495 instance if the protocol is never referenced (either from a 1496 @protocol() or from a class/category implementation). These 1497 statically allocated objects can be referred to via the static 1498 (that is, private to this module) symbols _OBJC_PROTOCOL_n. 1499 1500 The statically allocated Protocol objects that we generate here 1501 need to be fixed up at runtime in order to be used: the 'isa' 1502 pointer of the objects need to be set up to point to the 'Protocol' 1503 class, as known at runtime. 1504 1505 The NeXT runtime fixes up all protocols at program startup time, 1506 before main() is entered. It uses a low-level trick to look up all 1507 those symbols, then loops on them and fixes them up. */ 1508 1509 /* TODO: finish getting rid of passing stuff around in globals. */ 1510 1511 static GTY(()) tree V1_Protocol_OPT_NST_METHODS_decl; 1512 static GTY(()) tree V1_Protocol_OPT_CLS_METHODS_decl; 1513 static GTY(()) tree V1_ProtocolExt_decl; 1514 static GTY(()) tree V1_Property_decl; 1515 1516 static void 1517 generate_v1_protocols (void) 1518 { 1519 tree p; 1520 1521 /* If a protocol was directly referenced, pull in indirect references. */ 1522 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 1523 if (PROTOCOL_FORWARD_DECL (p) && PROTOCOL_LIST (p)) 1524 generate_protocol_references (PROTOCOL_LIST (p)); 1525 1526 for (p = protocol_chain; p; p = TREE_CHAIN (p)) 1527 { 1528 tree decl, encoding, initlist, protocol_name_expr; 1529 tree refs_type, refs_decl, refs_expr; 1530 location_t loc; 1531 tree nst_methods = PROTOCOL_NST_METHODS (p); 1532 tree cls_methods = PROTOCOL_CLS_METHODS (p); 1533 1534 /* If protocol wasn't referenced, don't generate any code. */ 1535 decl = PROTOCOL_FORWARD_DECL (p); 1536 1537 if (!decl) 1538 continue; 1539 1540 /* Make sure we link in the Protocol class. */ 1541 add_class_reference (get_identifier (PROTOCOL_OBJECT_CLASS_NAME)); 1542 1543 while (nst_methods) 1544 { 1545 if (! METHOD_ENCODING (nst_methods)) 1546 { 1547 encoding = encode_method_prototype (nst_methods); 1548 METHOD_ENCODING (nst_methods) = encoding; 1549 } 1550 nst_methods = TREE_CHAIN (nst_methods); 1551 } 1552 1553 UOBJC_INSTANCE_METHODS_decl = 1554 generate_v1_meth_descriptor_table (PROTOCOL_NST_METHODS (p), p, 1555 "_OBJC_ProtocolInstanceMethods", 1556 meta_proto_nst_meth); 1557 1558 while (cls_methods) 1559 { 1560 if (! METHOD_ENCODING (cls_methods)) 1561 { 1562 encoding = encode_method_prototype (cls_methods); 1563 METHOD_ENCODING (cls_methods) = encoding; 1564 } 1565 1566 cls_methods = TREE_CHAIN (cls_methods); 1567 } 1568 1569 UOBJC_CLASS_METHODS_decl = 1570 generate_v1_meth_descriptor_table (PROTOCOL_CLS_METHODS (p), p, 1571 "_OBJC_ProtocolClassMethods", 1572 meta_proto_cls_meth); 1573 1574 /* There should be no optional methods for ABI-0 - but we need to 1575 check all this here before the lists are made. */ 1576 nst_methods = PROTOCOL_OPTIONAL_NST_METHODS (p); 1577 while (nst_methods) 1578 { 1579 if (! METHOD_ENCODING (nst_methods)) 1580 { 1581 encoding = encode_method_prototype (nst_methods); 1582 METHOD_ENCODING (nst_methods) = encoding; 1583 } 1584 nst_methods = TREE_CHAIN (nst_methods); 1585 } 1586 1587 V1_Protocol_OPT_NST_METHODS_decl = 1588 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_NST_METHODS (p), p, 1589 "_OBJC_OptionalProtocolInstanceMethods", 1590 meta_proto_nst_meth); 1591 1592 cls_methods = PROTOCOL_OPTIONAL_CLS_METHODS (p); 1593 while (cls_methods) 1594 { 1595 if (! METHOD_ENCODING (cls_methods)) 1596 { 1597 encoding = encode_method_prototype (cls_methods); 1598 METHOD_ENCODING (cls_methods) = encoding; 1599 } 1600 1601 cls_methods = TREE_CHAIN (cls_methods); 1602 } 1603 1604 V1_Protocol_OPT_CLS_METHODS_decl = 1605 generate_v1_meth_descriptor_table (PROTOCOL_OPTIONAL_CLS_METHODS (p), p, 1606 "_OBJC_OptionalProtocolClassMethods", 1607 meta_proto_cls_meth); 1608 1609 if (PROTOCOL_LIST (p)) 1610 refs_decl = generate_v1_protocol_list (p, objc_implementation_context); 1611 else 1612 refs_decl = 0; 1613 1614 /* static struct objc_protocol _OBJC_PROTOCOL_<mumble>; */ 1615 protocol_name_expr = add_objc_string (PROTOCOL_NAME (p), class_names); 1616 /* TODO: more locations to be fixed up... */ 1617 loc = UNKNOWN_LOCATION; 1618 refs_type = 1619 build_pointer_type (build_pointer_type (objc_protocol_template)); 1620 if (refs_decl) 1621 refs_expr = convert (refs_type, 1622 build_unary_op (loc, ADDR_EXPR, refs_decl, 0)); 1623 else 1624 refs_expr = convert (refs_type, null_pointer_node); 1625 1626 if (flag_objc_abi < 1) 1627 { 1628 /* Original ABI. */ 1629 initlist = 1630 build_protocol_initializer (TREE_TYPE (decl), 1631 protocol_name_expr, refs_expr, 1632 UOBJC_INSTANCE_METHODS_decl, 1633 UOBJC_CLASS_METHODS_decl); 1634 finish_var_decl (decl, initlist); 1635 continue; 1636 } 1637 1638 /* else - V1 extensions. */ 1639 1640 V1_Property_decl = 1641 generate_v1_property_table (p, NULL_TREE); 1642 1643 V1_ProtocolExt_decl = 1644 generate_v1_objc_protocol_extension (p, 1645 V1_Protocol_OPT_NST_METHODS_decl, 1646 V1_Protocol_OPT_CLS_METHODS_decl, 1647 V1_Property_decl); 1648 1649 initlist = build_v1_protocol_initializer (TREE_TYPE (decl), 1650 protocol_name_expr, refs_expr, 1651 UOBJC_INSTANCE_METHODS_decl, 1652 UOBJC_CLASS_METHODS_decl, 1653 V1_ProtocolExt_decl); 1654 finish_var_decl (decl, initlist); 1655 } 1656 } 1657 1658 static tree 1659 generate_dispatch_table (tree chain, const char *name, tree attr) 1660 { 1661 tree decl, method_list_template, initlist; 1662 vec<constructor_elt, va_gc> *v = NULL; 1663 int size;; 1664 1665 if (!chain || !name || !(size = list_length (chain))) 1666 return NULL_TREE; 1667 1668 if (!objc_method_template) 1669 objc_method_template = build_method_template (); 1670 1671 method_list_template = build_method_list_template (objc_method_template, 1672 size); 1673 initlist = build_dispatch_table_initializer (objc_method_template, chain); 1674 1675 decl = start_var_decl (method_list_template, name); 1676 1677 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, integer_zero_node); 1678 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 1679 build_int_cst (integer_type_node, size)); 1680 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, initlist); 1681 1682 OBJCMETA (decl, objc_meta, attr); 1683 finish_var_decl (decl, 1684 objc_build_constructor (TREE_TYPE (decl), v)); 1685 1686 return decl; 1687 } 1688 1689 /* Init a category. */ 1690 static tree 1691 build_v1_category_initializer (tree type, tree cat_name, tree class_name, 1692 tree inst_methods, tree class_methods, 1693 tree protocol_list, tree property_list, 1694 location_t loc) 1695 { 1696 tree expr, ltyp; 1697 vec<constructor_elt, va_gc> *v = NULL; 1698 1699 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, cat_name); 1700 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, class_name); 1701 1702 ltyp = objc_method_list_ptr; 1703 if (inst_methods) 1704 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, inst_methods, 0)); 1705 else 1706 expr = convert (ltyp, null_pointer_node); 1707 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1708 1709 if (class_methods) 1710 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_methods, 0)); 1711 else 1712 expr = convert (ltyp, null_pointer_node); 1713 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1714 1715 /* protocol_list = */ 1716 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template)); 1717 if (protocol_list) 1718 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0)); 1719 else 1720 expr = convert (ltyp, null_pointer_node); 1721 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1722 1723 if (flag_objc_abi >= 1) 1724 { 1725 int val = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_category_template)); 1726 expr = build_int_cst (NULL_TREE, val); 1727 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1728 ltyp = objc_prop_list_ptr; 1729 if (property_list) 1730 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); 1731 else 1732 expr = convert (ltyp, null_pointer_node); 1733 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1734 } 1735 1736 return objc_build_constructor (type, v); 1737 } 1738 1739 /* static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */ 1740 /* TODO: get rid of passing stuff around in globals. */ 1741 static void 1742 generate_v1_category (struct imp_entry *impent) 1743 { 1744 tree initlist, cat_name_expr, class_name_expr; 1745 tree protocol_decl, category, cat_decl; 1746 tree inst_methods = NULL_TREE, class_methods = NULL_TREE; 1747 tree cat = impent->imp_context; 1748 location_t loc; 1749 char buf[BUFSIZE]; 1750 1751 cat_decl = impent->class_decl; 1752 loc = DECL_SOURCE_LOCATION (cat_decl); 1753 1754 add_class_reference (CLASS_NAME (cat)); 1755 cat_name_expr = add_objc_string (CLASS_SUPER_NAME (cat), class_names); 1756 class_name_expr = add_objc_string (CLASS_NAME (cat), class_names); 1757 1758 category = lookup_category (impent->imp_template, CLASS_SUPER_NAME (cat)); 1759 1760 if (category && CLASS_PROTOCOL_LIST (category)) 1761 { 1762 generate_protocol_references (CLASS_PROTOCOL_LIST (category)); 1763 protocol_decl = generate_v1_protocol_list (category, cat); 1764 } 1765 else 1766 protocol_decl = 0; 1767 1768 if (flag_objc_abi >= 1) 1769 V1_Property_decl = generate_v1_property_table (NULL_TREE, cat); 1770 else 1771 V1_Property_decl = NULL_TREE; 1772 1773 if (CLASS_NST_METHODS (cat)) 1774 { 1775 snprintf (buf, BUFSIZE, "_OBJC_CategoryInstanceMethods_%s_%s", 1776 IDENTIFIER_POINTER (CLASS_NAME (cat)), 1777 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))); 1778 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (cat), buf, 1779 meta_cati_meth); 1780 } 1781 1782 if (CLASS_CLS_METHODS (cat)) 1783 { 1784 snprintf (buf, BUFSIZE, "_OBJC_CategoryClassMethods_%s_%s", 1785 IDENTIFIER_POINTER (CLASS_NAME (cat)), 1786 IDENTIFIER_POINTER (CLASS_SUPER_NAME (cat))); 1787 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (cat), buf, 1788 meta_catc_meth); 1789 } 1790 1791 initlist = build_v1_category_initializer (TREE_TYPE (cat_decl), 1792 cat_name_expr, class_name_expr, 1793 inst_methods, class_methods, 1794 protocol_decl, V1_Property_decl, 1795 loc); 1796 1797 finish_var_decl (cat_decl, initlist); 1798 impent->class_decl = cat_decl; 1799 } 1800 1801 /* This routine builds the class extension used by v1 NeXT. */ 1802 1803 static tree 1804 generate_objc_class_ext (tree property_list, tree context) 1805 { 1806 tree decl, expr, ltyp; 1807 tree weak_ivar_layout_tree; 1808 int size; 1809 location_t loc; 1810 vec<constructor_elt, va_gc> *v = NULL; 1811 char buf[BUFSIZE]; 1812 1813 /* TODO: pass the loc in or find it from args. */ 1814 loc = UNKNOWN_LOCATION; 1815 1816 /* const char *weak_ivar_layout 1817 TODO: Figure the ivar layouts out... */ 1818 weak_ivar_layout_tree = NULL_TREE; 1819 1820 if (!property_list && !weak_ivar_layout_tree) 1821 return NULL_TREE; 1822 1823 if (!objc_class_ext_template) 1824 build_objc_class_ext_template (); 1825 1826 /* uint32_t size */ 1827 size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (objc_class_ext_template)); 1828 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, size)); 1829 1830 ltyp = const_string_type_node; 1831 if (weak_ivar_layout_tree) 1832 expr = convert (ltyp, weak_ivar_layout_tree); 1833 else 1834 expr = convert (ltyp, null_pointer_node); 1835 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1836 1837 /* struct _prop_list_t *properties; */ 1838 ltyp = objc_prop_list_ptr; 1839 if (property_list) 1840 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, property_list, 0)); 1841 else 1842 expr = convert (ltyp, null_pointer_node); 1843 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1844 1845 snprintf (buf, BUFSIZE, "_OBJC_ClassExt_%s", 1846 IDENTIFIER_POINTER (CLASS_NAME (context))); 1847 decl = start_var_decl (objc_class_ext_template, buf); 1848 expr = objc_build_constructor (TREE_TYPE (decl), v); 1849 OBJCMETA (decl, objc_meta, meta_class_extension); 1850 finish_var_decl (decl, expr); 1851 return decl; 1852 } 1853 1854 /* struct _objc_class { 1855 struct objc_class *isa; 1856 struct objc_class *super_class; 1857 char *name; 1858 long version; 1859 long info; 1860 long instance_size; 1861 struct objc_ivar_list *ivars; 1862 struct objc_method_list *methods; 1863 struct objc_cache *cache; 1864 struct objc_protocol_list *protocols; 1865 #if ABI >= 1 1866 const char *ivar_layout; 1867 struct _objc_class_ext *ext; 1868 #else 1869 void *sel_id; 1870 void *gc_object_type; 1871 #endif 1872 }; */ 1873 1874 static tree 1875 build_v1_shared_structure_initializer (tree type, tree isa, tree super, 1876 tree name, tree size, int status, 1877 tree dispatch_table, tree ivar_list, 1878 tree protocol_list, tree class_ext) 1879 { 1880 tree expr, ltyp; 1881 location_t loc; 1882 vec<constructor_elt, va_gc> *v = NULL; 1883 1884 /* TODO: fish the location out of the input data. */ 1885 loc = UNKNOWN_LOCATION; 1886 1887 /* isa = */ 1888 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, isa); 1889 1890 /* super_class = */ 1891 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, super); 1892 1893 /* name = */ 1894 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, default_conversion (name)); 1895 1896 /* version = */ 1897 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 1898 build_int_cst (long_integer_type_node, 0)); 1899 1900 /* info = */ 1901 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 1902 build_int_cst (long_integer_type_node, status)); 1903 1904 /* instance_size = */ 1905 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 1906 convert (long_integer_type_node, size)); 1907 1908 /* objc_ivar_list = */ 1909 ltyp = objc_ivar_list_ptr; 1910 if (ivar_list) 1911 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, ivar_list, 0)); 1912 else 1913 expr = convert (ltyp, null_pointer_node); 1914 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1915 1916 /* objc_method_list = */ 1917 ltyp = objc_method_list_ptr; 1918 if (dispatch_table) 1919 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, dispatch_table, 0)); 1920 else 1921 expr = convert (ltyp, null_pointer_node); 1922 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1923 1924 ltyp = build_pointer_type (xref_tag (RECORD_TYPE, 1925 get_identifier ("objc_cache"))); 1926 /* method_cache = */ 1927 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, convert (ltyp, null_pointer_node)); 1928 1929 /* protocol_list = */ 1930 ltyp = build_pointer_type (build_pointer_type (objc_protocol_template)); 1931 if (protocol_list) 1932 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, protocol_list, 0)); 1933 else 1934 expr = convert (ltyp, null_pointer_node); 1935 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1936 1937 if (flag_objc_abi >= 1) 1938 { 1939 /* TODO: figure out the ivar_layout stuff. */ 1940 expr = convert (const_string_type_node, null_pointer_node); 1941 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1942 if (!objc_class_ext_template) 1943 build_objc_class_ext_template (); 1944 ltyp = build_pointer_type (objc_class_ext_template); 1945 if (class_ext) 1946 expr = convert (ltyp, build_unary_op (loc, ADDR_EXPR, class_ext, 0)); 1947 else 1948 expr = convert (ltyp, null_pointer_node); 1949 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 1950 } 1951 else 1952 { 1953 /* sel_id = NULL */ 1954 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node); 1955 1956 /* gc_object_type = NULL */ 1957 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, null_pointer_node); 1958 } 1959 return objc_build_constructor (type, v); 1960 } 1961 1962 static tree 1963 generate_ivars_list (tree chain, const char *name, tree attr) 1964 { 1965 tree initlist, ivar_list_template, decl; 1966 int size; 1967 vec<constructor_elt, va_gc> *inits = NULL; 1968 1969 if (!chain) 1970 return NULL_TREE; 1971 1972 if (!objc_ivar_template) 1973 objc_ivar_template = build_ivar_template (); 1974 1975 size = ivar_list_length (chain); 1976 1977 generating_instance_variables = 1; 1978 ivar_list_template = build_ivar_list_template (objc_ivar_template, size); 1979 initlist = build_ivar_list_initializer (objc_ivar_template, chain); 1980 generating_instance_variables = 0; 1981 1982 decl = start_var_decl (ivar_list_template, name); 1983 1984 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, build_int_cst (NULL_TREE, size)); 1985 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, initlist); 1986 1987 OBJCMETA (decl, objc_meta, attr); 1988 finish_var_decl (decl, 1989 objc_build_constructor (TREE_TYPE (decl), inits)); 1990 1991 return decl; 1992 } 1993 1994 /* static struct objc_class _OBJC_METACLASS_Foo={ ... }; 1995 static struct objc_class _OBJC_CLASS_Foo={ ... }; */ 1996 1997 static void 1998 generate_v1_class_structs (struct imp_entry *impent) 1999 { 2000 tree name_expr, super_expr, root_expr, class_decl, meta_decl; 2001 tree my_root_id, my_super_id; 2002 tree cast_type, initlist, protocol_decl; 2003 tree class_ext_decl = NULL_TREE, props = NULL_TREE; 2004 tree inst_methods = NULL_TREE, class_methods = NULL_TREE; 2005 tree chain, inst_ivars = NULL_TREE, class_ivars = NULL_TREE; 2006 int cls_flags; 2007 location_t loc; 2008 char buf[BUFSIZE]; 2009 2010 /* objc_implementation_context = impent->imp_context; 2011 implementation_template = impent->imp_template;*/ 2012 class_decl = impent->class_decl; 2013 meta_decl = impent->meta_decl; 2014 cls_flags = impent->has_cxx_cdtors ? CLS_HAS_CXX_STRUCTORS : 0 ; 2015 2016 loc = DECL_SOURCE_LOCATION (impent->class_decl); 2017 2018 if (flag_objc_abi >= 1) 2019 { 2020 /* ABI=1 additions. */ 2021 props = generate_v1_property_table (NULL_TREE, impent->imp_context); 2022 class_ext_decl = generate_objc_class_ext (props, impent->imp_context); 2023 } 2024 2025 my_super_id = CLASS_SUPER_NAME (impent->imp_template); 2026 if (my_super_id) 2027 { 2028 add_class_reference (my_super_id); 2029 2030 /* Compute "my_root_id" - this is required for code generation. 2031 the "isa" for all meta class structures points to the root of 2032 the inheritance hierarchy (e.g. "__Object")... */ 2033 my_root_id = my_super_id; 2034 do 2035 { 2036 tree my_root_int = lookup_interface (my_root_id); 2037 2038 if (my_root_int && CLASS_SUPER_NAME (my_root_int)) 2039 my_root_id = CLASS_SUPER_NAME (my_root_int); 2040 else 2041 break; 2042 } 2043 while (1); 2044 super_expr = add_objc_string (my_super_id, class_names); 2045 } 2046 else 2047 { 2048 /* No super class. */ 2049 my_root_id = CLASS_NAME (impent->imp_template); 2050 super_expr = null_pointer_node; 2051 } 2052 2053 /* Install class `isa' and `super' pointers at runtime. */ 2054 cast_type = build_pointer_type (objc_class_template); 2055 super_expr = build_c_cast (loc, cast_type, super_expr); 2056 2057 root_expr = add_objc_string (my_root_id, class_names); 2058 root_expr = build_c_cast (loc, cast_type, root_expr); 2059 2060 if (CLASS_PROTOCOL_LIST (impent->imp_template)) 2061 { 2062 generate_protocol_references (CLASS_PROTOCOL_LIST (impent->imp_template)); 2063 protocol_decl = generate_v1_protocol_list (impent->imp_template, 2064 impent->imp_context); 2065 } 2066 else 2067 protocol_decl = NULL_TREE; 2068 2069 if (CLASS_CLS_METHODS (impent->imp_context)) 2070 { 2071 snprintf (buf, BUFSIZE, "_OBJC_ClassMethods_%s", 2072 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 2073 class_methods = generate_dispatch_table (CLASS_CLS_METHODS (impent->imp_context), 2074 buf, meta_clac_meth); 2075 } 2076 2077 if (CLASS_SUPER_NAME (impent->imp_template) == NULL_TREE 2078 && (chain = TYPE_FIELDS (objc_class_template))) 2079 { 2080 snprintf (buf, BUFSIZE, "_OBJC_ClassIvars_%s", 2081 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 2082 class_ivars = generate_ivars_list (chain, buf, meta_clac_vars); 2083 } 2084 /* TODO: get rid of hidden passing of stuff in globals. */ 2085 /* UOBJC_INSTANCE/CLASS_Variables_decl made in generate_ivarlists(). */ 2086 2087 name_expr = add_objc_string (CLASS_NAME (impent->imp_template), class_names); 2088 2089 /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ 2090 2091 initlist = build_v1_shared_structure_initializer 2092 (TREE_TYPE (meta_decl), 2093 root_expr, super_expr, name_expr, 2094 convert (integer_type_node, TYPE_SIZE_UNIT (objc_class_template)), 2095 CLS_META, class_methods, class_ivars, 2096 protocol_decl, NULL_TREE); 2097 2098 finish_var_decl (meta_decl, initlist); 2099 impent->meta_decl = meta_decl; 2100 2101 /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ 2102 if (CLASS_NST_METHODS (impent->imp_context)) 2103 { 2104 snprintf (buf, BUFSIZE, "_OBJC_InstanceMethods_%s", 2105 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 2106 inst_methods = generate_dispatch_table (CLASS_NST_METHODS (impent->imp_context), 2107 buf, meta_clai_meth); 2108 } 2109 2110 if ((chain = CLASS_IVARS (impent->imp_template))) 2111 { 2112 snprintf (buf, BUFSIZE, "_OBJC_InstanceIvars_%s", 2113 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 2114 inst_ivars = generate_ivars_list (chain, buf, meta_clai_vars); 2115 } 2116 2117 initlist = build_v1_shared_structure_initializer 2118 (TREE_TYPE (class_decl), 2119 build_unary_op (loc, ADDR_EXPR, meta_decl, 0), 2120 super_expr, name_expr, 2121 convert (integer_type_node, 2122 TYPE_SIZE_UNIT (CLASS_STATIC_TEMPLATE (impent->imp_template))), 2123 CLS_FACTORY | cls_flags, inst_methods, inst_ivars, 2124 protocol_decl, class_ext_decl); 2125 2126 finish_var_decl (class_decl, initlist); 2127 impent->class_decl = class_decl; 2128 } 2129 2130 /* --- Output NeXT V1 Metadata --- */ 2131 2132 /* Create the initial value for the `defs' field of _objc_symtab. 2133 This is a CONSTRUCTOR. */ 2134 2135 static tree 2136 init_def_list (tree type) 2137 { 2138 tree expr; 2139 location_t loc; 2140 struct imp_entry *impent; 2141 vec<constructor_elt, va_gc> *v = NULL; 2142 2143 if (imp_count) 2144 for (impent = imp_list; impent; impent = impent->next) 2145 { 2146 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) 2147 { 2148 loc = DECL_SOURCE_LOCATION (impent->class_decl); 2149 expr = build_unary_op (loc, 2150 ADDR_EXPR, impent->class_decl, 0); 2151 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2152 } 2153 } 2154 2155 if (cat_count) 2156 for (impent = imp_list; impent; impent = impent->next) 2157 { 2158 if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) 2159 { 2160 loc = DECL_SOURCE_LOCATION (impent->class_decl); 2161 expr = build_unary_op (loc, 2162 ADDR_EXPR, impent->class_decl, 0); 2163 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, expr); 2164 } 2165 } 2166 2167 return objc_build_constructor (type, v); 2168 } 2169 2170 /* Take care of defining and initializing _OBJC_SYMBOLS. */ 2171 2172 /* Predefine the following data type: 2173 2174 struct _objc_symtab 2175 { 2176 long sel_ref_cnt; 2177 SEL *refs; 2178 short cls_def_cnt; 2179 short cat_def_cnt; 2180 void *defs[cls_def_cnt + cat_def_cnt]; 2181 }; */ 2182 2183 static void 2184 build_objc_symtab_template (void) 2185 { 2186 tree fields, *chain = NULL; 2187 2188 objc_symtab_template = objc_start_struct (get_identifier (UTAG_SYMTAB)); 2189 2190 /* long sel_ref_cnt; */ 2191 fields = add_field_decl (long_integer_type_node, "sel_ref_cnt", &chain); 2192 2193 /* SEL *refs; */ 2194 add_field_decl (build_pointer_type (objc_selector_type), "refs", &chain); 2195 2196 /* short cls_def_cnt; */ 2197 add_field_decl (short_integer_type_node, "cls_def_cnt", &chain); 2198 2199 /* short cat_def_cnt; */ 2200 add_field_decl (short_integer_type_node, "cat_def_cnt", &chain); 2201 2202 if (imp_count || cat_count) 2203 { 2204 /* void *defs[imp_count + cat_count (+ 1)]; */ 2205 /* NB: The index is one less than the size of the array. */ 2206 int index = imp_count + cat_count; 2207 tree array_type = build_sized_array_type (ptr_type_node, index); 2208 add_field_decl (array_type, "defs", &chain); 2209 } 2210 2211 objc_finish_struct (objc_symtab_template, fields); 2212 } 2213 /* Construct the initial value for all of _objc_symtab. */ 2214 2215 static tree 2216 init_objc_symtab (tree type) 2217 { 2218 vec<constructor_elt, va_gc> *v = NULL; 2219 2220 /* sel_ref_cnt = { ..., 5, ... } */ 2221 2222 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2223 build_int_cst (long_integer_type_node, 0)); 2224 2225 /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ 2226 2227 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2228 convert (build_pointer_type (objc_selector_type), 2229 integer_zero_node)); 2230 2231 /* cls_def_cnt = { ..., 5, ... } */ 2232 2233 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2234 build_int_cst (short_integer_type_node, imp_count)); 2235 2236 /* cat_def_cnt = { ..., 5, ... } */ 2237 2238 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, 2239 build_int_cst (short_integer_type_node, cat_count)); 2240 2241 /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ 2242 2243 if (imp_count || cat_count) 2244 { 2245 tree field = TYPE_FIELDS (type); 2246 field = DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (DECL_CHAIN (field)))); 2247 2248 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_def_list (TREE_TYPE (field))); 2249 } 2250 2251 return objc_build_constructor (type, v); 2252 } 2253 2254 /* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab' 2255 and initialized appropriately. */ 2256 2257 static void 2258 generate_objc_symtab_decl (void) 2259 { 2260 build_objc_symtab_template (); 2261 UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_Symbols"); 2262 /* Allow the runtime to mark meta-data such that it can be assigned to target 2263 specific sections by the back-end. */ 2264 OBJCMETA (UOBJC_SYMBOLS_decl, objc_meta, meta_symtab); 2265 finish_var_decl (UOBJC_SYMBOLS_decl, 2266 init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl))); 2267 } 2268 2269 /* Any target implementing NeXT ObjC m32 ABI has to ensure that objects 2270 refer to, and define, symbols that enforce linkage of classes into the 2271 executable image, preserving unix archive semantics. 2272 2273 At present (4.8), the only targets implementing this are Darwin; these 2274 use top level asms to implement a scheme (see config/darwin-c.c). The 2275 latter method is a hack, but compatible with LTO see also PR48109 for 2276 further discussion and other possible methods. */ 2277 2278 static void 2279 handle_next_class_ref (tree chain ATTRIBUTE_UNUSED) 2280 { 2281 if (targetcm.objc_declare_unresolved_class_reference) 2282 { 2283 const char *name = IDENTIFIER_POINTER (TREE_VALUE (chain)); 2284 char *string = (char *) alloca (strlen (name) + 30); 2285 sprintf (string, ".objc_class_name_%s", name); 2286 targetcm.objc_declare_unresolved_class_reference (string); 2287 } 2288 } 2289 2290 static void 2291 handle_next_impent (struct imp_entry *impent ATTRIBUTE_UNUSED) 2292 { 2293 if (targetcm.objc_declare_class_definition) 2294 { 2295 char buf[BUFSIZE]; 2296 2297 switch (TREE_CODE (impent->imp_context)) 2298 { 2299 case CLASS_IMPLEMENTATION_TYPE: 2300 snprintf (buf, BUFSIZE, ".objc_class_name_%s", 2301 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))); 2302 break; 2303 case CATEGORY_IMPLEMENTATION_TYPE: 2304 snprintf (buf, BUFSIZE, "*.objc_category_name_%s_%s", 2305 IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)), 2306 IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context))); 2307 break; 2308 default: 2309 return; 2310 } 2311 targetcm.objc_declare_class_definition (buf); 2312 } 2313 } 2314 2315 static void 2316 generate_classref_translation_entry (tree chain) 2317 { 2318 tree expr, decl, type; 2319 2320 decl = TREE_PURPOSE (chain); 2321 type = TREE_TYPE (decl); 2322 2323 expr = add_objc_string (TREE_VALUE (chain), class_names); 2324 expr = convert (type, expr); /* cast! */ 2325 2326 /* This is a class reference. It is re-written by the runtime, 2327 but will be optimized away unless we force it. */ 2328 DECL_PRESERVE_P (decl) = 1; 2329 OBJCMETA (decl, objc_meta, meta_class_reference); 2330 finish_var_decl (decl, expr); 2331 return; 2332 } 2333 2334 static void 2335 objc_generate_v1_next_metadata (void) 2336 { 2337 struct imp_entry *impent; 2338 tree chain, attr; 2339 long vers; 2340 2341 /* FIXME: Make sure that we generate no metadata if there is nothing 2342 to put into it. */ 2343 2344 if (objc_static_instances) 2345 gcc_unreachable (); /* Not for NeXT */ 2346 2347 build_metadata_templates (); 2348 objc_implementation_context = 2349 implementation_template = 2350 UOBJC_CLASS_decl = 2351 UOBJC_METACLASS_decl = NULL_TREE; 2352 2353 for (impent = imp_list; impent; impent = impent->next) 2354 { 2355 2356 /* If -gen-decls is present, Dump the @interface of each class. 2357 TODO: Dump the classes in the order they were found, rather than in 2358 reverse order as we are doing now. */ 2359 if (flag_gen_declaration) 2360 dump_interface (gen_declaration_file, impent->imp_context); 2361 2362 /* all of the following reference the string pool... */ 2363 if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) 2364 generate_v1_class_structs (impent); 2365 else 2366 generate_v1_category (impent); 2367 } 2368 2369 /* If we are using an array of selectors, we must always 2370 finish up the array decl even if no selectors were used. */ 2371 build_next_selector_translation_table (); 2372 2373 if (protocol_chain) 2374 generate_v1_protocols (); 2375 2376 /* Pass summary information to the runtime. */ 2377 if (imp_count || cat_count) 2378 generate_objc_symtab_decl (); 2379 2380 vers = OBJC_VERSION; 2381 attr = build_tree_list (objc_meta, meta_modules); 2382 build_module_descriptor (vers, attr); 2383 2384 /* Dump the class references. This forces the appropriate classes 2385 to be linked into the executable image, preserving unix archive 2386 semantics. */ 2387 for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain)) 2388 { 2389 handle_next_class_ref (chain); 2390 if (TREE_PURPOSE (chain)) 2391 generate_classref_translation_entry (chain); 2392 } 2393 2394 for (impent = imp_list; impent; impent = impent->next) 2395 handle_next_impent (impent); 2396 2397 /* Emit the strings tables. */ 2398 generate_strings (); 2399 } 2400 2401 /* --- exceptions stuff --- */ 2402 2403 /* Predefine the following data type: 2404 2405 struct _objc_exception_data 2406 { 2407 int buf[OBJC_JBLEN]; 2408 void *pointers[4]; 2409 }; */ 2410 2411 /* The following yuckiness should prevent users from having to #include 2412 <setjmp.h> in their code... */ 2413 2414 /* Define to a harmless positive value so the below code doesn't die. */ 2415 #ifndef OBJC_JBLEN 2416 #define OBJC_JBLEN 18 2417 #endif 2418 2419 static void 2420 build_next_objc_exception_stuff (void) 2421 { 2422 tree decls, temp_type, *chain = NULL; 2423 2424 objc_exception_data_template 2425 = objc_start_struct (get_identifier (UTAG_EXCDATA)); 2426 2427 /* int buf[OBJC_JBLEN]; */ 2428 2429 temp_type = build_sized_array_type (integer_type_node, OBJC_JBLEN); 2430 decls = add_field_decl (temp_type, "buf", &chain); 2431 2432 /* void *pointers[4]; */ 2433 2434 temp_type = build_sized_array_type (ptr_type_node, 4); 2435 add_field_decl (temp_type, "pointers", &chain); 2436 2437 objc_finish_struct (objc_exception_data_template, decls); 2438 2439 /* int _setjmp(...); */ 2440 /* If the user includes <setjmp.h>, this shall be superseded by 2441 'int _setjmp(jmp_buf);' */ 2442 temp_type = build_varargs_function_type_list (integer_type_node, NULL_TREE); 2443 objc_setjmp_decl 2444 = add_builtin_function (TAG_SETJMP, temp_type, 0, NOT_BUILT_IN, NULL, NULL_TREE); 2445 2446 /* id objc_exception_extract(struct _objc_exception_data *); */ 2447 temp_type 2448 = build_function_type_list (objc_object_type, 2449 build_pointer_type (objc_exception_data_template), 2450 NULL_TREE); 2451 objc_exception_extract_decl 2452 = add_builtin_function (TAG_EXCEPTIONEXTRACT, temp_type, 0, NOT_BUILT_IN, NULL, 2453 NULL_TREE); 2454 /* void objc_exception_try_enter(struct _objc_exception_data *); */ 2455 /* void objc_exception_try_exit(struct _objc_exception_data *); */ 2456 temp_type 2457 = build_function_type_list (void_type_node, 2458 build_pointer_type (objc_exception_data_template), 2459 NULL_TREE); 2460 objc_exception_try_enter_decl 2461 = add_builtin_function (TAG_EXCEPTIONTRYENTER, temp_type, 0, NOT_BUILT_IN, NULL, 2462 NULL_TREE); 2463 objc_exception_try_exit_decl 2464 = add_builtin_function (TAG_EXCEPTIONTRYEXIT, temp_type, 0, NOT_BUILT_IN, NULL, 2465 NULL_TREE); 2466 2467 /* int objc_exception_match(id, id); */ 2468 temp_type 2469 = build_function_type_list (integer_type_node, 2470 objc_object_type, objc_object_type, NULL_TREE); 2471 objc_exception_match_decl 2472 = add_builtin_function (TAG_EXCEPTIONMATCH, temp_type, 0, NOT_BUILT_IN, NULL, 2473 NULL_TREE); 2474 2475 /* id objc_assign_ivar (id, id, unsigned int); */ 2476 /* id objc_assign_ivar_Fast (id, id, unsigned int) 2477 __attribute__ ((hard_coded_address (OFFS_ASSIGNIVAR_FAST))); */ 2478 temp_type 2479 = build_function_type_list (objc_object_type, 2480 objc_object_type, 2481 objc_object_type, 2482 unsigned_type_node, 2483 NULL_TREE); 2484 objc_assign_ivar_decl 2485 = add_builtin_function (TAG_ASSIGNIVAR, temp_type, 0, NOT_BUILT_IN, 2486 NULL, NULL_TREE); 2487 #ifdef OFFS_ASSIGNIVAR_FAST 2488 objc_assign_ivar_fast_decl 2489 = add_builtin_function (TAG_ASSIGNIVAR_FAST, temp_type, 0, 2490 NOT_BUILT_IN, NULL, NULL_TREE); 2491 DECL_ATTRIBUTES (objc_assign_ivar_fast_decl) 2492 = tree_cons (get_identifier ("hard_coded_address"), 2493 build_int_cst (NULL_TREE, OFFS_ASSIGNIVAR_FAST), 2494 NULL_TREE); 2495 #else 2496 /* Default to slower ivar method. */ 2497 objc_assign_ivar_fast_decl = objc_assign_ivar_decl; 2498 #endif 2499 2500 /* id objc_assign_global (id, id *); */ 2501 /* id objc_assign_strongCast (id, id *); */ 2502 temp_type = build_function_type_list (objc_object_type, 2503 objc_object_type, 2504 build_pointer_type (objc_object_type), 2505 NULL_TREE); 2506 objc_assign_global_decl 2507 = add_builtin_function (TAG_ASSIGNGLOBAL, temp_type, 0, NOT_BUILT_IN, NULL, 2508 NULL_TREE); 2509 objc_assign_strong_cast_decl 2510 = add_builtin_function (TAG_ASSIGNSTRONGCAST, temp_type, 0, NOT_BUILT_IN, NULL, 2511 NULL_TREE); 2512 } 2513 2514 /* --- NeXT V1 SJLJ Exceptions --- */ 2515 2516 /* Build "objc_exception_try_exit(&_stack)". */ 2517 2518 static tree 2519 next_sjlj_build_try_exit (struct objc_try_context **ctcp) 2520 { 2521 tree t; 2522 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); 2523 t = tree_cons (NULL, t, NULL); 2524 t = build_function_call (input_location, 2525 objc_exception_try_exit_decl, t); 2526 return t; 2527 } 2528 2529 /* Build 2530 objc_exception_try_enter (&_stack); 2531 if (_setjmp(&_stack.buf)) 2532 ; 2533 else 2534 ; 2535 Return the COND_EXPR. Note that the THEN and ELSE fields are left 2536 empty, ready for the caller to fill them in. */ 2537 2538 static tree 2539 next_sjlj_build_enter_and_setjmp (struct objc_try_context **ctcp) 2540 { 2541 tree t, enter, sj, cond; 2542 2543 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); 2544 t = tree_cons (NULL, t, NULL); 2545 enter = build_function_call (input_location, 2546 objc_exception_try_enter_decl, t); 2547 2548 t = objc_build_component_ref ((*ctcp)->stack_decl, 2549 get_identifier ("buf")); 2550 t = build_fold_addr_expr_loc (input_location, t); 2551 #ifdef OBJCPLUS 2552 /* Convert _setjmp argument to type that is expected. */ 2553 if (prototype_p (TREE_TYPE (objc_setjmp_decl))) 2554 t = convert (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (objc_setjmp_decl))), t); 2555 else 2556 t = convert (ptr_type_node, t); 2557 #else 2558 t = convert (ptr_type_node, t); 2559 #endif 2560 t = tree_cons (NULL, t, NULL); 2561 sj = build_function_call (input_location, 2562 objc_setjmp_decl, t); 2563 2564 cond = build2 (COMPOUND_EXPR, TREE_TYPE (sj), enter, sj); 2565 cond = c_common_truthvalue_conversion (input_location, cond); 2566 2567 return build3 (COND_EXPR, void_type_node, cond, NULL, NULL); 2568 } 2569 2570 /* Build: 2571 2572 DECL = objc_exception_extract(&_stack); */ 2573 2574 static tree 2575 next_sjlj_build_exc_extract (struct objc_try_context **ctcp, tree decl) 2576 { 2577 tree t; 2578 2579 t = build_fold_addr_expr_loc (input_location, (*ctcp)->stack_decl); 2580 t = tree_cons (NULL, t, NULL); 2581 t = build_function_call (input_location, 2582 objc_exception_extract_decl, t); 2583 t = convert (TREE_TYPE (decl), t); 2584 t = build2 (MODIFY_EXPR, void_type_node, decl, t); 2585 2586 return t; 2587 } 2588 2589 /* Build 2590 if (objc_exception_match(obj_get_class(TYPE), _caught) 2591 BODY 2592 else if (...) 2593 ... 2594 else 2595 { 2596 _rethrow = _caught; 2597 objc_exception_try_exit(&_stack); 2598 } 2599 from the sequence of CATCH_EXPRs in the current try context. */ 2600 2601 static tree 2602 next_sjlj_build_catch_list (struct objc_try_context **ctcp) 2603 { 2604 tree_stmt_iterator i = tsi_start ((*ctcp)->catch_list); 2605 tree catch_seq, t; 2606 tree *last = &catch_seq; 2607 bool saw_id = false; 2608 2609 for (; !tsi_end_p (i); tsi_next (&i)) 2610 { 2611 tree stmt = tsi_stmt (i); 2612 tree type = CATCH_TYPES (stmt); 2613 tree body = CATCH_BODY (stmt); 2614 2615 if (type != error_mark_node 2616 && objc_is_object_id (TREE_TYPE (type))) 2617 { 2618 *last = body; 2619 saw_id = true; 2620 break; 2621 } 2622 else 2623 { 2624 tree args, cond; 2625 2626 if (type == error_mark_node) 2627 cond = error_mark_node; 2628 else 2629 { 2630 args = tree_cons (NULL, (*ctcp)->caught_decl, NULL); 2631 t = objc_get_class_reference (OBJC_TYPE_NAME (TREE_TYPE (type))); 2632 args = tree_cons (NULL, t, args); 2633 t = build_function_call (input_location, 2634 objc_exception_match_decl, args); 2635 cond = c_common_truthvalue_conversion (input_location, t); 2636 } 2637 t = build3 (COND_EXPR, void_type_node, cond, body, NULL); 2638 SET_EXPR_LOCATION (t, EXPR_LOCATION (stmt)); 2639 2640 *last = t; 2641 last = &COND_EXPR_ELSE (t); 2642 } 2643 } 2644 2645 if (!saw_id) 2646 { 2647 t = build2 (MODIFY_EXPR, void_type_node, (*ctcp)->rethrow_decl, 2648 (*ctcp)->caught_decl); 2649 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus); 2650 append_to_statement_list (t, last); 2651 2652 t = next_sjlj_build_try_exit (ctcp); 2653 SET_EXPR_LOCATION (t, (*ctcp)->end_catch_locus); 2654 append_to_statement_list (t, last); 2655 } 2656 2657 return catch_seq; 2658 } 2659 2660 /* Build a complete @try-@catch-@finally block for legacy Darwin setjmp 2661 exception handling. We aim to build: 2662 2663 { 2664 struct _objc_exception_data _stack; 2665 id _rethrow = 0; 2666 try 2667 { 2668 objc_exception_try_enter (&_stack); 2669 if (_setjmp(&_stack.buf)) 2670 { 2671 id _caught = objc_exception_extract(&_stack); 2672 objc_exception_try_enter (&_stack); 2673 if (_setjmp(&_stack.buf)) 2674 _rethrow = objc_exception_extract(&_stack); 2675 else 2676 CATCH-LIST 2677 } 2678 else 2679 TRY-BLOCK 2680 } 2681 finally 2682 { 2683 if (!_rethrow) 2684 objc_exception_try_exit(&_stack); 2685 FINALLY-BLOCK 2686 if (_rethrow) 2687 objc_exception_throw(_rethrow); 2688 } 2689 } 2690 2691 If CATCH-LIST is empty, we can omit all of the block containing 2692 "_caught" except for the setting of _rethrow. Note the use of 2693 a real TRY_FINALLY_EXPR here, which is not involved in EH per-se, 2694 but handles goto and other exits from the block. */ 2695 2696 static tree 2697 next_sjlj_build_try_catch_finally (struct objc_try_context **ctcp) 2698 { 2699 tree rethrow_decl, stack_decl, t; 2700 tree catch_seq, try_fin, bind; 2701 struct objc_try_context *cur_try_context = *ctcp; 2702 2703 /* Create the declarations involved. */ 2704 t = xref_tag (RECORD_TYPE, get_identifier (UTAG_EXCDATA)); 2705 stack_decl = objc_create_temporary_var (t, NULL); 2706 cur_try_context->stack_decl = stack_decl; 2707 2708 rethrow_decl = objc_create_temporary_var (objc_object_type, NULL); 2709 cur_try_context->rethrow_decl = rethrow_decl; 2710 TREE_CHAIN (rethrow_decl) = stack_decl; 2711 2712 /* Build the outermost variable binding level. */ 2713 bind = build3 (BIND_EXPR, void_type_node, rethrow_decl, NULL, NULL); 2714 SET_EXPR_LOCATION (bind, cur_try_context->try_locus); 2715 TREE_SIDE_EFFECTS (bind) = 1; 2716 2717 /* Initialize rethrow_decl. */ 2718 t = build2 (MODIFY_EXPR, void_type_node, rethrow_decl, 2719 convert (objc_object_type, null_pointer_node)); 2720 SET_EXPR_LOCATION (t, cur_try_context->try_locus); 2721 append_to_statement_list (t, &BIND_EXPR_BODY (bind)); 2722 2723 /* Build the outermost TRY_FINALLY_EXPR. */ 2724 try_fin = build2 (TRY_FINALLY_EXPR, void_type_node, NULL, NULL); 2725 SET_EXPR_LOCATION (try_fin, cur_try_context->try_locus); 2726 TREE_SIDE_EFFECTS (try_fin) = 1; 2727 append_to_statement_list (try_fin, &BIND_EXPR_BODY (bind)); 2728 2729 /* Create the complete catch sequence. */ 2730 if (cur_try_context->catch_list) 2731 { 2732 tree caught_decl = objc_build_exc_ptr (ctcp); 2733 catch_seq = build_stmt (input_location, BIND_EXPR, caught_decl, NULL, NULL); 2734 TREE_SIDE_EFFECTS (catch_seq) = 1; 2735 2736 t = next_sjlj_build_exc_extract (ctcp, caught_decl); 2737 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq)); 2738 2739 t = next_sjlj_build_enter_and_setjmp (ctcp); 2740 COND_EXPR_THEN (t) = next_sjlj_build_exc_extract (ctcp, rethrow_decl); 2741 COND_EXPR_ELSE (t) = next_sjlj_build_catch_list (ctcp); 2742 append_to_statement_list (t, &BIND_EXPR_BODY (catch_seq)); 2743 } 2744 else 2745 catch_seq = next_sjlj_build_exc_extract (ctcp, rethrow_decl); 2746 SET_EXPR_LOCATION (catch_seq, cur_try_context->end_try_locus); 2747 2748 /* Build the main register-and-try if statement. */ 2749 t = next_sjlj_build_enter_and_setjmp (ctcp); 2750 SET_EXPR_LOCATION (t, cur_try_context->try_locus); 2751 COND_EXPR_THEN (t) = catch_seq; 2752 COND_EXPR_ELSE (t) = cur_try_context->try_body; 2753 TREE_OPERAND (try_fin, 0) = t; 2754 2755 /* Build the complete FINALLY statement list. */ 2756 t = next_sjlj_build_try_exit (ctcp); 2757 t = build_stmt (input_location, COND_EXPR, 2758 c_common_truthvalue_conversion 2759 (input_location, rethrow_decl), 2760 NULL, t); 2761 SET_EXPR_LOCATION (t, cur_try_context->finally_locus); 2762 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1)); 2763 2764 append_to_statement_list (cur_try_context->finally_body, 2765 &TREE_OPERAND (try_fin, 1)); 2766 2767 t = tree_cons (NULL, rethrow_decl, NULL); 2768 t = build_function_call (input_location, 2769 objc_exception_throw_decl, t); 2770 t = build_stmt (input_location, COND_EXPR, 2771 c_common_truthvalue_conversion (input_location, 2772 rethrow_decl), 2773 t, NULL); 2774 SET_EXPR_LOCATION (t, cur_try_context->end_finally_locus); 2775 append_to_statement_list (t, &TREE_OPERAND (try_fin, 1)); 2776 2777 return bind; 2778 } 2779 2780 /* We do not expect this to be used at the moment. 2781 If (a) it is possible to implement unwinder exceptions. 2782 (b) we do it... then it might be possibly useful. 2783 */ 2784 static GTY(()) tree objc_eh_personality_decl; 2785 2786 static tree 2787 objc_eh_runtime_type (tree type) 2788 { 2789 tree ident, eh_id, decl, str; 2790 2791 gcc_unreachable (); 2792 if (type == error_mark_node) 2793 { 2794 /* Use 'ErrorMarkNode' as class name when error_mark_node is found 2795 to prevent an ICE. Note that we know that the compiler will 2796 terminate with an error and this 'ErrorMarkNode' class name will 2797 never be actually used. */ 2798 ident = get_identifier ("ErrorMarkNode"); 2799 goto make_err_class; 2800 } 2801 2802 if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type))) 2803 { 2804 ident = get_identifier ("id"); 2805 goto make_err_class; 2806 } 2807 2808 if (!POINTER_TYPE_P (type) || !TYPED_OBJECT (TREE_TYPE (type))) 2809 { 2810 #ifdef OBJCPLUS 2811 /* This routine is also called for c++'s catch clause; in which case, 2812 we use c++'s typeinfo decl. */ 2813 return build_eh_type_type (type); 2814 #else 2815 error ("non-objective-c type '%T' cannot be caught", type); 2816 ident = get_identifier ("ErrorMarkNode"); 2817 goto make_err_class; 2818 #endif 2819 } 2820 else 2821 ident = OBJC_TYPE_NAME (TREE_TYPE (type)); 2822 2823 make_err_class: 2824 /* If this class was already referenced, then it will be output during 2825 meta-data emission, so we don't need to do it here. */ 2826 decl = get_objc_string_decl (ident, class_names); 2827 eh_id = add_objc_string (ident, class_names); 2828 if (!decl) 2829 { 2830 /* Not found ... so we need to build it - from the freshly-entered id. */ 2831 decl = get_objc_string_decl (ident, class_names); 2832 str = my_build_string (IDENTIFIER_LENGTH (ident) + 1, 2833 IDENTIFIER_POINTER (ident)); 2834 /* We have to finalize this var here, because this might be called after 2835 all the other metadata strings have been emitted. */ 2836 finish_var_decl (decl, str); 2837 } 2838 return eh_id; 2839 } 2840 2841 /* For NeXT ABI 0 and 1, the personality routines are just those of the 2842 underlying language. */ 2843 2844 static tree 2845 objc_eh_personality (void) 2846 { 2847 if (!objc_eh_personality_decl) 2848 #ifndef OBJCPLUS 2849 objc_eh_personality_decl = build_personality_function ("gcc"); 2850 #else 2851 objc_eh_personality_decl = build_personality_function ("gxx"); 2852 #endif 2853 return objc_eh_personality_decl; 2854 } 2855 2856 /* --- interfaces --- */ 2857 2858 static tree 2859 build_throw_stmt (location_t loc, tree throw_expr, bool rethrown ATTRIBUTE_UNUSED) 2860 { 2861 tree t; 2862 vec<tree, va_gc> *parms; 2863 vec_alloc (parms, 1); 2864 /* A throw is just a call to the runtime throw function with the 2865 object as a parameter. */ 2866 parms->quick_push (throw_expr); 2867 t = build_function_call_vec (loc, vNULL, objc_exception_throw_decl, parms, 2868 NULL); 2869 vec_free (parms); 2870 return add_stmt (t); 2871 } 2872 2873 /* Build __builtin_eh_pointer, or the moral equivalent. In the case 2874 of Darwin, we'll arrange for it to be initialized (and associated 2875 with a binding) later. */ 2876 2877 static tree 2878 objc_build_exc_ptr (struct objc_try_context **cur_try_context) 2879 { 2880 if (flag_objc_sjlj_exceptions) 2881 { 2882 tree var = (*cur_try_context)->caught_decl; 2883 if (!var) 2884 { 2885 var = objc_create_temporary_var (objc_object_type, NULL); 2886 (*cur_try_context)->caught_decl = var; 2887 } 2888 return var; 2889 } 2890 else 2891 { 2892 tree t; 2893 t = builtin_decl_explicit (BUILT_IN_EH_POINTER); 2894 t = build_call_expr (t, 1, integer_zero_node); 2895 return fold_convert (objc_object_type, t); 2896 } 2897 } 2898 2899 static tree 2900 begin_catch (struct objc_try_context **cur_try_context, tree type, 2901 tree decl, tree compound, bool ellipsis ATTRIBUTE_UNUSED) 2902 { 2903 tree t; 2904 /* Record the data for the catch in the try context so that we can 2905 finalize it later. We treat ellipsis the same way as catching 2906 with 'id xyz'. */ 2907 t = build_stmt (input_location, CATCH_EXPR, type, compound); 2908 (*cur_try_context)->current_catch = t; 2909 2910 /* Initialize the decl from the EXC_PTR_EXPR we get from the runtime. */ 2911 t = objc_build_exc_ptr (cur_try_context); 2912 t = convert (TREE_TYPE (decl), t); 2913 return build2 (MODIFY_EXPR, void_type_node, decl, t); 2914 } 2915 2916 static void 2917 finish_catch (struct objc_try_context **cur_try_context, tree current_catch) 2918 { 2919 append_to_statement_list (current_catch, &((*cur_try_context)->catch_list)); 2920 } 2921 2922 static tree 2923 finish_try_stmt (struct objc_try_context **cur_try_context) 2924 { 2925 tree stmt; 2926 struct objc_try_context *c = *cur_try_context; 2927 /* If we're doing Darwin setjmp exceptions, build the big nasty. */ 2928 if (flag_objc_sjlj_exceptions) 2929 { 2930 bool save = in_late_binary_op; 2931 in_late_binary_op = true; 2932 if (!c->finally_body) 2933 { 2934 c->finally_locus = input_location; 2935 c->end_finally_locus = input_location; 2936 } 2937 stmt = next_sjlj_build_try_catch_finally (cur_try_context); 2938 in_late_binary_op = save; 2939 } 2940 else 2941 /* This doesn't happen at the moment... but maybe one day... */ 2942 { 2943 /* Otherwise, nest the CATCH inside a FINALLY. */ 2944 stmt = c->try_body; 2945 if (c->catch_list) 2946 stmt = build_stmt (c->try_locus, TRY_CATCH_EXPR, stmt, c->catch_list); 2947 if (c->finally_body) 2948 stmt = build_stmt (c->try_locus, TRY_FINALLY_EXPR, stmt, c->finally_body); 2949 } 2950 return stmt; 2951 } 2952 2953 #include "gt-objc-objc-next-runtime-abi-01.h" 2954