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 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
236 if (name != current_name)
238 current_function_uses_pic_offset_table = 1;
240 /* Save mucho space and time. Some of the C++ mangled names are over
241 700 characters long! Note that we produce a label containing a '-'
242 if the function we're compiling is an Objective-C method, as evinced
243 by the incredibly scientific test below. This is because code in
244 rs6000.c makes the same ugly test when loading the PIC reg. */
246 ++current_pic_label_num;
247 if (*current_name == '+' || *current_name == '-')
248 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
250 sprintf (function_base, "*L%d$pb", current_pic_label_num);
255 return function_base;
258 static GTY(()) tree machopic_non_lazy_pointers;
260 /* Return a non-lazy pointer name corresponding to the given name,
261 either by finding it in our list of pointer names, or by generating
265 machopic_non_lazy_ptr_name (name)
268 const char *temp_name;
269 tree temp, ident = get_identifier (name);
271 for (temp = machopic_non_lazy_pointers;
273 temp = TREE_CHAIN (temp))
275 if (ident == TREE_VALUE (temp))
276 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279 name = darwin_strip_name_encoding (name);
281 /* Try again, but comparing names this time. */
282 for (temp = machopic_non_lazy_pointers;
284 temp = TREE_CHAIN (temp))
286 if (TREE_VALUE (temp))
288 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
289 temp_name = darwin_strip_name_encoding (temp_name);
290 if (strcmp (name, temp_name) == 0)
291 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
299 buffer = alloca (strlen (name) + 20);
301 strcpy (buffer, "&L");
303 strcat (buffer, name+1);
306 strcat (buffer, "_");
307 strcat (buffer, name);
310 strcat (buffer, "$non_lazy_ptr");
311 ptr_name = get_identifier (buffer);
313 machopic_non_lazy_pointers
314 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
316 TREE_USED (machopic_non_lazy_pointers) = 0;
318 return IDENTIFIER_POINTER (ptr_name);
322 static GTY(()) tree machopic_stubs;
324 /* Return the name of the stub corresponding to the given name,
325 generating a new stub name if necessary. */
328 machopic_stub_name (name)
331 tree temp, ident = get_identifier (name);
334 for (temp = machopic_stubs;
336 temp = TREE_CHAIN (temp))
338 if (ident == TREE_VALUE (temp))
339 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
340 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
341 if (strcmp (name, tname) == 0)
342 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
343 /* A library call name might not be section-encoded yet, so try
344 it against a stripped name. */
347 && strcmp (name, tname + 4) == 0)
348 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
351 name = darwin_strip_name_encoding (name);
356 int needs_quotes = name_needs_quotes (name);
358 buffer = alloca (strlen (name) + 20);
361 strcpy (buffer, "&\"L");
363 strcpy (buffer, "&L");
366 strcat (buffer, name+1);
370 strcat (buffer, "_");
371 strcat (buffer, name);
375 strcat (buffer, "$stub\"");
377 strcat (buffer, "$stub");
378 ptr_name = get_identifier (buffer);
380 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
381 TREE_USED (machopic_stubs) = 0;
383 return IDENTIFIER_POINTER (ptr_name);
388 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
392 const char *real_name;
393 tree temp, ident = get_identifier (name), id2;
395 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
397 temp = TREE_CHAIN (temp))
398 if (ident == TREE_PURPOSE (temp))
400 /* Mark both the stub or non-lazy pointer as well as the
401 original symbol as being referenced. */
402 TREE_USED (temp) = 1;
403 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
404 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
405 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
406 real_name = darwin_strip_name_encoding (real_name);
407 id2 = maybe_get_identifier (real_name);
409 TREE_SYMBOL_REFERENCED (id2) = 1;
413 /* Transform ORIG, which may be any data source, to the corresponding
414 source using indirections. */
417 machopic_indirect_data_reference (orig, reg)
422 if (! MACHOPIC_INDIRECT)
425 if (GET_CODE (orig) == SYMBOL_REF)
427 const char *name = XSTR (orig, 0);
429 if (machopic_data_defined_p (name))
431 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
432 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
433 machopic_function_base_name ());
434 rtx offset = gen_rtx (CONST, Pmode,
435 gen_rtx (MINUS, Pmode, orig, pic_base));
438 #if defined (TARGET_TOC) /* i.e., PowerPC */
439 rtx hi_sum_reg = reg;
444 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
445 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
446 gen_rtx (HIGH, Pmode, offset))));
447 emit_insn (gen_rtx (SET, Pmode, reg,
448 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
452 #if defined (HAVE_lo_sum)
453 if (reg == 0) abort ();
455 emit_insn (gen_rtx (SET, VOIDmode, reg,
456 gen_rtx (HIGH, Pmode, offset)));
457 emit_insn (gen_rtx (SET, VOIDmode, reg,
458 gen_rtx (LO_SUM, Pmode, reg, offset)));
459 emit_insn (gen_rtx (USE, VOIDmode,
460 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
462 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
468 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
469 machopic_non_lazy_ptr_name (name));
471 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
472 RTX_UNCHANGING_P (ptr_ref) = 1;
476 else if (GET_CODE (orig) == CONST)
480 /* legitimize both operands of the PLUS */
481 if (GET_CODE (XEXP (orig, 0)) == PLUS)
483 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
485 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
486 (base == reg ? 0 : reg));
491 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
492 result = plus_constant (base, INTVAL (orig));
494 result = gen_rtx (PLUS, Pmode, base, orig);
496 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
500 emit_move_insn (reg, result);
505 result = force_reg (GET_MODE (result), result);
512 else if (GET_CODE (orig) == MEM)
513 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
514 /* When the target is i386, this code prevents crashes due to the
515 compiler's ignorance on how to move the PIC base register to
516 other registers. (The reload phase sometimes introduces such
518 else if (GET_CODE (orig) == PLUS
519 && GET_CODE (XEXP (orig, 0)) == REG
520 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
522 /* Prevent the same register from being erroneously used
523 as both the base and index registers. */
524 && GET_CODE (XEXP (orig, 1)) == CONST
528 emit_move_insn (reg, XEXP (orig, 0));
529 XEXP (ptr_ref, 0) = reg;
534 /* Transform TARGET (a MEM), which is a function call target, to the
535 corresponding symbol_stub if necessary. Return a new MEM. */
538 machopic_indirect_call_target (target)
541 if (GET_CODE (target) != MEM)
544 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
546 enum machine_mode mode = GET_MODE (XEXP (target, 0));
547 const char *name = XSTR (XEXP (target, 0), 0);
549 /* If the name is already defined, we need do nothing. */
550 if (name[0] == '!' && name[1] == 'T')
553 if (!machopic_name_defined_p (name))
555 const char *stub_name = machopic_stub_name (name);
557 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
558 RTX_UNCHANGING_P (target) = 1;
566 machopic_legitimize_pic_address (orig, mode, reg)
568 enum machine_mode mode;
575 /* First handle a simple SYMBOL_REF or LABEL_REF */
576 if (GET_CODE (orig) == LABEL_REF
577 || (GET_CODE (orig) == SYMBOL_REF
580 /* addr(foo) = &func+(foo-func) */
583 orig = machopic_indirect_data_reference (orig, reg);
585 if (GET_CODE (orig) == PLUS
586 && GET_CODE (XEXP (orig, 0)) == REG)
589 return force_reg (mode, orig);
591 emit_move_insn (reg, orig);
595 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
597 if (GET_CODE (orig) == MEM)
601 if (reload_in_progress)
604 reg = gen_reg_rtx (Pmode);
608 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
609 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
611 rtx offset = gen_rtx (CONST, Pmode,
612 gen_rtx (MINUS, Pmode,
613 XEXP (orig, 0), pic_base));
614 #if defined (TARGET_TOC) /* i.e., PowerPC */
615 /* Generating a new reg may expose opportunities for
616 common subexpression elimination. */
618 (reload_in_progress ? reg : gen_reg_rtx (SImode));
620 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
621 gen_rtx (PLUS, Pmode,
622 pic_offset_table_rtx,
623 gen_rtx (HIGH, Pmode, offset))));
624 emit_insn (gen_rtx (SET, VOIDmode, reg,
625 gen_rtx (MEM, GET_MODE (orig),
626 gen_rtx (LO_SUM, Pmode,
627 hi_sum_reg, offset))));
631 emit_insn (gen_rtx (USE, VOIDmode,
632 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
634 emit_insn (gen_rtx (SET, VOIDmode, reg,
635 gen_rtx (HIGH, Pmode,
636 gen_rtx (CONST, Pmode, offset))));
637 emit_insn (gen_rtx (SET, VOIDmode, reg,
638 gen_rtx (LO_SUM, Pmode, reg,
639 gen_rtx (CONST, Pmode, offset))));
640 pic_ref = gen_rtx (PLUS, Pmode,
641 pic_offset_table_rtx, reg);
645 #endif /* HAVE_lo_sum */
647 rtx pic = pic_offset_table_rtx;
648 if (GET_CODE (pic) != REG)
650 emit_move_insn (reg, pic);
654 emit_insn (gen_rtx (USE, VOIDmode,
655 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
658 pic_ref = gen_rtx (PLUS, Pmode,
660 gen_rtx (CONST, Pmode,
661 gen_rtx (MINUS, Pmode,
666 #if !defined (TARGET_TOC)
667 emit_move_insn (reg, pic_ref);
668 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
670 RTX_UNCHANGING_P (pic_ref) = 1;
676 if (GET_CODE (orig) == SYMBOL_REF
677 || GET_CODE (orig) == LABEL_REF)
679 rtx offset = gen_rtx (CONST, Pmode,
680 gen_rtx (MINUS, Pmode, orig, pic_base));
681 #if defined (TARGET_TOC) /* i.e., PowerPC */
686 if (reload_in_progress)
689 reg = gen_reg_rtx (SImode);
694 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
695 gen_rtx (PLUS, Pmode,
696 pic_offset_table_rtx,
697 gen_rtx (HIGH, Pmode, offset))));
698 emit_insn (gen_rtx (SET, VOIDmode, reg,
699 gen_rtx (LO_SUM, Pmode,
700 hi_sum_reg, offset)));
702 RTX_UNCHANGING_P (pic_ref) = 1;
704 emit_insn (gen_rtx (SET, VOIDmode, reg,
705 gen_rtx (HIGH, Pmode, offset)));
706 emit_insn (gen_rtx (SET, VOIDmode, reg,
707 gen_rtx (LO_SUM, Pmode, reg, offset)));
708 pic_ref = gen_rtx (PLUS, Pmode,
709 pic_offset_table_rtx, reg);
710 RTX_UNCHANGING_P (pic_ref) = 1;
714 #endif /* HAVE_lo_sum */
716 if (GET_CODE (orig) == REG)
722 rtx pic = pic_offset_table_rtx;
723 if (GET_CODE (pic) != REG)
725 emit_move_insn (reg, pic);
729 emit_insn (gen_rtx (USE, VOIDmode,
730 pic_offset_table_rtx));
732 pic_ref = gen_rtx (PLUS, Pmode,
734 gen_rtx (CONST, Pmode,
735 gen_rtx (MINUS, Pmode,
741 if (GET_CODE (pic_ref) != REG)
745 emit_move_insn (reg, pic_ref);
750 return force_reg (mode, pic_ref);
759 else if (GET_CODE (orig) == SYMBOL_REF)
762 else if (GET_CODE (orig) == PLUS
763 && (GET_CODE (XEXP (orig, 0)) == MEM
764 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
765 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
766 && XEXP (orig, 0) != pic_offset_table_rtx
767 && GET_CODE (XEXP (orig, 1)) != REG)
771 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
773 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
774 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
775 Pmode, (base == reg ? 0 : reg));
776 if (GET_CODE (orig) == CONST_INT)
778 pic_ref = plus_constant (base, INTVAL (orig));
782 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
784 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
785 RTX_UNCHANGING_P (pic_ref) = 1;
787 if (reg && is_complex)
789 emit_move_insn (reg, pic_ref);
792 /* Likewise, should we set special REG_NOTEs here? */
795 else if (GET_CODE (orig) == CONST)
797 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
800 else if (GET_CODE (orig) == MEM
801 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
803 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
805 addr = gen_rtx (MEM, GET_MODE (orig), addr);
806 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
807 emit_move_insn (reg, addr);
816 machopic_finish (asm_out_file)
821 for (temp = machopic_stubs;
823 temp = TREE_CHAIN (temp))
825 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
826 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
830 if (! TREE_USED (temp))
833 /* If the symbol is actually defined, we don't need a stub. */
834 if (sym_name[0] == '!' && sym_name[1] == 'T')
837 sym_name = darwin_strip_name_encoding (sym_name);
839 sym = alloca (strlen (sym_name) + 2);
840 if (sym_name[0] == '*' || sym_name[0] == '&')
841 strcpy (sym, sym_name + 1);
842 else if (sym_name[0] == '-' || sym_name[0] == '+')
843 strcpy (sym, sym_name);
845 sym[0] = '_', strcpy (sym + 1, sym_name);
847 stub = alloca (strlen (stub_name) + 2);
848 if (stub_name[0] == '*' || stub_name[0] == '&')
849 strcpy (stub, stub_name + 1);
851 stub[0] = '_', strcpy (stub + 1, stub_name);
853 machopic_output_stub (asm_out_file, sym, stub);
856 for (temp = machopic_non_lazy_pointers;
858 temp = TREE_CHAIN (temp))
860 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
861 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
863 if (! TREE_USED (temp))
866 if (machopic_ident_defined_p (TREE_VALUE (temp)))
869 assemble_align (GET_MODE_ALIGNMENT (Pmode));
870 assemble_label (lazy_name);
871 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
872 GET_MODE_SIZE (Pmode),
873 GET_MODE_ALIGNMENT (Pmode), 1);
877 machopic_nl_symbol_ptr_section ();
878 assemble_name (asm_out_file, lazy_name);
879 fprintf (asm_out_file, ":\n");
881 fprintf (asm_out_file, "\t.indirect_symbol ");
882 assemble_name (asm_out_file, sym_name);
883 fprintf (asm_out_file, "\n");
885 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
886 GET_MODE_ALIGNMENT (Pmode), 1);
892 machopic_operand_p (op)
895 if (MACHOPIC_JUST_INDIRECT)
897 while (GET_CODE (op) == CONST)
900 if (GET_CODE (op) == SYMBOL_REF)
901 return machopic_name_defined_p (XSTR (op, 0));
906 while (GET_CODE (op) == CONST)
909 if (GET_CODE (op) == MINUS
910 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
911 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
912 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
913 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
919 /* This function records whether a given name corresponds to a defined
920 or undefined function or variable, for machopic_classify_ident to
924 darwin_encode_section_info (decl, first)
926 int first ATTRIBUTE_UNUSED;
931 const char *orig_str;
935 if ((TREE_CODE (decl) == FUNCTION_DECL
936 || TREE_CODE (decl) == VAR_DECL)
937 && !DECL_EXTERNAL (decl)
938 && ((TREE_STATIC (decl)
939 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
940 || (DECL_INITIAL (decl)
941 && DECL_INITIAL (decl) != error_mark_node)))
944 if (TREE_CODE (decl) == FUNCTION_DECL)
945 code = (defined ? 'T' : 't');
946 else if (TREE_CODE (decl) == VAR_DECL)
947 code = (defined ? 'D' : 'd');
952 sym_ref = XEXP (DECL_RTL (decl), 0);
953 orig_str = XSTR (sym_ref, 0);
954 len = strlen (orig_str) + 1;
956 if (orig_str[0] == '!')
958 /* Already encoded; see if we need to change it. */
959 if (code == orig_str[1])
961 /* Yes, tweak a copy of the name and put it in a new string. */
962 new_str = alloca (len);
963 memcpy (new_str, orig_str, len);
965 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
969 /* Add the encoding. */
971 new_str = alloca (new_len);
976 memcpy (new_str + 4, orig_str, len);
977 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
979 /* The non-lazy pointer list may have captured references to the
980 old encoded name, change them. */
981 if (TREE_CODE (decl) == VAR_DECL)
982 update_non_lazy_ptrs (XSTR (sym_ref, 0));
984 update_stubs (XSTR (sym_ref, 0));
987 /* Undo the effects of the above. */
990 darwin_strip_name_encoding (str)
993 return str[0] == '!' ? str + 4 : str;
996 /* Scan the list of non-lazy pointers and update any recorded names whose
997 stripped name matches the argument. */
1000 update_non_lazy_ptrs (name)
1003 const char *name1, *name2;
1006 name1 = darwin_strip_name_encoding (name);
1008 for (temp = machopic_non_lazy_pointers;
1010 temp = TREE_CHAIN (temp))
1012 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1014 if (*sym_name == '!')
1016 name2 = darwin_strip_name_encoding (sym_name);
1017 if (strcmp (name1, name2) == 0)
1019 /* FIXME: This breaks the identifier hash table. */
1020 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1021 = (unsigned char *) name;
1028 /* Function NAME is being defined, and its label has just been output.
1029 If there's already a reference to a stub for this function, we can
1030 just emit the stub label now and we don't bother emitting the stub later. */
1033 machopic_output_possible_stub_label (file, name)
1040 /* Ensure we're looking at a section-encoded name. */
1041 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1044 for (temp = machopic_stubs;
1046 temp = TREE_CHAIN (temp))
1048 const char *sym_name;
1050 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1051 if (sym_name[0] == '!' && sym_name[1] == 'T'
1052 && ! strcmp (name+2, sym_name+2))
1054 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1055 /* Avoid generating a stub for this. */
1056 TREE_USED (temp) = 0;
1062 /* Scan the list of stubs and update any recorded names whose
1063 stripped name matches the argument. */
1069 const char *name1, *name2;
1072 name1 = darwin_strip_name_encoding (name);
1074 for (temp = machopic_stubs;
1076 temp = TREE_CHAIN (temp))
1078 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1080 if (*sym_name == '!')
1082 name2 = darwin_strip_name_encoding (sym_name);
1083 if (strcmp (name1, name2) == 0)
1085 /* FIXME: This breaks the identifier hash table. */
1086 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1087 = (unsigned char *) name;
1095 machopic_select_section (exp, reloc, align)
1098 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1100 if (TREE_CODE (exp) == STRING_CST)
1102 if (flag_writable_strings)
1104 else if ((size_t) TREE_STRING_LENGTH (exp) !=
1105 strlen (TREE_STRING_POINTER (exp)) + 1)
1106 readonly_data_section ();
1110 else if (TREE_CODE (exp) == INTEGER_CST
1111 || TREE_CODE (exp) == REAL_CST)
1113 tree size = TYPE_SIZE (TREE_TYPE (exp));
1115 if (TREE_CODE (size) == INTEGER_CST &&
1116 TREE_INT_CST_LOW (size) == 4 &&
1117 TREE_INT_CST_HIGH (size) == 0)
1118 literal4_section ();
1119 else if (TREE_CODE (size) == INTEGER_CST &&
1120 TREE_INT_CST_LOW (size) == 8 &&
1121 TREE_INT_CST_HIGH (size) == 0)
1122 literal8_section ();
1124 readonly_data_section ();
1126 else if (TREE_CODE (exp) == CONSTRUCTOR
1128 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1129 && TYPE_NAME (TREE_TYPE (exp)))
1131 tree name = TYPE_NAME (TREE_TYPE (exp));
1132 if (TREE_CODE (name) == TYPE_DECL)
1133 name = DECL_NAME (name);
1134 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1135 objc_constant_string_object_section ();
1136 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1137 objc_string_object_section ();
1138 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1140 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1141 const_data_section ();
1143 readonly_data_section ();
1148 else if (TREE_CODE (exp) == VAR_DECL &&
1150 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1151 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1152 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1154 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1156 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1157 objc_cls_meth_section ();
1158 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1159 objc_inst_meth_section ();
1160 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1161 objc_cat_cls_meth_section ();
1162 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1163 objc_cat_inst_meth_section ();
1164 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1165 objc_class_vars_section ();
1166 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1167 objc_instance_vars_section ();
1168 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1169 objc_cat_cls_meth_section ();
1170 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1171 objc_class_names_section ();
1172 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1173 objc_meth_var_names_section ();
1174 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1175 objc_meth_var_types_section ();
1176 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1177 objc_cls_refs_section ();
1178 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1179 objc_class_section ();
1180 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1181 objc_meta_class_section ();
1182 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1183 objc_category_section ();
1184 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1185 objc_selector_refs_section ();
1186 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1187 objc_selector_fixup_section ();
1188 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1189 objc_symbols_section ();
1190 else if (!strncmp (name, "_OBJC_MODULES", 13))
1191 objc_module_info_section ();
1192 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1193 objc_cat_inst_meth_section ();
1194 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1195 objc_cat_cls_meth_section ();
1196 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1197 objc_cat_cls_meth_section ();
1198 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1199 objc_protocol_section ();
1200 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1201 && !TREE_SIDE_EFFECTS (exp))
1203 if (flag_pic && reloc)
1204 const_data_section ();
1206 readonly_data_section ();
1211 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1213 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1214 const_data_section ();
1216 readonly_data_section ();
1222 /* This can be called with address expressions as "rtx".
1223 They must go in "const". */
1226 machopic_select_rtx_section (mode, x, align)
1227 enum machine_mode mode;
1229 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1231 if (GET_MODE_SIZE (mode) == 8)
1232 literal8_section ();
1233 else if (GET_MODE_SIZE (mode) == 4
1234 && (GET_CODE (x) == CONST_INT
1235 || GET_CODE (x) == CONST_DOUBLE))
1236 literal4_section ();
1242 machopic_asm_out_constructor (symbol, priority)
1244 int priority ATTRIBUTE_UNUSED;
1247 mod_init_section ();
1249 constructor_section ();
1250 assemble_align (POINTER_SIZE);
1251 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1254 fprintf (asm_out_file, ".reference .constructors_used\n");
1258 machopic_asm_out_destructor (symbol, priority)
1260 int priority ATTRIBUTE_UNUSED;
1263 mod_term_section ();
1265 destructor_section ();
1266 assemble_align (POINTER_SIZE);
1267 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1270 fprintf (asm_out_file, ".reference .destructors_used\n");
1274 darwin_globalize_label (stream, name)
1278 if (!!strncmp (name, "_OBJC_", 6))
1279 default_globalize_label (stream, name);
1282 /* Output a difference of two labels that will be an assembly time
1283 constant if the two labels are local. (.long lab1-lab2 will be
1284 very different if lab1 is at the boundary between two sections; it
1285 will be relocated according to the second section, not the first,
1286 so one ends up with a difference between labels in different
1287 sections, which is bad in the dwarf2 eh context for instance.) */
1289 static int darwin_dwarf_label_counter;
1292 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1294 int size ATTRIBUTE_UNUSED;
1295 const char *lab1, *lab2;
1297 const char *p = lab1 + (lab1[0] == '*');
1298 int islocaldiff = (p[0] == 'L');
1301 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1303 fprintf (file, "\t%s\t", ".long");
1304 assemble_name (file, lab1);
1305 fprintf (file, "-");
1306 assemble_name (file, lab2);
1308 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1311 #include "gt-darwin.h"