00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "insn-flags.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "flags.h"
00038 #include "tree.h"
00039 #include "expr.h"
00040 #include "reload.h"
00041 #include "function.h"
00042 #include "ggc.h"
00043 #include "langhooks.h"
00044 #include "target.h"
00045 #include "tm_p.h"
00046 #include "errors.h"
00047 #include "hashtab.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 const char *darwin_one_byte_bool = 0;
00083
00084 int
00085 name_needs_quotes (const char *name)
00086 {
00087 int c;
00088 while ((c = *name++) != '\0')
00089 if (! ISIDNUM (c) && c != '.' && c != '$')
00090 return 1;
00091 return 0;
00092 }
00093
00094
00095 static int
00096 machopic_symbol_defined_p (rtx sym_ref)
00097 {
00098 if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
00099 return true;
00100
00101
00102
00103 if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
00104 {
00105
00106
00107 if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
00108 {
00109 tree decl = SYMBOL_REF_DECL (sym_ref);
00110 if (!decl)
00111 return true;
00112 if (DECL_COMMON (decl))
00113 return false;
00114 }
00115 return true;
00116 }
00117 return false;
00118 }
00119
00120
00121
00122
00123 enum machopic_addr_class
00124 machopic_classify_symbol (rtx sym_ref)
00125 {
00126 int flags;
00127 bool function_p;
00128
00129 flags = SYMBOL_REF_FLAGS (sym_ref);
00130 function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
00131 if (machopic_symbol_defined_p (sym_ref))
00132 return (function_p
00133 ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
00134 else
00135 return (function_p
00136 ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
00137 }
00138
00139 #ifndef TARGET_FIX_AND_CONTINUE
00140 #define TARGET_FIX_AND_CONTINUE 0
00141 #endif
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 static int
00154 indirect_data (rtx sym_ref)
00155 {
00156 int lprefix;
00157 const char *name;
00158
00159
00160 if (TARGET_FIX_AND_CONTINUE == 0)
00161 return 0;
00162
00163
00164
00165
00166
00167
00168 name = XSTR (sym_ref, 0);
00169
00170 lprefix = (((name[0] == '*' || name[0] == '&')
00171 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
00172 || (strncmp (name, "_OBJC_", 6) == 0));
00173
00174 return ! lprefix;
00175 }
00176
00177
00178 static int
00179 machopic_data_defined_p (rtx sym_ref)
00180 {
00181 if (indirect_data (sym_ref))
00182 return 0;
00183
00184 switch (machopic_classify_symbol (sym_ref))
00185 {
00186 case MACHOPIC_DEFINED_DATA:
00187 case MACHOPIC_DEFINED_FUNCTION:
00188 return 1;
00189 default:
00190 return 0;
00191 }
00192 }
00193
00194 void
00195 machopic_define_symbol (rtx mem)
00196 {
00197 rtx sym_ref;
00198 if (GET_CODE (mem) != MEM)
00199 abort ();
00200 sym_ref = XEXP (mem, 0);
00201 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
00202 }
00203
00204 static GTY(()) char * function_base;
00205
00206 const char *
00207 machopic_function_base_name (void)
00208 {
00209
00210 if (MACHO_DYNAMIC_NO_PIC_P)
00211 abort ();
00212
00213 if (function_base == NULL)
00214 function_base =
00215 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
00216
00217 current_function_uses_pic_offset_table = 1;
00218
00219 return function_base;
00220 }
00221
00222
00223
00224 rtx
00225 machopic_function_base_sym (void)
00226 {
00227 rtx sym_ref;
00228
00229 sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
00230 SYMBOL_REF_FLAGS (sym_ref)
00231 |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
00232 return sym_ref;
00233 }
00234
00235
00236
00237 static inline rtx
00238 gen_pic_offset (rtx orig, rtx pic_base)
00239 {
00240 if (!pic_base)
00241 return orig;
00242 else
00243 return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base));
00244 }
00245
00246 static GTY(()) const char * function_base_func_name;
00247 static GTY(()) int current_pic_label_num;
00248
00249 void
00250 machopic_output_function_base_name (FILE *file)
00251 {
00252 const char *current_name;
00253
00254
00255 if (MACHO_DYNAMIC_NO_PIC_P)
00256 abort ();
00257 current_name =
00258 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
00259 if (function_base_func_name != current_name)
00260 {
00261 ++current_pic_label_num;
00262 function_base_func_name = current_name;
00263 }
00264 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
00265 }
00266
00267
00268 #define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
00269
00270 #define STUB_SUFFIX "$stub"
00271
00272 typedef struct machopic_indirection GTY (())
00273 {
00274
00275 rtx symbol;
00276
00277 const char * ptr_name;
00278
00279
00280 bool stub_p;
00281
00282 bool used;
00283 } machopic_indirection;
00284
00285
00286
00287
00288 static GTY ((param_is (struct machopic_indirection))) htab_t
00289 machopic_indirections;
00290
00291
00292
00293 static hashval_t
00294 machopic_indirection_hash (const void *slot)
00295 {
00296 const machopic_indirection *p = (const machopic_indirection *) slot;
00297 return htab_hash_string (p->ptr_name);
00298 }
00299
00300
00301
00302
00303 static int
00304 machopic_indirection_eq (const void *slot, const void *key)
00305 {
00306 return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
00307 }
00308
00309
00310
00311
00312 const char *
00313 machopic_indirection_name (rtx sym_ref, bool stub_p)
00314 {
00315 char *buffer;
00316 const char *name = XSTR (sym_ref, 0);
00317 size_t namelen = strlen (name);
00318 machopic_indirection *p;
00319 void ** slot;
00320
00321
00322 if (stub_p)
00323 {
00324 int needs_quotes = name_needs_quotes (name);
00325 buffer = alloca (strlen ("&L")
00326 + namelen
00327 + strlen (STUB_SUFFIX)
00328 + 2
00329 + 1 );
00330
00331 if (needs_quotes)
00332 {
00333 if (name[0] == '*')
00334 sprintf (buffer, "&\"L%s" STUB_SUFFIX "\"", name + 1);
00335 else
00336 sprintf (buffer, "&\"L%s%s" STUB_SUFFIX "\"", user_label_prefix,
00337 name);
00338 }
00339 else if (name[0] == '*')
00340 sprintf (buffer, "&L%s" STUB_SUFFIX, name + 1);
00341 else
00342 sprintf (buffer, "&L%s%s" STUB_SUFFIX, user_label_prefix, name);
00343 }
00344 else
00345 {
00346 buffer = alloca (strlen ("&L")
00347 + strlen (user_label_prefix)
00348 + namelen
00349 + strlen (NON_LAZY_POINTER_SUFFIX)
00350 + 1 );
00351 if (name[0] == '*')
00352 sprintf (buffer, "&L%s" NON_LAZY_POINTER_SUFFIX, name + 1);
00353 else
00354 sprintf (buffer, "&L%s%s" NON_LAZY_POINTER_SUFFIX,
00355 user_label_prefix, name);
00356 }
00357
00358 if (!machopic_indirections)
00359 machopic_indirections = htab_create_ggc (37,
00360 machopic_indirection_hash,
00361 machopic_indirection_eq,
00362 NULL);
00363
00364 slot = htab_find_slot_with_hash (machopic_indirections, buffer,
00365 htab_hash_string (buffer), INSERT);
00366 if (*slot)
00367 {
00368 p = (machopic_indirection *) *slot;
00369 }
00370 else
00371 {
00372 p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
00373 p->symbol = sym_ref;
00374 p->ptr_name = xstrdup (buffer);
00375 p->stub_p = stub_p;
00376 p->used = false;
00377 *slot = p;
00378 }
00379
00380 return p->ptr_name;
00381 }
00382
00383
00384
00385 const char*
00386 machopic_mcount_stub_name (void)
00387 {
00388 rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
00389 return machopic_indirection_name (symbol, true);
00390 }
00391
00392
00393
00394
00395
00396
00397 void
00398 machopic_validate_stub_or_non_lazy_ptr (const char *name)
00399 {
00400 machopic_indirection *p;
00401
00402 p = ((machopic_indirection *)
00403 (htab_find_with_hash (machopic_indirections, name,
00404 htab_hash_string (name))));
00405 if (p && ! p->used)
00406 {
00407 const char *real_name;
00408 tree id;
00409
00410 p->used = true;
00411
00412
00413 if (SYMBOL_REF_DECL (p->symbol))
00414 mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
00415
00416 real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
00417
00418 id = maybe_get_identifier (real_name);
00419 if (id)
00420 mark_referenced (id);
00421 }
00422 }
00423
00424
00425
00426
00427 rtx
00428 machopic_indirect_data_reference (rtx orig, rtx reg)
00429 {
00430 rtx ptr_ref = orig;
00431
00432 if (! MACHOPIC_INDIRECT)
00433 return orig;
00434
00435 if (GET_CODE (orig) == SYMBOL_REF)
00436 {
00437 int defined = machopic_data_defined_p (orig);
00438
00439 if (defined && MACHO_DYNAMIC_NO_PIC_P)
00440 {
00441 #if defined (TARGET_TOC)
00442 emit_insn (gen_macho_high (reg, orig));
00443 emit_insn (gen_macho_low (reg, reg, orig));
00444 #else
00445
00446 abort ();
00447 #endif
00448 return reg;
00449 }
00450 else if (defined)
00451 {
00452 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
00453 rtx pic_base = machopic_function_base_sym ();
00454 rtx offset = gen_pic_offset (orig, pic_base);
00455 #endif
00456
00457 #if defined (TARGET_TOC)
00458 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
00459
00460 if (reg == NULL)
00461 abort ();
00462
00463 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
00464 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
00465 gen_rtx_HIGH (Pmode, offset))));
00466 emit_insn (gen_rtx_SET (Pmode, reg,
00467 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
00468
00469 orig = reg;
00470 #else
00471 #if defined (HAVE_lo_sum)
00472 if (reg == 0) abort ();
00473
00474 emit_insn (gen_rtx_SET (VOIDmode, reg,
00475 gen_rtx_HIGH (Pmode, offset)));
00476 emit_insn (gen_rtx_SET (VOIDmode, reg,
00477 gen_rtx_LO_SUM (Pmode, reg, offset)));
00478 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
00479
00480 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
00481 #endif
00482 #endif
00483 return orig;
00484 }
00485
00486 ptr_ref = (gen_rtx_SYMBOL_REF
00487 (Pmode,
00488 machopic_indirection_name (orig, false)));
00489
00490 SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
00491
00492 ptr_ref = gen_const_mem (Pmode, ptr_ref);
00493 machopic_define_symbol (ptr_ref);
00494
00495 return ptr_ref;
00496 }
00497 else if (GET_CODE (orig) == CONST)
00498 {
00499 rtx base, result;
00500
00501
00502 if (GET_CODE (XEXP (orig, 0)) == PLUS)
00503 {
00504 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
00505 reg);
00506 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
00507 (base == reg ? 0 : reg));
00508 }
00509 else
00510 return orig;
00511
00512 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
00513 result = plus_constant (base, INTVAL (orig));
00514 else
00515 result = gen_rtx_PLUS (Pmode, base, orig);
00516
00517 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
00518 {
00519 if (reg)
00520 {
00521 emit_move_insn (reg, result);
00522 result = reg;
00523 }
00524 else
00525 {
00526 result = force_reg (GET_MODE (result), result);
00527 }
00528 }
00529
00530 return result;
00531
00532 }
00533 else if (GET_CODE (orig) == MEM)
00534 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
00535
00536
00537
00538
00539 else if (GET_CODE (orig) == PLUS
00540 && GET_CODE (XEXP (orig, 0)) == REG
00541 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
00542 #ifdef I386
00543
00544
00545 && GET_CODE (XEXP (orig, 1)) == CONST
00546 #endif
00547 && reg)
00548 {
00549 emit_move_insn (reg, XEXP (orig, 0));
00550 XEXP (ptr_ref, 0) = reg;
00551 }
00552 return ptr_ref;
00553 }
00554
00555
00556
00557
00558 rtx
00559 machopic_indirect_call_target (rtx target)
00560 {
00561 if (GET_CODE (target) != MEM)
00562 return target;
00563
00564 if (MACHOPIC_INDIRECT
00565 && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
00566 && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
00567 & MACHO_SYMBOL_FLAG_DEFINED))
00568 {
00569 rtx sym_ref = XEXP (target, 0);
00570 const char *stub_name = machopic_indirection_name (sym_ref,
00571 true);
00572 enum machine_mode mode = GET_MODE (sym_ref);
00573 tree decl = SYMBOL_REF_DECL (sym_ref);
00574
00575 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
00576 SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
00577 MEM_READONLY_P (target) = 1;
00578 MEM_NOTRAP_P (target) = 1;
00579 }
00580
00581 return target;
00582 }
00583
00584 rtx
00585 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
00586 {
00587 rtx pic_ref = orig;
00588
00589 if (! MACHOPIC_INDIRECT)
00590 return orig;
00591
00592
00593 if (GET_CODE (orig) == LABEL_REF
00594 || (GET_CODE (orig) == SYMBOL_REF
00595 ))
00596 {
00597
00598 rtx pic_base;
00599
00600 orig = machopic_indirect_data_reference (orig, reg);
00601
00602 if (GET_CODE (orig) == PLUS
00603 && GET_CODE (XEXP (orig, 0)) == REG)
00604 {
00605 if (reg == 0)
00606 return force_reg (mode, orig);
00607
00608 emit_move_insn (reg, orig);
00609 return reg;
00610 }
00611
00612
00613 if (MACHO_DYNAMIC_NO_PIC_P)
00614 pic_base = NULL;
00615 else
00616 pic_base = machopic_function_base_sym ();
00617
00618 if (GET_CODE (orig) == MEM)
00619 {
00620 if (reg == 0)
00621 {
00622 if (reload_in_progress)
00623 abort ();
00624 else
00625 reg = gen_reg_rtx (Pmode);
00626 }
00627
00628 #ifdef HAVE_lo_sum
00629 if (MACHO_DYNAMIC_NO_PIC_P
00630 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
00631 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
00632 {
00633 #if defined (TARGET_TOC)
00634 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
00635 rtx asym = XEXP (orig, 0);
00636 rtx mem;
00637
00638 emit_insn (gen_macho_high (temp_reg, asym));
00639 mem = gen_const_mem (GET_MODE (orig),
00640 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
00641 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
00642 #else
00643
00644 abort ();
00645 #endif
00646 pic_ref = reg;
00647 }
00648 else
00649 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
00650 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
00651 {
00652 rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base);
00653 #if defined (TARGET_TOC)
00654
00655
00656 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
00657 rtx mem;
00658 rtx insn;
00659 rtx sum;
00660
00661 sum = gen_rtx_HIGH (Pmode, offset);
00662 if (! MACHO_DYNAMIC_NO_PIC_P)
00663 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
00664
00665 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
00666
00667 mem = gen_const_mem (GET_MODE (orig),
00668 gen_rtx_LO_SUM (Pmode,
00669 hi_sum_reg, offset));
00670 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
00671 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
00672 REG_NOTES (insn));
00673
00674 pic_ref = reg;
00675 #else
00676 emit_insn (gen_rtx_USE (VOIDmode,
00677 gen_rtx_REG (Pmode,
00678 PIC_OFFSET_TABLE_REGNUM)));
00679
00680 emit_insn (gen_rtx_SET (VOIDmode, reg,
00681 gen_rtx_HIGH (Pmode,
00682 gen_rtx_CONST (Pmode,
00683 offset))));
00684 emit_insn (gen_rtx_SET (VOIDmode, reg,
00685 gen_rtx_LO_SUM (Pmode, reg,
00686 gen_rtx_CONST (Pmode, offset))));
00687 pic_ref = gen_rtx_PLUS (Pmode,
00688 pic_offset_table_rtx, reg);
00689 #endif
00690 }
00691 else
00692 #endif
00693 {
00694 rtx pic = pic_offset_table_rtx;
00695 if (GET_CODE (pic) != REG)
00696 {
00697 emit_move_insn (reg, pic);
00698 pic = reg;
00699 }
00700 #if 0
00701 emit_insn (gen_rtx_USE (VOIDmode,
00702 gen_rtx_REG (Pmode,
00703 PIC_OFFSET_TABLE_REGNUM)));
00704 #endif
00705
00706 pic_ref = gen_rtx_PLUS (Pmode, pic,
00707 gen_pic_offset (XEXP (orig, 0),
00708 pic_base));
00709 }
00710
00711 #if !defined (TARGET_TOC)
00712 emit_move_insn (reg, pic_ref);
00713 pic_ref = gen_const_mem (GET_MODE (orig), reg);
00714 #endif
00715 }
00716 else
00717 {
00718
00719 #ifdef HAVE_lo_sum
00720 if (GET_CODE (orig) == SYMBOL_REF
00721 || GET_CODE (orig) == LABEL_REF)
00722 {
00723 rtx offset = gen_pic_offset (orig, pic_base);
00724 #if defined (TARGET_TOC)
00725 rtx hi_sum_reg;
00726
00727 if (reg == 0)
00728 {
00729 if (reload_in_progress)
00730 abort ();
00731 else
00732 reg = gen_reg_rtx (Pmode);
00733 }
00734
00735 hi_sum_reg = reg;
00736
00737 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
00738 (MACHO_DYNAMIC_NO_PIC_P)
00739 ? gen_rtx_HIGH (Pmode, offset)
00740 : gen_rtx_PLUS (Pmode,
00741 pic_offset_table_rtx,
00742 gen_rtx_HIGH (Pmode,
00743 offset))));
00744 emit_insn (gen_rtx_SET (VOIDmode, reg,
00745 gen_rtx_LO_SUM (Pmode,
00746 hi_sum_reg, offset)));
00747 pic_ref = reg;
00748 #else
00749 emit_insn (gen_rtx_SET (VOIDmode, reg,
00750 gen_rtx_HIGH (Pmode, offset)));
00751 emit_insn (gen_rtx_SET (VOIDmode, reg,
00752 gen_rtx_LO_SUM (Pmode, reg, offset)));
00753 pic_ref = gen_rtx_PLUS (Pmode,
00754 pic_offset_table_rtx, reg);
00755 #endif
00756 }
00757 else
00758 #endif
00759 {
00760 if (REG_P (orig)
00761 || GET_CODE (orig) == SUBREG)
00762 {
00763 return orig;
00764 }
00765 else
00766 {
00767 rtx pic = pic_offset_table_rtx;
00768 if (GET_CODE (pic) != REG)
00769 {
00770 emit_move_insn (reg, pic);
00771 pic = reg;
00772 }
00773 #if 0
00774 emit_insn (gen_rtx_USE (VOIDmode,
00775 pic_offset_table_rtx));
00776 #endif
00777 pic_ref = gen_rtx_PLUS (Pmode,
00778 pic,
00779 gen_pic_offset (orig, pic_base));
00780 }
00781 }
00782 }
00783
00784 if (GET_CODE (pic_ref) != REG)
00785 {
00786 if (reg != 0)
00787 {
00788 emit_move_insn (reg, pic_ref);
00789 return reg;
00790 }
00791 else
00792 {
00793 return force_reg (mode, pic_ref);
00794 }
00795 }
00796 else
00797 {
00798 return pic_ref;
00799 }
00800 }
00801
00802 else if (GET_CODE (orig) == SYMBOL_REF)
00803 return orig;
00804
00805 else if (GET_CODE (orig) == PLUS
00806 && (GET_CODE (XEXP (orig, 0)) == MEM
00807 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
00808 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
00809 && XEXP (orig, 0) != pic_offset_table_rtx
00810 && GET_CODE (XEXP (orig, 1)) != REG)
00811
00812 {
00813 rtx base;
00814 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
00815
00816 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
00817 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
00818 Pmode, (base == reg ? 0 : reg));
00819 if (GET_CODE (orig) == CONST_INT)
00820 {
00821 pic_ref = plus_constant (base, INTVAL (orig));
00822 is_complex = 1;
00823 }
00824 else
00825 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
00826
00827 if (reg && is_complex)
00828 {
00829 emit_move_insn (reg, pic_ref);
00830 pic_ref = reg;
00831 }
00832
00833 }
00834
00835 else if (GET_CODE (orig) == CONST)
00836 {
00837 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
00838 }
00839
00840 else if (GET_CODE (orig) == MEM
00841 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
00842 {
00843 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
00844 addr = replace_equiv_address (orig, addr);
00845 emit_move_insn (reg, addr);
00846 pic_ref = reg;
00847 }
00848
00849 return pic_ref;
00850 }
00851
00852
00853
00854
00855
00856 static int
00857 machopic_output_indirection (void **slot, void *data)
00858 {
00859 machopic_indirection *p = *((machopic_indirection **) slot);
00860 FILE *asm_out_file = (FILE *) data;
00861 rtx symbol;
00862 const char *sym_name;
00863 const char *ptr_name;
00864
00865 if (!p->used)
00866 return 1;
00867
00868 symbol = p->symbol;
00869 sym_name = XSTR (symbol, 0);
00870 ptr_name = p->ptr_name;
00871
00872 if (p->stub_p)
00873 {
00874 char *sym;
00875 char *stub;
00876
00877 sym = alloca (strlen (sym_name) + 2);
00878 if (sym_name[0] == '*' || sym_name[0] == '&')
00879 strcpy (sym, sym_name + 1);
00880 else if (sym_name[0] == '-' || sym_name[0] == '+')
00881 strcpy (sym, sym_name);
00882 else
00883 sprintf (sym, "%s%s", user_label_prefix, sym_name);
00884
00885 stub = alloca (strlen (ptr_name) + 2);
00886 if (ptr_name[0] == '*' || ptr_name[0] == '&')
00887 strcpy (stub, ptr_name + 1);
00888 else
00889 sprintf (stub, "%s%s", user_label_prefix, ptr_name);
00890
00891 machopic_output_stub (asm_out_file, sym, stub);
00892 }
00893 else if (! indirect_data (symbol)
00894 && (machopic_symbol_defined_p (symbol)
00895 || SYMBOL_REF_LOCAL_P (symbol)))
00896 {
00897 data_section ();
00898 assemble_align (GET_MODE_ALIGNMENT (Pmode));
00899 assemble_label (ptr_name);
00900 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
00901 GET_MODE_SIZE (Pmode),
00902 GET_MODE_ALIGNMENT (Pmode), 1);
00903 }
00904 else
00905 {
00906 rtx init = const0_rtx;
00907
00908 machopic_nl_symbol_ptr_section ();
00909 assemble_name (asm_out_file, ptr_name);
00910 fprintf (asm_out_file, ":\n");
00911
00912 fprintf (asm_out_file, "\t.indirect_symbol ");
00913 assemble_name (asm_out_file, sym_name);
00914 fprintf (asm_out_file, "\n");
00915
00916
00917
00918
00919
00920
00921
00922
00923 if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
00924 && machopic_symbol_defined_p (symbol))
00925 init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
00926
00927 assemble_integer (init, GET_MODE_SIZE (Pmode),
00928 GET_MODE_ALIGNMENT (Pmode), 1);
00929 }
00930
00931 return 1;
00932 }
00933
00934 void
00935 machopic_finish (FILE *asm_out_file)
00936 {
00937 if (machopic_indirections)
00938 htab_traverse_noresize (machopic_indirections,
00939 machopic_output_indirection,
00940 asm_out_file);
00941 }
00942
00943 int
00944 machopic_operand_p (rtx op)
00945 {
00946 if (MACHOPIC_JUST_INDIRECT)
00947 {
00948 while (GET_CODE (op) == CONST)
00949 op = XEXP (op, 0);
00950
00951 if (GET_CODE (op) == SYMBOL_REF)
00952 return machopic_symbol_defined_p (op);
00953 else
00954 return 0;
00955 }
00956
00957 while (GET_CODE (op) == CONST)
00958 op = XEXP (op, 0);
00959
00960 if (GET_CODE (op) == MINUS
00961 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
00962 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
00963 && machopic_symbol_defined_p (XEXP (op, 0))
00964 && machopic_symbol_defined_p (XEXP (op, 1)))
00965 return 1;
00966
00967 return 0;
00968 }
00969
00970
00971
00972
00973
00974 void
00975 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
00976 {
00977 rtx sym_ref;
00978
00979
00980 default_encode_section_info (decl, rtl, first);
00981
00982 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
00983 return;
00984
00985 sym_ref = XEXP (rtl, 0);
00986 if (TREE_CODE (decl) == VAR_DECL)
00987 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
00988
00989 if (!DECL_EXTERNAL (decl)
00990 && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
00991 && ((TREE_STATIC (decl)
00992 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
00993 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
00994 && DECL_INITIAL (decl) != error_mark_node)))
00995 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
00996
00997 if (TREE_CODE (decl) == VAR_DECL
00998 && indirect_data (sym_ref)
00999 && ! TREE_PUBLIC (decl))
01000 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
01001 }
01002
01003 void
01004 darwin_mark_decl_preserved (const char *name)
01005 {
01006 fprintf (asm_out_file, ".no_dead_strip ");
01007 assemble_name (asm_out_file, name);
01008 fputc ('\n', asm_out_file);
01009 }
01010
01011 void
01012 machopic_select_section (tree exp, int reloc,
01013 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
01014 {
01015 void (*base_function)(void);
01016 bool weak_p = DECL_P (exp) && DECL_WEAK (exp);
01017 static void (* const base_funs[][2])(void) = {
01018 { text_section, text_coal_section },
01019 { text_unlikely_section, text_unlikely_coal_section },
01020 { readonly_data_section, const_coal_section },
01021 { const_data_section, const_data_coal_section },
01022 { data_section, data_coal_section }
01023 };
01024
01025 if (TREE_CODE (exp) == FUNCTION_DECL)
01026 base_function = base_funs[reloc][weak_p];
01027 else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
01028 base_function = base_funs[2][weak_p];
01029 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
01030 base_function = base_funs[3][weak_p];
01031 else
01032 base_function = base_funs[4][weak_p];
01033
01034 if (TREE_CODE (exp) == STRING_CST
01035 && ((size_t) TREE_STRING_LENGTH (exp)
01036 == strlen (TREE_STRING_POINTER (exp)) + 1))
01037 cstring_section ();
01038 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
01039 && flag_merge_constants)
01040 {
01041 tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
01042
01043 if (TREE_CODE (size) == INTEGER_CST &&
01044 TREE_INT_CST_LOW (size) == 4 &&
01045 TREE_INT_CST_HIGH (size) == 0)
01046 literal4_section ();
01047 else if (TREE_CODE (size) == INTEGER_CST &&
01048 TREE_INT_CST_LOW (size) == 8 &&
01049 TREE_INT_CST_HIGH (size) == 0)
01050 literal8_section ();
01051 else
01052 base_function ();
01053 }
01054 else if (TREE_CODE (exp) == CONSTRUCTOR
01055 && TREE_TYPE (exp)
01056 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
01057 && TYPE_NAME (TREE_TYPE (exp)))
01058 {
01059 tree name = TYPE_NAME (TREE_TYPE (exp));
01060 if (TREE_CODE (name) == TYPE_DECL)
01061 name = DECL_NAME (name);
01062 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
01063 objc_constant_string_object_section ();
01064 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
01065 objc_string_object_section ();
01066 else
01067 base_function ();
01068 }
01069 else if (TREE_CODE (exp) == VAR_DECL &&
01070 DECL_NAME (exp) &&
01071 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
01072 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
01073 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
01074 {
01075 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
01076
01077 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
01078 objc_cls_meth_section ();
01079 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
01080 objc_inst_meth_section ();
01081 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
01082 objc_cat_cls_meth_section ();
01083 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
01084 objc_cat_inst_meth_section ();
01085 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
01086 objc_class_vars_section ();
01087 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
01088 objc_instance_vars_section ();
01089 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
01090 objc_cat_cls_meth_section ();
01091 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
01092 objc_class_names_section ();
01093 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
01094 objc_meth_var_names_section ();
01095 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
01096 objc_meth_var_types_section ();
01097 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
01098 objc_cls_refs_section ();
01099 else if (!strncmp (name, "_OBJC_CLASS_", 12))
01100 objc_class_section ();
01101 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
01102 objc_meta_class_section ();
01103 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
01104 objc_category_section ();
01105 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
01106 objc_selector_refs_section ();
01107 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
01108 objc_selector_fixup_section ();
01109 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
01110 objc_symbols_section ();
01111 else if (!strncmp (name, "_OBJC_MODULES", 13))
01112 objc_module_info_section ();
01113 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
01114 objc_image_info_section ();
01115 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
01116 objc_cat_inst_meth_section ();
01117 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
01118 objc_cat_cls_meth_section ();
01119 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
01120 objc_cat_cls_meth_section ();
01121 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
01122 objc_protocol_section ();
01123 else
01124 base_function ();
01125 }
01126 else
01127 base_function ();
01128 }
01129
01130
01131
01132
01133 void
01134 machopic_select_rtx_section (enum machine_mode mode, rtx x,
01135 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
01136 {
01137 if (GET_MODE_SIZE (mode) == 8
01138 && (GET_CODE (x) == CONST_INT
01139 || GET_CODE (x) == CONST_DOUBLE))
01140 literal8_section ();
01141 else if (GET_MODE_SIZE (mode) == 4
01142 && (GET_CODE (x) == CONST_INT
01143 || GET_CODE (x) == CONST_DOUBLE))
01144 literal4_section ();
01145 else if (MACHOPIC_INDIRECT
01146 && (GET_CODE (x) == SYMBOL_REF
01147 || GET_CODE (x) == CONST
01148 || GET_CODE (x) == LABEL_REF))
01149 const_data_section ();
01150 else
01151 const_section ();
01152 }
01153
01154 void
01155 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
01156 {
01157 if (MACHOPIC_INDIRECT)
01158 mod_init_section ();
01159 else
01160 constructor_section ();
01161 assemble_align (POINTER_SIZE);
01162 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01163
01164 if (! MACHOPIC_INDIRECT)
01165 fprintf (asm_out_file, ".reference .constructors_used\n");
01166 }
01167
01168 void
01169 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
01170 {
01171 if (MACHOPIC_INDIRECT)
01172 mod_term_section ();
01173 else
01174 destructor_section ();
01175 assemble_align (POINTER_SIZE);
01176 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
01177
01178 if (! MACHOPIC_INDIRECT)
01179 fprintf (asm_out_file, ".reference .destructors_used\n");
01180 }
01181
01182 void
01183 darwin_globalize_label (FILE *stream, const char *name)
01184 {
01185 if (!!strncmp (name, "_OBJC_", 6))
01186 default_globalize_label (stream, name);
01187 }
01188
01189 void
01190 darwin_asm_named_section (const char *name,
01191 unsigned int flags ATTRIBUTE_UNUSED,
01192 tree decl ATTRIBUTE_UNUSED)
01193 {
01194 fprintf (asm_out_file, "\t.section %s\n", name);
01195 }
01196
01197 void
01198 darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
01199 {
01200
01201 }
01202
01203
01204
01205
01206 tree
01207 darwin_handle_weak_import_attribute (tree *node, tree name,
01208 tree ARG_UNUSED (args),
01209 int ARG_UNUSED (flags),
01210 bool * no_add_attrs)
01211 {
01212 if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
01213 {
01214 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
01215 *no_add_attrs = true;
01216 }
01217 else
01218 declare_weak (*node);
01219
01220 return NULL_TREE;
01221 }
01222
01223 static void
01224 no_dead_strip (FILE *file, const char *lab)
01225 {
01226 fprintf (file, ".no_dead_strip %s\n", lab);
01227 }
01228
01229
01230
01231
01232
01233
01234 void
01235 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
01236 {
01237 tree id = DECL_ASSEMBLER_NAME (decl)
01238 ? DECL_ASSEMBLER_NAME (decl)
01239 : DECL_NAME (decl);
01240
01241 const char *prefix = "_";
01242 const int prefix_len = 1;
01243
01244 const char *base = IDENTIFIER_POINTER (id);
01245 unsigned int base_len = IDENTIFIER_LENGTH (id);
01246
01247 const char *suffix = ".eh";
01248
01249 int need_quotes = name_needs_quotes (base);
01250 int quotes_len = need_quotes ? 2 : 0;
01251 char *lab;
01252
01253 if (! for_eh)
01254 suffix = ".eh1";
01255
01256 lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
01257 lab[0] = '\0';
01258
01259 if (need_quotes)
01260 strcat(lab, "\"");
01261 strcat(lab, prefix);
01262 strcat(lab, base);
01263 strcat(lab, suffix);
01264 if (need_quotes)
01265 strcat(lab, "\"");
01266
01267 if (TREE_PUBLIC (decl))
01268 fprintf (file, "\t%s %s\n",
01269 (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
01270 ? ".globl"
01271 : ".private_extern"),
01272 lab);
01273
01274 if (DECL_WEAK (decl))
01275 fprintf (file, "\t.weak_definition %s\n", lab);
01276
01277 if (empty)
01278 {
01279 fprintf (file, "%s = 0\n", lab);
01280
01281
01282
01283
01284
01285 no_dead_strip (file, lab);
01286 }
01287 else
01288 fprintf (file, "%s:\n", lab);
01289
01290 free (lab);
01291 }
01292
01293
01294
01295 void
01296 darwin_non_lazy_pcrel (FILE *file, rtx addr)
01297 {
01298 const char *nlp_name;
01299
01300 if (GET_CODE (addr) != SYMBOL_REF)
01301 abort ();
01302
01303 nlp_name = machopic_indirection_name (addr, false);
01304 fputs ("\t.long\t", file);
01305 ASM_OUTPUT_LABELREF (file, nlp_name);
01306 fputs ("-.", file);
01307 }
01308
01309
01310
01311
01312
01313
01314
01315 void
01316 darwin_assemble_visibility (tree decl, int vis)
01317 {
01318 if (vis == VISIBILITY_DEFAULT)
01319 ;
01320 else if (vis == VISIBILITY_HIDDEN)
01321 {
01322 fputs ("\t.private_extern ", asm_out_file);
01323 assemble_name (asm_out_file,
01324 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
01325 fputs ("\n", asm_out_file);
01326 }
01327 else
01328 warning ("internal and protected visibility attributes not supported "
01329 "in this configuration; ignored");
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339 static int darwin_dwarf_label_counter;
01340
01341 void
01342 darwin_asm_output_dwarf_delta (FILE *file, int size,
01343 const char *lab1, const char *lab2)
01344 {
01345 int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
01346 && lab2[0] == '*' && lab2[1] == 'L');
01347 const char *directive = (size == 8 ? ".quad" : ".long");
01348
01349 if (islocaldiff)
01350 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
01351 else
01352 fprintf (file, "\t%s\t", directive);
01353 assemble_name_raw (file, lab1);
01354 fprintf (file, "-");
01355 assemble_name_raw (file, lab2);
01356 if (islocaldiff)
01357 fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
01358 }
01359
01360 void
01361 darwin_file_end (void)
01362 {
01363 machopic_finish (asm_out_file);
01364 if (strcmp (lang_hooks.name, "GNU C++") == 0)
01365 {
01366 constructor_section ();
01367 destructor_section ();
01368 ASM_OUTPUT_ALIGN (asm_out_file, 1);
01369 }
01370 fprintf (asm_out_file, "\t.subsections_via_symbols\n");
01371 }
01372
01373
01374
01375
01376
01377
01378
01379 int darwin_fix_and_continue;
01380 const char *darwin_fix_and_continue_switch;
01381
01382 #include "gt-darwin.h"