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 FIXME: The rest of the compiler doesn't expect strings to change. */
226 static GTY(()) char * function_base;
227 static GTY(()) const char * function_base_func_name;
228 static GTY(()) int current_pic_label_num;
231 machopic_function_base_name ()
233 const char *current_name;
235 /* if dynamic-no-pic is on, we should not get here */
236 if (MACHO_DYNAMIC_NO_PIC_P)
239 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
241 if (function_base_func_name != current_name)
243 current_function_uses_pic_offset_table = 1;
245 /* Save mucho space and time. Some of the C++ mangled names are over
246 700 characters long! Note that we produce a label containing a '-'
247 if the function we're compiling is an Objective-C method, as evinced
248 by the incredibly scientific test below. This is because code in
249 rs6000.c makes the same ugly test when loading the PIC reg. */
251 /* It's hard to describe just how ugly this is. The reason for
252 the '%011d' is that after a PCH load, we can't change the
253 size of the string, because PCH will have uniqued it and
254 allocated it in the string pool. */
255 if (function_base == NULL)
257 (char *) ggc_alloc_string ("", sizeof ("*\"L12345678901$pb\""));
259 ++current_pic_label_num;
260 if (*current_name == '+' || *current_name == '-')
261 sprintf (function_base, "*\"L-%010d$pb\"", current_pic_label_num);
263 sprintf (function_base, "*\"L%011d$pb\"", current_pic_label_num);
265 function_base_func_name = current_name;
268 return function_base;
271 static GTY(()) tree machopic_non_lazy_pointers;
273 /* Return a non-lazy pointer name corresponding to the given name,
274 either by finding it in our list of pointer names, or by generating
278 machopic_non_lazy_ptr_name (name)
281 const char *temp_name;
282 tree temp, ident = get_identifier (name);
284 for (temp = machopic_non_lazy_pointers;
286 temp = TREE_CHAIN (temp))
288 if (ident == TREE_VALUE (temp))
289 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
292 name = darwin_strip_name_encoding (name);
294 /* Try again, but comparing names this time. */
295 for (temp = machopic_non_lazy_pointers;
297 temp = TREE_CHAIN (temp))
299 if (TREE_VALUE (temp))
301 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
302 temp_name = darwin_strip_name_encoding (temp_name);
303 if (strcmp (name, temp_name) == 0)
304 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
312 buffer = alloca (strlen (name) + 20);
314 strcpy (buffer, "&L");
316 strcat (buffer, name+1);
319 strcat (buffer, "_");
320 strcat (buffer, name);
323 strcat (buffer, "$non_lazy_ptr");
324 ptr_name = get_identifier (buffer);
326 machopic_non_lazy_pointers
327 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
329 TREE_USED (machopic_non_lazy_pointers) = 0;
331 return IDENTIFIER_POINTER (ptr_name);
335 static GTY(()) tree machopic_stubs;
337 /* Return the name of the stub corresponding to the given name,
338 generating a new stub name if necessary. */
341 machopic_stub_name (name)
344 tree temp, ident = get_identifier (name);
347 for (temp = machopic_stubs;
349 temp = TREE_CHAIN (temp))
351 if (ident == TREE_VALUE (temp))
352 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
353 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
354 if (strcmp (name, tname) == 0)
355 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
356 /* A library call name might not be section-encoded yet, so try
357 it against a stripped name. */
360 && strcmp (name, tname + 4) == 0)
361 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
364 name = darwin_strip_name_encoding (name);
369 int needs_quotes = name_needs_quotes (name);
371 buffer = alloca (strlen (name) + 20);
374 strcpy (buffer, "&\"L");
376 strcpy (buffer, "&L");
379 strcat (buffer, name+1);
383 strcat (buffer, "_");
384 strcat (buffer, name);
388 strcat (buffer, "$stub\"");
390 strcat (buffer, "$stub");
391 ptr_name = get_identifier (buffer);
393 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
394 TREE_USED (machopic_stubs) = 0;
396 return IDENTIFIER_POINTER (ptr_name);
401 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
405 const char *real_name;
406 tree temp, ident = get_identifier (name), id2;
408 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
410 temp = TREE_CHAIN (temp))
411 if (ident == TREE_PURPOSE (temp))
413 /* Mark both the stub or non-lazy pointer as well as the
414 original symbol as being referenced. */
415 TREE_USED (temp) = 1;
416 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
417 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
418 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
419 real_name = darwin_strip_name_encoding (real_name);
420 id2 = maybe_get_identifier (real_name);
422 TREE_SYMBOL_REFERENCED (id2) = 1;
426 /* Transform ORIG, which may be any data source, to the corresponding
427 source using indirections. */
430 machopic_indirect_data_reference (orig, reg)
435 if (! MACHOPIC_INDIRECT)
438 if (GET_CODE (orig) == SYMBOL_REF)
440 const char *name = XSTR (orig, 0);
442 int defined = machopic_data_defined_p (name);
444 if (defined && MACHO_DYNAMIC_NO_PIC_P)
446 #if defined (TARGET_TOC)
447 emit_insn (gen_macho_high (reg, orig));
448 emit_insn (gen_macho_low (reg, reg, orig));
450 /* some other cpu -- writeme! */
457 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
458 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
459 machopic_function_base_name ());
460 rtx offset = gen_rtx (CONST, Pmode,
461 gen_rtx (MINUS, Pmode, orig, pic_base));
464 #if defined (TARGET_TOC) /* i.e., PowerPC */
465 rtx hi_sum_reg = reg;
470 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
471 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
472 gen_rtx (HIGH, Pmode, offset))));
473 emit_insn (gen_rtx (SET, Pmode, reg,
474 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
478 #if defined (HAVE_lo_sum)
479 if (reg == 0) abort ();
481 emit_insn (gen_rtx (SET, VOIDmode, reg,
482 gen_rtx (HIGH, Pmode, offset)));
483 emit_insn (gen_rtx (SET, VOIDmode, reg,
484 gen_rtx (LO_SUM, Pmode, reg, offset)));
485 emit_insn (gen_rtx (USE, VOIDmode,
486 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
488 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
494 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
495 machopic_non_lazy_ptr_name (name));
497 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
498 RTX_UNCHANGING_P (ptr_ref) = 1;
502 else if (GET_CODE (orig) == CONST)
506 /* legitimize both operands of the PLUS */
507 if (GET_CODE (XEXP (orig, 0)) == PLUS)
509 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
511 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
512 (base == reg ? 0 : reg));
517 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
518 result = plus_constant (base, INTVAL (orig));
520 result = gen_rtx (PLUS, Pmode, base, orig);
522 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
526 emit_move_insn (reg, result);
531 result = force_reg (GET_MODE (result), result);
538 else if (GET_CODE (orig) == MEM)
539 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
540 /* When the target is i386, this code prevents crashes due to the
541 compiler's ignorance on how to move the PIC base register to
542 other registers. (The reload phase sometimes introduces such
544 else if (GET_CODE (orig) == PLUS
545 && GET_CODE (XEXP (orig, 0)) == REG
546 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
548 /* Prevent the same register from being erroneously used
549 as both the base and index registers. */
550 && GET_CODE (XEXP (orig, 1)) == CONST
554 emit_move_insn (reg, XEXP (orig, 0));
555 XEXP (ptr_ref, 0) = reg;
560 /* Transform TARGET (a MEM), which is a function call target, to the
561 corresponding symbol_stub if necessary. Return a new MEM. */
564 machopic_indirect_call_target (target)
567 if (GET_CODE (target) != MEM)
570 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
572 enum machine_mode mode = GET_MODE (XEXP (target, 0));
573 const char *name = XSTR (XEXP (target, 0), 0);
575 /* If the name is already defined, we need do nothing. */
576 if (name[0] == '!' && name[1] == 'T')
579 if (!machopic_name_defined_p (name))
581 const char *stub_name = machopic_stub_name (name);
583 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
584 RTX_UNCHANGING_P (target) = 1;
592 machopic_legitimize_pic_address (orig, mode, reg)
594 enum machine_mode mode;
598 if (! MACHOPIC_INDIRECT)
601 /* First handle a simple SYMBOL_REF or LABEL_REF */
602 if (GET_CODE (orig) == LABEL_REF
603 || (GET_CODE (orig) == SYMBOL_REF
606 /* addr(foo) = &func+(foo-func) */
609 orig = machopic_indirect_data_reference (orig, reg);
611 if (GET_CODE (orig) == PLUS
612 && GET_CODE (XEXP (orig, 0)) == REG)
615 return force_reg (mode, orig);
617 emit_move_insn (reg, orig);
621 /* if dynamic-no-pic then use 0 as the pic base */
622 if (MACHO_DYNAMIC_NO_PIC_P)
623 pic_base = CONST0_RTX (Pmode);
625 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
627 if (GET_CODE (orig) == MEM)
631 if (reload_in_progress)
634 reg = gen_reg_rtx (Pmode);
638 if (MACHO_DYNAMIC_NO_PIC_P
639 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
640 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
642 #if defined (TARGET_TOC) /* ppc */
643 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
644 rtx asym = XEXP (orig, 0);
647 emit_insn (gen_macho_high (temp_reg, asym));
648 mem = gen_rtx_MEM (GET_MODE (orig),
649 gen_rtx (LO_SUM, Pmode, temp_reg, asym));
650 RTX_UNCHANGING_P (mem) = 1;
651 emit_insn (gen_rtx (SET, VOIDmode, reg, mem));
653 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
659 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
660 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
662 rtx offset = gen_rtx (CONST, Pmode,
663 gen_rtx (MINUS, Pmode,
664 XEXP (orig, 0), pic_base));
665 #if defined (TARGET_TOC) /* i.e., PowerPC */
666 /* Generating a new reg may expose opportunities for
667 common subexpression elimination. */
669 (reload_in_progress ? reg : gen_reg_rtx (SImode));
671 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
672 gen_rtx (PLUS, Pmode,
673 pic_offset_table_rtx,
674 gen_rtx (HIGH, Pmode, offset))));
675 emit_insn (gen_rtx (SET, VOIDmode, reg,
676 gen_rtx (MEM, GET_MODE (orig),
677 gen_rtx (LO_SUM, Pmode,
678 hi_sum_reg, offset))));
682 emit_insn (gen_rtx (USE, VOIDmode,
683 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
685 emit_insn (gen_rtx (SET, VOIDmode, reg,
686 gen_rtx (HIGH, Pmode,
687 gen_rtx (CONST, Pmode, offset))));
688 emit_insn (gen_rtx (SET, VOIDmode, reg,
689 gen_rtx (LO_SUM, Pmode, reg,
690 gen_rtx (CONST, Pmode, offset))));
691 pic_ref = gen_rtx (PLUS, Pmode,
692 pic_offset_table_rtx, reg);
696 #endif /* HAVE_lo_sum */
698 rtx pic = pic_offset_table_rtx;
699 if (GET_CODE (pic) != REG)
701 emit_move_insn (reg, pic);
705 emit_insn (gen_rtx (USE, VOIDmode,
706 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
709 pic_ref = gen_rtx (PLUS, Pmode,
711 gen_rtx (CONST, Pmode,
712 gen_rtx (MINUS, Pmode,
717 #if !defined (TARGET_TOC)
718 emit_move_insn (reg, pic_ref);
719 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
721 RTX_UNCHANGING_P (pic_ref) = 1;
727 if (GET_CODE (orig) == SYMBOL_REF
728 || GET_CODE (orig) == LABEL_REF)
730 rtx offset = gen_rtx (CONST, Pmode,
731 gen_rtx (MINUS, Pmode, orig, pic_base));
732 #if defined (TARGET_TOC) /* i.e., PowerPC */
737 if (reload_in_progress)
740 reg = gen_reg_rtx (SImode);
745 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
746 (MACHO_DYNAMIC_NO_PIC_P)
747 ? gen_rtx (HIGH, Pmode, offset)
748 : gen_rtx (PLUS, Pmode,
749 pic_offset_table_rtx,
750 gen_rtx (HIGH, Pmode, offset))));
751 emit_insn (gen_rtx (SET, VOIDmode, reg,
752 gen_rtx (LO_SUM, Pmode,
753 hi_sum_reg, offset)));
755 RTX_UNCHANGING_P (pic_ref) = 1;
757 emit_insn (gen_rtx (SET, VOIDmode, reg,
758 gen_rtx (HIGH, Pmode, offset)));
759 emit_insn (gen_rtx (SET, VOIDmode, reg,
760 gen_rtx (LO_SUM, Pmode, reg, offset)));
761 pic_ref = gen_rtx (PLUS, Pmode,
762 pic_offset_table_rtx, reg);
763 RTX_UNCHANGING_P (pic_ref) = 1;
767 #endif /* HAVE_lo_sum */
769 if (GET_CODE (orig) == REG)
775 rtx pic = pic_offset_table_rtx;
776 if (GET_CODE (pic) != REG)
778 emit_move_insn (reg, pic);
782 emit_insn (gen_rtx (USE, VOIDmode,
783 pic_offset_table_rtx));
785 pic_ref = gen_rtx (PLUS, Pmode,
787 gen_rtx (CONST, Pmode,
788 gen_rtx (MINUS, Pmode,
794 if (GET_CODE (pic_ref) != REG)
798 emit_move_insn (reg, pic_ref);
803 return force_reg (mode, pic_ref);
812 else if (GET_CODE (orig) == SYMBOL_REF)
815 else if (GET_CODE (orig) == PLUS
816 && (GET_CODE (XEXP (orig, 0)) == MEM
817 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
818 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
819 && XEXP (orig, 0) != pic_offset_table_rtx
820 && GET_CODE (XEXP (orig, 1)) != REG)
824 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
826 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
827 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
828 Pmode, (base == reg ? 0 : reg));
829 if (GET_CODE (orig) == CONST_INT)
831 pic_ref = plus_constant (base, INTVAL (orig));
835 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
837 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
838 RTX_UNCHANGING_P (pic_ref) = 1;
840 if (reg && is_complex)
842 emit_move_insn (reg, pic_ref);
845 /* Likewise, should we set special REG_NOTEs here? */
848 else if (GET_CODE (orig) == CONST)
850 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
853 else if (GET_CODE (orig) == MEM
854 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
856 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
858 addr = gen_rtx (MEM, GET_MODE (orig), addr);
859 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
860 emit_move_insn (reg, addr);
869 machopic_finish (asm_out_file)
874 for (temp = machopic_stubs;
876 temp = TREE_CHAIN (temp))
878 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
879 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
883 if (! TREE_USED (temp))
886 /* If the symbol is actually defined, we don't need a stub. */
887 if (sym_name[0] == '!' && sym_name[1] == 'T')
890 sym_name = darwin_strip_name_encoding (sym_name);
892 sym = alloca (strlen (sym_name) + 2);
893 if (sym_name[0] == '*' || sym_name[0] == '&')
894 strcpy (sym, sym_name + 1);
895 else if (sym_name[0] == '-' || sym_name[0] == '+')
896 strcpy (sym, sym_name);
898 sym[0] = '_', strcpy (sym + 1, sym_name);
900 stub = alloca (strlen (stub_name) + 2);
901 if (stub_name[0] == '*' || stub_name[0] == '&')
902 strcpy (stub, stub_name + 1);
904 stub[0] = '_', strcpy (stub + 1, stub_name);
906 machopic_output_stub (asm_out_file, sym, stub);
909 for (temp = machopic_non_lazy_pointers;
911 temp = TREE_CHAIN (temp))
913 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
914 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
916 if (! TREE_USED (temp))
919 if (machopic_ident_defined_p (TREE_VALUE (temp)))
922 assemble_align (GET_MODE_ALIGNMENT (Pmode));
923 assemble_label (lazy_name);
924 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
925 GET_MODE_SIZE (Pmode),
926 GET_MODE_ALIGNMENT (Pmode), 1);
930 machopic_nl_symbol_ptr_section ();
931 assemble_name (asm_out_file, lazy_name);
932 fprintf (asm_out_file, ":\n");
934 fprintf (asm_out_file, "\t.indirect_symbol ");
935 assemble_name (asm_out_file, sym_name);
936 fprintf (asm_out_file, "\n");
938 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
939 GET_MODE_ALIGNMENT (Pmode), 1);
945 machopic_operand_p (op)
948 if (MACHOPIC_JUST_INDIRECT)
950 while (GET_CODE (op) == CONST)
953 if (GET_CODE (op) == SYMBOL_REF)
954 return machopic_name_defined_p (XSTR (op, 0));
959 while (GET_CODE (op) == CONST)
962 if (GET_CODE (op) == MINUS
963 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
964 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
965 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
966 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
972 /* This function records whether a given name corresponds to a defined
973 or undefined function or variable, for machopic_classify_ident to
977 darwin_encode_section_info (decl, first)
979 int first ATTRIBUTE_UNUSED;
984 const char *orig_str;
988 if ((TREE_CODE (decl) == FUNCTION_DECL
989 || TREE_CODE (decl) == VAR_DECL)
990 && !DECL_EXTERNAL (decl)
991 && ((TREE_STATIC (decl)
992 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
993 || (DECL_INITIAL (decl)
994 && DECL_INITIAL (decl) != error_mark_node)))
997 if (TREE_CODE (decl) == FUNCTION_DECL)
998 code = (defined ? 'T' : 't');
999 else if (TREE_CODE (decl) == VAR_DECL)
1000 code = (defined ? 'D' : 'd');
1005 sym_ref = XEXP (DECL_RTL (decl), 0);
1006 orig_str = XSTR (sym_ref, 0);
1007 len = strlen (orig_str) + 1;
1009 if (orig_str[0] == '!')
1011 /* Already encoded; see if we need to change it. */
1012 if (code == orig_str[1])
1014 /* Yes, tweak a copy of the name and put it in a new string. */
1015 new_str = alloca (len);
1016 memcpy (new_str, orig_str, len);
1018 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1022 /* Add the encoding. */
1024 new_str = alloca (new_len);
1029 memcpy (new_str + 4, orig_str, len);
1030 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1032 /* The non-lazy pointer list may have captured references to the
1033 old encoded name, change them. */
1034 if (TREE_CODE (decl) == VAR_DECL)
1035 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1037 update_stubs (XSTR (sym_ref, 0));
1040 /* Undo the effects of the above. */
1043 darwin_strip_name_encoding (str)
1046 return str[0] == '!' ? str + 4 : str;
1049 /* Scan the list of non-lazy pointers and update any recorded names whose
1050 stripped name matches the argument. */
1053 update_non_lazy_ptrs (name)
1056 const char *name1, *name2;
1059 name1 = darwin_strip_name_encoding (name);
1061 for (temp = machopic_non_lazy_pointers;
1063 temp = TREE_CHAIN (temp))
1065 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1067 if (*sym_name == '!')
1069 name2 = darwin_strip_name_encoding (sym_name);
1070 if (strcmp (name1, name2) == 0)
1072 /* FIXME: This breaks the identifier hash table. */
1073 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1074 = (unsigned char *) name;
1081 /* Function NAME is being defined, and its label has just been output.
1082 If there's already a reference to a stub for this function, we can
1083 just emit the stub label now and we don't bother emitting the stub later. */
1086 machopic_output_possible_stub_label (file, name)
1093 /* Ensure we're looking at a section-encoded name. */
1094 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1097 for (temp = machopic_stubs;
1099 temp = TREE_CHAIN (temp))
1101 const char *sym_name;
1103 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1104 if (sym_name[0] == '!' && sym_name[1] == 'T'
1105 && ! strcmp (name+2, sym_name+2))
1107 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1108 /* Avoid generating a stub for this. */
1109 TREE_USED (temp) = 0;
1115 /* Scan the list of stubs and update any recorded names whose
1116 stripped name matches the argument. */
1122 const char *name1, *name2;
1125 name1 = darwin_strip_name_encoding (name);
1127 for (temp = machopic_stubs;
1129 temp = TREE_CHAIN (temp))
1131 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1133 if (*sym_name == '!')
1135 name2 = darwin_strip_name_encoding (sym_name);
1136 if (strcmp (name1, name2) == 0)
1138 /* FIXME: This breaks the identifier hash table. */
1139 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1140 = (unsigned char *) name;
1148 machopic_select_section (exp, reloc, align)
1151 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1153 if (TREE_CODE (exp) == STRING_CST)
1155 if (flag_writable_strings)
1157 else if ((size_t) TREE_STRING_LENGTH (exp) !=
1158 strlen (TREE_STRING_POINTER (exp)) + 1)
1159 readonly_data_section ();
1163 else if (TREE_CODE (exp) == INTEGER_CST
1164 || TREE_CODE (exp) == REAL_CST)
1166 tree size = TYPE_SIZE (TREE_TYPE (exp));
1168 if (TREE_CODE (size) == INTEGER_CST &&
1169 TREE_INT_CST_LOW (size) == 4 &&
1170 TREE_INT_CST_HIGH (size) == 0)
1171 literal4_section ();
1172 else if (TREE_CODE (size) == INTEGER_CST &&
1173 TREE_INT_CST_LOW (size) == 8 &&
1174 TREE_INT_CST_HIGH (size) == 0)
1175 literal8_section ();
1177 readonly_data_section ();
1179 else if (TREE_CODE (exp) == CONSTRUCTOR
1181 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1182 && TYPE_NAME (TREE_TYPE (exp)))
1184 tree name = TYPE_NAME (TREE_TYPE (exp));
1185 if (TREE_CODE (name) == TYPE_DECL)
1186 name = DECL_NAME (name);
1187 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1188 objc_constant_string_object_section ();
1189 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1190 objc_string_object_section ();
1191 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1194 if (TREE_SIDE_EFFECTS (exp) || (MACHOPIC_INDIRECT && reloc))
1195 const_data_section ();
1197 readonly_data_section ();
1202 else if (TREE_CODE (exp) == VAR_DECL &&
1204 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1205 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1206 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1208 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1210 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1211 objc_cls_meth_section ();
1212 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1213 objc_inst_meth_section ();
1214 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1215 objc_cat_cls_meth_section ();
1216 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1217 objc_cat_inst_meth_section ();
1218 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1219 objc_class_vars_section ();
1220 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1221 objc_instance_vars_section ();
1222 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1223 objc_cat_cls_meth_section ();
1224 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1225 objc_class_names_section ();
1226 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1227 objc_meth_var_names_section ();
1228 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1229 objc_meth_var_types_section ();
1230 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1231 objc_cls_refs_section ();
1232 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1233 objc_class_section ();
1234 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1235 objc_meta_class_section ();
1236 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1237 objc_category_section ();
1238 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1239 objc_selector_refs_section ();
1240 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1241 objc_selector_fixup_section ();
1242 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1243 objc_symbols_section ();
1244 else if (!strncmp (name, "_OBJC_MODULES", 13))
1245 objc_module_info_section ();
1246 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1247 objc_cat_inst_meth_section ();
1248 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1249 objc_cat_cls_meth_section ();
1250 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1251 objc_cat_cls_meth_section ();
1252 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1253 objc_protocol_section ();
1254 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1255 && !TREE_SIDE_EFFECTS (exp))
1258 if (MACHOPIC_INDIRECT && reloc)
1259 const_data_section ();
1261 readonly_data_section ();
1266 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1269 if (TREE_SIDE_EFFECTS (exp) || (MACHOPIC_INDIRECT && reloc))
1270 const_data_section ();
1272 readonly_data_section ();
1278 /* This can be called with address expressions as "rtx".
1279 They must go in "const". */
1282 machopic_select_rtx_section (mode, x, align)
1283 enum machine_mode mode;
1285 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1287 if (GET_MODE_SIZE (mode) == 8)
1288 literal8_section ();
1289 else if (GET_MODE_SIZE (mode) == 4
1290 && (GET_CODE (x) == CONST_INT
1291 || GET_CODE (x) == CONST_DOUBLE))
1292 literal4_section ();
1298 machopic_asm_out_constructor (symbol, priority)
1300 int priority ATTRIBUTE_UNUSED;
1303 if (MACHOPIC_INDIRECT)
1304 mod_init_section ();
1306 constructor_section ();
1307 assemble_align (POINTER_SIZE);
1308 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1311 if (! MACHOPIC_INDIRECT)
1312 fprintf (asm_out_file, ".reference .constructors_used\n");
1316 machopic_asm_out_destructor (symbol, priority)
1318 int priority ATTRIBUTE_UNUSED;
1321 if (MACHOPIC_INDIRECT)
1322 mod_term_section ();
1324 destructor_section ();
1325 assemble_align (POINTER_SIZE);
1326 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1328 if (! MACHOPIC_INDIRECT)
1329 fprintf (asm_out_file, ".reference .destructors_used\n");
1333 darwin_globalize_label (stream, name)
1337 if (!!strncmp (name, "_OBJC_", 6))
1338 default_globalize_label (stream, name);
1341 /* Output a difference of two labels that will be an assembly time
1342 constant if the two labels are local. (.long lab1-lab2 will be
1343 very different if lab1 is at the boundary between two sections; it
1344 will be relocated according to the second section, not the first,
1345 so one ends up with a difference between labels in different
1346 sections, which is bad in the dwarf2 eh context for instance.) */
1348 static int darwin_dwarf_label_counter;
1351 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1353 int size ATTRIBUTE_UNUSED;
1354 const char *lab1, *lab2;
1356 const char *p = lab1 + (lab1[0] == '*');
1357 int islocaldiff = (p[0] == 'L');
1360 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1362 fprintf (file, "\t%s\t", ".long");
1363 assemble_name (file, lab1);
1364 fprintf (file, "-");
1365 assemble_name (file, lab2);
1367 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1370 #include "gt-darwin.h"