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