|
|
1.1 ! root 1: /* NeXTSTEP mach-o pic support functions. ! 2: Copyright (C) 1992, 1994 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 2, or (at your option) ! 9: any later version. ! 10: ! 11: GNU CC is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GNU CC; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: /* ! 21: * flag_pic = 1 ... generate only indirections ! 22: * flag_pic = 2 ... generate indirections and pure code ! 23: */ ! 24: ! 25: ! 26: /* ! 27: * This module assumes that (const (symbol_ref "foo")) is ! 28: * a legal pic reference, which will not be changed. ! 29: */ ! 30: #include "config.h" ! 31: ! 32: #ifdef MACHO_PIC ! 33: ! 34: #include "tree.h" ! 35: #include "rtl.h" ! 36: #include "output.h" ! 37: #include "machopic.h" ! 38: #include "insn-config.h" ! 39: #include "insn-flags.h" ! 40: ! 41: #include <stdio.h> ! 42: ! 43: /* Answer if the symbol named IDENT is known to be defined in ! 44: the current module. It is critical, that it *never* says ! 45: something is defined, when it isn't. However, it is ok to be ! 46: sloppy on the other end of the scale, it will only generate ! 47: worse code than if it guessed correct. */ ! 48: ! 49: static tree machopic_defined_list = 0; ! 50: ! 51: extern int flag_dave_indirect; ! 52: ! 53: enum machopic_addr_class ! 54: machopic_classify_ident (ident) ! 55: tree ident; ! 56: { ! 57: char *name = IDENTIFIER_POINTER (ident); ! 58: int lprefix = (name[0] == '*' ! 59: && (name[1] == 'L' ! 60: || (name[1] == '"' && name[2] == 'L'))); ! 61: ! 62: tree temp, decl = (tree)lookup_name (ident); ! 63: ! 64: if (!decl) ! 65: { ! 66: if (lprefix) ! 67: { ! 68: char *name = IDENTIFIER_POINTER (ident); ! 69: while (*name++) ! 70: { ! 71: if (! strncmp (name, "$stub\0", 6)) ! 72: return MACHOPIC_DEFINED_FUNCTION; ! 73: } ! 74: return MACHOPIC_DEFINED_DATA; ! 75: } ! 76: ! 77: for (temp = machopic_defined_list; ! 78: temp != NULL_TREE; ! 79: temp = TREE_CHAIN (temp)) ! 80: { ! 81: if (ident == TREE_VALUE (temp)) ! 82: return MACHOPIC_DEFINED_DATA; ! 83: } ! 84: ! 85: return MACHOPIC_UNDEFINED; ! 86: } ! 87: ! 88: /* variable declarations */ ! 89: else if (TREE_CODE (decl) == VAR_DECL) ! 90: { ! 91: if ((DECL_INITIAL (decl) ! 92: || TREE_STATIC (decl)) ! 93: && ! TREE_PUBLIC (decl)) ! 94: return MACHOPIC_DEFINED_DATA; ! 95: } ! 96: ! 97: /* function declarations */ ! 98: else if (TREE_CODE (decl) == FUNCTION_DECL) ! 99: { ! 100: if (TREE_STATIC (decl) ! 101: || TREE_ASM_WRITTEN (decl)) ! 102: return MACHOPIC_DEFINED_FUNCTION; ! 103: } ! 104: ! 105: for (temp = machopic_defined_list; ! 106: temp != NULL_TREE; ! 107: temp = TREE_CHAIN (temp)) ! 108: { ! 109: if (ident == TREE_VALUE (temp)) ! 110: if (TREE_CODE (decl) == FUNCTION_DECL) ! 111: return MACHOPIC_DEFINED_FUNCTION; ! 112: else ! 113: return MACHOPIC_DEFINED_DATA; ! 114: } ! 115: ! 116: if (TREE_CODE (decl) == FUNCTION_DECL) ! 117: { ! 118: if (lprefix) ! 119: return MACHOPIC_DEFINED_FUNCTION; ! 120: else ! 121: return MACHOPIC_UNDEFINED_FUNCTION; ! 122: } ! 123: else ! 124: { ! 125: if (lprefix) ! 126: return MACHOPIC_DEFINED_DATA; ! 127: else ! 128: return MACHOPIC_UNDEFINED_DATA; ! 129: } ! 130: } ! 131: ! 132: ! 133: enum machopic_addr_class ! 134: machopic_classify_name (name) ! 135: char *name; ! 136: { ! 137: return machopic_classify_ident (get_identifier (name)); ! 138: } ! 139: ! 140: int ! 141: machopic_ident_defined_p (ident) ! 142: tree ident; ! 143: { ! 144: switch (machopic_classify_ident (ident)) ! 145: { ! 146: case MACHOPIC_UNDEFINED: ! 147: case MACHOPIC_UNDEFINED_DATA: ! 148: case MACHOPIC_UNDEFINED_FUNCTION: ! 149: return 0; ! 150: default: ! 151: return 1; ! 152: } ! 153: } ! 154: ! 155: int ! 156: machopic_name_defined_p (name) ! 157: char *name; ! 158: { ! 159: return machopic_ident_defined_p (get_identifier (name)); ! 160: } ! 161: ! 162: void ! 163: machopic_define_ident (ident) ! 164: tree ident; ! 165: { ! 166: if (!machopic_ident_defined_p (ident)) ! 167: machopic_defined_list = ! 168: perm_tree_cons (NULL_TREE, ident, machopic_defined_list); ! 169: } ! 170: ! 171: void ! 172: machopic_define_name (name) ! 173: char *name; ! 174: { ! 175: machopic_define_ident (get_identifier (name)); ! 176: } ! 177: ! 178: /* This is a static to make inline functions work. The rtx */ ! 179: /* representing the PIC base symbol allways points to here. */ ! 180: static char function_base[256]; ! 181: ! 182: char* ! 183: machopic_function_base_name () ! 184: { ! 185: static char *name = 0, *curr_name; ! 186: static int base = 0; ! 187: ! 188: curr_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); ! 189: ! 190: if (name != curr_name) ! 191: { ! 192: current_function_uses_pic_offset_table = 1; ! 193: ! 194: if (strchr (curr_name, ' ')) ! 195: sprintf (function_base, "*\"L%s$pic_base\"", curr_name); ! 196: else ! 197: sprintf (function_base, "*L%s$pic_base", curr_name); ! 198: ! 199: name = curr_name; ! 200: } ! 201: ! 202: return function_base; ! 203: } ! 204: ! 205: static tree machopic_non_lazy_pointers = 0; ! 206: ! 207: char* ! 208: machopic_non_lazy_ptr_name (name) ! 209: char *name; ! 210: { ! 211: tree temp, ident = get_identifier (name); ! 212: ! 213: for (temp = machopic_non_lazy_pointers; ! 214: temp != NULL_TREE; ! 215: temp = TREE_CHAIN (temp)) ! 216: { ! 217: if (ident == TREE_VALUE (temp)) ! 218: return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); ! 219: } ! 220: ! 221: { ! 222: char buffer[256]; ! 223: tree ptr_name; ! 224: ! 225: strcpy (buffer, "*L"); ! 226: if (name[0] == '*') ! 227: strcat (buffer, name+1); ! 228: else ! 229: { ! 230: strcat (buffer, "_"); ! 231: strcat (buffer, name); ! 232: } ! 233: ! 234: strcat (buffer, "$non_lazy_ptr"); ! 235: ptr_name = get_identifier (buffer); ! 236: ! 237: machopic_non_lazy_pointers ! 238: = perm_tree_cons (ptr_name, ident, machopic_non_lazy_pointers); ! 239: ! 240: return IDENTIFIER_POINTER (ptr_name); ! 241: } ! 242: } ! 243: ! 244: static tree machopic_stubs = 0; ! 245: ! 246: char* ! 247: machopic_stub_name (name) ! 248: char *name; ! 249: { ! 250: tree temp, ident = get_identifier (name); ! 251: ! 252: for (temp = machopic_stubs; ! 253: temp != NULL_TREE; ! 254: temp = TREE_CHAIN (temp)) ! 255: { ! 256: if (ident == TREE_VALUE (temp)) ! 257: return IDENTIFIER_POINTER (TREE_PURPOSE (temp)); ! 258: } ! 259: ! 260: { ! 261: char buffer[256]; ! 262: tree ptr_name; ! 263: ! 264: strcpy (buffer, "*L"); ! 265: if (name[0] == '*') ! 266: { ! 267: strcat (buffer, name+1); ! 268: } ! 269: else ! 270: { ! 271: strcat (buffer, "_"); ! 272: strcat (buffer, name); ! 273: } ! 274: ! 275: strcat (buffer, "$stub"); ! 276: ptr_name = get_identifier (buffer); ! 277: ! 278: machopic_stubs = perm_tree_cons (ptr_name, ident, machopic_stubs); ! 279: ! 280: return IDENTIFIER_POINTER (ptr_name); ! 281: } ! 282: } ! 283: ! 284: /* ! 285: * Transfrom ORIG, which any data source to the corresponding ! 286: * source using indirections. ! 287: */ ! 288: ! 289: rtx ! 290: machopic_indirect_data_reference (orig, reg) ! 291: rtx orig, reg; ! 292: { ! 293: rtx ptr_ref = orig; ! 294: ! 295: if (! MACHOPIC_INDIRECT) ! 296: return orig; ! 297: ! 298: if (GET_CODE (orig) == SYMBOL_REF) ! 299: { ! 300: char *name = XSTR (orig, 0); ! 301: ! 302: if (machopic_name_defined_p (name)) ! 303: { ! 304: #ifdef HAVE_hi_sum ! 305: rtx hi_sum; ! 306: rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, ! 307: machopic_function_base_name ()); ! 308: rtx offset = gen_rtx (CONST, Pmode, gen_rtx (MINUS, Pmode, orig, pic_base)); ! 309: ! 310: ! 311: if (reg == 0) abort (); ! 312: ! 313: hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX, ! 314: gen_rtx (PLUS, Pmode, ! 315: pic_offset_table_rtx, ! 316: gen_rtx (HIGH, Pmode, offset))); ! 317: ! 318: #if 1 ! 319: emit_insn (hi_sum); ! 320: #else ! 321: emit_insn (gen_rtx (PARALLEL, VOIDmode, ! 322: gen_rtvec (2, ! 323: hi_sum, ! 324: gen_rtx (USE, VOIDmode, ! 325: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))))); ! 326: #endif ! 327: ! 328: emit_insn (gen_rtx (SET, Pmode, reg, ! 329: gen_rtx (LO_SUM, Pmode, ! 330: HI_SUM_TARGET_RTX, ! 331: offset))); ! 332: ! 333: { ! 334: rtx insn = get_last_insn (); ! 335: rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX); ! 336: ! 337: if (note) ! 338: XEXP (note, 0) = orig; ! 339: else ! 340: REG_NOTES (insn) = gen_rtx (EXPR_LIST, ! 341: REG_EQUAL, orig, REG_NOTES (insn)); ! 342: } ! 343: ! 344: orig = reg; ! 345: #else ! 346: #ifdef HAVE_lo_sum ! 347: rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, ! 348: machopic_function_base_name ()); ! 349: ! 350: if (reg == 0) abort (); ! 351: ! 352: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 353: gen_rtx (HIGH, Pmode, ! 354: gen_rtx (CONST, Pmode, ! 355: gen_rtx (MINUS, Pmode, ! 356: orig, pic_base))))); ! 357: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 358: gen_rtx (LO_SUM, Pmode, reg, ! 359: gen_rtx (CONST, Pmode, ! 360: gen_rtx (MINUS, Pmode, ! 361: orig, pic_base))))); ! 362: emit_insn (gen_rtx (USE, VOIDmode, ! 363: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); ! 364: ! 365: orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg); ! 366: #endif ! 367: #endif ! 368: return orig; ! 369: } ! 370: ! 371: ! 372: if (flag_dave_indirect) ! 373: { ! 374: extern tree string_type_node; ! 375: extern tree char_array_type_node; ! 376: tree params; ! 377: tree call; ! 378: tree get_addr_decl; ! 379: ! 380: if (reg == 0) ! 381: reg = gen_reg_rtx (Pmode); ! 382: ! 383: get_addr_decl ! 384: = (tree) lookup_name (get_identifier ("__get_address")); ! 385: if (get_addr_decl == 0) ! 386: error ("cannot find declaration for __get_address"); ! 387: ! 388: params = build_string (strlen (name), name); ! 389: TREE_TYPE (params) = char_array_type_node; ! 390: params = build1 (ADDR_EXPR, string_type_node, params); ! 391: params = build_tree_list (NULL_TREE, params); ! 392: ! 393: call = (tree) build_function_call (get_addr_decl, params); ! 394: expand_call (call, reg, 0); ! 395: RTX_UNCHANGING_P (reg) = 1; ! 396: return reg; ! 397: } ! 398: else /* kevin_indirect */ ! 399: { ! 400: ptr_ref = gen_rtx (SYMBOL_REF, Pmode, ! 401: machopic_non_lazy_ptr_name (name)); ! 402: ! 403: ! 404: /* generating real pure code */ ! 405: /* ! 406: if (MACHOPIC_PURE) ! 407: ptr_ref = machopic_legitimize_pic_address (ptr_ref, SImode, reg); ! 408: */ ! 409: ptr_ref = gen_rtx (MEM, Pmode, ptr_ref); ! 410: RTX_UNCHANGING_P (ptr_ref) = 1; ! 411: } ! 412: ! 413: return ptr_ref; ! 414: } ! 415: else if (GET_CODE (orig) == CONST) ! 416: { ! 417: rtx base, offset, result; ! 418: ! 419: /* legitimize both operands of the PLUS */ ! 420: if (GET_CODE (XEXP (orig, 0)) == PLUS) ! 421: { ! 422: base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0), reg); ! 423: orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1), ! 424: base == reg ? 0 : reg); ! 425: } ! 426: else ! 427: return orig; ! 428: ! 429: if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT) ! 430: result = plus_constant_for_output (base, INTVAL (orig)); ! 431: else ! 432: result = gen_rtx (PLUS, Pmode, base, orig); ! 433: ! 434: if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig)) ! 435: RTX_UNCHANGING_P (result) = 1; ! 436: ! 437: if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM) ! 438: { ! 439: if (reg) ! 440: { ! 441: emit_move_insn (reg, result); ! 442: result = reg; ! 443: } ! 444: else ! 445: { ! 446: result = force_reg (GET_MODE (result), result); ! 447: } ! 448: } ! 449: ! 450: return result; ! 451: ! 452: } ! 453: else if (GET_CODE (orig) == MEM) ! 454: { ! 455: XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg); ! 456: return ptr_ref; ! 457: } ! 458: else ! 459: return ptr_ref; ! 460: } ! 461: ! 462: ! 463: /* ! 464: * Transform TARGET (a MEM), which is a function call target, to the ! 465: * corresponding symbol_stub if nessecary. Return the a new MEM. ! 466: */ ! 467: ! 468: rtx ! 469: machopic_indirect_call_target (target) ! 470: rtx target; ! 471: { ! 472: if (GET_CODE (target) != MEM) ! 473: return target; ! 474: if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF) ! 475: { ! 476: enum machine_mode mode = GET_MODE (XEXP (target, 0)); ! 477: char *name = XSTR (XEXP (target, 0), 0); ! 478: if (!machopic_name_defined_p (name)) ! 479: { ! 480: if (flag_dave_indirect) ! 481: { ! 482: XEXP (target, 0) = force_reg (Pmode, XEXP (target, 0)); ! 483: } ! 484: else /* kevin_indirect */ ! 485: { ! 486: char *stub_name = (char*)machopic_stub_name (name); ! 487: XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name); ! 488: RTX_UNCHANGING_P (target) = 1; ! 489: } ! 490: } ! 491: } ! 492: return target; ! 493: } ! 494: ! 495: ! 496: rtx ! 497: machopic_legitimize_pic_address (orig, mode, reg) ! 498: rtx orig, reg; ! 499: enum machine_mode mode; ! 500: { ! 501: rtx pic_ref = orig; ! 502: ! 503: if (! MACHOPIC_PURE) ! 504: return orig; ! 505: ! 506: /* First handle a simple SYMBOL_REF or LABEL_REF */ ! 507: if (GET_CODE (orig) == LABEL_REF ! 508: || (GET_CODE (orig) == SYMBOL_REF ! 509: #if 0 ! 510: && !((machopic_classify_name (XSTR (orig, 0)) ! 511: == MACHOPIC_DEFINED_FUNCTION) ! 512: && XSTR (orig, 0)[0] == '*') ! 513: #endif ! 514: )) ! 515: { ! 516: /* addr(foo) = &func+(foo-func) */ ! 517: rtx equiv = orig; ! 518: rtx pic_base; ! 519: orig = machopic_indirect_data_reference (orig, reg); ! 520: if (GET_CODE (orig) == PLUS ! 521: && GET_CODE (XEXP (orig, 0)) == REG) ! 522: { ! 523: if (reg == 0) ! 524: return force_reg (mode, orig); ! 525: ! 526: emit_move_insn (reg, orig); ! 527: return reg; ! 528: } ! 529: ! 530: pic_base = gen_rtx (SYMBOL_REF, Pmode, ! 531: machopic_function_base_name ()); ! 532: ! 533: if (GET_CODE (orig) == MEM) ! 534: { ! 535: if (reg == 0) ! 536: abort (); ! 537: #ifdef HAVE_lo_sum ! 538: if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF ! 539: || GET_CODE (XEXP (orig, 0)) == LABEL_REF) ! 540: { ! 541: #ifdef HAVE_hi_sum ! 542: rtx hi_sum; ! 543: rtx offset = gen_rtx (CONST, Pmode, ! 544: gen_rtx (MINUS, Pmode, XEXP (orig, 0), pic_base)); ! 545: ! 546: ! 547: if (reg == 0) ! 548: if (reload_in_progress) ! 549: abort (); ! 550: else ! 551: reg = gen_reg_rtx (Pmode); ! 552: ! 553: hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX, ! 554: gen_rtx (PLUS, Pmode, ! 555: pic_offset_table_rtx, ! 556: gen_rtx (HIGH, Pmode, offset))); ! 557: ! 558: #if 1 ! 559: emit_insn (hi_sum); ! 560: #else ! 561: emit_insn (gen_rtx (PARALLEL, VOIDmode, ! 562: gen_rtvec (2, ! 563: hi_sum, ! 564: gen_rtx (USE, VOIDmode, ! 565: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))))); ! 566: #endif ! 567: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 568: gen_rtx (MEM, GET_MODE (orig), ! 569: gen_rtx (LO_SUM, Pmode, ! 570: HI_SUM_TARGET_RTX, ! 571: offset)))); ! 572: pic_ref = reg; ! 573: ! 574: #else ! 575: emit_insn (gen_rtx (USE, VOIDmode, ! 576: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); ! 577: ! 578: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 579: gen_rtx (HIGH, Pmode, ! 580: gen_rtx (CONST, Pmode, ! 581: gen_rtx (MINUS, Pmode, ! 582: XEXP (orig, 0), ! 583: pic_base))))); ! 584: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 585: gen_rtx (LO_SUM, Pmode, reg, ! 586: gen_rtx (CONST, Pmode, ! 587: gen_rtx (MINUS, Pmode, ! 588: XEXP (orig, 0), ! 589: pic_base))))); ! 590: pic_ref = gen_rtx (PLUS, Pmode, ! 591: pic_offset_table_rtx, reg); ! 592: #endif ! 593: } ! 594: else ! 595: #endif ! 596: { ! 597: emit_insn (gen_rtx (USE, VOIDmode, ! 598: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); ! 599: ! 600: pic_ref = gen_rtx (PLUS, Pmode, ! 601: pic_offset_table_rtx, ! 602: gen_rtx (CONST, Pmode, ! 603: gen_rtx (MINUS, Pmode, ! 604: XEXP (orig, 0), ! 605: pic_base))); ! 606: } ! 607: ! 608: #ifndef HAVE_hi_sum ! 609: RTX_UNCHANGING_P (pic_ref) = 1; ! 610: emit_move_insn (reg, pic_ref); ! 611: pic_ref = gen_rtx (MEM, GET_MODE (orig), reg); ! 612: #endif ! 613: } ! 614: else ! 615: { ! 616: ! 617: #ifdef HAVE_lo_sum ! 618: if (GET_CODE (orig) == SYMBOL_REF ! 619: || GET_CODE (orig) == LABEL_REF) ! 620: { ! 621: #ifdef HAVE_hi_sum ! 622: rtx hi_sum; ! 623: rtx offset = gen_rtx (CONST, Pmode, ! 624: gen_rtx (MINUS, Pmode, orig, pic_base)); ! 625: ! 626: if (reg == 0) ! 627: if (reload_in_progress) ! 628: abort (); ! 629: else ! 630: reg = gen_reg_rtx (SImode); ! 631: ! 632: hi_sum = gen_rtx (SET, Pmode, HI_SUM_TARGET_RTX, ! 633: gen_rtx (PLUS, Pmode, ! 634: pic_offset_table_rtx, ! 635: gen_rtx (HIGH, Pmode, offset))); ! 636: ! 637: #if 1 ! 638: emit_insn (hi_sum); ! 639: #else ! 640: emit_insn (gen_rtx (PARALLEL, VOIDmode, ! 641: gen_rtvec (2, ! 642: hi_sum, ! 643: gen_rtx (USE, VOIDmode, ! 644: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))))); ! 645: #endif ! 646: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 647: gen_rtx (LO_SUM, Pmode, ! 648: HI_SUM_TARGET_RTX, ! 649: offset))); ! 650: pic_ref = reg; ! 651: #else ! 652: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 653: gen_rtx (HIGH, Pmode, ! 654: gen_rtx (CONST, Pmode, ! 655: gen_rtx (MINUS, Pmode, ! 656: orig, pic_base))))); ! 657: emit_insn (gen_rtx (SET, VOIDmode, reg, ! 658: gen_rtx (LO_SUM, Pmode, reg, ! 659: gen_rtx (CONST, Pmode, ! 660: gen_rtx (MINUS, Pmode, ! 661: orig, pic_base))))); ! 662: pic_ref = gen_rtx (PLUS, Pmode, ! 663: pic_offset_table_rtx, reg); ! 664: #endif ! 665: } ! 666: else ! 667: #endif ! 668: if (GET_CODE (orig) == REG) ! 669: { ! 670: return orig; ! 671: } ! 672: else ! 673: { ! 674: emit_insn (gen_rtx (USE, VOIDmode, ! 675: gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM))); ! 676: ! 677: pic_ref = gen_rtx (PLUS, Pmode, ! 678: pic_offset_table_rtx, ! 679: gen_rtx (CONST, Pmode, ! 680: gen_rtx (MINUS, Pmode, ! 681: orig, pic_base))); ! 682: } ! 683: } ! 684: ! 685: RTX_UNCHANGING_P (pic_ref) = 1; ! 686: ! 687: if (reg == 0) ! 688: return force_reg (mode, pic_ref); ! 689: else ! 690: { ! 691: if (GET_CODE (pic_ref) != REG) ! 692: emit_move_insn (reg, pic_ref); ! 693: else ! 694: reg = pic_ref; ! 695: ! 696: { ! 697: rtx insn = get_last_insn (); ! 698: rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX); ! 699: ! 700: if (note) ! 701: XEXP (note, 0) = equiv; ! 702: else ! 703: REG_NOTES (insn) = gen_rtx (EXPR_LIST, ! 704: REG_EQUAL, equiv, REG_NOTES (insn)); ! 705: } ! 706: ! 707: return reg; ! 708: } ! 709: } ! 710: ! 711: else if (GET_CODE (orig) == SYMBOL_REF) ! 712: return orig; ! 713: ! 714: else if (GET_CODE (orig) == PLUS ! 715: && (GET_CODE (XEXP (orig, 0)) == MEM ! 716: || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF ! 717: || GET_CODE (XEXP (orig, 0)) == LABEL_REF) ! 718: && XEXP (orig, 0) != pic_offset_table_rtx ! 719: && GET_CODE (XEXP (orig, 1)) != REG) ! 720: ! 721: { ! 722: rtx base, offset; ! 723: int is_complex; ! 724: ! 725: is_complex = (GET_CODE (XEXP (orig, 0)) == MEM); ! 726: ! 727: base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); ! 728: orig = machopic_legitimize_pic_address (XEXP (orig, 1), ! 729: Pmode, base == reg ? 0 : reg); ! 730: if (GET_CODE (orig) == CONST_INT) ! 731: { ! 732: pic_ref = plus_constant_for_output (base, INTVAL (orig)); ! 733: is_complex = 1; ! 734: } ! 735: else ! 736: { ! 737: pic_ref = gen_rtx (PLUS, Pmode, base, orig); ! 738: } ! 739: ! 740: if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig)) ! 741: RTX_UNCHANGING_P (pic_ref) = 1; ! 742: ! 743: if (reg && is_complex) ! 744: { ! 745: emit_move_insn (reg, pic_ref); ! 746: pic_ref = reg; ! 747: } ! 748: /* Likewise, should we set special REG_NOTEs here? */ ! 749: } ! 750: ! 751: else if (GET_CODE (orig) == CONST) ! 752: { ! 753: return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); ! 754: } ! 755: ! 756: else if (GET_CODE (orig) == MEM ! 757: && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF) ! 758: { ! 759: rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg); ! 760: ! 761: emit_move_insn (reg, gen_rtx (MEM, GET_MODE (orig), addr)); ! 762: pic_ref = reg; ! 763: } ! 764: ! 765: return pic_ref; ! 766: } ! 767: ! 768: ! 769: void ! 770: machopic_finish (asm_out_file) ! 771: FILE *asm_out_file; ! 772: { ! 773: tree temp; ! 774: ! 775: for (temp = machopic_stubs; ! 776: temp != NULL_TREE; ! 777: temp = TREE_CHAIN (temp)) ! 778: { ! 779: char symb[256]; ! 780: char stub[256]; ! 781: char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); ! 782: char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); ! 783: ! 784: if (symb_name[0] == '*') ! 785: strcpy (symb, symb_name+1); ! 786: else ! 787: symb[0] = '_', strcpy (symb+1, symb_name); ! 788: ! 789: if (stub_name[0] == '*') ! 790: strcpy (stub, stub_name+1); ! 791: else ! 792: stub[0] = '_', strcpy (stub+1, stub_name); ! 793: ! 794: /* must be in aux-out.c */ ! 795: machopic_output_stub (asm_out_file, symb, stub); ! 796: ! 797: } ! 798: ! 799: for (temp = machopic_non_lazy_pointers; ! 800: temp != NULL_TREE; ! 801: temp = TREE_CHAIN (temp)) ! 802: { ! 803: char *symb_name = IDENTIFIER_POINTER (TREE_VALUE (temp)); ! 804: char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp)); ! 805: ! 806: ! 807: if (machopic_ident_defined_p (TREE_VALUE (temp))) ! 808: { ! 809: char symb[256]; ! 810: ! 811: if (symb_name[0] == '*') ! 812: strcpy (symb, symb_name+1); ! 813: else ! 814: strcpy (symb, symb_name); ! 815: ! 816: readonly_data_section (); ! 817: assemble_label (lazy_name); ! 818: assemble_integer (gen_rtx (SYMBOL_REF, Pmode, symb_name), ! 819: GET_MODE_SIZE (Pmode), 1); ! 820: } ! 821: else ! 822: { ! 823: machopic_nl_symbol_ptr_section (); ! 824: assemble_name (asm_out_file, lazy_name); ! 825: fprintf (asm_out_file, ":\n"); ! 826: ! 827: fprintf (asm_out_file, "\t.indirect_symbol "); ! 828: assemble_name (asm_out_file, symb_name); ! 829: fprintf (asm_out_file, "\n"); ! 830: ! 831: assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1); ! 832: } ! 833: } ! 834: } ! 835: ! 836: int ! 837: machopic_operand_p (op) ! 838: rtx op; ! 839: { ! 840: if (MACHOPIC_JUST_INDIRECT) ! 841: { ! 842: while (GET_CODE (op) == CONST) ! 843: op = XEXP (op, 0); ! 844: ! 845: if (GET_CODE (op) == SYMBOL_REF) ! 846: return machopic_name_defined_p (XSTR (op, 0)); ! 847: else ! 848: return 0; ! 849: } ! 850: ! 851: while (GET_CODE (op) == CONST) ! 852: op = XEXP (op, 0); ! 853: ! 854: if (GET_CODE (op) == MINUS ! 855: && GET_CODE (XEXP (op, 0)) == SYMBOL_REF ! 856: && GET_CODE (XEXP (op, 1)) == SYMBOL_REF ! 857: && machopic_name_defined_p (XSTR (XEXP (op, 0), 0)) ! 858: && machopic_name_defined_p (XSTR (XEXP (op, 1), 0))) ! 859: { ! 860: return 1; ! 861: } ! 862: ! 863: #if 0 ! 864: else if (GET_CODE (op) == SYMBOL_REF ! 865: && (machopic_classify_name (XSTR (op, 0)) ! 866: == MACHOPIC_DEFINED_FUNCTION)) ! 867: { ! 868: return 1; ! 869: } ! 870: #endif ! 871: ! 872: return 0; ! 873: } ! 874: ! 875: #endif ! 876:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.