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