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