1 /* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by Apple Computer Inc.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
42 #include "langhooks.h"
45 static int machopic_data_defined_p PARAMS ((const char *));
46 static void update_non_lazy_ptrs PARAMS ((const char *));
47 static void update_stubs PARAMS ((const char *));
50 name_needs_quotes (name)
54 while ((c = *name++) != '\0')
61 * flag_pic = 1 ... generate only indirections
62 * flag_pic = 2 ... generate indirections and pure code
65 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
66 reference, which will not be changed. */
68 static GTY(()) tree machopic_defined_list;
70 enum machopic_addr_class
71 machopic_classify_ident (ident)
74 const char *name = IDENTIFIER_POINTER (ident);
75 int lprefix = (((name[0] == '*' || name[0] == '&')
76 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
87 /* Here if no special encoding to be found. */
90 const char *name = IDENTIFIER_POINTER (ident);
91 int len = strlen (name);
93 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
94 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
95 return MACHOPIC_DEFINED_FUNCTION;
96 return MACHOPIC_DEFINED_DATA;
99 for (temp = machopic_defined_list;
101 temp = TREE_CHAIN (temp))
103 if (ident == TREE_VALUE (temp))
104 return MACHOPIC_DEFINED_DATA;
107 if (TREE_ASM_WRITTEN (ident))
108 return MACHOPIC_DEFINED_DATA;
110 return MACHOPIC_UNDEFINED;
113 else if (name[1] == 'D')
114 return MACHOPIC_DEFINED_DATA;
116 else if (name[1] == 'T')
117 return MACHOPIC_DEFINED_FUNCTION;
119 /* It is possible that someone is holding a "stale" name, which has
120 since been defined. See if there is a "defined" name (i.e,
121 different from NAME only in having a '!D_' or a '!T_' instead of
122 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
123 that this identifier is defined. */
124 else if (name[1] == 'd' || name[1] == 't')
127 new_name = (char *)alloca (strlen (name) + 1);
128 strcpy (new_name, name);
129 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
130 if (maybe_get_identifier (new_name) != NULL)
131 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
132 : MACHOPIC_DEFINED_FUNCTION;
135 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
137 if (ident == TREE_VALUE (temp))
140 return MACHOPIC_DEFINED_FUNCTION;
142 return MACHOPIC_DEFINED_DATA;
146 if (name[1] == 't' || name[1] == 'T')
149 return MACHOPIC_DEFINED_FUNCTION;
151 return MACHOPIC_UNDEFINED_FUNCTION;
156 return MACHOPIC_DEFINED_DATA;
158 return MACHOPIC_UNDEFINED_DATA;
163 enum machopic_addr_class
164 machopic_classify_name (name)
167 return machopic_classify_ident (get_identifier (name));
171 machopic_ident_defined_p (ident)
174 switch (machopic_classify_ident (ident))
176 case MACHOPIC_UNDEFINED:
177 case MACHOPIC_UNDEFINED_DATA:
178 case MACHOPIC_UNDEFINED_FUNCTION:
186 machopic_data_defined_p (name)
189 switch (machopic_classify_ident (get_identifier (name)))
191 case MACHOPIC_DEFINED_DATA:
199 machopic_name_defined_p (name)
202 return machopic_ident_defined_p (get_identifier (name));
206 machopic_define_ident (ident)
209 if (!machopic_ident_defined_p (ident))
210 machopic_defined_list =
211 tree_cons (NULL_TREE, ident, machopic_defined_list);
215 machopic_define_name (name)
218 machopic_define_ident (get_identifier (name));
221 /* This is a static to make inline functions work. The rtx
222 representing the PIC base symbol always points to here. */
224 static char function_base[32];
226 static GTY(()) int current_pic_label_num;
229 machopic_function_base_name ()
231 static const char *name = NULL;
232 static const char *current_name;
234 /* if dynamic-no-pic is on, we should not get here */
235 if (MACHO_DYNAMIC_NO_PIC_P)
237 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
239 if (name != current_name)
241 current_function_uses_pic_offset_table = 1;
243 /* Save mucho space and time. Some of the C++ mangled names are over
244 700 characters long! Note that we produce a label containing a '-'
245 if the function we're compiling is an Objective-C method, as evinced
246 by the incredibly scientific test below. This is because code in
247 rs6000.c makes the same ugly test when loading the PIC reg. */
249 ++current_pic_label_num;
250 if (*current_name == '+' || *current_name == '-')
251 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
253 sprintf (function_base, "*L%d$pb", current_pic_label_num);
258 return function_base;
261 static GTY(()) tree machopic_non_lazy_pointers;
263 /* Return a non-lazy pointer name corresponding to the given name,
264 either by finding it in our list of pointer names, or by generating
268 machopic_non_lazy_ptr_name (name)
271 const char *temp_name;
272 tree temp, ident = get_identifier (name);
274 for (temp = machopic_non_lazy_pointers;
276 temp = TREE_CHAIN (temp))
278 if (ident == TREE_VALUE (temp))
279 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
282 name = darwin_strip_name_encoding (name);
284 /* Try again, but comparing names this time. */
285 for (temp = machopic_non_lazy_pointers;
287 temp = TREE_CHAIN (temp))
289 if (TREE_VALUE (temp))
291 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
292 temp_name = darwin_strip_name_encoding (temp_name);
293 if (strcmp (name, temp_name) == 0)
294 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
302 buffer = alloca (strlen (name) + 20);
304 strcpy (buffer, "&L");
306 strcat (buffer, name+1);
309 strcat (buffer, "_");
310 strcat (buffer, name);
313 strcat (buffer, "$non_lazy_ptr");
314 ptr_name = get_identifier (buffer);
316 machopic_non_lazy_pointers
317 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
319 TREE_USED (machopic_non_lazy_pointers) = 0;
321 return IDENTIFIER_POINTER (ptr_name);
325 static GTY(()) tree machopic_stubs;
327 /* Return the name of the stub corresponding to the given name,
328 generating a new stub name if necessary. */
331 machopic_stub_name (name)
334 tree temp, ident = get_identifier (name);
337 for (temp = machopic_stubs;
339 temp = TREE_CHAIN (temp))
341 if (ident == TREE_VALUE (temp))
342 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
343 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
344 if (strcmp (name, tname) == 0)
345 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
346 /* A library call name might not be section-encoded yet, so try
347 it against a stripped name. */
350 && strcmp (name, tname + 4) == 0)
351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
354 name = darwin_strip_name_encoding (name);
359 int needs_quotes = name_needs_quotes (name);
361 buffer = alloca (strlen (name) + 20);
364 strcpy (buffer, "&\"L");
366 strcpy (buffer, "&L");
369 strcat (buffer, name+1);
373 strcat (buffer, "_");
374 strcat (buffer, name);
378 strcat (buffer, "$stub\"");
380 strcat (buffer, "$stub");
381 ptr_name = get_identifier (buffer);
383 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
384 TREE_USED (machopic_stubs) = 0;
386 return IDENTIFIER_POINTER (ptr_name);
391 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
395 const char *real_name;
396 tree temp, ident = get_identifier (name), id2;
398 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
400 temp = TREE_CHAIN (temp))
401 if (ident == TREE_PURPOSE (temp))
403 /* Mark both the stub or non-lazy pointer as well as the
404 original symbol as being referenced. */
405 TREE_USED (temp) = 1;
406 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
407 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
408 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
409 real_name = darwin_strip_name_encoding (real_name);
410 id2 = maybe_get_identifier (real_name);
412 TREE_SYMBOL_REFERENCED (id2) = 1;
416 /* Transform ORIG, which may be any data source, to the corresponding
417 source using indirections. */
420 machopic_indirect_data_reference (orig, reg)
425 if (! MACHOPIC_INDIRECT)
428 if (GET_CODE (orig) == SYMBOL_REF)
430 const char *name = XSTR (orig, 0);
432 int defined = machopic_data_defined_p (name);
434 if (defined && MACHO_DYNAMIC_NO_PIC_P)
436 #if defined (TARGET_TOC)
437 emit_insn (gen_macho_high (reg, orig));
438 emit_insn (gen_macho_low (reg, reg, orig));
440 /* some other cpu -- writeme! */
447 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
448 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
449 machopic_function_base_name ());
450 rtx offset = gen_rtx (CONST, Pmode,
451 gen_rtx (MINUS, Pmode, orig, pic_base));
454 #if defined (TARGET_TOC) /* i.e., PowerPC */
455 rtx hi_sum_reg = reg;
460 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
461 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
462 gen_rtx (HIGH, Pmode, offset))));
463 emit_insn (gen_rtx (SET, Pmode, reg,
464 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
468 #if defined (HAVE_lo_sum)
469 if (reg == 0) abort ();
471 emit_insn (gen_rtx (SET, VOIDmode, reg,
472 gen_rtx (HIGH, Pmode, offset)));
473 emit_insn (gen_rtx (SET, VOIDmode, reg,
474 gen_rtx (LO_SUM, Pmode, reg, offset)));
475 emit_insn (gen_rtx (USE, VOIDmode,
476 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
478 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
484 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
485 machopic_non_lazy_ptr_name (name));
487 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
488 RTX_UNCHANGING_P (ptr_ref) = 1;
492 else if (GET_CODE (orig) == CONST)
496 /* legitimize both operands of the PLUS */
497 if (GET_CODE (XEXP (orig, 0)) == PLUS)
499 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
501 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
502 (base == reg ? 0 : reg));
507 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
508 result = plus_constant (base, INTVAL (orig));
510 result = gen_rtx (PLUS, Pmode, base, orig);
512 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
516 emit_move_insn (reg, result);
521 result = force_reg (GET_MODE (result), result);
528 else if (GET_CODE (orig) == MEM)
529 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
530 /* When the target is i386, this code prevents crashes due to the
531 compiler's ignorance on how to move the PIC base register to
532 other registers. (The reload phase sometimes introduces such
534 else if (GET_CODE (orig) == PLUS
535 && GET_CODE (XEXP (orig, 0)) == REG
536 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
538 /* Prevent the same register from being erroneously used
539 as both the base and index registers. */
540 && GET_CODE (XEXP (orig, 1)) == CONST
544 emit_move_insn (reg, XEXP (orig, 0));
545 XEXP (ptr_ref, 0) = reg;
550 /* Transform TARGET (a MEM), which is a function call target, to the
551 corresponding symbol_stub if necessary. Return a new MEM. */
554 machopic_indirect_call_target (target)
557 if (GET_CODE (target) != MEM)
560 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
562 enum machine_mode mode = GET_MODE (XEXP (target, 0));
563 const char *name = XSTR (XEXP (target, 0), 0);
565 /* If the name is already defined, we need do nothing. */
566 if (name[0] == '!' && name[1] == 'T')
569 if (!machopic_name_defined_p (name))
571 const char *stub_name = machopic_stub_name (name);
573 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
574 RTX_UNCHANGING_P (target) = 1;
582 machopic_legitimize_pic_address (orig, mode, reg)
584 enum machine_mode mode;
588 if (! MACHOPIC_INDIRECT)
591 /* First handle a simple SYMBOL_REF or LABEL_REF */
592 if (GET_CODE (orig) == LABEL_REF
593 || (GET_CODE (orig) == SYMBOL_REF
596 /* addr(foo) = &func+(foo-func) */
599 orig = machopic_indirect_data_reference (orig, reg);
601 if (GET_CODE (orig) == PLUS
602 && GET_CODE (XEXP (orig, 0)) == REG)
605 return force_reg (mode, orig);
607 emit_move_insn (reg, orig);
611 /* if dynamic-no-pic then use 0 as the pic base */
612 if (MACHO_DYNAMIC_NO_PIC_P)
613 pic_base = CONST0_RTX (Pmode);
615 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
617 if (GET_CODE (orig) == MEM)
621 if (reload_in_progress)
624 reg = gen_reg_rtx (Pmode);
628 if (MACHO_DYNAMIC_NO_PIC_P
629 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
630 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
632 #if defined (TARGET_TOC) /* ppc */
633 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
634 rtx asym = XEXP (orig, 0);
637 emit_insn (gen_macho_high (temp_reg, asym));
638 mem = gen_rtx_MEM (GET_MODE (orig),
639 gen_rtx (LO_SUM, Pmode, temp_reg, asym));
640 RTX_UNCHANGING_P (mem) = 1;
641 emit_insn (gen_rtx (SET, VOIDmode, reg, mem));
643 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
649 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
650 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
652 rtx offset = gen_rtx (CONST, Pmode,
653 gen_rtx (MINUS, Pmode,
654 XEXP (orig, 0), pic_base));
655 #if defined (TARGET_TOC) /* i.e., PowerPC */
656 /* Generating a new reg may expose opportunities for
657 common subexpression elimination. */
659 (reload_in_progress ? reg : gen_reg_rtx (SImode));
661 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
662 gen_rtx (PLUS, Pmode,
663 pic_offset_table_rtx,
664 gen_rtx (HIGH, Pmode, offset))));
665 emit_insn (gen_rtx (SET, VOIDmode, reg,
666 gen_rtx (MEM, GET_MODE (orig),
667 gen_rtx (LO_SUM, Pmode,
668 hi_sum_reg, offset))));
672 emit_insn (gen_rtx (USE, VOIDmode,
673 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
675 emit_insn (gen_rtx (SET, VOIDmode, reg,
676 gen_rtx (HIGH, Pmode,
677 gen_rtx (CONST, Pmode, offset))));
678 emit_insn (gen_rtx (SET, VOIDmode, reg,
679 gen_rtx (LO_SUM, Pmode, reg,
680 gen_rtx (CONST, Pmode, offset))));
681 pic_ref = gen_rtx (PLUS, Pmode,
682 pic_offset_table_rtx, reg);
686 #endif /* HAVE_lo_sum */
688 rtx pic = pic_offset_table_rtx;
689 if (GET_CODE (pic) != REG)
691 emit_move_insn (reg, pic);
695 emit_insn (gen_rtx (USE, VOIDmode,
696 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
699 pic_ref = gen_rtx (PLUS, Pmode,
701 gen_rtx (CONST, Pmode,
702 gen_rtx (MINUS, Pmode,
707 #if !defined (TARGET_TOC)
708 emit_move_insn (reg, pic_ref);
709 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
711 RTX_UNCHANGING_P (pic_ref) = 1;
717 if (GET_CODE (orig) == SYMBOL_REF
718 || GET_CODE (orig) == LABEL_REF)
720 rtx offset = gen_rtx (CONST, Pmode,
721 gen_rtx (MINUS, Pmode, orig, pic_base));
722 #if defined (TARGET_TOC) /* i.e., PowerPC */
727 if (reload_in_progress)
730 reg = gen_reg_rtx (SImode);
735 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
736 (MACHO_DYNAMIC_NO_PIC_P)
737 ? gen_rtx (HIGH, Pmode, offset)
738 : gen_rtx (PLUS, Pmode,
739 pic_offset_table_rtx,
740 gen_rtx (HIGH, Pmode, offset))));
741 emit_insn (gen_rtx (SET, VOIDmode, reg,
742 gen_rtx (LO_SUM, Pmode,
743 hi_sum_reg, offset)));
745 RTX_UNCHANGING_P (pic_ref) = 1;
747 emit_insn (gen_rtx (SET, VOIDmode, reg,
748 gen_rtx (HIGH, Pmode, offset)));
749 emit_insn (gen_rtx (SET, VOIDmode, reg,
750 gen_rtx (LO_SUM, Pmode, reg, offset)));
751 pic_ref = gen_rtx (PLUS, Pmode,
752 pic_offset_table_rtx, reg);
753 RTX_UNCHANGING_P (pic_ref) = 1;
757 #endif /* HAVE_lo_sum */
759 if (GET_CODE (orig) == REG)
765 rtx pic = pic_offset_table_rtx;
766 if (GET_CODE (pic) != REG)
768 emit_move_insn (reg, pic);
772 emit_insn (gen_rtx (USE, VOIDmode,
773 pic_offset_table_rtx));
775 pic_ref = gen_rtx (PLUS, Pmode,
777 gen_rtx (CONST, Pmode,
778 gen_rtx (MINUS, Pmode,
784 if (GET_CODE (pic_ref) != REG)
788 emit_move_insn (reg, pic_ref);
793 return force_reg (mode, pic_ref);
802 else if (GET_CODE (orig) == SYMBOL_REF)
805 else if (GET_CODE (orig) == PLUS
806 && (GET_CODE (XEXP (orig, 0)) == MEM
807 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
808 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
809 && XEXP (orig, 0) != pic_offset_table_rtx
810 && GET_CODE (XEXP (orig, 1)) != REG)
814 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
816 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
817 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
818 Pmode, (base == reg ? 0 : reg));
819 if (GET_CODE (orig) == CONST_INT)
821 pic_ref = plus_constant (base, INTVAL (orig));
825 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
827 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
828 RTX_UNCHANGING_P (pic_ref) = 1;
830 if (reg && is_complex)
832 emit_move_insn (reg, pic_ref);
835 /* Likewise, should we set special REG_NOTEs here? */
838 else if (GET_CODE (orig) == CONST)
840 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
843 else if (GET_CODE (orig) == MEM
844 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
846 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
848 addr = gen_rtx (MEM, GET_MODE (orig), addr);
849 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
850 emit_move_insn (reg, addr);
859 machopic_finish (asm_out_file)
864 for (temp = machopic_stubs;
866 temp = TREE_CHAIN (temp))
868 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
869 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
873 if (! TREE_USED (temp))
876 /* If the symbol is actually defined, we don't need a stub. */
877 if (sym_name[0] == '!' && sym_name[1] == 'T')
880 sym_name = darwin_strip_name_encoding (sym_name);
882 sym = alloca (strlen (sym_name) + 2);
883 if (sym_name[0] == '*' || sym_name[0] == '&')
884 strcpy (sym, sym_name + 1);
885 else if (sym_name[0] == '-' || sym_name[0] == '+')
886 strcpy (sym, sym_name);
888 sym[0] = '_', strcpy (sym + 1, sym_name);
890 stub = alloca (strlen (stub_name) + 2);
891 if (stub_name[0] == '*' || stub_name[0] == '&')
892 strcpy (stub, stub_name + 1);
894 stub[0] = '_', strcpy (stub + 1, stub_name);
896 machopic_output_stub (asm_out_file, sym, stub);
899 for (temp = machopic_non_lazy_pointers;
901 temp = TREE_CHAIN (temp))
903 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
904 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
906 if (! TREE_USED (temp))
909 if (machopic_ident_defined_p (TREE_VALUE (temp)))
912 assemble_align (GET_MODE_ALIGNMENT (Pmode));
913 assemble_label (lazy_name);
914 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
915 GET_MODE_SIZE (Pmode),
916 GET_MODE_ALIGNMENT (Pmode), 1);
920 machopic_nl_symbol_ptr_section ();
921 assemble_name (asm_out_file, lazy_name);
922 fprintf (asm_out_file, ":\n");
924 fprintf (asm_out_file, "\t.indirect_symbol ");
925 assemble_name (asm_out_file, sym_name);
926 fprintf (asm_out_file, "\n");
928 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
929 GET_MODE_ALIGNMENT (Pmode), 1);
935 machopic_operand_p (op)
938 if (MACHOPIC_JUST_INDIRECT)
940 while (GET_CODE (op) == CONST)
943 if (GET_CODE (op) == SYMBOL_REF)
944 return machopic_name_defined_p (XSTR (op, 0));
949 while (GET_CODE (op) == CONST)
952 if (GET_CODE (op) == MINUS
953 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
954 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
955 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
956 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
962 /* This function records whether a given name corresponds to a defined
963 or undefined function or variable, for machopic_classify_ident to
967 darwin_encode_section_info (decl, first)
969 int first ATTRIBUTE_UNUSED;
974 const char *orig_str;
978 if ((TREE_CODE (decl) == FUNCTION_DECL
979 || TREE_CODE (decl) == VAR_DECL)
980 && !DECL_EXTERNAL (decl)
981 && ((TREE_STATIC (decl)
982 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
983 || (DECL_INITIAL (decl)
984 && DECL_INITIAL (decl) != error_mark_node)))
987 if (TREE_CODE (decl) == FUNCTION_DECL)
988 code = (defined ? 'T' : 't');
989 else if (TREE_CODE (decl) == VAR_DECL)
990 code = (defined ? 'D' : 'd');
995 sym_ref = XEXP (DECL_RTL (decl), 0);
996 orig_str = XSTR (sym_ref, 0);
997 len = strlen (orig_str) + 1;
999 if (orig_str[0] == '!')
1001 /* Already encoded; see if we need to change it. */
1002 if (code == orig_str[1])
1004 /* Yes, tweak a copy of the name and put it in a new string. */
1005 new_str = alloca (len);
1006 memcpy (new_str, orig_str, len);
1008 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1012 /* Add the encoding. */
1014 new_str = alloca (new_len);
1019 memcpy (new_str + 4, orig_str, len);
1020 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1022 /* The non-lazy pointer list may have captured references to the
1023 old encoded name, change them. */
1024 if (TREE_CODE (decl) == VAR_DECL)
1025 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1027 update_stubs (XSTR (sym_ref, 0));
1030 /* Undo the effects of the above. */
1033 darwin_strip_name_encoding (str)
1036 return str[0] == '!' ? str + 4 : str;
1039 /* Scan the list of non-lazy pointers and update any recorded names whose
1040 stripped name matches the argument. */
1043 update_non_lazy_ptrs (name)
1046 const char *name1, *name2;
1049 name1 = darwin_strip_name_encoding (name);
1051 for (temp = machopic_non_lazy_pointers;
1053 temp = TREE_CHAIN (temp))
1055 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1057 if (*sym_name == '!')
1059 name2 = darwin_strip_name_encoding (sym_name);
1060 if (strcmp (name1, name2) == 0)
1062 /* FIXME: This breaks the identifier hash table. */
1063 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1064 = (unsigned char *) name;
1071 /* Function NAME is being defined, and its label has just been output.
1072 If there's already a reference to a stub for this function, we can
1073 just emit the stub label now and we don't bother emitting the stub later. */
1076 machopic_output_possible_stub_label (file, name)
1083 /* Ensure we're looking at a section-encoded name. */
1084 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1087 for (temp = machopic_stubs;
1089 temp = TREE_CHAIN (temp))
1091 const char *sym_name;
1093 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1094 if (sym_name[0] == '!' && sym_name[1] == 'T'
1095 && ! strcmp (name+2, sym_name+2))
1097 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1098 /* Avoid generating a stub for this. */
1099 TREE_USED (temp) = 0;
1105 /* Scan the list of stubs and update any recorded names whose
1106 stripped name matches the argument. */
1112 const char *name1, *name2;
1115 name1 = darwin_strip_name_encoding (name);
1117 for (temp = machopic_stubs;
1119 temp = TREE_CHAIN (temp))
1121 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1123 if (*sym_name == '!')
1125 name2 = darwin_strip_name_encoding (sym_name);
1126 if (strcmp (name1, name2) == 0)
1128 /* FIXME: This breaks the identifier hash table. */
1129 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1130 = (unsigned char *) name;
1138 machopic_select_section (exp, reloc, align)
1141 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1143 if (TREE_CODE (exp) == STRING_CST)
1145 if (flag_writable_strings)
1147 else if ((size_t) TREE_STRING_LENGTH (exp) !=
1148 strlen (TREE_STRING_POINTER (exp)) + 1)
1149 readonly_data_section ();
1153 else if (TREE_CODE (exp) == INTEGER_CST
1154 || TREE_CODE (exp) == REAL_CST)
1156 tree size = TYPE_SIZE (TREE_TYPE (exp));
1158 if (TREE_CODE (size) == INTEGER_CST &&
1159 TREE_INT_CST_LOW (size) == 4 &&
1160 TREE_INT_CST_HIGH (size) == 0)
1161 literal4_section ();
1162 else if (TREE_CODE (size) == INTEGER_CST &&
1163 TREE_INT_CST_LOW (size) == 8 &&
1164 TREE_INT_CST_HIGH (size) == 0)
1165 literal8_section ();
1167 readonly_data_section ();
1169 else if (TREE_CODE (exp) == CONSTRUCTOR
1171 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1172 && TYPE_NAME (TREE_TYPE (exp)))
1174 tree name = TYPE_NAME (TREE_TYPE (exp));
1175 if (TREE_CODE (name) == TYPE_DECL)
1176 name = DECL_NAME (name);
1177 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1178 objc_constant_string_object_section ();
1179 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1180 objc_string_object_section ();
1181 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1184 if (TREE_SIDE_EFFECTS (exp) || (MACHOPIC_INDIRECT && reloc))
1185 const_data_section ();
1187 readonly_data_section ();
1192 else if (TREE_CODE (exp) == VAR_DECL &&
1194 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1195 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1196 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1198 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1200 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1201 objc_cls_meth_section ();
1202 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1203 objc_inst_meth_section ();
1204 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1205 objc_cat_cls_meth_section ();
1206 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1207 objc_cat_inst_meth_section ();
1208 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1209 objc_class_vars_section ();
1210 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1211 objc_instance_vars_section ();
1212 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1213 objc_cat_cls_meth_section ();
1214 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1215 objc_class_names_section ();
1216 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1217 objc_meth_var_names_section ();
1218 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1219 objc_meth_var_types_section ();
1220 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1221 objc_cls_refs_section ();
1222 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1223 objc_class_section ();
1224 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1225 objc_meta_class_section ();
1226 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1227 objc_category_section ();
1228 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1229 objc_selector_refs_section ();
1230 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1231 objc_selector_fixup_section ();
1232 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1233 objc_symbols_section ();
1234 else if (!strncmp (name, "_OBJC_MODULES", 13))
1235 objc_module_info_section ();
1236 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1237 objc_cat_inst_meth_section ();
1238 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1239 objc_cat_cls_meth_section ();
1240 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1241 objc_cat_cls_meth_section ();
1242 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1243 objc_protocol_section ();
1244 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1245 && !TREE_SIDE_EFFECTS (exp))
1248 if (MACHOPIC_INDIRECT && reloc)
1249 const_data_section ();
1251 readonly_data_section ();
1256 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1259 if (TREE_SIDE_EFFECTS (exp) || (MACHOPIC_INDIRECT && reloc))
1260 const_data_section ();
1262 readonly_data_section ();
1268 /* This can be called with address expressions as "rtx".
1269 They must go in "const". */
1272 machopic_select_rtx_section (mode, x, align)
1273 enum machine_mode mode;
1275 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1277 if (GET_MODE_SIZE (mode) == 8)
1278 literal8_section ();
1279 else if (GET_MODE_SIZE (mode) == 4
1280 && (GET_CODE (x) == CONST_INT
1281 || GET_CODE (x) == CONST_DOUBLE))
1282 literal4_section ();
1288 machopic_asm_out_constructor (symbol, priority)
1290 int priority ATTRIBUTE_UNUSED;
1293 if (MACHOPIC_INDIRECT)
1294 mod_init_section ();
1296 constructor_section ();
1297 assemble_align (POINTER_SIZE);
1298 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1301 if (! MACHOPIC_INDIRECT)
1302 fprintf (asm_out_file, ".reference .constructors_used\n");
1306 machopic_asm_out_destructor (symbol, priority)
1308 int priority ATTRIBUTE_UNUSED;
1311 if (MACHOPIC_INDIRECT)
1312 mod_term_section ();
1314 destructor_section ();
1315 assemble_align (POINTER_SIZE);
1316 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1318 if (! MACHOPIC_INDIRECT)
1319 fprintf (asm_out_file, ".reference .destructors_used\n");
1323 darwin_globalize_label (stream, name)
1327 if (!!strncmp (name, "_OBJC_", 6))
1328 default_globalize_label (stream, name);
1331 /* Output a difference of two labels that will be an assembly time
1332 constant if the two labels are local. (.long lab1-lab2 will be
1333 very different if lab1 is at the boundary between two sections; it
1334 will be relocated according to the second section, not the first,
1335 so one ends up with a difference between labels in different
1336 sections, which is bad in the dwarf2 eh context for instance.) */
1338 static int darwin_dwarf_label_counter;
1341 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1343 int size ATTRIBUTE_UNUSED;
1344 const char *lab1, *lab2;
1346 const char *p = lab1 + (lab1[0] == '*');
1347 int islocaldiff = (p[0] == 'L');
1350 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1352 fprintf (file, "\t%s\t", ".long");
1353 assemble_name (file, lab1);
1354 fprintf (file, "-");
1355 assemble_name (file, lab2);
1357 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1360 #include "gt-darwin.h"