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