190075Sobrien/* Functions for generic Darwin as target machine for GNU C compiler. 2169689Skan Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004, 3169689Skan 2005 490075Sobrien Free Software Foundation, Inc. 590075Sobrien Contributed by Apple Computer Inc. 690075Sobrien 7132718SkanThis file is part of GCC. 890075Sobrien 9132718SkanGCC is free software; you can redistribute it and/or modify 1090075Sobrienit under the terms of the GNU General Public License as published by 1190075Sobrienthe Free Software Foundation; either version 2, or (at your option) 1290075Sobrienany later version. 1390075Sobrien 14132718SkanGCC is distributed in the hope that it will be useful, 1590075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1690075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1790075SobrienGNU General Public License for more details. 1890075Sobrien 1990075SobrienYou should have received a copy of the GNU General Public License 20132718Skanalong with GCC; see the file COPYING. If not, write to 21169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 22169689SkanBoston, MA 02110-1301, USA. */ 2390075Sobrien 2490075Sobrien#include "config.h" 2590075Sobrien#include "system.h" 26132718Skan#include "coretypes.h" 27132718Skan#include "tm.h" 2890075Sobrien#include "rtl.h" 2990075Sobrien#include "regs.h" 3090075Sobrien#include "hard-reg-set.h" 3190075Sobrien#include "real.h" 3290075Sobrien#include "insn-config.h" 3390075Sobrien#include "conditions.h" 3490075Sobrien#include "insn-flags.h" 3590075Sobrien#include "output.h" 3690075Sobrien#include "insn-attr.h" 3790075Sobrien#include "flags.h" 3890075Sobrien#include "tree.h" 3990075Sobrien#include "expr.h" 4090075Sobrien#include "reload.h" 4190075Sobrien#include "function.h" 4290075Sobrien#include "ggc.h" 4390075Sobrien#include "langhooks.h" 44169689Skan#include "target.h" 45117395Skan#include "tm_p.h" 46169689Skan#include "toplev.h" 47169689Skan#include "hashtab.h" 4890075Sobrien 49169689Skan/* Darwin supports a feature called fix-and-continue, which is used 50169689Skan for rapid turn around debugging. When code is compiled with the 51169689Skan -mfix-and-continue flag, two changes are made to the generated code 52169689Skan that allow the system to do things that it would normally not be 53169689Skan able to do easily. These changes allow gdb to load in 54169689Skan recompilation of a translation unit that has been changed into a 55169689Skan running program and replace existing functions and methods of that 56169689Skan translation unit with versions of those functions and methods 57169689Skan from the newly compiled translation unit. The new functions access 58169689Skan the existing static symbols from the old translation unit, if the 59169689Skan symbol existed in the unit to be replaced, and from the new 60169689Skan translation unit, otherwise. 6190075Sobrien 62169689Skan The changes are to insert 5 nops at the beginning of all functions 63169689Skan and to use indirection to get at static symbols. The 5 nops 64169689Skan are required by consumers of the generated code. Currently, gdb 65169689Skan uses this to patch in a jump to the overriding function, this 66169689Skan allows all uses of the old name to forward to the replacement, 67169689Skan including existing function pointers and virtual methods. See 68169689Skan rs6000_emit_prologue for the code that handles the nop insertions. 6990075Sobrien 70169689Skan The added indirection allows gdb to redirect accesses to static 71169689Skan symbols from the newly loaded translation unit to the existing 72169689Skan symbol, if any. @code{static} symbols are special and are handled by 73169689Skan setting the second word in the .non_lazy_symbol_pointer data 74169689Skan structure to symbol. See indirect_data for the code that handles 75169689Skan the extra indirection, and machopic_output_indirection and its use 76169689Skan of MACHO_SYMBOL_STATIC for the code that handles @code{static} 77169689Skan symbol indirection. */ 7890075Sobrien 79169689Skan/* Section names. */ 80169689Skansection * darwin_sections[NUM_DARWIN_SECTIONS]; 8190075Sobrien 82169689Skan/* True if we're setting __attribute__ ((ms_struct)). */ 83169689Skanint darwin_ms_struct = false; 8490075Sobrien 85169689Skan/* A get_unnamed_section callback used to switch to an ObjC section. 86169689Skan DIRECTIVE is as for output_section_asm_op. */ 87169689Skan 88169689Skanstatic void 89169689Skanoutput_objc_section_asm_op (const void *directive) 9090075Sobrien{ 91169689Skan static bool been_here = false; 9290075Sobrien 93169689Skan if (! been_here) 9490075Sobrien { 95169689Skan static const enum darwin_section_enum tomark[] = 9690075Sobrien { 97169689Skan /* written, cold -> hot */ 98169689Skan objc_cat_cls_meth_section, 99169689Skan objc_cat_inst_meth_section, 100169689Skan objc_string_object_section, 101169689Skan objc_constant_string_object_section, 102169689Skan objc_selector_refs_section, 103169689Skan objc_selector_fixup_section, 104169689Skan objc_cls_refs_section, 105169689Skan objc_class_section, 106169689Skan objc_meta_class_section, 107169689Skan /* shared, hot -> cold */ 108169689Skan objc_cls_meth_section, 109169689Skan objc_inst_meth_section, 110169689Skan objc_protocol_section, 111169689Skan objc_class_names_section, 112169689Skan objc_meth_var_types_section, 113169689Skan objc_meth_var_names_section, 114169689Skan objc_category_section, 115169689Skan objc_class_vars_section, 116169689Skan objc_instance_vars_section, 117169689Skan objc_module_info_section, 118169689Skan objc_symbols_section 119169689Skan }; 120169689Skan size_t i; 12190075Sobrien 122169689Skan been_here = true; 123169689Skan for (i = 0; i < ARRAY_SIZE (tomark); i++) 124169689Skan switch_to_section (darwin_sections[tomark[i]]); 125169689Skan } 126169689Skan output_section_asm_op (directive); 127169689Skan} 12890075Sobrien 129169689Skan/* Implement TARGET_ASM_INIT_SECTIONS. */ 13090075Sobrien 131169689Skanvoid 132169689Skandarwin_init_sections (void) 133169689Skan{ 134169689Skan#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC) \ 135169689Skan darwin_sections[NAME] = \ 136169689Skan get_unnamed_section (FLAGS, (OBJC \ 137169689Skan ? output_objc_section_asm_op \ 138169689Skan : output_section_asm_op), \ 139169689Skan "\t" DIRECTIVE); 140169689Skan#include "config/darwin-sections.def" 141169689Skan#undef DEF_SECTION 14290075Sobrien 143169689Skan readonly_data_section = darwin_sections[const_section]; 144169689Skan exception_section = darwin_sections[darwin_exception_section]; 145169689Skan eh_frame_section = darwin_sections[darwin_eh_frame_section]; 146169689Skan} 14790075Sobrien 148169689Skanint 149169689Skanname_needs_quotes (const char *name) 150169689Skan{ 151169689Skan int c; 152169689Skan while ((c = *name++) != '\0') 153169689Skan if (! ISIDNUM (c) && c != '.' && c != '$') 154169689Skan return 1; 155169689Skan return 0; 156169689Skan} 15790075Sobrien 158169689Skan/* Return true if SYM_REF can be used without an indirection. */ 159169689Skanstatic int 160169689Skanmachopic_symbol_defined_p (rtx sym_ref) 161169689Skan{ 162169689Skan if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED) 163169689Skan return true; 16490075Sobrien 165169689Skan /* If a symbol references local and is not an extern to this 166169689Skan file, then the symbol might be able to declared as defined. */ 167169689Skan if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref)) 16890075Sobrien { 169169689Skan /* If the symbol references a variable and the variable is a 170169689Skan common symbol, then this symbol is not defined. */ 171169689Skan if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE) 17290075Sobrien { 173169689Skan tree decl = SYMBOL_REF_DECL (sym_ref); 174169689Skan if (!decl) 175169689Skan return true; 176169689Skan if (DECL_COMMON (decl)) 177169689Skan return false; 17890075Sobrien } 179169689Skan return true; 18090075Sobrien } 181169689Skan return false; 18290075Sobrien} 18390075Sobrien 184169689Skan/* This module assumes that (const (symbol_ref "foo")) is a legal pic 185169689Skan reference, which will not be changed. */ 186132718Skan 18790075Sobrienenum machopic_addr_class 188169689Skanmachopic_classify_symbol (rtx sym_ref) 18990075Sobrien{ 190169689Skan int flags; 191169689Skan bool function_p; 192169689Skan 193169689Skan flags = SYMBOL_REF_FLAGS (sym_ref); 194169689Skan function_p = SYMBOL_REF_FUNCTION_P (sym_ref); 195169689Skan if (machopic_symbol_defined_p (sym_ref)) 196169689Skan return (function_p 197169689Skan ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA); 198169689Skan else 199169689Skan return (function_p 200169689Skan ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA); 20190075Sobrien} 20290075Sobrien 203169689Skan#ifndef TARGET_FIX_AND_CONTINUE 204169689Skan#define TARGET_FIX_AND_CONTINUE 0 205169689Skan#endif 206169689Skan 207169689Skan/* Indicate when fix-and-continue style code generation is being used 208169689Skan and when a reference to data should be indirected so that it can be 209169689Skan rebound in a new translation unit to reference the original instance 210169689Skan of that data. Symbol names that are for code generation local to 211169689Skan the translation unit are bound to the new translation unit; 212169689Skan currently this means symbols that begin with L or _OBJC_; 213169689Skan otherwise, we indicate that an indirect reference should be made to 214169689Skan permit the runtime to rebind new instances of the translation unit 215169689Skan to the original instance of the data. */ 216169689Skan 217169689Skanstatic int 218169689Skanindirect_data (rtx sym_ref) 21990075Sobrien{ 220169689Skan int lprefix; 221169689Skan const char *name; 222169689Skan 223169689Skan /* If we aren't generating fix-and-continue code, don't do anything special. */ 224169689Skan if (TARGET_FIX_AND_CONTINUE == 0) 225169689Skan return 0; 226169689Skan 227169689Skan /* Otherwise, all symbol except symbols that begin with L or _OBJC_ 228169689Skan are indirected. Symbols that begin with L and _OBJC_ are always 229169689Skan bound to the current translation unit as they are used for 230169689Skan generated local data of the translation unit. */ 231169689Skan 232169689Skan name = XSTR (sym_ref, 0); 233169689Skan 234169689Skan lprefix = (((name[0] == '*' || name[0] == '&') 235169689Skan && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L'))) 236169689Skan || (strncmp (name, "_OBJC_", 6) == 0)); 237169689Skan 238169689Skan return ! lprefix; 23990075Sobrien} 24090075Sobrien 241169689Skan 24290075Sobrienstatic int 243169689Skanmachopic_data_defined_p (rtx sym_ref) 24490075Sobrien{ 245169689Skan if (indirect_data (sym_ref)) 246169689Skan return 0; 247169689Skan 248169689Skan switch (machopic_classify_symbol (sym_ref)) 24990075Sobrien { 25090075Sobrien case MACHOPIC_DEFINED_DATA: 251169689Skan case MACHOPIC_DEFINED_FUNCTION: 25290075Sobrien return 1; 25390075Sobrien default: 25490075Sobrien return 0; 25590075Sobrien } 25690075Sobrien} 25790075Sobrien 25890075Sobrienvoid 259169689Skanmachopic_define_symbol (rtx mem) 26090075Sobrien{ 261169689Skan rtx sym_ref; 26290075Sobrien 263169689Skan gcc_assert (GET_CODE (mem) == MEM); 264169689Skan sym_ref = XEXP (mem, 0); 265169689Skan SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED; 26690075Sobrien} 26790075Sobrien 268132718Skanstatic GTY(()) char * function_base; 26990075Sobrien 270132718Skanconst char * 271132718Skanmachopic_function_base_name (void) 272132718Skan{ 273132718Skan /* if dynamic-no-pic is on, we should not get here */ 274169689Skan gcc_assert (!MACHO_DYNAMIC_NO_PIC_P); 27590075Sobrien 276132718Skan if (function_base == NULL) 277132718Skan function_base = 278132718Skan (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>")); 27990075Sobrien 280132718Skan current_function_uses_pic_offset_table = 1; 281132718Skan 282132718Skan return function_base; 283132718Skan} 284132718Skan 285169689Skan/* Return a SYMBOL_REF for the PIC function base. */ 286169689Skan 287169689Skanrtx 288169689Skanmachopic_function_base_sym (void) 289169689Skan{ 290169689Skan rtx sym_ref; 291169689Skan 292169689Skan sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ()); 293169689Skan SYMBOL_REF_FLAGS (sym_ref) 294169689Skan |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED); 295169689Skan return sym_ref; 296169689Skan} 297169689Skan 298169689Skan/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending 299169689Skan on whether pic_base is NULL or not. */ 300169689Skanstatic inline rtx 301169689Skangen_pic_offset (rtx orig, rtx pic_base) 302169689Skan{ 303169689Skan if (!pic_base) 304169689Skan return orig; 305169689Skan else 306169689Skan return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base)); 307169689Skan} 308169689Skan 309132718Skanstatic GTY(()) const char * function_base_func_name; 310132718Skanstatic GTY(()) int current_pic_label_num; 311132718Skan 312132718Skanvoid 313132718Skanmachopic_output_function_base_name (FILE *file) 31490075Sobrien{ 315132718Skan const char *current_name; 31690075Sobrien 317169689Skan /* If dynamic-no-pic is on, we should not get here. */ 318169689Skan gcc_assert (!MACHO_DYNAMIC_NO_PIC_P); 319132718Skan current_name = 320132718Skan IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); 321132718Skan if (function_base_func_name != current_name) 32290075Sobrien { 32390075Sobrien ++current_pic_label_num; 324132718Skan function_base_func_name = current_name; 32590075Sobrien } 326132718Skan fprintf (file, "\"L%011d$pb\"", current_pic_label_num); 32790075Sobrien} 32890075Sobrien 329169689Skan/* The suffix attached to non-lazy pointer symbols. */ 330169689Skan#define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr" 331169689Skan/* The suffix attached to stub symbols. */ 332169689Skan#define STUB_SUFFIX "$stub" 33390075Sobrien 334169689Skantypedef struct machopic_indirection GTY (()) 335169689Skan{ 336169689Skan /* The SYMBOL_REF for the entity referenced. */ 337169689Skan rtx symbol; 338169689Skan /* The name of the stub or non-lazy pointer. */ 339169689Skan const char * ptr_name; 340169689Skan /* True iff this entry is for a stub (as opposed to a non-lazy 341169689Skan pointer). */ 342169689Skan bool stub_p; 343169689Skan /* True iff this stub or pointer pointer has been referenced. */ 344169689Skan bool used; 345169689Skan} machopic_indirection; 34690075Sobrien 347169689Skan/* A table mapping stub names and non-lazy pointer names to 348169689Skan SYMBOL_REFs for the stubbed-to and pointed-to entities. */ 349169689Skan 350169689Skanstatic GTY ((param_is (struct machopic_indirection))) htab_t 351169689Skan machopic_indirections; 352169689Skan 353169689Skan/* Return a hash value for a SLOT in the indirections hash table. */ 354169689Skan 355169689Skanstatic hashval_t 356169689Skanmachopic_indirection_hash (const void *slot) 35790075Sobrien{ 358169689Skan const machopic_indirection *p = (const machopic_indirection *) slot; 359169689Skan return htab_hash_string (p->ptr_name); 360169689Skan} 361132718Skan 362169689Skan/* Returns true if the KEY is the same as that associated with 363169689Skan SLOT. */ 36490075Sobrien 365169689Skanstatic int 366169689Skanmachopic_indirection_eq (const void *slot, const void *key) 367169689Skan{ 368169689Skan return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0; 369169689Skan} 37090075Sobrien 371169689Skan/* Return the name of the non-lazy pointer (if STUB_P is false) or 372169689Skan stub (if STUB_B is true) corresponding to the given name. */ 373169689Skan 374169689Skanconst char * 375169689Skanmachopic_indirection_name (rtx sym_ref, bool stub_p) 376169689Skan{ 377169689Skan char *buffer; 378169689Skan const char *name = XSTR (sym_ref, 0); 379169689Skan size_t namelen = strlen (name); 380169689Skan machopic_indirection *p; 381169689Skan void ** slot; 382169689Skan bool saw_star = false; 383169689Skan bool needs_quotes; 384169689Skan const char *suffix; 385169689Skan const char *prefix = user_label_prefix; 386169689Skan const char *quote = ""; 387169689Skan tree id; 388169689Skan 389169689Skan id = maybe_get_identifier (name); 390169689Skan if (id) 39190075Sobrien { 392169689Skan tree id_orig = id; 393169689Skan 394169689Skan while (IDENTIFIER_TRANSPARENT_ALIAS (id)) 395169689Skan id = TREE_CHAIN (id); 396169689Skan if (id != id_orig) 39790075Sobrien { 398169689Skan name = IDENTIFIER_POINTER (id); 399169689Skan namelen = strlen (name); 40090075Sobrien } 40190075Sobrien } 40290075Sobrien 403169689Skan if (name[0] == '*') 404169689Skan { 405169689Skan saw_star = true; 406169689Skan prefix = ""; 407169689Skan ++name; 408169689Skan --namelen; 409169689Skan } 41090075Sobrien 411169689Skan needs_quotes = name_needs_quotes (name); 412169689Skan if (needs_quotes) 413169689Skan { 414169689Skan quote = "\""; 415169689Skan } 41690075Sobrien 417169689Skan if (stub_p) 418169689Skan suffix = STUB_SUFFIX; 419169689Skan else 420169689Skan suffix = NON_LAZY_POINTER_SUFFIX; 421132718Skan 422169689Skan buffer = alloca (strlen ("&L") 423169689Skan + strlen (prefix) 424169689Skan + namelen 425169689Skan + strlen (suffix) 426169689Skan + 2 * strlen (quote) 427169689Skan + 1 /* '\0' */); 42890075Sobrien 429169689Skan /* Construct the name of the non-lazy pointer or stub. */ 430169689Skan sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote); 43190075Sobrien 432169689Skan if (!machopic_indirections) 433169689Skan machopic_indirections = htab_create_ggc (37, 434169689Skan machopic_indirection_hash, 435169689Skan machopic_indirection_eq, 436169689Skan /*htab_del=*/NULL); 43790075Sobrien 438169689Skan slot = htab_find_slot_with_hash (machopic_indirections, buffer, 439169689Skan htab_hash_string (buffer), INSERT); 440169689Skan if (*slot) 441169689Skan { 442169689Skan p = (machopic_indirection *) *slot; 443169689Skan } 444169689Skan else 445169689Skan { 446169689Skan p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection)); 447169689Skan p->symbol = sym_ref; 448169689Skan p->ptr_name = xstrdup (buffer); 449169689Skan p->stub_p = stub_p; 450169689Skan p->used = false; 451169689Skan *slot = p; 452169689Skan } 453169689Skan 454169689Skan return p->ptr_name; 45590075Sobrien} 45690075Sobrien 457169689Skan/* Return the name of the stub for the mcount function. */ 45890075Sobrien 459169689Skanconst char* 460169689Skanmachopic_mcount_stub_name (void) 461169689Skan{ 462169689Skan rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount"); 463169689Skan return machopic_indirection_name (symbol, /*stub_p=*/true); 464169689Skan} 46590075Sobrien 466169689Skan/* If NAME is the name of a stub or a non-lazy pointer , mark the stub 467169689Skan or non-lazy pointer as used -- and mark the object to which the 468169689Skan pointer/stub refers as used as well, since the pointer/stub will 469169689Skan emit a reference to it. */ 470169689Skan 471169689Skanvoid 472169689Skanmachopic_validate_stub_or_non_lazy_ptr (const char *name) 47390075Sobrien{ 474169689Skan machopic_indirection *p; 47590075Sobrien 476169689Skan p = ((machopic_indirection *) 477169689Skan (htab_find_with_hash (machopic_indirections, name, 478169689Skan htab_hash_string (name)))); 479169689Skan if (p && ! p->used) 48090075Sobrien { 481169689Skan const char *real_name; 482169689Skan tree id; 48390075Sobrien 484169689Skan p->used = true; 48590075Sobrien 486169689Skan /* Do what output_addr_const will do when we actually call it. */ 487169689Skan if (SYMBOL_REF_DECL (p->symbol)) 488169689Skan mark_decl_referenced (SYMBOL_REF_DECL (p->symbol)); 48990075Sobrien 490169689Skan real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0)); 49190075Sobrien 492169689Skan id = maybe_get_identifier (real_name); 493169689Skan if (id) 494169689Skan mark_referenced (id); 495169689Skan } 49690075Sobrien} 49790075Sobrien 49890075Sobrien/* Transform ORIG, which may be any data source, to the corresponding 49990075Sobrien source using indirections. */ 50090075Sobrien 50190075Sobrienrtx 502132718Skanmachopic_indirect_data_reference (rtx orig, rtx reg) 50390075Sobrien{ 50490075Sobrien rtx ptr_ref = orig; 505132718Skan 50690075Sobrien if (! MACHOPIC_INDIRECT) 50790075Sobrien return orig; 50890075Sobrien 50990075Sobrien if (GET_CODE (orig) == SYMBOL_REF) 51090075Sobrien { 511169689Skan int defined = machopic_data_defined_p (orig); 51290075Sobrien 513132718Skan if (defined && MACHO_DYNAMIC_NO_PIC_P) 51490075Sobrien { 515132718Skan#if defined (TARGET_TOC) 516169689Skan /* Create a new register for CSE opportunities. */ 517169689Skan rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode)); 518169689Skan emit_insn (gen_macho_high (hi_reg, orig)); 519169689Skan emit_insn (gen_macho_low (reg, hi_reg, orig)); 520132718Skan#else 521132718Skan /* some other cpu -- writeme! */ 522169689Skan gcc_unreachable (); 523132718Skan#endif 524132718Skan return reg; 525132718Skan } 526132718Skan else if (defined) 527132718Skan { 528117395Skan#if defined (TARGET_TOC) || defined (HAVE_lo_sum) 529169689Skan rtx pic_base = machopic_function_base_sym (); 530169689Skan rtx offset = gen_pic_offset (orig, pic_base); 531117395Skan#endif 53290075Sobrien 53390075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */ 534132718Skan rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode)); 53590075Sobrien 536169689Skan gcc_assert (reg); 53790075Sobrien 538132718Skan emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, 539132718Skan gen_rtx_PLUS (Pmode, pic_offset_table_rtx, 540132718Skan gen_rtx_HIGH (Pmode, offset)))); 541132718Skan emit_insn (gen_rtx_SET (Pmode, reg, 542132718Skan gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset))); 54390075Sobrien 54490075Sobrien orig = reg; 54590075Sobrien#else 54690075Sobrien#if defined (HAVE_lo_sum) 547169689Skan gcc_assert (reg); 54890075Sobrien 549132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 550132718Skan gen_rtx_HIGH (Pmode, offset))); 551132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 552132718Skan gen_rtx_LO_SUM (Pmode, reg, offset))); 553132718Skan emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); 55490075Sobrien 555132718Skan orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg); 55690075Sobrien#endif 55790075Sobrien#endif 55890075Sobrien return orig; 55990075Sobrien } 56090075Sobrien 561169689Skan ptr_ref = (gen_rtx_SYMBOL_REF 562169689Skan (Pmode, 563169689Skan machopic_indirection_name (orig, /*stub_p=*/false))); 56490075Sobrien 565169689Skan SYMBOL_REF_DATA (ptr_ref) = SYMBOL_REF_DATA (orig); 56690075Sobrien 567169689Skan ptr_ref = gen_const_mem (Pmode, ptr_ref); 568169689Skan machopic_define_symbol (ptr_ref); 569169689Skan 57090075Sobrien return ptr_ref; 57190075Sobrien } 57290075Sobrien else if (GET_CODE (orig) == CONST) 57390075Sobrien { 57490075Sobrien rtx base, result; 57590075Sobrien 57690075Sobrien /* legitimize both operands of the PLUS */ 57790075Sobrien if (GET_CODE (XEXP (orig, 0)) == PLUS) 57890075Sobrien { 57990075Sobrien base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), 58090075Sobrien reg); 58190075Sobrien orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1), 58290075Sobrien (base == reg ? 0 : reg)); 58390075Sobrien } 584132718Skan else 58590075Sobrien return orig; 58690075Sobrien 58790075Sobrien if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT) 58890075Sobrien result = plus_constant (base, INTVAL (orig)); 58990075Sobrien else 590132718Skan result = gen_rtx_PLUS (Pmode, base, orig); 59190075Sobrien 59290075Sobrien if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM) 59390075Sobrien { 59490075Sobrien if (reg) 59590075Sobrien { 59690075Sobrien emit_move_insn (reg, result); 59790075Sobrien result = reg; 59890075Sobrien } 59990075Sobrien else 60090075Sobrien { 60190075Sobrien result = force_reg (GET_MODE (result), result); 60290075Sobrien } 60390075Sobrien } 60490075Sobrien 60590075Sobrien return result; 60690075Sobrien 60790075Sobrien } 60890075Sobrien else if (GET_CODE (orig) == MEM) 60990075Sobrien XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg); 61090075Sobrien /* When the target is i386, this code prevents crashes due to the 61190075Sobrien compiler's ignorance on how to move the PIC base register to 61290075Sobrien other registers. (The reload phase sometimes introduces such 61390075Sobrien insns.) */ 61490075Sobrien else if (GET_CODE (orig) == PLUS 61590075Sobrien && GET_CODE (XEXP (orig, 0)) == REG 61690075Sobrien && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM 61790075Sobrien#ifdef I386 61890075Sobrien /* Prevent the same register from being erroneously used 61990075Sobrien as both the base and index registers. */ 62090075Sobrien && GET_CODE (XEXP (orig, 1)) == CONST 62190075Sobrien#endif 62290075Sobrien && reg) 62390075Sobrien { 62490075Sobrien emit_move_insn (reg, XEXP (orig, 0)); 62590075Sobrien XEXP (ptr_ref, 0) = reg; 62690075Sobrien } 62790075Sobrien return ptr_ref; 62890075Sobrien} 62990075Sobrien 63090075Sobrien/* Transform TARGET (a MEM), which is a function call target, to the 63190075Sobrien corresponding symbol_stub if necessary. Return a new MEM. */ 63290075Sobrien 63390075Sobrienrtx 634132718Skanmachopic_indirect_call_target (rtx target) 63590075Sobrien{ 63690075Sobrien if (GET_CODE (target) != MEM) 63790075Sobrien return target; 63890075Sobrien 639169689Skan if (MACHOPIC_INDIRECT 640169689Skan && GET_CODE (XEXP (target, 0)) == SYMBOL_REF 641169689Skan && !(SYMBOL_REF_FLAGS (XEXP (target, 0)) 642169689Skan & MACHO_SYMBOL_FLAG_DEFINED)) 643132718Skan { 644169689Skan rtx sym_ref = XEXP (target, 0); 645169689Skan const char *stub_name = machopic_indirection_name (sym_ref, 646169689Skan /*stub_p=*/true); 647169689Skan enum machine_mode mode = GET_MODE (sym_ref); 64890075Sobrien 649169689Skan XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name); 650169689Skan SYMBOL_REF_DATA (XEXP (target, 0)) = SYMBOL_REF_DATA (sym_ref); 651169689Skan MEM_READONLY_P (target) = 1; 652169689Skan MEM_NOTRAP_P (target) = 1; 65390075Sobrien } 65490075Sobrien 65590075Sobrien return target; 65690075Sobrien} 65790075Sobrien 65890075Sobrienrtx 659132718Skanmachopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) 66090075Sobrien{ 66190075Sobrien rtx pic_ref = orig; 66290075Sobrien 663132718Skan if (! MACHOPIC_INDIRECT) 66490075Sobrien return orig; 66590075Sobrien 66690075Sobrien /* First handle a simple SYMBOL_REF or LABEL_REF */ 66790075Sobrien if (GET_CODE (orig) == LABEL_REF 66890075Sobrien || (GET_CODE (orig) == SYMBOL_REF 66990075Sobrien )) 67090075Sobrien { 67190075Sobrien /* addr(foo) = &func+(foo-func) */ 67290075Sobrien rtx pic_base; 67390075Sobrien 67490075Sobrien orig = machopic_indirect_data_reference (orig, reg); 67590075Sobrien 676132718Skan if (GET_CODE (orig) == PLUS 67790075Sobrien && GET_CODE (XEXP (orig, 0)) == REG) 67890075Sobrien { 67990075Sobrien if (reg == 0) 68090075Sobrien return force_reg (mode, orig); 68190075Sobrien 68290075Sobrien emit_move_insn (reg, orig); 68390075Sobrien return reg; 684132718Skan } 68590075Sobrien 686169689Skan /* if dynamic-no-pic we don't have a pic base */ 687132718Skan if (MACHO_DYNAMIC_NO_PIC_P) 688169689Skan pic_base = NULL; 689132718Skan else 690169689Skan pic_base = machopic_function_base_sym (); 69190075Sobrien 69290075Sobrien if (GET_CODE (orig) == MEM) 69390075Sobrien { 69490075Sobrien if (reg == 0) 69590075Sobrien { 696169689Skan gcc_assert (!reload_in_progress); 697169689Skan reg = gen_reg_rtx (Pmode); 69890075Sobrien } 699132718Skan 70090075Sobrien#ifdef HAVE_lo_sum 701132718Skan if (MACHO_DYNAMIC_NO_PIC_P 702132718Skan && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 703132718Skan || GET_CODE (XEXP (orig, 0)) == LABEL_REF)) 704132718Skan { 705132718Skan#if defined (TARGET_TOC) /* ppc */ 706132718Skan rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode); 707132718Skan rtx asym = XEXP (orig, 0); 708132718Skan rtx mem; 709132718Skan 710132718Skan emit_insn (gen_macho_high (temp_reg, asym)); 711169689Skan mem = gen_const_mem (GET_MODE (orig), 712169689Skan gen_rtx_LO_SUM (Pmode, temp_reg, asym)); 713132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, mem)); 714132718Skan#else 715132718Skan /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */ 716169689Skan gcc_unreachable (); 717132718Skan#endif 718132718Skan pic_ref = reg; 719132718Skan } 720132718Skan else 721132718Skan if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 72290075Sobrien || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 72390075Sobrien { 724169689Skan rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base); 72590075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */ 72690075Sobrien /* Generating a new reg may expose opportunities for 72790075Sobrien common subexpression elimination. */ 728169689Skan rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode); 729132718Skan rtx mem; 730132718Skan rtx insn; 731132718Skan rtx sum; 732169689Skan 733132718Skan sum = gen_rtx_HIGH (Pmode, offset); 734132718Skan if (! MACHO_DYNAMIC_NO_PIC_P) 735132718Skan sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum); 73690075Sobrien 737132718Skan emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum)); 738132718Skan 739169689Skan mem = gen_const_mem (GET_MODE (orig), 740169689Skan gen_rtx_LO_SUM (Pmode, 741169689Skan hi_sum_reg, offset)); 742132718Skan insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem)); 743169689Skan REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref, 744132718Skan REG_NOTES (insn)); 745132718Skan 74690075Sobrien pic_ref = reg; 74790075Sobrien#else 748132718Skan emit_insn (gen_rtx_USE (VOIDmode, 749169689Skan gen_rtx_REG (Pmode, 750132718Skan PIC_OFFSET_TABLE_REGNUM))); 75190075Sobrien 752132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 753132718Skan gen_rtx_HIGH (Pmode, 754169689Skan gen_rtx_CONST (Pmode, 755132718Skan offset)))); 756132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 757132718Skan gen_rtx_LO_SUM (Pmode, reg, 758132718Skan gen_rtx_CONST (Pmode, offset)))); 759132718Skan pic_ref = gen_rtx_PLUS (Pmode, 760132718Skan pic_offset_table_rtx, reg); 76190075Sobrien#endif 76290075Sobrien } 76390075Sobrien else 76490075Sobrien#endif /* HAVE_lo_sum */ 76590075Sobrien { 76690075Sobrien rtx pic = pic_offset_table_rtx; 76790075Sobrien if (GET_CODE (pic) != REG) 76890075Sobrien { 76990075Sobrien emit_move_insn (reg, pic); 77090075Sobrien pic = reg; 77190075Sobrien } 77290075Sobrien#if 0 773132718Skan emit_insn (gen_rtx_USE (VOIDmode, 774169689Skan gen_rtx_REG (Pmode, 775132718Skan PIC_OFFSET_TABLE_REGNUM))); 77690075Sobrien#endif 77790075Sobrien 778169689Skan if (reload_in_progress) 779169689Skan regs_ever_live[REGNO (pic)] = 1; 780169689Skan pic_ref = gen_rtx_PLUS (Pmode, pic, 781169689Skan gen_pic_offset (XEXP (orig, 0), 782169689Skan pic_base)); 78390075Sobrien } 784132718Skan 78590075Sobrien#if !defined (TARGET_TOC) 78690075Sobrien emit_move_insn (reg, pic_ref); 787169689Skan pic_ref = gen_const_mem (GET_MODE (orig), reg); 78890075Sobrien#endif 78990075Sobrien } 79090075Sobrien else 79190075Sobrien { 79290075Sobrien 79390075Sobrien#ifdef HAVE_lo_sum 794132718Skan if (GET_CODE (orig) == SYMBOL_REF 79590075Sobrien || GET_CODE (orig) == LABEL_REF) 79690075Sobrien { 797169689Skan rtx offset = gen_pic_offset (orig, pic_base); 79890075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */ 79990075Sobrien rtx hi_sum_reg; 80090075Sobrien 80190075Sobrien if (reg == 0) 80290075Sobrien { 803169689Skan gcc_assert (!reload_in_progress); 804169689Skan reg = gen_reg_rtx (Pmode); 80590075Sobrien } 806132718Skan 80790075Sobrien hi_sum_reg = reg; 80890075Sobrien 809132718Skan emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, 810132718Skan (MACHO_DYNAMIC_NO_PIC_P) 811132718Skan ? gen_rtx_HIGH (Pmode, offset) 812132718Skan : gen_rtx_PLUS (Pmode, 813132718Skan pic_offset_table_rtx, 814169689Skan gen_rtx_HIGH (Pmode, 815132718Skan offset)))); 816132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 817132718Skan gen_rtx_LO_SUM (Pmode, 818132718Skan hi_sum_reg, offset))); 81990075Sobrien pic_ref = reg; 82090075Sobrien#else 821132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 822132718Skan gen_rtx_HIGH (Pmode, offset))); 823132718Skan emit_insn (gen_rtx_SET (VOIDmode, reg, 824132718Skan gen_rtx_LO_SUM (Pmode, reg, offset))); 825132718Skan pic_ref = gen_rtx_PLUS (Pmode, 826132718Skan pic_offset_table_rtx, reg); 82790075Sobrien#endif 82890075Sobrien } 82990075Sobrien else 83090075Sobrien#endif /* HAVE_lo_sum */ 83190075Sobrien { 832169689Skan if (REG_P (orig) 833169689Skan || GET_CODE (orig) == SUBREG) 83490075Sobrien { 83590075Sobrien return orig; 83690075Sobrien } 83790075Sobrien else 83890075Sobrien { 83990075Sobrien rtx pic = pic_offset_table_rtx; 84090075Sobrien if (GET_CODE (pic) != REG) 84190075Sobrien { 84290075Sobrien emit_move_insn (reg, pic); 84390075Sobrien pic = reg; 84490075Sobrien } 84590075Sobrien#if 0 846132718Skan emit_insn (gen_rtx_USE (VOIDmode, 847132718Skan pic_offset_table_rtx)); 84890075Sobrien#endif 849169689Skan if (reload_in_progress) 850169689Skan regs_ever_live[REGNO (pic)] = 1; 851132718Skan pic_ref = gen_rtx_PLUS (Pmode, 852132718Skan pic, 853169689Skan gen_pic_offset (orig, pic_base)); 85490075Sobrien } 85590075Sobrien } 85690075Sobrien } 85790075Sobrien 85890075Sobrien if (GET_CODE (pic_ref) != REG) 85990075Sobrien { 86090075Sobrien if (reg != 0) 86190075Sobrien { 86290075Sobrien emit_move_insn (reg, pic_ref); 86390075Sobrien return reg; 86490075Sobrien } 86590075Sobrien else 86690075Sobrien { 86790075Sobrien return force_reg (mode, pic_ref); 86890075Sobrien } 86990075Sobrien } 87090075Sobrien else 87190075Sobrien { 87290075Sobrien return pic_ref; 87390075Sobrien } 87490075Sobrien } 87590075Sobrien 87690075Sobrien else if (GET_CODE (orig) == SYMBOL_REF) 87790075Sobrien return orig; 87890075Sobrien 87990075Sobrien else if (GET_CODE (orig) == PLUS 88090075Sobrien && (GET_CODE (XEXP (orig, 0)) == MEM 88190075Sobrien || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 88290075Sobrien || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 88390075Sobrien && XEXP (orig, 0) != pic_offset_table_rtx 88490075Sobrien && GET_CODE (XEXP (orig, 1)) != REG) 885132718Skan 88690075Sobrien { 88790075Sobrien rtx base; 88890075Sobrien int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM); 88990075Sobrien 89090075Sobrien base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 89190075Sobrien orig = machopic_legitimize_pic_address (XEXP (orig, 1), 89290075Sobrien Pmode, (base == reg ? 0 : reg)); 89390075Sobrien if (GET_CODE (orig) == CONST_INT) 89490075Sobrien { 89590075Sobrien pic_ref = plus_constant (base, INTVAL (orig)); 89690075Sobrien is_complex = 1; 89790075Sobrien } 89890075Sobrien else 899132718Skan pic_ref = gen_rtx_PLUS (Pmode, base, orig); 90090075Sobrien 90190075Sobrien if (reg && is_complex) 90290075Sobrien { 90390075Sobrien emit_move_insn (reg, pic_ref); 90490075Sobrien pic_ref = reg; 90590075Sobrien } 90690075Sobrien /* Likewise, should we set special REG_NOTEs here? */ 90790075Sobrien } 90890075Sobrien 90990075Sobrien else if (GET_CODE (orig) == CONST) 91090075Sobrien { 91190075Sobrien return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 91290075Sobrien } 91390075Sobrien 91490075Sobrien else if (GET_CODE (orig) == MEM 91590075Sobrien && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF) 91690075Sobrien { 91790075Sobrien rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 918169689Skan addr = replace_equiv_address (orig, addr); 91990075Sobrien emit_move_insn (reg, addr); 92090075Sobrien pic_ref = reg; 92190075Sobrien } 92290075Sobrien 92390075Sobrien return pic_ref; 92490075Sobrien} 92590075Sobrien 926169689Skan/* Output the stub or non-lazy pointer in *SLOT, if it has been used. 927169689Skan DATA is the FILE* for assembly output. Called from 928169689Skan htab_traverse. */ 92990075Sobrien 930169689Skanstatic int 931169689Skanmachopic_output_indirection (void **slot, void *data) 93290075Sobrien{ 933169689Skan machopic_indirection *p = *((machopic_indirection **) slot); 934169689Skan FILE *asm_out_file = (FILE *) data; 935169689Skan rtx symbol; 936169689Skan const char *sym_name; 937169689Skan const char *ptr_name; 93890075Sobrien 939169689Skan if (!p->used) 940169689Skan return 1; 941169689Skan 942169689Skan symbol = p->symbol; 943169689Skan sym_name = XSTR (symbol, 0); 944169689Skan ptr_name = p->ptr_name; 945169689Skan 946169689Skan if (p->stub_p) 94790075Sobrien { 94890075Sobrien char *sym; 94990075Sobrien char *stub; 950169689Skan tree id; 95190075Sobrien 952169689Skan id = maybe_get_identifier (sym_name); 953169689Skan if (id) 954169689Skan { 955169689Skan tree id_orig = id; 95690075Sobrien 957169689Skan while (IDENTIFIER_TRANSPARENT_ALIAS (id)) 958169689Skan id = TREE_CHAIN (id); 959169689Skan if (id != id_orig) 960169689Skan sym_name = IDENTIFIER_POINTER (id); 961169689Skan } 96290075Sobrien 96390075Sobrien sym = alloca (strlen (sym_name) + 2); 96490075Sobrien if (sym_name[0] == '*' || sym_name[0] == '&') 96590075Sobrien strcpy (sym, sym_name + 1); 96690075Sobrien else if (sym_name[0] == '-' || sym_name[0] == '+') 967132718Skan strcpy (sym, sym_name); 96890075Sobrien else 969169689Skan sprintf (sym, "%s%s", user_label_prefix, sym_name); 97090075Sobrien 971169689Skan stub = alloca (strlen (ptr_name) + 2); 972169689Skan if (ptr_name[0] == '*' || ptr_name[0] == '&') 973169689Skan strcpy (stub, ptr_name + 1); 97490075Sobrien else 975169689Skan sprintf (stub, "%s%s", user_label_prefix, ptr_name); 97690075Sobrien 97790075Sobrien machopic_output_stub (asm_out_file, sym, stub); 97890075Sobrien } 979169689Skan else if (! indirect_data (symbol) 980169689Skan && (machopic_symbol_defined_p (symbol) 981169689Skan || SYMBOL_REF_LOCAL_P (symbol))) 98290075Sobrien { 983169689Skan switch_to_section (data_section); 984169689Skan assemble_align (GET_MODE_ALIGNMENT (Pmode)); 985169689Skan assemble_label (ptr_name); 986169689Skan assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name), 987169689Skan GET_MODE_SIZE (Pmode), 988169689Skan GET_MODE_ALIGNMENT (Pmode), 1); 989169689Skan } 990169689Skan else 991169689Skan { 992169689Skan rtx init = const0_rtx; 99390075Sobrien 994169689Skan switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]); 995169689Skan assemble_name (asm_out_file, ptr_name); 996169689Skan fprintf (asm_out_file, ":\n"); 99790075Sobrien 998169689Skan fprintf (asm_out_file, "\t.indirect_symbol "); 999169689Skan assemble_name (asm_out_file, sym_name); 1000169689Skan fprintf (asm_out_file, "\n"); 100190075Sobrien 1002169689Skan /* Variables that are marked with MACHO_SYMBOL_STATIC need to 1003169689Skan have their symbol name instead of 0 in the second entry of 1004169689Skan the non-lazy symbol pointer data structure when they are 1005169689Skan defined. This allows the runtime to rebind newer instances 1006169689Skan of the translation unit with the original instance of the 1007169689Skan symbol. */ 100890075Sobrien 1009169689Skan if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC) 1010169689Skan && machopic_symbol_defined_p (symbol)) 1011169689Skan init = gen_rtx_SYMBOL_REF (Pmode, sym_name); 1012169689Skan 1013169689Skan assemble_integer (init, GET_MODE_SIZE (Pmode), 1014169689Skan GET_MODE_ALIGNMENT (Pmode), 1); 101590075Sobrien } 1016169689Skan 1017169689Skan return 1; 101890075Sobrien} 101990075Sobrien 1020169689Skanvoid 1021169689Skanmachopic_finish (FILE *asm_out_file) 1022169689Skan{ 1023169689Skan if (machopic_indirections) 1024169689Skan htab_traverse_noresize (machopic_indirections, 1025169689Skan machopic_output_indirection, 1026169689Skan asm_out_file); 1027169689Skan} 1028169689Skan 1029132718Skanint 1030132718Skanmachopic_operand_p (rtx op) 103190075Sobrien{ 103290075Sobrien if (MACHOPIC_JUST_INDIRECT) 103390075Sobrien { 103490075Sobrien while (GET_CODE (op) == CONST) 103590075Sobrien op = XEXP (op, 0); 103690075Sobrien 103790075Sobrien if (GET_CODE (op) == SYMBOL_REF) 1038169689Skan return machopic_symbol_defined_p (op); 103990075Sobrien else 104090075Sobrien return 0; 104190075Sobrien } 104290075Sobrien 104390075Sobrien while (GET_CODE (op) == CONST) 104490075Sobrien op = XEXP (op, 0); 104590075Sobrien 104690075Sobrien if (GET_CODE (op) == MINUS 104790075Sobrien && GET_CODE (XEXP (op, 0)) == SYMBOL_REF 104890075Sobrien && GET_CODE (XEXP (op, 1)) == SYMBOL_REF 1049169689Skan && machopic_symbol_defined_p (XEXP (op, 0)) 1050169689Skan && machopic_symbol_defined_p (XEXP (op, 1))) 105190075Sobrien return 1; 105290075Sobrien 105390075Sobrien return 0; 105490075Sobrien} 105590075Sobrien 105690075Sobrien/* This function records whether a given name corresponds to a defined 105790075Sobrien or undefined function or variable, for machopic_classify_ident to 105890075Sobrien use later. */ 105990075Sobrien 106090075Sobrienvoid 1061132718Skandarwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED) 106290075Sobrien{ 106390075Sobrien rtx sym_ref; 106490075Sobrien 1065132718Skan /* Do the standard encoding things first. */ 1066132718Skan default_encode_section_info (decl, rtl, first); 1067132718Skan 1068169689Skan if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL) 1069169689Skan return; 1070132718Skan 1071169689Skan sym_ref = XEXP (rtl, 0); 1072169689Skan if (TREE_CODE (decl) == VAR_DECL) 1073169689Skan SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE; 1074169689Skan 1075169689Skan if (!DECL_EXTERNAL (decl) 1076169689Skan && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl)) 1077169689Skan && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) 107890075Sobrien && ((TREE_STATIC (decl) 107990075Sobrien && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl))) 1080132718Skan || (!DECL_COMMON (decl) && DECL_INITIAL (decl) 108190075Sobrien && DECL_INITIAL (decl) != error_mark_node))) 1082169689Skan SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED; 108390075Sobrien 1084169689Skan if (! TREE_PUBLIC (decl)) 1085169689Skan SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC; 108690075Sobrien} 108790075Sobrien 1088169689Skanvoid 1089169689Skandarwin_mark_decl_preserved (const char *name) 1090117395Skan{ 1091169689Skan fprintf (asm_out_file, ".no_dead_strip "); 1092169689Skan assemble_name (asm_out_file, name); 1093169689Skan fputc ('\n', asm_out_file); 1094117395Skan} 1095117395Skan 1096169689Skanint 1097169689Skanmachopic_reloc_rw_mask (void) 109890075Sobrien{ 1099169689Skan return MACHOPIC_INDIRECT ? 3 : 0; 110090075Sobrien} 110190075Sobrien 1102169689Skansection * 1103169689Skanmachopic_select_section (tree exp, int reloc, 1104169689Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) 110590075Sobrien{ 1106169689Skan section *base_section; 1107169689Skan bool weak_p = (DECL_P (exp) && DECL_WEAK (exp) 1108169689Skan && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp)) 1109169689Skan || ! lookup_attribute ("weak_import", 1110169689Skan DECL_ATTRIBUTES (exp)))); 111190075Sobrien 1112169689Skan if (TREE_CODE (exp) == FUNCTION_DECL) 111390075Sobrien { 1114169689Skan if (reloc == 1) 1115169689Skan base_section = (weak_p 1116169689Skan ? darwin_sections[text_unlikely_coal_section] 1117169689Skan : unlikely_text_section ()); 1118169689Skan else 1119169689Skan base_section = weak_p ? darwin_sections[text_coal_section] : text_section; 112090075Sobrien } 1121169689Skan else if (decl_readonly_section (exp, reloc)) 1122169689Skan base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section]; 1123119256Skan else if (TREE_READONLY (exp) || TREE_CONSTANT (exp)) 1124169689Skan base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section]; 1125119256Skan else 1126169689Skan base_section = weak_p ? darwin_sections[data_coal_section] : data_section; 1127119256Skan 1128119256Skan if (TREE_CODE (exp) == STRING_CST 1129132718Skan && ((size_t) TREE_STRING_LENGTH (exp) 1130169689Skan == strlen (TREE_STRING_POINTER (exp)) + 1)) 1131169689Skan return darwin_sections[cstring_section]; 1132119256Skan else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST) 1133119256Skan && flag_merge_constants) 1134117395Skan { 1135169689Skan tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp)); 1136117395Skan 1137117395Skan if (TREE_CODE (size) == INTEGER_CST && 1138117395Skan TREE_INT_CST_LOW (size) == 4 && 1139117395Skan TREE_INT_CST_HIGH (size) == 0) 1140169689Skan return darwin_sections[literal4_section]; 1141117395Skan else if (TREE_CODE (size) == INTEGER_CST && 1142117395Skan TREE_INT_CST_LOW (size) == 8 && 1143117395Skan TREE_INT_CST_HIGH (size) == 0) 1144169689Skan return darwin_sections[literal8_section]; 1145169689Skan else if (TARGET_64BIT 1146169689Skan && TREE_CODE (size) == INTEGER_CST 1147169689Skan && TREE_INT_CST_LOW (size) == 16 1148169689Skan && TREE_INT_CST_HIGH (size) == 0) 1149169689Skan return darwin_sections[literal16_section]; 1150117395Skan else 1151169689Skan return base_section; 1152117395Skan } 1153117395Skan else if (TREE_CODE (exp) == CONSTRUCTOR 1154117395Skan && TREE_TYPE (exp) 1155117395Skan && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE 1156117395Skan && TYPE_NAME (TREE_TYPE (exp))) 1157117395Skan { 1158117395Skan tree name = TYPE_NAME (TREE_TYPE (exp)); 1159117395Skan if (TREE_CODE (name) == TYPE_DECL) 1160117395Skan name = DECL_NAME (name); 1161169689Skan 1162169689Skan if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString")) 1163169689Skan { 1164169689Skan if (flag_next_runtime) 1165169689Skan return darwin_sections[objc_constant_string_object_section]; 1166169689Skan else 1167169689Skan return darwin_sections[objc_string_object_section]; 1168169689Skan } 1169132718Skan else 1170169689Skan return base_section; 1171117395Skan } 1172117395Skan else if (TREE_CODE (exp) == VAR_DECL && 1173117395Skan DECL_NAME (exp) && 1174117395Skan TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE && 1175117395Skan IDENTIFIER_POINTER (DECL_NAME (exp)) && 1176117395Skan !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6)) 1177117395Skan { 1178117395Skan const char *name = IDENTIFIER_POINTER (DECL_NAME (exp)); 1179117395Skan 1180117395Skan if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20)) 1181169689Skan return darwin_sections[objc_cls_meth_section]; 1182117395Skan else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23)) 1183169689Skan return darwin_sections[objc_inst_meth_section]; 1184117395Skan else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20)) 1185169689Skan return darwin_sections[objc_cat_cls_meth_section]; 1186117395Skan else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23)) 1187169689Skan return darwin_sections[objc_cat_inst_meth_section]; 1188117395Skan else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22)) 1189169689Skan return darwin_sections[objc_class_vars_section]; 1190117395Skan else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25)) 1191169689Skan return darwin_sections[objc_instance_vars_section]; 1192117395Skan else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22)) 1193169689Skan return darwin_sections[objc_cat_cls_meth_section]; 1194117395Skan else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17)) 1195169689Skan return darwin_sections[objc_class_names_section]; 1196117395Skan else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20)) 1197169689Skan return darwin_sections[objc_meth_var_names_section]; 1198117395Skan else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20)) 1199169689Skan return darwin_sections[objc_meth_var_types_section]; 1200117395Skan else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22)) 1201169689Skan return darwin_sections[objc_cls_refs_section]; 1202117395Skan else if (!strncmp (name, "_OBJC_CLASS_", 12)) 1203169689Skan return darwin_sections[objc_class_section]; 1204117395Skan else if (!strncmp (name, "_OBJC_METACLASS_", 16)) 1205169689Skan return darwin_sections[objc_meta_class_section]; 1206117395Skan else if (!strncmp (name, "_OBJC_CATEGORY_", 15)) 1207169689Skan return darwin_sections[objc_category_section]; 1208117395Skan else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25)) 1209169689Skan return darwin_sections[objc_selector_refs_section]; 1210117395Skan else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20)) 1211169689Skan return darwin_sections[objc_selector_fixup_section]; 1212117395Skan else if (!strncmp (name, "_OBJC_SYMBOLS", 13)) 1213169689Skan return darwin_sections[objc_symbols_section]; 1214117395Skan else if (!strncmp (name, "_OBJC_MODULES", 13)) 1215169689Skan return darwin_sections[objc_module_info_section]; 1216132718Skan else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16)) 1217169689Skan return darwin_sections[objc_image_info_section]; 1218117395Skan else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32)) 1219169689Skan return darwin_sections[objc_cat_inst_meth_section]; 1220117395Skan else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29)) 1221169689Skan return darwin_sections[objc_cat_cls_meth_section]; 1222117395Skan else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20)) 1223169689Skan return darwin_sections[objc_cat_cls_meth_section]; 1224117395Skan else if (!strncmp (name, "_OBJC_PROTOCOL_", 15)) 1225169689Skan return darwin_sections[objc_protocol_section]; 1226132718Skan else 1227169689Skan return base_section; 1228117395Skan } 1229132718Skan else 1230169689Skan return base_section; 1231117395Skan} 1232117395Skan 1233117395Skan/* This can be called with address expressions as "rtx". 1234117395Skan They must go in "const". */ 1235117395Skan 1236169689Skansection * 1237132718Skanmachopic_select_rtx_section (enum machine_mode mode, rtx x, 1238132718Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) 1239117395Skan{ 1240169689Skan if (GET_MODE_SIZE (mode) == 8 1241169689Skan && (GET_CODE (x) == CONST_INT 1242169689Skan || GET_CODE (x) == CONST_DOUBLE)) 1243169689Skan return darwin_sections[literal8_section]; 1244117395Skan else if (GET_MODE_SIZE (mode) == 4 1245117395Skan && (GET_CODE (x) == CONST_INT 1246117395Skan || GET_CODE (x) == CONST_DOUBLE)) 1247169689Skan return darwin_sections[literal4_section]; 1248169689Skan else if (TARGET_64BIT 1249169689Skan && GET_MODE_SIZE (mode) == 16 1250169689Skan && (GET_CODE (x) == CONST_INT 1251169689Skan || GET_CODE (x) == CONST_DOUBLE 1252169689Skan || GET_CODE (x) == CONST_VECTOR)) 1253169689Skan return darwin_sections[literal16_section]; 1254132718Skan else if (MACHOPIC_INDIRECT 1255132718Skan && (GET_CODE (x) == SYMBOL_REF 1256132718Skan || GET_CODE (x) == CONST 1257132718Skan || GET_CODE (x) == LABEL_REF)) 1258169689Skan return darwin_sections[const_data_section]; 1259117395Skan else 1260169689Skan return darwin_sections[const_section]; 1261117395Skan} 1262117395Skan 1263117395Skanvoid 1264132718Skanmachopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED) 126590075Sobrien{ 1266132718Skan if (MACHOPIC_INDIRECT) 1267169689Skan switch_to_section (darwin_sections[mod_init_section]); 126890075Sobrien else 1269169689Skan switch_to_section (darwin_sections[constructor_section]); 127090075Sobrien assemble_align (POINTER_SIZE); 127190075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 127290075Sobrien 1273132718Skan if (! MACHOPIC_INDIRECT) 127490075Sobrien fprintf (asm_out_file, ".reference .constructors_used\n"); 127590075Sobrien} 127690075Sobrien 127790075Sobrienvoid 1278132718Skanmachopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED) 127990075Sobrien{ 1280132718Skan if (MACHOPIC_INDIRECT) 1281169689Skan switch_to_section (darwin_sections[mod_term_section]); 128290075Sobrien else 1283169689Skan switch_to_section (darwin_sections[destructor_section]); 128490075Sobrien assemble_align (POINTER_SIZE); 128590075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 128690075Sobrien 1287132718Skan if (! MACHOPIC_INDIRECT) 128890075Sobrien fprintf (asm_out_file, ".reference .destructors_used\n"); 128990075Sobrien} 1290117395Skan 1291117395Skanvoid 1292132718Skandarwin_globalize_label (FILE *stream, const char *name) 1293117395Skan{ 1294117395Skan if (!!strncmp (name, "_OBJC_", 6)) 1295117395Skan default_globalize_label (stream, name); 1296117395Skan} 1297117395Skan 1298169689Skanvoid 1299169689Skandarwin_asm_named_section (const char *name, 1300169689Skan unsigned int flags ATTRIBUTE_UNUSED, 1301169689Skan tree decl ATTRIBUTE_UNUSED) 1302169689Skan{ 1303169689Skan fprintf (asm_out_file, "\t.section %s\n", name); 1304169689Skan} 1305169689Skan 1306169689Skanvoid 1307169689Skandarwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED) 1308169689Skan{ 1309169689Skan /* Darwin does not use unique sections. */ 1310169689Skan} 1311169689Skan 1312169689Skan/* Handle __attribute__ ((apple_kext_compatibility)). 1313169689Skan This only applies to darwin kexts for 2.95 compatibility -- it shrinks the 1314169689Skan vtable for classes with this attribute (and their descendants) by not 1315169689Skan outputting the new 3.0 nondeleting destructor. This means that such 1316169689Skan objects CANNOT be allocated on the stack or as globals UNLESS they have 1317169689Skan a completely empty `operator delete'. 1318169689Skan Luckily, this fits in with the Darwin kext model. 1319169689Skan 1320169689Skan This attribute also disables gcc3's potential overlaying of derived 1321169689Skan class data members on the padding at the end of the base class. */ 1322169689Skan 1323169689Skantree 1324169689Skandarwin_handle_kext_attribute (tree *node, tree name, 1325169689Skan tree args ATTRIBUTE_UNUSED, 1326169689Skan int flags ATTRIBUTE_UNUSED, 1327169689Skan bool *no_add_attrs) 1328169689Skan{ 1329169689Skan /* APPLE KEXT stuff -- only applies with pure static C++ code. */ 1330169689Skan if (! TARGET_KEXTABI) 1331169689Skan { 1332169689Skan warning (0, "%<%s%> 2.95 vtable-compatability attribute applies " 1333169689Skan "only when compiling a kext", IDENTIFIER_POINTER (name)); 1334169689Skan 1335169689Skan *no_add_attrs = true; 1336169689Skan } 1337169689Skan else if (TREE_CODE (*node) != RECORD_TYPE) 1338169689Skan { 1339169689Skan warning (0, "%<%s%> 2.95 vtable-compatability attribute applies " 1340169689Skan "only to C++ classes", IDENTIFIER_POINTER (name)); 1341169689Skan 1342169689Skan *no_add_attrs = true; 1343169689Skan } 1344169689Skan 1345169689Skan return NULL_TREE; 1346169689Skan} 1347169689Skan 1348169689Skan/* Handle a "weak_import" attribute; arguments as in 1349169689Skan struct attribute_spec.handler. */ 1350169689Skan 1351169689Skantree 1352169689Skandarwin_handle_weak_import_attribute (tree *node, tree name, 1353169689Skan tree ARG_UNUSED (args), 1354169689Skan int ARG_UNUSED (flags), 1355169689Skan bool * no_add_attrs) 1356169689Skan{ 1357169689Skan if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL) 1358169689Skan { 1359169689Skan warning (OPT_Wattributes, "%qs attribute ignored", 1360169689Skan IDENTIFIER_POINTER (name)); 1361169689Skan *no_add_attrs = true; 1362169689Skan } 1363169689Skan else 1364169689Skan declare_weak (*node); 1365169689Skan 1366169689Skan return NULL_TREE; 1367169689Skan} 1368169689Skan 1369169689Skanstatic void 1370169689Skanno_dead_strip (FILE *file, const char *lab) 1371169689Skan{ 1372169689Skan fprintf (file, ".no_dead_strip %s\n", lab); 1373169689Skan} 1374169689Skan 1375169689Skan/* Emit a label for an FDE, making it global and/or weak if appropriate. 1376169689Skan The third parameter is nonzero if this is for exception handling. 1377169689Skan The fourth parameter is nonzero if this is just a placeholder for an 1378169689Skan FDE that we are omitting. */ 1379169689Skan 1380169689Skanvoid 1381169689Skandarwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty) 1382169689Skan{ 1383169689Skan const char *base; 1384169689Skan char *lab; 1385169689Skan bool need_quotes; 1386169689Skan 1387169689Skan if (DECL_ASSEMBLER_NAME_SET_P (decl)) 1388169689Skan base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 1389169689Skan else 1390169689Skan base = IDENTIFIER_POINTER (DECL_NAME (decl)); 1391169689Skan 1392169689Skan base = targetm.strip_name_encoding (base); 1393169689Skan need_quotes = name_needs_quotes (base); 1394169689Skan 1395169689Skan if (! for_eh) 1396169689Skan return; 1397169689Skan 1398169689Skan lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh", 1399169689Skan need_quotes ? "\"" : "", NULL); 1400169689Skan 1401169689Skan if (TREE_PUBLIC (decl)) 1402169689Skan fprintf (file, "\t%s %s\n", 1403169689Skan (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN 1404169689Skan ? ".globl" 1405169689Skan : ".private_extern"), 1406169689Skan lab); 1407169689Skan 1408169689Skan if (DECL_WEAK (decl)) 1409169689Skan fprintf (file, "\t.weak_definition %s\n", lab); 1410169689Skan 1411169689Skan if (empty) 1412169689Skan { 1413169689Skan fprintf (file, "%s = 0\n", lab); 1414169689Skan 1415169689Skan /* Mark the absolute .eh and .eh1 style labels as needed to 1416169689Skan ensure that we don't dead code strip them and keep such 1417169689Skan labels from another instantiation point until we can fix this 1418169689Skan properly with group comdat support. */ 1419169689Skan no_dead_strip (file, lab); 1420169689Skan } 1421169689Skan else 1422169689Skan fprintf (file, "%s:\n", lab); 1423169689Skan 1424169689Skan free (lab); 1425169689Skan} 1426169689Skan 1427169689Skanstatic GTY(()) unsigned long except_table_label_num; 1428169689Skan 1429169689Skanvoid 1430169689Skandarwin_emit_except_table_label (FILE *file) 1431169689Skan{ 1432169689Skan char section_start_label[30]; 1433169689Skan 1434169689Skan ASM_GENERATE_INTERNAL_LABEL (section_start_label, "GCC_except_table", 1435169689Skan except_table_label_num++); 1436169689Skan ASM_OUTPUT_LABEL (file, section_start_label); 1437169689Skan} 1438169689Skan/* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */ 1439169689Skan 1440169689Skanvoid 1441169689Skandarwin_non_lazy_pcrel (FILE *file, rtx addr) 1442169689Skan{ 1443169689Skan const char *nlp_name; 1444169689Skan 1445169689Skan gcc_assert (GET_CODE (addr) == SYMBOL_REF); 1446169689Skan 1447169689Skan nlp_name = machopic_indirection_name (addr, /*stub_p=*/false); 1448169689Skan fputs ("\t.long\t", file); 1449169689Skan ASM_OUTPUT_LABELREF (file, nlp_name); 1450169689Skan fputs ("-.", file); 1451169689Skan} 1452169689Skan 1453132718Skan/* Emit an assembler directive to set visibility for a symbol. The 1454132718Skan only supported visibilities are VISIBILITY_DEFAULT and 1455132718Skan VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private 1456132718Skan extern". There is no MACH-O equivalent of ELF's 1457132718Skan VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */ 1458132718Skan 1459169689Skanvoid 1460132718Skandarwin_assemble_visibility (tree decl, int vis) 1461132718Skan{ 1462132718Skan if (vis == VISIBILITY_DEFAULT) 1463132718Skan ; 1464132718Skan else if (vis == VISIBILITY_HIDDEN) 1465132718Skan { 1466132718Skan fputs ("\t.private_extern ", asm_out_file); 1467132718Skan assemble_name (asm_out_file, 1468132718Skan (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)))); 1469132718Skan fputs ("\n", asm_out_file); 1470132718Skan } 1471132718Skan else 1472169689Skan warning (OPT_Wattributes, "internal and protected visibility attributes " 1473169689Skan "not supported in this configuration; ignored"); 1474132718Skan} 1475132718Skan 1476117395Skan/* Output a difference of two labels that will be an assembly time 1477117395Skan constant if the two labels are local. (.long lab1-lab2 will be 1478117395Skan very different if lab1 is at the boundary between two sections; it 1479117395Skan will be relocated according to the second section, not the first, 1480117395Skan so one ends up with a difference between labels in different 1481117395Skan sections, which is bad in the dwarf2 eh context for instance.) */ 1482117395Skan 1483117395Skanstatic int darwin_dwarf_label_counter; 1484117395Skan 1485117395Skanvoid 1486169689Skandarwin_asm_output_dwarf_delta (FILE *file, int size, 1487132718Skan const char *lab1, const char *lab2) 1488117395Skan{ 1489169689Skan int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L' 1490169689Skan && lab2[0] == '*' && lab2[1] == 'L'); 1491169689Skan const char *directive = (size == 8 ? ".quad" : ".long"); 1492117395Skan 1493117395Skan if (islocaldiff) 1494117395Skan fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter); 1495117395Skan else 1496169689Skan fprintf (file, "\t%s\t", directive); 1497169689Skan assemble_name_raw (file, lab1); 1498117395Skan fprintf (file, "-"); 1499169689Skan assemble_name_raw (file, lab2); 1500117395Skan if (islocaldiff) 1501169689Skan fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++); 1502117395Skan} 1503117395Skan 1504169689Skan/* Output labels for the start of the DWARF sections if necessary. */ 1505132718Skanvoid 1506169689Skandarwin_file_start (void) 1507169689Skan{ 1508169689Skan if (write_symbols == DWARF2_DEBUG) 1509169689Skan { 1510169689Skan static const char * const debugnames[] = 1511169689Skan { 1512169689Skan DEBUG_FRAME_SECTION, 1513169689Skan DEBUG_INFO_SECTION, 1514169689Skan DEBUG_ABBREV_SECTION, 1515169689Skan DEBUG_ARANGES_SECTION, 1516169689Skan DEBUG_MACINFO_SECTION, 1517169689Skan DEBUG_LINE_SECTION, 1518169689Skan DEBUG_LOC_SECTION, 1519169689Skan DEBUG_PUBNAMES_SECTION, 1520260395Spfg DEBUG_PUBTYPES_SECTION, 1521169689Skan DEBUG_STR_SECTION, 1522169689Skan DEBUG_RANGES_SECTION 1523169689Skan }; 1524169689Skan size_t i; 1525169689Skan 1526169689Skan for (i = 0; i < ARRAY_SIZE (debugnames); i++) 1527169689Skan { 1528169689Skan int namelen; 1529169689Skan 1530169689Skan switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL)); 1531169689Skan 1532169689Skan gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0); 1533169689Skan gcc_assert (strchr (debugnames[i] + 8, ',')); 1534169689Skan 1535169689Skan namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8); 1536169689Skan fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8); 1537169689Skan } 1538169689Skan } 1539169689Skan} 1540169689Skan 1541169689Skan/* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section 1542169689Skan offsets are not represented using relocs in .o files; either the 1543169689Skan section never leaves the .o file, or the linker or other tool is 1544169689Skan responsible for parsing the DWARF and updating the offsets. */ 1545169689Skan 1546169689Skanvoid 1547169689Skandarwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab, 1548169689Skan section *base) 1549169689Skan{ 1550169689Skan char sname[64]; 1551169689Skan int namelen; 1552169689Skan 1553169689Skan gcc_assert (base->common.flags & SECTION_NAMED); 1554169689Skan gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0); 1555169689Skan gcc_assert (strchr (base->named.name + 8, ',')); 1556169689Skan 1557169689Skan namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8); 1558169689Skan sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8); 1559169689Skan darwin_asm_output_dwarf_delta (file, size, lab, sname); 1560169689Skan} 1561169689Skan 1562169689Skanvoid 1563132718Skandarwin_file_end (void) 1564132718Skan{ 1565132718Skan machopic_finish (asm_out_file); 1566132718Skan if (strcmp (lang_hooks.name, "GNU C++") == 0) 1567132718Skan { 1568169689Skan switch_to_section (darwin_sections[constructor_section]); 1569169689Skan switch_to_section (darwin_sections[destructor_section]); 1570132718Skan ASM_OUTPUT_ALIGN (asm_out_file, 1); 1571132718Skan } 1572169689Skan fprintf (asm_out_file, "\t.subsections_via_symbols\n"); 1573132718Skan} 1574132718Skan 1575169689Skan/* TODO: Add a language hook for identifying if a decl is a vtable. */ 1576169689Skan#define DARWIN_VTABLE_P(DECL) 0 1577169689Skan 1578169689Skan/* Cross-module name binding. Darwin does not support overriding 1579169689Skan functions at dynamic-link time, except for vtables in kexts. */ 1580169689Skan 1581169689Skanbool 1582169689Skandarwin_binds_local_p (tree decl) 1583169689Skan{ 1584169689Skan return default_binds_local_p_1 (decl, 1585169689Skan TARGET_KEXTABI && DARWIN_VTABLE_P (decl)); 1586169689Skan} 1587169689Skan 1588169689Skan#if 0 1589169689Skan/* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet. */ 1590169689Skan/* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR. Define the 1591169689Skan anchor relative to ".", the current section position. We cannot use 1592169689Skan the default one because ASM_OUTPUT_DEF is wrong for Darwin. */ 1593169689Skan 1594169689Skanvoid 1595169689Skandarwin_asm_output_anchor (rtx symbol) 1596169689Skan{ 1597169689Skan fprintf (asm_out_file, "\t.set\t"); 1598169689Skan assemble_name (asm_out_file, XSTR (symbol, 0)); 1599169689Skan fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n", 1600169689Skan SYMBOL_REF_BLOCK_OFFSET (symbol)); 1601169689Skan} 1602169689Skan#endif 1603169689Skan 1604169689Skan/* Set the darwin specific attributes on TYPE. */ 1605169689Skanvoid 1606169689Skandarwin_set_default_type_attributes (tree type) 1607169689Skan{ 1608169689Skan if (darwin_ms_struct 1609169689Skan && TREE_CODE (type) == RECORD_TYPE) 1610169689Skan TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"), 1611169689Skan NULL_TREE, 1612169689Skan TYPE_ATTRIBUTES (type)); 1613169689Skan} 1614169689Skan 1615169689Skan/* True, iff we're generating code for loadable kernel extentions. */ 1616169689Skan 1617169689Skanbool 1618169689Skandarwin_kextabi_p (void) { 1619169689Skan return flag_apple_kext; 1620169689Skan} 1621169689Skan 1622169689Skanvoid 1623169689Skandarwin_override_options (void) 1624169689Skan{ 1625169689Skan if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0) 1626169689Skan { 1627169689Skan warning (0, "command line option %<-fapple-kext%> is only valid for C++"); 1628169689Skan flag_apple_kext = 0; 1629169689Skan } 1630169689Skan if (flag_mkernel || flag_apple_kext) 1631169689Skan { 1632169689Skan /* -mkernel implies -fapple-kext for C++ */ 1633169689Skan if (strcmp (lang_hooks.name, "GNU C++") == 0) 1634169689Skan flag_apple_kext = 1; 1635169689Skan 1636169689Skan flag_no_common = 1; 1637169689Skan 1638169689Skan /* No EH in kexts. */ 1639169689Skan flag_exceptions = 0; 1640169689Skan /* No -fnon-call-exceptions data in kexts. */ 1641169689Skan flag_non_call_exceptions = 0; 1642169689Skan } 1643169689Skan} 1644169689Skan 1645117395Skan#include "gt-darwin.h" 1646