darwin.c revision 90075
1/* Functions for generic Darwin as target machine for GNU C compiler. 2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001 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 42#include "darwin-protos.h" 43 44extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *)); 45 46static int machopic_data_defined_p PARAMS ((const char *)); 47static int func_name_maybe_scoped PARAMS ((const char *)); 48static void update_non_lazy_ptrs PARAMS ((const char *)); 49static void update_stubs PARAMS ((const char *)); 50 51int 52name_needs_quotes (name) 53 const char *name; 54{ 55 int c; 56 while ((c = *name++) != '\0') 57 if (! ISIDNUM (c)) 58 return 1; 59 return 0; 60} 61 62/* 63 * flag_pic = 1 ... generate only indirections 64 * flag_pic = 2 ... generate indirections and pure code 65 */ 66 67/* This module assumes that (const (symbol_ref "foo")) is a legal pic 68 reference, which will not be changed. */ 69 70static tree machopic_defined_list; 71 72enum machopic_addr_class 73machopic_classify_ident (ident) 74 tree ident; 75{ 76 const char *name = IDENTIFIER_POINTER (ident); 77 int lprefix = (((name[0] == '*' || name[0] == '&') 78 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L'))) 79 || ( name[0] == '_' 80 && name[1] == 'O' 81 && name[2] == 'B' 82 && name[3] == 'J' 83 && name[4] == 'C' 84 && name[5] == '_')); 85 tree temp; 86 87 if (name[0] != '!') 88 { 89 /* Here if no special encoding to be found. */ 90 if (lprefix) 91 { 92 const char *name = IDENTIFIER_POINTER (ident); 93 int len = strlen (name); 94 95 if ((len > 5 && !strcmp (name + len - 5, "$stub")) 96 || (len > 6 && !strcmp (name + len - 6, "$stub\""))) 97 return MACHOPIC_DEFINED_FUNCTION; 98 return MACHOPIC_DEFINED_DATA; 99 } 100 101 for (temp = machopic_defined_list; 102 temp != NULL_TREE; 103 temp = TREE_CHAIN (temp)) 104 { 105 if (ident == TREE_VALUE (temp)) 106 return MACHOPIC_DEFINED_DATA; 107 } 108 109 if (TREE_ASM_WRITTEN (ident)) 110 return MACHOPIC_DEFINED_DATA; 111 112 return MACHOPIC_UNDEFINED; 113 } 114 115 else if (name[1] == 'D') 116 return MACHOPIC_DEFINED_DATA; 117 118 else if (name[1] == 'T') 119 return MACHOPIC_DEFINED_FUNCTION; 120 121 /* It is possible that someone is holding a "stale" name, which has 122 since been defined. See if there is a "defined" name (i.e, 123 different from NAME only in having a '!D_' or a '!T_' instead of 124 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say 125 that this identifier is defined. */ 126 else if (name[1] == 'd' || name[1] == 't') 127 { 128 char *new_name; 129 new_name = (char *)alloca (strlen (name) + 1); 130 strcpy (new_name, name); 131 new_name[1] = (name[1] == 'd') ? 'D' : 'T'; 132 if (maybe_get_identifier (new_name) != NULL) 133 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA 134 : MACHOPIC_DEFINED_FUNCTION; 135 } 136 137 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp)) 138 { 139 if (ident == TREE_VALUE (temp)) 140 { 141 if (name[1] == 'T') 142 return MACHOPIC_DEFINED_FUNCTION; 143 else 144 return MACHOPIC_DEFINED_DATA; 145 } 146 } 147 148 if (name[1] == 't' || name[1] == 'T') 149 { 150 if (lprefix) 151 return MACHOPIC_DEFINED_FUNCTION; 152 else 153 return MACHOPIC_UNDEFINED_FUNCTION; 154 } 155 else 156 { 157 if (lprefix) 158 return MACHOPIC_DEFINED_DATA; 159 else 160 return MACHOPIC_UNDEFINED_DATA; 161 } 162} 163 164 165enum machopic_addr_class 166machopic_classify_name (name) 167 const char *name; 168{ 169 return machopic_classify_ident (get_identifier (name)); 170} 171 172int 173machopic_ident_defined_p (ident) 174 tree ident; 175{ 176 switch (machopic_classify_ident (ident)) 177 { 178 case MACHOPIC_UNDEFINED: 179 case MACHOPIC_UNDEFINED_DATA: 180 case MACHOPIC_UNDEFINED_FUNCTION: 181 return 0; 182 default: 183 return 1; 184 } 185} 186 187static int 188machopic_data_defined_p (name) 189 const char *name; 190{ 191 switch (machopic_classify_ident (get_identifier (name))) 192 { 193 case MACHOPIC_DEFINED_DATA: 194 return 1; 195 default: 196 return 0; 197 } 198} 199 200int 201machopic_name_defined_p (name) 202 const char *name; 203{ 204 return machopic_ident_defined_p (get_identifier (name)); 205} 206 207void 208machopic_define_ident (ident) 209 tree ident; 210{ 211 if (!machopic_ident_defined_p (ident)) 212 machopic_defined_list = 213 tree_cons (NULL_TREE, ident, machopic_defined_list); 214} 215 216void 217machopic_define_name (name) 218 const char *name; 219{ 220 machopic_define_ident (get_identifier (name)); 221} 222 223/* This is a static to make inline functions work. The rtx 224 representing the PIC base symbol always points to here. */ 225 226static char function_base[32]; 227 228static int current_pic_label_num; 229 230char * 231machopic_function_base_name () 232{ 233 static const char *name = NULL; 234 static const char *current_name; 235 236 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); 237 238 if (name != current_name) 239 { 240 current_function_uses_pic_offset_table = 1; 241 242 /* Save mucho space and time. Some of the C++ mangled names are over 243 700 characters long! Note that we produce a label containing a '-' 244 if the function we're compiling is an Objective-C method, as evinced 245 by the incredibly scientific test below. This is because code in 246 rs6000.c makes the same ugly test when loading the PIC reg. */ 247 248 ++current_pic_label_num; 249 if (*current_name == '+' || *current_name == '-') 250 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num); 251 else 252 sprintf (function_base, "*L%d$pb", current_pic_label_num); 253 254 name = current_name; 255 } 256 257 return function_base; 258} 259 260static tree machopic_non_lazy_pointers = NULL; 261 262/* Return a non-lazy pointer name corresponding to the given name, 263 either by finding it in our list of pointer names, or by generating 264 a new one. */ 265 266char * 267machopic_non_lazy_ptr_name (name) 268 const char *name; 269{ 270 char *temp_name; 271 tree temp, ident = get_identifier (name); 272 273 for (temp = machopic_non_lazy_pointers; 274 temp != NULL_TREE; 275 temp = TREE_CHAIN (temp)) 276 { 277 if (ident == TREE_VALUE (temp)) 278 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 279 } 280 281 STRIP_NAME_ENCODING (name, name); 282 283 /* Try again, but comparing names this time. */ 284 for (temp = machopic_non_lazy_pointers; 285 temp != NULL_TREE; 286 temp = TREE_CHAIN (temp)) 287 { 288 if (TREE_VALUE (temp)) 289 { 290 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 291 STRIP_NAME_ENCODING (temp_name, temp_name); 292 if (strcmp (name, temp_name) == 0) 293 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 294 } 295 } 296 297 { 298 char *buffer; 299 tree ptr_name; 300 301 buffer = alloca (strlen (name) + 20); 302 303 strcpy (buffer, "&L"); 304 if (name[0] == '*') 305 strcat (buffer, name+1); 306 else 307 { 308 strcat (buffer, "_"); 309 strcat (buffer, name); 310 } 311 312 strcat (buffer, "$non_lazy_ptr"); 313 ptr_name = get_identifier (buffer); 314 315 machopic_non_lazy_pointers 316 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers); 317 318 TREE_USED (machopic_non_lazy_pointers) = 0; 319 320 return IDENTIFIER_POINTER (ptr_name); 321 } 322} 323 324static tree machopic_stubs = 0; 325 326/* Make sure the GC knows about our homemade lists. */ 327 328void 329machopic_add_gc_roots () 330{ 331 ggc_add_tree_root (&machopic_defined_list, 1); 332 ggc_add_tree_root (&machopic_non_lazy_pointers, 1); 333 ggc_add_tree_root (&machopic_stubs, 1); 334} 335 336/* Return the name of the stub corresponding to the given name, 337 generating a new stub name if necessary. */ 338 339char * 340machopic_stub_name (name) 341 const char *name; 342{ 343 tree temp, ident = get_identifier (name); 344 const char *tname; 345 346 for (temp = machopic_stubs; 347 temp != NULL_TREE; 348 temp = TREE_CHAIN (temp)) 349 { 350 if (ident == TREE_VALUE (temp)) 351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 352 tname = IDENTIFIER_POINTER (TREE_VALUE (temp)); 353 if (strcmp (name, tname) == 0) 354 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 355 /* A library call name might not be section-encoded yet, so try 356 it against a stripped name. */ 357 if (name[0] != '!' 358 && tname[0] == '!' 359 && strcmp (name, tname + 4) == 0) 360 return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 361 } 362 363 STRIP_NAME_ENCODING (name, name); 364 365 { 366 char *buffer; 367 tree ptr_name; 368 int needs_quotes = name_needs_quotes (name); 369 370 buffer = alloca (strlen (name) + 20); 371 372 if (needs_quotes) 373 strcpy (buffer, "&\"L"); 374 else 375 strcpy (buffer, "&L"); 376 if (name[0] == '*') 377 { 378 strcat (buffer, name+1); 379 } 380 else 381 { 382 strcat (buffer, "_"); 383 strcat (buffer, name); 384 } 385 386 if (needs_quotes) 387 strcat (buffer, "$stub\""); 388 else 389 strcat (buffer, "$stub"); 390 ptr_name = get_identifier (buffer); 391 392 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs); 393 TREE_USED (machopic_stubs) = 0; 394 395 return IDENTIFIER_POINTER (ptr_name); 396 } 397} 398 399void 400machopic_validate_stub_or_non_lazy_ptr (name, validate_stub) 401 const char *name; 402 int validate_stub; 403{ 404 char *real_name; 405 tree temp, ident = get_identifier (name), id2; 406 407 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers); 408 temp != NULL_TREE; 409 temp = TREE_CHAIN (temp)) 410 if (ident == TREE_PURPOSE (temp)) 411 { 412 /* Mark both the stub or non-lazy pointer as well as the 413 original symbol as being referenced. */ 414 TREE_USED (temp) = 1; 415 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE) 416 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1; 417 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp))); 418 id2 = maybe_get_identifier (real_name); 419 if (id2) 420 TREE_SYMBOL_REFERENCED (id2) = 1; 421 } 422} 423 424/* Transform ORIG, which may be any data source, to the corresponding 425 source using indirections. */ 426 427rtx 428machopic_indirect_data_reference (orig, reg) 429 rtx orig, reg; 430{ 431 rtx ptr_ref = orig; 432 433 if (! MACHOPIC_INDIRECT) 434 return orig; 435 436 if (GET_CODE (orig) == SYMBOL_REF) 437 { 438 const char *name = XSTR (orig, 0); 439 440 if (machopic_data_defined_p (name)) 441 { 442 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 443 machopic_function_base_name ()); 444 rtx offset = gen_rtx (CONST, Pmode, 445 gen_rtx (MINUS, Pmode, orig, pic_base)); 446 447#if defined (TARGET_TOC) /* i.e., PowerPC */ 448 rtx hi_sum_reg = reg; 449 450 if (reg == NULL) 451 abort (); 452 453 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 454 gen_rtx (PLUS, Pmode, pic_offset_table_rtx, 455 gen_rtx (HIGH, Pmode, offset)))); 456 emit_insn (gen_rtx (SET, Pmode, reg, 457 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset))); 458 459 orig = reg; 460#else 461#if defined (HAVE_lo_sum) 462 if (reg == 0) abort (); 463 464 emit_insn (gen_rtx (SET, VOIDmode, reg, 465 gen_rtx (HIGH, Pmode, offset))); 466 emit_insn (gen_rtx (SET, VOIDmode, reg, 467 gen_rtx (LO_SUM, Pmode, reg, offset))); 468 emit_insn (gen_rtx (USE, VOIDmode, 469 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM))); 470 471 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg); 472#endif 473#endif 474 return orig; 475 } 476 477 ptr_ref = gen_rtx (SYMBOL_REF, Pmode, 478 machopic_non_lazy_ptr_name (name)); 479 480 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref); 481 RTX_UNCHANGING_P (ptr_ref) = 1; 482 483 return ptr_ref; 484 } 485 else if (GET_CODE (orig) == CONST) 486 { 487 rtx base, result; 488 489 /* legitimize both operands of the PLUS */ 490 if (GET_CODE (XEXP (orig, 0)) == PLUS) 491 { 492 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), 493 reg); 494 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1), 495 (base == reg ? 0 : reg)); 496 } 497 else 498 return orig; 499 500 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT) 501 result = plus_constant (base, INTVAL (orig)); 502 else 503 result = gen_rtx (PLUS, Pmode, base, orig); 504 505 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig)) 506 RTX_UNCHANGING_P (result) = 1; 507 508 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM) 509 { 510 if (reg) 511 { 512 emit_move_insn (reg, result); 513 result = reg; 514 } 515 else 516 { 517 result = force_reg (GET_MODE (result), result); 518 } 519 } 520 521 return result; 522 523 } 524 else if (GET_CODE (orig) == MEM) 525 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg); 526 /* When the target is i386, this code prevents crashes due to the 527 compiler's ignorance on how to move the PIC base register to 528 other registers. (The reload phase sometimes introduces such 529 insns.) */ 530 else if (GET_CODE (orig) == PLUS 531 && GET_CODE (XEXP (orig, 0)) == REG 532 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM 533#ifdef I386 534 /* Prevent the same register from being erroneously used 535 as both the base and index registers. */ 536 && GET_CODE (XEXP (orig, 1)) == CONST 537#endif 538 && reg) 539 { 540 emit_move_insn (reg, XEXP (orig, 0)); 541 XEXP (ptr_ref, 0) = reg; 542 } 543 return ptr_ref; 544} 545 546/* Transform TARGET (a MEM), which is a function call target, to the 547 corresponding symbol_stub if necessary. Return a new MEM. */ 548 549rtx 550machopic_indirect_call_target (target) 551 rtx target; 552{ 553 if (GET_CODE (target) != MEM) 554 return target; 555 556 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF) 557 { 558 enum machine_mode mode = GET_MODE (XEXP (target, 0)); 559 const char *name = XSTR (XEXP (target, 0), 0); 560 561 /* If the name is already defined, we need do nothing. */ 562 if (name[0] == '!' && name[1] == 'T') 563 return target; 564 565 if (!machopic_name_defined_p (name)) 566 { 567 const char *stub_name = machopic_stub_name (name); 568 569 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name); 570 RTX_UNCHANGING_P (target) = 1; 571 } 572 } 573 574 return target; 575} 576 577rtx 578machopic_legitimize_pic_address (orig, mode, reg) 579 rtx orig, reg; 580 enum machine_mode mode; 581{ 582 rtx pic_ref = orig; 583 584 if (! MACHOPIC_PURE) 585 return orig; 586 587 /* First handle a simple SYMBOL_REF or LABEL_REF */ 588 if (GET_CODE (orig) == LABEL_REF 589 || (GET_CODE (orig) == SYMBOL_REF 590 )) 591 { 592 /* addr(foo) = &func+(foo-func) */ 593 rtx pic_base; 594 595 orig = machopic_indirect_data_reference (orig, reg); 596 597 if (GET_CODE (orig) == PLUS 598 && GET_CODE (XEXP (orig, 0)) == REG) 599 { 600 if (reg == 0) 601 return force_reg (mode, orig); 602 603 emit_move_insn (reg, orig); 604 return reg; 605 } 606 607 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ()); 608 609 if (GET_CODE (orig) == MEM) 610 { 611 if (reg == 0) 612 { 613 if (reload_in_progress) 614 abort (); 615 else 616 reg = gen_reg_rtx (Pmode); 617 } 618 619#ifdef HAVE_lo_sum 620 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 621 || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 622 { 623 rtx offset = gen_rtx (CONST, Pmode, 624 gen_rtx (MINUS, Pmode, 625 XEXP (orig, 0), pic_base)); 626#if defined (TARGET_TOC) /* i.e., PowerPC */ 627 /* Generating a new reg may expose opportunities for 628 common subexpression elimination. */ 629 rtx hi_sum_reg = 630 (reload_in_progress ? reg : gen_reg_rtx (SImode)); 631 632 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 633 gen_rtx (PLUS, Pmode, 634 pic_offset_table_rtx, 635 gen_rtx (HIGH, Pmode, offset)))); 636 emit_insn (gen_rtx (SET, VOIDmode, reg, 637 gen_rtx (MEM, GET_MODE (orig), 638 gen_rtx (LO_SUM, Pmode, 639 hi_sum_reg, offset)))); 640 pic_ref = reg; 641 642#else 643 emit_insn (gen_rtx (USE, VOIDmode, 644 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM))); 645 646 emit_insn (gen_rtx (SET, VOIDmode, reg, 647 gen_rtx (HIGH, Pmode, 648 gen_rtx (CONST, Pmode, offset)))); 649 emit_insn (gen_rtx (SET, VOIDmode, reg, 650 gen_rtx (LO_SUM, Pmode, reg, 651 gen_rtx (CONST, Pmode, offset)))); 652 pic_ref = gen_rtx (PLUS, Pmode, 653 pic_offset_table_rtx, reg); 654#endif 655 } 656 else 657#endif /* HAVE_lo_sum */ 658 { 659 rtx pic = pic_offset_table_rtx; 660 if (GET_CODE (pic) != REG) 661 { 662 emit_move_insn (reg, pic); 663 pic = reg; 664 } 665#if 0 666 emit_insn (gen_rtx (USE, VOIDmode, 667 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); 668#endif 669 670 pic_ref = gen_rtx (PLUS, Pmode, 671 pic, 672 gen_rtx (CONST, Pmode, 673 gen_rtx (MINUS, Pmode, 674 XEXP (orig, 0), 675 pic_base))); 676 } 677 678#if !defined (TARGET_TOC) 679 RTX_UNCHANGING_P (pic_ref) = 1; 680 emit_move_insn (reg, pic_ref); 681 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg); 682#endif 683 } 684 else 685 { 686 687#ifdef HAVE_lo_sum 688 if (GET_CODE (orig) == SYMBOL_REF 689 || GET_CODE (orig) == LABEL_REF) 690 { 691 rtx offset = gen_rtx (CONST, Pmode, 692 gen_rtx (MINUS, Pmode, orig, pic_base)); 693#if defined (TARGET_TOC) /* i.e., PowerPC */ 694 rtx hi_sum_reg; 695 696 if (reg == 0) 697 { 698 if (reload_in_progress) 699 abort (); 700 else 701 reg = gen_reg_rtx (SImode); 702 } 703 704 hi_sum_reg = reg; 705 706 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg, 707 gen_rtx (PLUS, Pmode, 708 pic_offset_table_rtx, 709 gen_rtx (HIGH, Pmode, offset)))); 710 emit_insn (gen_rtx (SET, VOIDmode, reg, 711 gen_rtx (LO_SUM, Pmode, 712 hi_sum_reg, offset))); 713 pic_ref = reg; 714#else 715 emit_insn (gen_rtx (SET, VOIDmode, reg, 716 gen_rtx (HIGH, Pmode, offset))); 717 emit_insn (gen_rtx (SET, VOIDmode, reg, 718 gen_rtx (LO_SUM, Pmode, reg, offset))); 719 pic_ref = gen_rtx (PLUS, Pmode, 720 pic_offset_table_rtx, reg); 721#endif 722 } 723 else 724#endif /* HAVE_lo_sum */ 725 { 726 if (GET_CODE (orig) == REG) 727 { 728 return orig; 729 } 730 else 731 { 732 rtx pic = pic_offset_table_rtx; 733 if (GET_CODE (pic) != REG) 734 { 735 emit_move_insn (reg, pic); 736 pic = reg; 737 } 738#if 0 739 emit_insn (gen_rtx (USE, VOIDmode, 740 pic_offset_table_rtx)); 741#endif 742 pic_ref = gen_rtx (PLUS, Pmode, 743 pic, 744 gen_rtx (CONST, Pmode, 745 gen_rtx (MINUS, Pmode, 746 orig, pic_base))); 747 } 748 } 749 } 750 751 RTX_UNCHANGING_P (pic_ref) = 1; 752 753 if (GET_CODE (pic_ref) != REG) 754 { 755 if (reg != 0) 756 { 757 emit_move_insn (reg, pic_ref); 758 return reg; 759 } 760 else 761 { 762 return force_reg (mode, pic_ref); 763 } 764 } 765 else 766 { 767 return pic_ref; 768 } 769 } 770 771 else if (GET_CODE (orig) == SYMBOL_REF) 772 return orig; 773 774 else if (GET_CODE (orig) == PLUS 775 && (GET_CODE (XEXP (orig, 0)) == MEM 776 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 777 || GET_CODE (XEXP (orig, 0)) == LABEL_REF) 778 && XEXP (orig, 0) != pic_offset_table_rtx 779 && GET_CODE (XEXP (orig, 1)) != REG) 780 781 { 782 rtx base; 783 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM); 784 785 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 786 orig = machopic_legitimize_pic_address (XEXP (orig, 1), 787 Pmode, (base == reg ? 0 : reg)); 788 if (GET_CODE (orig) == CONST_INT) 789 { 790 pic_ref = plus_constant (base, INTVAL (orig)); 791 is_complex = 1; 792 } 793 else 794 pic_ref = gen_rtx (PLUS, Pmode, base, orig); 795 796 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig)) 797 RTX_UNCHANGING_P (pic_ref) = 1; 798 799 if (reg && is_complex) 800 { 801 emit_move_insn (reg, pic_ref); 802 pic_ref = reg; 803 } 804 /* Likewise, should we set special REG_NOTEs here? */ 805 } 806 807 else if (GET_CODE (orig) == CONST) 808 { 809 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 810 } 811 812 else if (GET_CODE (orig) == MEM 813 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF) 814 { 815 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); 816 817 addr = gen_rtx (MEM, GET_MODE (orig), addr); 818 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig); 819 emit_move_insn (reg, addr); 820 pic_ref = reg; 821 } 822 823 return pic_ref; 824} 825 826 827void 828machopic_finish (asm_out_file) 829 FILE *asm_out_file; 830{ 831 tree temp; 832 833 for (temp = machopic_stubs; 834 temp != NULL_TREE; 835 temp = TREE_CHAIN (temp)) 836 { 837 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 838 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 839 char *sym; 840 char *stub; 841 842 if (! TREE_USED (temp)) 843 continue; 844 845 /* If the symbol is actually defined, we don't need a stub. */ 846 if (sym_name[0] == '!' && sym_name[1] == 'T') 847 continue; 848 849 STRIP_NAME_ENCODING (sym_name, sym_name); 850 851 sym = alloca (strlen (sym_name) + 2); 852 if (sym_name[0] == '*' || sym_name[0] == '&') 853 strcpy (sym, sym_name + 1); 854 else if (sym_name[0] == '-' || sym_name[0] == '+') 855 strcpy (sym, sym_name); 856 else 857 sym[0] = '_', strcpy (sym + 1, sym_name); 858 859 stub = alloca (strlen (stub_name) + 2); 860 if (stub_name[0] == '*' || stub_name[0] == '&') 861 strcpy (stub, stub_name + 1); 862 else 863 stub[0] = '_', strcpy (stub + 1, stub_name); 864 865 machopic_output_stub (asm_out_file, sym, stub); 866 } 867 868 for (temp = machopic_non_lazy_pointers; 869 temp != NULL_TREE; 870 temp = TREE_CHAIN (temp)) 871 { 872 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 873 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); 874#if 0 875 tree decl = lookup_name_darwin (TREE_VALUE (temp)); 876#endif 877 878 if (! TREE_USED (temp)) 879 continue; 880 881 if (machopic_ident_defined_p (TREE_VALUE (temp)) 882#if 0 /* add back when we have private externs */ 883 || (decl && DECL_PRIVATE_EXTERN (decl)) 884#endif 885 ) 886 { 887 data_section (); 888 assemble_align (GET_MODE_ALIGNMENT (Pmode)); 889 assemble_label (lazy_name); 890 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name), 891 GET_MODE_SIZE (Pmode), 892 GET_MODE_ALIGNMENT (Pmode), 1); 893 } 894 else 895 { 896 machopic_nl_symbol_ptr_section (); 897 assemble_name (asm_out_file, lazy_name); 898 fprintf (asm_out_file, ":\n"); 899 900 fprintf (asm_out_file, "\t.indirect_symbol "); 901 assemble_name (asm_out_file, sym_name); 902 fprintf (asm_out_file, "\n"); 903 904 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 905 GET_MODE_ALIGNMENT (Pmode), 1); 906 } 907 } 908} 909 910int 911machopic_operand_p (op) 912 rtx op; 913{ 914 if (MACHOPIC_JUST_INDIRECT) 915 { 916 while (GET_CODE (op) == CONST) 917 op = XEXP (op, 0); 918 919 if (GET_CODE (op) == SYMBOL_REF) 920 return machopic_name_defined_p (XSTR (op, 0)); 921 else 922 return 0; 923 } 924 925 while (GET_CODE (op) == CONST) 926 op = XEXP (op, 0); 927 928 if (GET_CODE (op) == MINUS 929 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF 930 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF 931 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0)) 932 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0))) 933 return 1; 934 935#if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */ 936 /* Without this statement, the compiler crashes while compiling enquire.c 937 when targetting PowerPC. It is not known why this code is not needed 938 when targetting other processors. */ 939 else if (GET_CODE (op) == SYMBOL_REF 940 && (machopic_classify_name (XSTR (op, 0)) 941 == MACHOPIC_DEFINED_FUNCTION)) 942 { 943 return 1; 944 } 945#endif 946 947 return 0; 948} 949 950/* This function records whether a given name corresponds to a defined 951 or undefined function or variable, for machopic_classify_ident to 952 use later. */ 953 954void 955darwin_encode_section_info (decl) 956 tree decl; 957{ 958 char code = '\0'; 959 int defined = 0; 960 rtx sym_ref; 961 const char *orig_str; 962 char *new_str; 963 size_t len, new_len; 964 965 if ((TREE_CODE (decl) == FUNCTION_DECL 966 || TREE_CODE (decl) == VAR_DECL) 967 && !DECL_EXTERNAL (decl) 968 && ((TREE_STATIC (decl) 969 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl))) 970 || (DECL_INITIAL (decl) 971 && DECL_INITIAL (decl) != error_mark_node))) 972 defined = 1; 973 974 if (TREE_CODE (decl) == FUNCTION_DECL) 975 code = (defined ? 'T' : 't'); 976 else if (TREE_CODE (decl) == VAR_DECL) 977 code = (defined ? 'D' : 'd'); 978 979 if (code == '\0') 980 return; 981 982 sym_ref = XEXP (DECL_RTL (decl), 0); 983 orig_str = XSTR (sym_ref, 0); 984 len = strlen (orig_str) + 1; 985 986 if (orig_str[0] == '!') 987 { 988 /* Already encoded; see if we need to change it. */ 989 if (code == orig_str[1]) 990 return; 991 /* Yes, tweak a copy of the name and put it in a new string. */ 992 new_str = alloca (len); 993 memcpy (new_str, orig_str, len); 994 new_str[1] = code; 995 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len); 996 } 997 else 998 { 999 /* Add the encoding. */ 1000 new_len = len + 4; 1001 new_str = alloca (new_len); 1002 new_str[0] = '!'; 1003 new_str[1] = code; 1004 new_str[2] = '_'; 1005 new_str[3] = '_'; 1006 memcpy (new_str + 4, orig_str, len); 1007 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len); 1008 } 1009 /* The non-lazy pointer list may have captured references to the 1010 old encoded name, change them. */ 1011 if (TREE_CODE (decl) == VAR_DECL) 1012 update_non_lazy_ptrs (XSTR (sym_ref, 0)); 1013 else 1014 update_stubs (XSTR (sym_ref, 0)); 1015} 1016 1017/* Scan the list of non-lazy pointers and update any recorded names whose 1018 stripped name matches the argument. */ 1019 1020static void 1021update_non_lazy_ptrs (name) 1022 const char *name; 1023{ 1024 const char *name1, *name2; 1025 tree temp; 1026 1027 STRIP_NAME_ENCODING (name1, name); 1028 1029 for (temp = machopic_non_lazy_pointers; 1030 temp != NULL_TREE; 1031 temp = TREE_CHAIN (temp)) 1032 { 1033 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1034 1035 if (*sym_name == '!') 1036 { 1037 STRIP_NAME_ENCODING (name2, sym_name); 1038 if (strcmp (name1, name2) == 0) 1039 { 1040 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name; 1041 break; 1042 } 1043 } 1044 } 1045} 1046 1047/* Function NAME is being defined, and its label has just been output. 1048 If there's already a reference to a stub for this function, we can 1049 just emit the stub label now and we don't bother emitting the stub later. */ 1050 1051void 1052machopic_output_possible_stub_label (file, name) 1053 FILE *file; 1054 const char *name; 1055{ 1056 tree temp; 1057 1058 1059 /* Ensure we're looking at a section-encoded name. */ 1060 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T')) 1061 return; 1062 1063 for (temp = machopic_stubs; 1064 temp != NULL_TREE; 1065 temp = TREE_CHAIN (temp)) 1066 { 1067 const char *sym_name; 1068 1069 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1070 if (sym_name[0] == '!' && sym_name[1] == 'T' 1071 && ! strcmp (name+2, sym_name+2)) 1072 { 1073 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp))); 1074 /* Avoid generating a stub for this. */ 1075 TREE_USED (temp) = 0; 1076 break; 1077 } 1078 } 1079} 1080 1081/* Scan the list of stubs and update any recorded names whose 1082 stripped name matches the argument. */ 1083 1084static void 1085update_stubs (name) 1086 const char *name; 1087{ 1088 const char *name1, *name2; 1089 tree temp; 1090 1091 STRIP_NAME_ENCODING (name1, name); 1092 1093 for (temp = machopic_stubs; 1094 temp != NULL_TREE; 1095 temp = TREE_CHAIN (temp)) 1096 { 1097 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); 1098 1099 if (*sym_name == '!') 1100 { 1101 STRIP_NAME_ENCODING (name2, sym_name); 1102 if (strcmp (name1, name2) == 0) 1103 { 1104 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name; 1105 break; 1106 } 1107 } 1108 } 1109} 1110 1111void 1112machopic_asm_out_constructor (symbol, priority) 1113 rtx symbol; 1114 int priority ATTRIBUTE_UNUSED; 1115{ 1116 if (flag_pic) 1117 mod_init_section (); 1118 else 1119 constructor_section (); 1120 assemble_align (POINTER_SIZE); 1121 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 1122 1123 if (!flag_pic) 1124 fprintf (asm_out_file, ".reference .constructors_used\n"); 1125} 1126 1127void 1128machopic_asm_out_destructor (symbol, priority) 1129 rtx symbol; 1130 int priority ATTRIBUTE_UNUSED; 1131{ 1132 if (flag_pic) 1133 mod_term_section (); 1134 else 1135 destructor_section (); 1136 assemble_align (POINTER_SIZE); 1137 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 1138 1139 if (!flag_pic) 1140 fprintf (asm_out_file, ".reference .destructors_used\n"); 1141} 1142