darwin.c revision 117395
1/* Functions for generic Darwin as target machine for GNU C compiler. 2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002 3 Free Software Foundation, Inc. 4 Contributed by Apple Computer Inc. 5 6This file is part of GNU CC. 7 8GNU CC is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 2, or (at your option) 11any later version. 12 13GNU CC is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with GNU CC; see the file COPYING. If not, write to 20the Free Software Foundation, 59 Temple Place - Suite 330, 21Boston, MA 02111-1307, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "rtl.h" 26#include "regs.h" 27#include "hard-reg-set.h" 28#include "real.h" 29#include "insn-config.h" 30#include "conditions.h" 31#include "insn-flags.h" 32#include "output.h" 33#include "insn-attr.h" 34#include "flags.h" 35#include "tree.h" 36#include "expr.h" 37#include "reload.h" 38#include "function.h" 39#include "ggc.h" 40#include "langhooks.h" 41#include "tm_p.h" 42 43static int machopic_data_defined_p PARAMS ((const char *)); 44static void update_non_lazy_ptrs PARAMS ((const char *)); 45static void update_stubs PARAMS ((const char *)); 46 47int 48name_needs_quotes (name) 49 const char *name; 50{ 51 int c; 52 while ((c = *name++) != '\0') 53 if (! ISIDNUM (c)) 54 return 1; 55 return 0; 56} 57 58/* 59 * flag_pic = 1 ... generate only indirections 60 * flag_pic = 2 ... generate indirections and pure code 61 */ 62 63/* This module assumes that (const (symbol_ref "foo")) is a legal pic 64 reference, which will not be changed. */ 65 66static GTY(()) tree machopic_defined_list; 67 68enum machopic_addr_class 69machopic_classify_ident (ident) 70 tree ident; 71{ 72 const char *name = IDENTIFIER_POINTER (ident); 73 int lprefix = (((name[0] == '*' || name[0] == '&') 74 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L'))) 75 || ( name[0] == '_' 76 && name[1] == 'O' 77 && name[2] == 'B' 78 && name[3] == 'J' 79 && name[4] == 'C' 80 && name[5] == '_')); 81 tree temp; 82 83 if (name[0] != '!') 84 { 85 /* Here if no special encoding to be found. */ 86 if (lprefix) 87 { 88 const char *name = IDENTIFIER_POINTER (ident); 89 int len = strlen (name); 90 91 if ((len > 5 && !strcmp (name + len - 5, "$stub")) 92 || (len > 6 && !strcmp (name + len - 6, "$stub\""))) 93 return MACHOPIC_DEFINED_FUNCTION; 94 return MACHOPIC_DEFINED_DATA; 95 } 96 97 for (temp = machopic_defined_list; 98 temp != NULL_TREE; 99 temp = TREE_CHAIN (temp)) 100 { 101 if (ident == TREE_VALUE (temp)) 102 return MACHOPIC_DEFINED_DATA; 103 } 104 105 if (TREE_ASM_WRITTEN (ident)) 106 return MACHOPIC_DEFINED_DATA; 107 108 return MACHOPIC_UNDEFINED; 109 } 110 111 else if (name[1] == 'D') 112 return MACHOPIC_DEFINED_DATA; 113 114 else if (name[1] == 'T') 115 return MACHOPIC_DEFINED_FUNCTION; 116 117 /* It is possible that someone is holding a "stale" name, which has 118 since been defined. See if there is a "defined" name (i.e, 119 different from NAME only in having a '!D_' or a '!T_' instead of 120 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say 121 that this identifier is defined. */ 122 else if (name[1] == 'd' || name[1] == 't') 123 { 124 char *new_name; 125 new_name = (char *)alloca (strlen (name) + 1); 126 strcpy (new_name, name); 127 new_name[1] = (name[1] == 'd') ? 'D' : 'T'; 128 if (maybe_get_identifier (new_name) != NULL) 129 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA 130 : MACHOPIC_DEFINED_FUNCTION; 131 } 132 133 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp)) 134 { 135 if (ident == TREE_VALUE (temp)) 136 { 137 if (name[1] == 'T') 138 return MACHOPIC_DEFINED_FUNCTION; 139 else 140 return MACHOPIC_DEFINED_DATA; 141 } 142 } 143 144 if (name[1] == 't' || name[1] == 'T') 145 { 146 if (lprefix) 147 return MACHOPIC_DEFINED_FUNCTION; 148 else 149 return MACHOPIC_UNDEFINED_FUNCTION; 150 } 151 else 152 { 153 if (lprefix) 154 return MACHOPIC_DEFINED_DATA; 155 else 156 return MACHOPIC_UNDEFINED_DATA; 157 } 158} 159 160 161enum machopic_addr_class 162machopic_classify_name (name) 163 const char *name; 164{ 165 return machopic_classify_ident (get_identifier (name)); 166} 167 168int 169machopic_ident_defined_p (ident) 170 tree ident; 171{ 172 switch (machopic_classify_ident (ident)) 173 { 174 case MACHOPIC_UNDEFINED: 175 case MACHOPIC_UNDEFINED_DATA: 176 case MACHOPIC_UNDEFINED_FUNCTION: 177 return 0; 178 default: 179 return 1; 180 } 181} 182 183static int 184machopic_data_defined_p (name) 185 const char *name; 186{ 187 switch (machopic_classify_ident (get_identifier (name))) 188 { 189 case MACHOPIC_DEFINED_DATA: 190 return 1; 191 default: 192 return 0; 193 } 194} 195 196int 197machopic_name_defined_p (name) 198 const char *name; 199{ 200 return machopic_ident_defined_p (get_identifier (name)); 201} 202 203void 204machopic_define_ident (ident) 205 tree ident; 206{ 207 if (!machopic_ident_defined_p (ident)) 208 machopic_defined_list = 209 tree_cons (NULL_TREE, ident, machopic_defined_list); 210} 211 212void 213machopic_define_name (name) 214 const char *name; 215{ 216 machopic_define_ident (get_identifier (name)); 217} 218 219/* This is a static to make inline functions work. The rtx 220 representing the PIC base symbol always points to here. */ 221 222static char function_base[32]; 223 224static int current_pic_label_num; 225 226const char * 227machopic_function_base_name () 228{ 229 static const char *name = NULL; 230 static const char *current_name; 231 232 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); 233 234 if (name != current_name) 235 { 236 current_function_uses_pic_offset_table = 1; 237 238 /* Save mucho space and time. Some of the C++ mangled names are over 239 700 characters long! Note that we produce a label containing a '-' 240 if the function we're compiling is an Objective-C method, as evinced 241 by the incredibly scientific test below. This is because code in 242 rs6000.c makes the same ugly test when loading the PIC reg. */ 243 244 ++current_pic_label_num; 245 if (*current_name == '+' || *current_name == '-') 246 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num); 247 else 248 sprintf (function_base, "*L%d$pb", current_pic_label_num); 249 250 name = current_name; 251 } 252 253 return function_base; 254} 255 256static GTY(()) tree machopic_non_lazy_pointers; 257 258/* Return a non-lazy pointer name corresponding to the given name, 259 either by finding it in our list of pointer names, or by generating 260 a new one. */ 261 262const char * 263machopic_non_lazy_ptr_name (name) 264 const char *name; 265{ 266 const char *temp_name; 267 tree temp, ident = get_identifier (name); 268 269 for (temp = machopic_non_lazy_pointers; 270 temp != NULL_TREE; 271 temp = TREE_CHAIN (temp)) 272 { 273 if (ident == TREE_VALUE (temp)) 274 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 275 } 276 277 name = darwin_strip_name_encoding (name); 278 279 /* Try again, but comparing names this time. */ 280 for (temp = machopic_non_lazy_pointers; 281 temp != NULL_TREE; 282 temp = TREE_CHAIN (temp)) 283 { 284 if (TREE_VALUE (temp)) 285 { 286 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 287 temp_name = darwin_strip_name_encoding (temp_name); 288 if (strcmp (name, temp_name) == 0) 289 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 290 } 291 } 292 293 { 294 char *buffer; 295 tree ptr_name; 296 297 buffer = alloca (strlen (name) + 20); 298 299 strcpy (buffer, "&L"); 300 if (name[0] == '*') 301 strcat (buffer, name+1); 302 else 303 { 304 strcat (buffer, "_"); 305 strcat (buffer, name); 306 } 307 308 strcat (buffer, "$non_lazy_ptr"); 309 ptr_name = get_identifier (buffer); 310 311 machopic_non_lazy_pointers 312 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers); 313 314 TREE_USED (machopic_non_lazy_pointers) = 0; 315 316 return IDENTIFIER_POINTER (ptr_name); 317 } 318} 319 320static GTY(()) tree machopic_stubs; 321 322/* Return the name of the stub corresponding to the given name, 323 generating a new stub name if necessary. */ 324 325const char * 326machopic_stub_name (name) 327 const char *name; 328{ 329 tree temp, ident = get_identifier (name); 330 const char *tname; 331 332 for (temp = machopic_stubs; 333 temp != NULL_TREE; 334 temp = TREE_CHAIN (temp)) 335 { 336 if (ident == TREE_VALUE (temp)) 337 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 338 tname = IDENTIFIER_POINTER (TREE_VALUE (temp)); 339 if (strcmp (name, tname) == 0) 340 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 341 /* A library call name might not be section-encoded yet, so try 342 it against a stripped name. */ 343 if (name[0] != '!' 344 && tname[0] == '!' 345 && strcmp (name, tname + 4) == 0) 346 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 347 } 348 349 name = darwin_strip_name_encoding (name); 350 351 { 352 char *buffer; 353 tree ptr_name; 354 int needs_quotes = name_needs_quotes (name); 355 356 buffer = alloca (strlen (name) + 20); 357 358 if (needs_quotes) 359 strcpy (buffer, "&\"L"); 360 else 361 strcpy (buffer, "&L"); 362 if (name[0] == '*') 363 { 364 strcat (buffer, name+1); 365 } 366 else 367 { 368 strcat (buffer, "_"); 369 strcat (buffer, name); 370 } 371 372 if (needs_quotes) 373 strcat (buffer, "$stub\""); 374 else 375 strcat (buffer, "$stub"); 376 ptr_name = get_identifier (buffer); 377 378 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs); 379 TREE_USED (machopic_stubs) = 0; 380 381 return IDENTIFIER_POINTER (ptr_name); 382 } 383} 384 385void 386machopic_validate_stub_or_non_lazy_ptr (name, validate_stub) 387 const char *name; 388 int validate_stub; 389{ 390 const char *real_name; 391 tree temp, ident = get_identifier (name), id2; 392 393 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers); 394 temp != NULL_TREE; 395 temp = TREE_CHAIN (temp)) 396 if (ident == TREE_PURPOSE (temp)) 397 { 398 /* Mark both the stub or non-lazy pointer as well as the 399 original symbol as being referenced. */ 400 TREE_USED (temp) = 1; 401 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE) 402 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1; 403 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 404 real_name = darwin_strip_name_encoding (real_name); 405 id2 = maybe_get_identifier (real_name); 406 if (id2) 407 TREE_SYMBOL_REFERENCED (id2) = 1; 408 } 409} 410 411/* Transform ORIG, which may be any data source, to the corresponding 412 source using indirections. */ 413 414rtx 415machopic_indirect_data_reference (orig, reg) 416 rtx orig, reg; 417{ 418 rtx ptr_ref = orig; 419 420 if (! MACHOPIC_INDIRECT) 421 return orig; 422 423 if (GET_CODE (orig) == SYMBOL_REF) 424 { 425 const char *name = XSTR (orig, 0); 426 427 if (machopic_data_defined_p (name)) 428 { 429#if defined (TARGET_TOC) || defined (HAVE_lo_sum) 430 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 431 machopic_function_base_name ()); 432 rtx offset = gen_rtx (CONST, Pmode, 433 gen_rtx (MINUS, Pmode, orig, pic_base)); 434#endif 435 436#if defined (TARGET_TOC) /* i.e., PowerPC */ 437 rtx hi_sum_reg = reg; 438 439 if (reg == NULL) 440 abort (); 441 442 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 443 gen_rtx (PLUS, Pmode, pic_offset_table_rtx, 444 gen_rtx (HIGH, Pmode, offset)))); 445 emit_insn (gen_rtx (SET, Pmode, reg, 446 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset))); 447 448 orig = reg; 449#else 450#if defined (HAVE_lo_sum) 451 if (reg == 0) abort (); 452 453 emit_insn (gen_rtx (SET, VOIDmode, reg, 454 gen_rtx (HIGH, Pmode, offset))); 455 emit_insn (gen_rtx (SET, VOIDmode, reg, 456 gen_rtx (LO_SUM, Pmode, reg, offset))); 457 emit_insn (gen_rtx (USE, VOIDmode, 458 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM))); 459 460 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg); 461#endif 462#endif 463 return orig; 464 } 465 466 ptr_ref = gen_rtx (SYMBOL_REF, Pmode, 467 machopic_non_lazy_ptr_name (name)); 468 469 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref); 470 RTX_UNCHANGING_P (ptr_ref) = 1; 471 472 return ptr_ref; 473 } 474 else if (GET_CODE (orig) == CONST) 475 { 476 rtx base, result; 477 478 /* legitimize both operands of the PLUS */ 479 if (GET_CODE (XEXP (orig, 0)) == PLUS) 480 { 481 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), 482 reg); 483 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1), 484 (base == reg ? 0 : reg)); 485 } 486 else 487 return orig; 488 489 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT) 490 result = plus_constant (base, INTVAL (orig)); 491 else 492 result = gen_rtx (PLUS, Pmode, base, orig); 493 494 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM) 495 { 496 if (reg) 497 { 498 emit_move_insn (reg, result); 499 result = reg; 500 } 501 else 502 { 503 result = force_reg (GET_MODE (result), result); 504 } 505 } 506 507 return result; 508 509 } 510 else if (GET_CODE (orig) == MEM) 511 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg); 512 /* When the target is i386, this code prevents crashes due to the 513 compiler's ignorance on how to move the PIC base register to 514 other registers. (The reload phase sometimes introduces such 515 insns.) */ 516 else if (GET_CODE (orig) == PLUS 517 && GET_CODE (XEXP (orig, 0)) == REG 518 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM 519#ifdef I386 520 /* Prevent the same register from being erroneously used 521 as both the base and index registers. */ 522 && GET_CODE (XEXP (orig, 1)) == CONST 523#endif 524 && reg) 525 { 526 emit_move_insn (reg, XEXP (orig, 0)); 527 XEXP (ptr_ref, 0) = reg; 528 } 529 return ptr_ref; 530} 531 532/* Transform TARGET (a MEM), which is a function call target, to the 533 corresponding symbol_stub if necessary. Return a new MEM. */ 534 535rtx 536machopic_indirect_call_target (target) 537 rtx target; 538{ 539 if (GET_CODE (target) != MEM) 540 return target; 541 542 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF) 543 { 544 enum machine_mode mode = GET_MODE (XEXP (target, 0)); 545 const char *name = XSTR (XEXP (target, 0), 0); 546 547 /* If the name is already defined, we need do nothing. */ 548 if (name[0] == '!' && name[1] == 'T') 549 return target; 550 551 if (!machopic_name_defined_p (name)) 552 { 553 const char *stub_name = machopic_stub_name (name); 554 555 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name); 556 RTX_UNCHANGING_P (target) = 1; 557 } 558 } 559 560 return target; 561} 562 563rtx 564machopic_legitimize_pic_address (orig, mode, reg) 565 rtx orig, reg; 566 enum machine_mode mode; 567{ 568 rtx pic_ref = orig; 569 570 if (! MACHOPIC_PURE) 571 return orig; 572 573 /* First handle a simple SYMBOL_REF or LABEL_REF */ 574 if (GET_CODE (orig) == LABEL_REF 575 || (GET_CODE (orig) == SYMBOL_REF 576 )) 577 { 578 /* addr(foo) = &func+(foo-func) */ 579 rtx pic_base; 580 581 orig = machopic_indirect_data_reference (orig, reg); 582 583 if (GET_CODE (orig) == PLUS 584 && GET_CODE (XEXP (orig, 0)) == REG) 585 { 586 if (reg == 0) 587 return force_reg (mode, orig); 588 589 emit_move_insn (reg, orig); 590 return reg; 591 } 592 593 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ()); 594 595 if (GET_CODE (orig) == MEM) 596 { 597 if (reg == 0) 598 { 599 if (reload_in_progress) 600 abort (); 601 else 602 reg = gen_reg_rtx (Pmode); 603 } 604 605#ifdef HAVE_lo_sum 606 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 607 || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 608 { 609 rtx offset = gen_rtx (CONST, Pmode, 610 gen_rtx (MINUS, Pmode, 611 XEXP (orig, 0), pic_base)); 612#if defined (TARGET_TOC) /* i.e., PowerPC */ 613 /* Generating a new reg may expose opportunities for 614 common subexpression elimination. */ 615 rtx hi_sum_reg = 616 (reload_in_progress ? reg : gen_reg_rtx (SImode)); 617 618 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 619 gen_rtx (PLUS, Pmode, 620 pic_offset_table_rtx, 621 gen_rtx (HIGH, Pmode, offset)))); 622 emit_insn (gen_rtx (SET, VOIDmode, reg, 623 gen_rtx (MEM, GET_MODE (orig), 624 gen_rtx (LO_SUM, Pmode, 625 hi_sum_reg, offset)))); 626 pic_ref = reg; 627 628#else 629 emit_insn (gen_rtx (USE, VOIDmode, 630 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM))); 631 632 emit_insn (gen_rtx (SET, VOIDmode, reg, 633 gen_rtx (HIGH, Pmode, 634 gen_rtx (CONST, Pmode, offset)))); 635 emit_insn (gen_rtx (SET, VOIDmode, reg, 636 gen_rtx (LO_SUM, Pmode, reg, 637 gen_rtx (CONST, Pmode, offset)))); 638 pic_ref = gen_rtx (PLUS, Pmode, 639 pic_offset_table_rtx, reg); 640#endif 641 } 642 else 643#endif /* HAVE_lo_sum */ 644 { 645 rtx pic = pic_offset_table_rtx; 646 if (GET_CODE (pic) != REG) 647 { 648 emit_move_insn (reg, pic); 649 pic = reg; 650 } 651#if 0 652 emit_insn (gen_rtx (USE, VOIDmode, 653 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); 654#endif 655 656 pic_ref = gen_rtx (PLUS, Pmode, 657 pic, 658 gen_rtx (CONST, Pmode, 659 gen_rtx (MINUS, Pmode, 660 XEXP (orig, 0), 661 pic_base))); 662 } 663 664#if !defined (TARGET_TOC) 665 emit_move_insn (reg, pic_ref); 666 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg); 667#endif 668 RTX_UNCHANGING_P (pic_ref) = 1; 669 } 670 else 671 { 672 673#ifdef HAVE_lo_sum 674 if (GET_CODE (orig) == SYMBOL_REF 675 || GET_CODE (orig) == LABEL_REF) 676 { 677 rtx offset = gen_rtx (CONST, Pmode, 678 gen_rtx (MINUS, Pmode, orig, pic_base)); 679#if defined (TARGET_TOC) /* i.e., PowerPC */ 680 rtx hi_sum_reg; 681 682 if (reg == 0) 683 { 684 if (reload_in_progress) 685 abort (); 686 else 687 reg = gen_reg_rtx (SImode); 688 } 689 690 hi_sum_reg = reg; 691 692 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 693 gen_rtx (PLUS, Pmode, 694 pic_offset_table_rtx, 695 gen_rtx (HIGH, Pmode, offset)))); 696 emit_insn (gen_rtx (SET, VOIDmode, reg, 697 gen_rtx (LO_SUM, Pmode, 698 hi_sum_reg, offset))); 699 pic_ref = reg; 700 RTX_UNCHANGING_P (pic_ref) = 1; 701#else 702 emit_insn (gen_rtx (SET, VOIDmode, reg, 703 gen_rtx (HIGH, Pmode, offset))); 704 emit_insn (gen_rtx (SET, VOIDmode, reg, 705 gen_rtx (LO_SUM, Pmode, reg, offset))); 706 pic_ref = gen_rtx (PLUS, Pmode, 707 pic_offset_table_rtx, reg); 708 RTX_UNCHANGING_P (pic_ref) = 1; 709#endif 710 } 711 else 712#endif /* HAVE_lo_sum */ 713 { 714 if (GET_CODE (orig) == REG) 715 { 716 return orig; 717 } 718 else 719 { 720 rtx pic = pic_offset_table_rtx; 721 if (GET_CODE (pic) != REG) 722 { 723 emit_move_insn (reg, pic); 724 pic = reg; 725 } 726#if 0 727 emit_insn (gen_rtx (USE, VOIDmode, 728 pic_offset_table_rtx)); 729#endif 730 pic_ref = gen_rtx (PLUS, Pmode, 731 pic, 732 gen_rtx (CONST, Pmode, 733 gen_rtx (MINUS, Pmode, 734 orig, pic_base))); 735 } 736 } 737 } 738 739 if (GET_CODE (pic_ref) != REG) 740 { 741 if (reg != 0) 742 { 743 emit_move_insn (reg, pic_ref); 744 return reg; 745 } 746 else 747 { 748 return force_reg (mode, pic_ref); 749 } 750 } 751 else 752 { 753 return pic_ref; 754 } 755 } 756 757 else if (GET_CODE (orig) == SYMBOL_REF) 758 return orig; 759 760 else if (GET_CODE (orig) == PLUS 761 && (GET_CODE (XEXP (orig, 0)) == MEM 762 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 763 || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 764 && XEXP (orig, 0) != pic_offset_table_rtx 765 && GET_CODE (XEXP (orig, 1)) != REG) 766 767 { 768 rtx base; 769 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM); 770 771 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 772 orig = machopic_legitimize_pic_address (XEXP (orig, 1), 773 Pmode, (base == reg ? 0 : reg)); 774 if (GET_CODE (orig) == CONST_INT) 775 { 776 pic_ref = plus_constant (base, INTVAL (orig)); 777 is_complex = 1; 778 } 779 else 780 pic_ref = gen_rtx (PLUS, Pmode, base, orig); 781 782 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig)) 783 RTX_UNCHANGING_P (pic_ref) = 1; 784 785 if (reg && is_complex) 786 { 787 emit_move_insn (reg, pic_ref); 788 pic_ref = reg; 789 } 790 /* Likewise, should we set special REG_NOTEs here? */ 791 } 792 793 else if (GET_CODE (orig) == CONST) 794 { 795 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 796 } 797 798 else if (GET_CODE (orig) == MEM 799 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF) 800 { 801 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 802 803 addr = gen_rtx (MEM, GET_MODE (orig), addr); 804 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig); 805 emit_move_insn (reg, addr); 806 pic_ref = reg; 807 } 808 809 return pic_ref; 810} 811 812 813void 814machopic_finish (asm_out_file) 815 FILE *asm_out_file; 816{ 817 tree temp; 818 819 for (temp = machopic_stubs; 820 temp != NULL_TREE; 821 temp = TREE_CHAIN (temp)) 822 { 823 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 824 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 825 char *sym; 826 char *stub; 827 828 if (! TREE_USED (temp)) 829 continue; 830 831 /* If the symbol is actually defined, we don't need a stub. */ 832 if (sym_name[0] == '!' && sym_name[1] == 'T') 833 continue; 834 835 sym_name = darwin_strip_name_encoding (sym_name); 836 837 sym = alloca (strlen (sym_name) + 2); 838 if (sym_name[0] == '*' || sym_name[0] == '&') 839 strcpy (sym, sym_name + 1); 840 else if (sym_name[0] == '-' || sym_name[0] == '+') 841 strcpy (sym, sym_name); 842 else 843 sym[0] = '_', strcpy (sym + 1, sym_name); 844 845 stub = alloca (strlen (stub_name) + 2); 846 if (stub_name[0] == '*' || stub_name[0] == '&') 847 strcpy (stub, stub_name + 1); 848 else 849 stub[0] = '_', strcpy (stub + 1, stub_name); 850 851 machopic_output_stub (asm_out_file, sym, stub); 852 } 853 854 for (temp = machopic_non_lazy_pointers; 855 temp != NULL_TREE; 856 temp = TREE_CHAIN (temp)) 857 { 858 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 859 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 860 861 if (! TREE_USED (temp)) 862 continue; 863 864 if (machopic_ident_defined_p (TREE_VALUE (temp))) 865 { 866 data_section (); 867 assemble_align (GET_MODE_ALIGNMENT (Pmode)); 868 assemble_label (lazy_name); 869 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name), 870 GET_MODE_SIZE (Pmode), 871 GET_MODE_ALIGNMENT (Pmode), 1); 872 } 873 else 874 { 875 machopic_nl_symbol_ptr_section (); 876 assemble_name (asm_out_file, lazy_name); 877 fprintf (asm_out_file, ":\n"); 878 879 fprintf (asm_out_file, "\t.indirect_symbol "); 880 assemble_name (asm_out_file, sym_name); 881 fprintf (asm_out_file, "\n"); 882 883 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 884 GET_MODE_ALIGNMENT (Pmode), 1); 885 } 886 } 887} 888 889int 890machopic_operand_p (op) 891 rtx op; 892{ 893 if (MACHOPIC_JUST_INDIRECT) 894 { 895 while (GET_CODE (op) == CONST) 896 op = XEXP (op, 0); 897 898 if (GET_CODE (op) == SYMBOL_REF) 899 return machopic_name_defined_p (XSTR (op, 0)); 900 else 901 return 0; 902 } 903 904 while (GET_CODE (op) == CONST) 905 op = XEXP (op, 0); 906 907 if (GET_CODE (op) == MINUS 908 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF 909 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF 910 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0)) 911 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0))) 912 return 1; 913 914 return 0; 915} 916 917/* This function records whether a given name corresponds to a defined 918 or undefined function or variable, for machopic_classify_ident to 919 use later. */ 920 921void 922darwin_encode_section_info (decl, first) 923 tree decl; 924 int first ATTRIBUTE_UNUSED; 925{ 926 char code = '\0'; 927 int defined = 0; 928 rtx sym_ref; 929 const char *orig_str; 930 char *new_str; 931 size_t len, new_len; 932 933 if ((TREE_CODE (decl) == FUNCTION_DECL 934 || TREE_CODE (decl) == VAR_DECL) 935 && !DECL_EXTERNAL (decl) 936 && ((TREE_STATIC (decl) 937 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl))) 938 || (DECL_INITIAL (decl) 939 && DECL_INITIAL (decl) != error_mark_node))) 940 defined = 1; 941 942 if (TREE_CODE (decl) == FUNCTION_DECL) 943 code = (defined ? 'T' : 't'); 944 else if (TREE_CODE (decl) == VAR_DECL) 945 code = (defined ? 'D' : 'd'); 946 947 if (code == '\0') 948 return; 949 950 sym_ref = XEXP (DECL_RTL (decl), 0); 951 orig_str = XSTR (sym_ref, 0); 952 len = strlen (orig_str) + 1; 953 954 if (orig_str[0] == '!') 955 { 956 /* Already encoded; see if we need to change it. */ 957 if (code == orig_str[1]) 958 return; 959 /* Yes, tweak a copy of the name and put it in a new string. */ 960 new_str = alloca (len); 961 memcpy (new_str, orig_str, len); 962 new_str[1] = code; 963 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len); 964 } 965 else 966 { 967 /* Add the encoding. */ 968 new_len = len + 4; 969 new_str = alloca (new_len); 970 new_str[0] = '!'; 971 new_str[1] = code; 972 new_str[2] = '_'; 973 new_str[3] = '_'; 974 memcpy (new_str + 4, orig_str, len); 975 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len); 976 } 977 /* The non-lazy pointer list may have captured references to the 978 old encoded name, change them. */ 979 if (TREE_CODE (decl) == VAR_DECL) 980 update_non_lazy_ptrs (XSTR (sym_ref, 0)); 981 else 982 update_stubs (XSTR (sym_ref, 0)); 983} 984 985/* Undo the effects of the above. */ 986 987const char * 988darwin_strip_name_encoding (str) 989 const char *str; 990{ 991 return str[0] == '!' ? str + 4 : str; 992} 993 994/* Scan the list of non-lazy pointers and update any recorded names whose 995 stripped name matches the argument. */ 996 997static void 998update_non_lazy_ptrs (name) 999 const char *name; 1000{ 1001 const char *name1, *name2; 1002 tree temp; 1003 1004 name1 = darwin_strip_name_encoding (name); 1005 1006 for (temp = machopic_non_lazy_pointers; 1007 temp != NULL_TREE; 1008 temp = TREE_CHAIN (temp)) 1009 { 1010 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1011 1012 if (*sym_name == '!') 1013 { 1014 name2 = darwin_strip_name_encoding (sym_name); 1015 if (strcmp (name1, name2) == 0) 1016 { 1017 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name; 1018 break; 1019 } 1020 } 1021 } 1022} 1023 1024/* Function NAME is being defined, and its label has just been output. 1025 If there's already a reference to a stub for this function, we can 1026 just emit the stub label now and we don't bother emitting the stub later. */ 1027 1028void 1029machopic_output_possible_stub_label (file, name) 1030 FILE *file; 1031 const char *name; 1032{ 1033 tree temp; 1034 1035 1036 /* Ensure we're looking at a section-encoded name. */ 1037 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T')) 1038 return; 1039 1040 for (temp = machopic_stubs; 1041 temp != NULL_TREE; 1042 temp = TREE_CHAIN (temp)) 1043 { 1044 const char *sym_name; 1045 1046 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1047 if (sym_name[0] == '!' && sym_name[1] == 'T' 1048 && ! strcmp (name+2, sym_name+2)) 1049 { 1050 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp))); 1051 /* Avoid generating a stub for this. */ 1052 TREE_USED (temp) = 0; 1053 break; 1054 } 1055 } 1056} 1057 1058/* Scan the list of stubs and update any recorded names whose 1059 stripped name matches the argument. */ 1060 1061static void 1062update_stubs (name) 1063 const char *name; 1064{ 1065 const char *name1, *name2; 1066 tree temp; 1067 1068 name1 = darwin_strip_name_encoding (name); 1069 1070 for (temp = machopic_stubs; 1071 temp != NULL_TREE; 1072 temp = TREE_CHAIN (temp)) 1073 { 1074 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1075 1076 if (*sym_name == '!') 1077 { 1078 name2 = darwin_strip_name_encoding (sym_name); 1079 if (strcmp (name1, name2) == 0) 1080 { 1081 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name; 1082 break; 1083 } 1084 } 1085 } 1086} 1087 1088void 1089machopic_select_section (exp, reloc, align) 1090 tree exp; 1091 int reloc; 1092 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 1093{ 1094 if (TREE_CODE (exp) == STRING_CST) 1095 { 1096 if (flag_writable_strings) 1097 data_section (); 1098 else if (TREE_STRING_LENGTH (exp) != 1099 strlen (TREE_STRING_POINTER (exp)) + 1) 1100 readonly_data_section (); 1101 else 1102 cstring_section (); 1103 } 1104 else if (TREE_CODE (exp) == INTEGER_CST 1105 || TREE_CODE (exp) == REAL_CST) 1106 { 1107 tree size = TYPE_SIZE (TREE_TYPE (exp)); 1108 1109 if (TREE_CODE (size) == INTEGER_CST && 1110 TREE_INT_CST_LOW (size) == 4 && 1111 TREE_INT_CST_HIGH (size) == 0) 1112 literal4_section (); 1113 else if (TREE_CODE (size) == INTEGER_CST && 1114 TREE_INT_CST_LOW (size) == 8 && 1115 TREE_INT_CST_HIGH (size) == 0) 1116 literal8_section (); 1117 else 1118 readonly_data_section (); 1119 } 1120 else if (TREE_CODE (exp) == CONSTRUCTOR 1121 && TREE_TYPE (exp) 1122 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE 1123 && TYPE_NAME (TREE_TYPE (exp))) 1124 { 1125 tree name = TYPE_NAME (TREE_TYPE (exp)); 1126 if (TREE_CODE (name) == TYPE_DECL) 1127 name = DECL_NAME (name); 1128 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString")) 1129 objc_constant_string_object_section (); 1130 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString")) 1131 objc_string_object_section (); 1132 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp)) 1133 { 1134 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc)) 1135 const_data_section (); 1136 else 1137 readonly_data_section (); 1138 } 1139 else 1140 data_section (); 1141 } 1142 else if (TREE_CODE (exp) == VAR_DECL && 1143 DECL_NAME (exp) && 1144 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE && 1145 IDENTIFIER_POINTER (DECL_NAME (exp)) && 1146 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6)) 1147 { 1148 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp)); 1149 1150 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20)) 1151 objc_cls_meth_section (); 1152 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23)) 1153 objc_inst_meth_section (); 1154 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20)) 1155 objc_cat_cls_meth_section (); 1156 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23)) 1157 objc_cat_inst_meth_section (); 1158 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22)) 1159 objc_class_vars_section (); 1160 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25)) 1161 objc_instance_vars_section (); 1162 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22)) 1163 objc_cat_cls_meth_section (); 1164 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17)) 1165 objc_class_names_section (); 1166 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20)) 1167 objc_meth_var_names_section (); 1168 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20)) 1169 objc_meth_var_types_section (); 1170 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22)) 1171 objc_cls_refs_section (); 1172 else if (!strncmp (name, "_OBJC_CLASS_", 12)) 1173 objc_class_section (); 1174 else if (!strncmp (name, "_OBJC_METACLASS_", 16)) 1175 objc_meta_class_section (); 1176 else if (!strncmp (name, "_OBJC_CATEGORY_", 15)) 1177 objc_category_section (); 1178 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25)) 1179 objc_selector_refs_section (); 1180 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20)) 1181 objc_selector_fixup_section (); 1182 else if (!strncmp (name, "_OBJC_SYMBOLS", 13)) 1183 objc_symbols_section (); 1184 else if (!strncmp (name, "_OBJC_MODULES", 13)) 1185 objc_module_info_section (); 1186 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32)) 1187 objc_cat_inst_meth_section (); 1188 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29)) 1189 objc_cat_cls_meth_section (); 1190 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20)) 1191 objc_cat_cls_meth_section (); 1192 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15)) 1193 objc_protocol_section (); 1194 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp)) 1195 && !TREE_SIDE_EFFECTS (exp)) 1196 { 1197 if (flag_pic && reloc) 1198 const_data_section (); 1199 else 1200 readonly_data_section (); 1201 } 1202 else 1203 data_section (); 1204 } 1205 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp)) 1206 { 1207 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc)) 1208 const_data_section (); 1209 else 1210 readonly_data_section (); 1211 } 1212 else 1213 data_section (); 1214} 1215 1216/* This can be called with address expressions as "rtx". 1217 They must go in "const". */ 1218 1219void 1220machopic_select_rtx_section (mode, x, align) 1221 enum machine_mode mode; 1222 rtx x; 1223 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 1224{ 1225 if (GET_MODE_SIZE (mode) == 8) 1226 literal8_section (); 1227 else if (GET_MODE_SIZE (mode) == 4 1228 && (GET_CODE (x) == CONST_INT 1229 || GET_CODE (x) == CONST_DOUBLE)) 1230 literal4_section (); 1231 else 1232 const_section (); 1233} 1234 1235void 1236machopic_asm_out_constructor (symbol, priority) 1237 rtx symbol; 1238 int priority ATTRIBUTE_UNUSED; 1239{ 1240 if (flag_pic) 1241 mod_init_section (); 1242 else 1243 constructor_section (); 1244 assemble_align (POINTER_SIZE); 1245 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 1246 1247 if (!flag_pic) 1248 fprintf (asm_out_file, ".reference .constructors_used\n"); 1249} 1250 1251void 1252machopic_asm_out_destructor (symbol, priority) 1253 rtx symbol; 1254 int priority ATTRIBUTE_UNUSED; 1255{ 1256 if (flag_pic) 1257 mod_term_section (); 1258 else 1259 destructor_section (); 1260 assemble_align (POINTER_SIZE); 1261 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 1262 1263 if (!flag_pic) 1264 fprintf (asm_out_file, ".reference .destructors_used\n"); 1265} 1266 1267void 1268darwin_globalize_label (stream, name) 1269 FILE *stream; 1270 const char *name; 1271{ 1272 if (!!strncmp (name, "_OBJC_", 6)) 1273 default_globalize_label (stream, name); 1274} 1275 1276/* Output a difference of two labels that will be an assembly time 1277 constant if the two labels are local. (.long lab1-lab2 will be 1278 very different if lab1 is at the boundary between two sections; it 1279 will be relocated according to the second section, not the first, 1280 so one ends up with a difference between labels in different 1281 sections, which is bad in the dwarf2 eh context for instance.) */ 1282 1283static int darwin_dwarf_label_counter; 1284 1285void 1286darwin_asm_output_dwarf_delta (file, size, lab1, lab2) 1287 FILE *file; 1288 int size ATTRIBUTE_UNUSED; 1289 const char *lab1, *lab2; 1290{ 1291 const char *p = lab1 + (lab1[0] == '*'); 1292 int islocaldiff = (p[0] == 'L'); 1293 1294 if (islocaldiff) 1295 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter); 1296 else 1297 fprintf (file, "\t%s\t", ".long"); 1298 assemble_name (file, lab1); 1299 fprintf (file, "-"); 1300 assemble_name (file, lab2); 1301 if (islocaldiff) 1302 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++); 1303} 1304 1305#include "gt-darwin.h" 1306 1307