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 GCC.
8 GCC 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 GCC 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 GCC; 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"
46 static int machopic_data_defined_p (const char *);
47 static void update_non_lazy_ptrs (const char *);
48 static void update_stubs (const char *);
49 static const char *machopic_non_lazy_ptr_name (const char*);
52 name_needs_quotes (const char *name)
55 while ((c = *name++) != '\0')
56 if (! ISIDNUM (c) && c != '.' && c != '$')
62 * flag_pic = 1 ... generate only indirections
63 * flag_pic = 2 ... generate indirections and pure code
66 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
67 reference, which will not be changed. */
69 static GTY(()) tree machopic_defined_list;
71 enum machopic_addr_class
72 machopic_classify_ident (tree ident)
74 const char *name = IDENTIFIER_POINTER (ident);
75 int lprefix = (((name[0] == '*' || name[0] == '&')
76 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
85 /* The PIC base symbol is always defined. */
86 if (! strcmp (name, "<pic base>"))
87 return MACHOPIC_DEFINED_DATA;
91 /* Here if no special encoding to be found. */
94 const char *name = IDENTIFIER_POINTER (ident);
95 int len = strlen (name);
97 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
98 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
99 return MACHOPIC_DEFINED_FUNCTION;
100 return MACHOPIC_DEFINED_DATA;
103 for (temp = machopic_defined_list;
105 temp = TREE_CHAIN (temp))
107 if (ident == TREE_VALUE (temp))
108 return MACHOPIC_DEFINED_DATA;
111 if (TREE_ASM_WRITTEN (ident))
112 return MACHOPIC_DEFINED_DATA;
114 return MACHOPIC_UNDEFINED;
117 else if (name[1] == 'D')
118 return MACHOPIC_DEFINED_DATA;
120 else if (name[1] == 'T')
121 return MACHOPIC_DEFINED_FUNCTION;
123 /* It is possible that someone is holding a "stale" name, which has
124 since been defined. See if there is a "defined" name (i.e,
125 different from NAME only in having a '!D_' or a '!T_' instead of
126 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
127 that this identifier is defined. */
128 else if (name[1] == 'd' || name[1] == 't')
131 new_name = (char *)alloca (strlen (name) + 1);
132 strcpy (new_name, name);
133 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
134 if (maybe_get_identifier (new_name) != NULL)
135 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
136 : MACHOPIC_DEFINED_FUNCTION;
139 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
141 if (ident == TREE_VALUE (temp))
144 return MACHOPIC_DEFINED_FUNCTION;
146 return MACHOPIC_DEFINED_DATA;
150 if (name[1] == 't' || name[1] == 'T')
153 return MACHOPIC_DEFINED_FUNCTION;
155 return MACHOPIC_UNDEFINED_FUNCTION;
160 return MACHOPIC_DEFINED_DATA;
162 return MACHOPIC_UNDEFINED_DATA;
167 enum machopic_addr_class
168 machopic_classify_name (const char *name)
170 return machopic_classify_ident (get_identifier (name));
174 machopic_ident_defined_p (tree ident)
176 switch (machopic_classify_ident (ident))
178 case MACHOPIC_UNDEFINED:
179 case MACHOPIC_UNDEFINED_DATA:
180 case MACHOPIC_UNDEFINED_FUNCTION:
188 machopic_data_defined_p (const char *name)
190 switch (machopic_classify_ident (get_identifier (name)))
192 case MACHOPIC_DEFINED_DATA:
200 machopic_name_defined_p (const char *name)
202 return machopic_ident_defined_p (get_identifier (name));
206 machopic_define_ident (tree ident)
208 if (!machopic_ident_defined_p (ident))
209 machopic_defined_list =
210 tree_cons (NULL_TREE, ident, machopic_defined_list);
214 machopic_define_name (const char *name)
216 machopic_define_ident (get_identifier (name));
219 static GTY(()) char * function_base;
222 machopic_function_base_name (void)
224 const char *current_name;
225 /* if dynamic-no-pic is on, we should not get here */
226 if (MACHO_DYNAMIC_NO_PIC_P)
229 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
231 if (function_base == NULL)
233 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
235 current_function_uses_pic_offset_table = 1;
237 return function_base;
240 static GTY(()) const char * function_base_func_name;
241 static GTY(()) int current_pic_label_num;
244 machopic_output_function_base_name (FILE *file)
246 const char *current_name;
248 /* If dynamic-no-pic is on, we should not get here. */
249 if (MACHO_DYNAMIC_NO_PIC_P)
252 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
253 if (function_base_func_name != current_name)
255 ++current_pic_label_num;
256 function_base_func_name = current_name;
258 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
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 (const char *name)
270 const char *temp_name;
271 tree temp, ident = get_identifier (name);
273 for (temp = machopic_non_lazy_pointers;
275 temp = TREE_CHAIN (temp))
277 if (ident == TREE_VALUE (temp))
278 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
281 name = darwin_strip_name_encoding (name);
283 /* Try again, but comparing names this time. */
284 for (temp = machopic_non_lazy_pointers;
286 temp = TREE_CHAIN (temp))
288 if (TREE_VALUE (temp))
290 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
291 temp_name = darwin_strip_name_encoding (temp_name);
292 if (strcmp (name, temp_name) == 0)
293 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
299 int namelen = strlen (name);
303 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
305 strcpy (buffer, "&L");
309 memcpy (buffer + bufferlen, name+1, namelen-1+1);
310 bufferlen += namelen-1;
314 buffer[bufferlen] = '_';
315 memcpy (buffer + bufferlen +1, name, namelen+1);
316 bufferlen += namelen +1;
319 memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
320 bufferlen += strlen("$non_lazy_ptr");
321 ptr_name = get_identifier (buffer);
323 machopic_non_lazy_pointers
324 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
326 TREE_USED (machopic_non_lazy_pointers) = 0;
328 return IDENTIFIER_POINTER (ptr_name);
332 static GTY(()) tree machopic_stubs;
334 /* Return the name of the stub corresponding to the given name,
335 generating a new stub name if necessary. */
338 machopic_stub_name (const char *name)
340 tree temp, ident = get_identifier (name);
343 for (temp = machopic_stubs;
345 temp = TREE_CHAIN (temp))
347 if (ident == TREE_VALUE (temp))
348 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
350 if (strcmp (name, tname) == 0)
351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
352 /* A library call name might not be section-encoded yet, so try
353 it against a stripped name. */
356 && strcmp (name, tname + 4) == 0)
357 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
360 name = darwin_strip_name_encoding (name);
365 int namelen = strlen (name);
367 int needs_quotes = name_needs_quotes (name);
369 buffer = alloca (namelen + 20);
373 strcpy (buffer, "&\"L");
374 bufferlen = strlen("&\"L");
378 strcpy (buffer, "&L");
379 bufferlen = strlen("&L");
384 memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
385 bufferlen += namelen - 1;
389 buffer[bufferlen] = '_';
390 memcpy (buffer + bufferlen +1, name, namelen+1);
391 bufferlen += namelen +1;
396 memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
397 bufferlen += strlen("$stub\"");
401 memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
402 bufferlen += strlen("$stub");
404 ptr_name = get_identifier (buffer);
406 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
407 TREE_USED (machopic_stubs) = 0;
409 return IDENTIFIER_POINTER (ptr_name);
414 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
416 const char *real_name;
417 tree temp, ident = get_identifier (name), id2;
419 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
421 temp = TREE_CHAIN (temp))
422 if (ident == TREE_PURPOSE (temp))
424 /* Mark both the stub or non-lazy pointer as well as the
425 original symbol as being referenced. */
426 TREE_USED (temp) = 1;
427 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
428 mark_referenced (TREE_VALUE (temp));
429 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
430 real_name = darwin_strip_name_encoding (real_name);
431 id2 = maybe_get_identifier (real_name);
433 mark_referenced (id2);
437 /* Transform ORIG, which may be any data source, to the corresponding
438 source using indirections. */
441 machopic_indirect_data_reference (rtx orig, rtx reg)
445 if (! MACHOPIC_INDIRECT)
448 if (GET_CODE (orig) == SYMBOL_REF)
450 const char *name = XSTR (orig, 0);
451 int defined = machopic_data_defined_p (name);
453 if (defined && MACHO_DYNAMIC_NO_PIC_P)
455 #if defined (TARGET_TOC)
456 emit_insn (gen_macho_high (reg, orig));
457 emit_insn (gen_macho_low (reg, reg, orig));
459 /* some other cpu -- writeme! */
466 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
467 rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
468 machopic_function_base_name ());
469 rtx offset = gen_rtx_CONST (Pmode,
470 gen_rtx_MINUS (Pmode, orig, pic_base));
473 #if defined (TARGET_TOC) /* i.e., PowerPC */
474 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
479 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
480 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
481 gen_rtx_HIGH (Pmode, offset))));
482 emit_insn (gen_rtx_SET (Pmode, reg,
483 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
487 #if defined (HAVE_lo_sum)
488 if (reg == 0) abort ();
490 emit_insn (gen_rtx_SET (VOIDmode, reg,
491 gen_rtx_HIGH (Pmode, offset)));
492 emit_insn (gen_rtx_SET (VOIDmode, reg,
493 gen_rtx_LO_SUM (Pmode, reg, offset)));
494 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
496 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
502 ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
503 machopic_non_lazy_ptr_name (name));
505 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
506 RTX_UNCHANGING_P (ptr_ref) = 1;
510 else if (GET_CODE (orig) == CONST)
514 /* legitimize both operands of the PLUS */
515 if (GET_CODE (XEXP (orig, 0)) == PLUS)
517 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
519 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
520 (base == reg ? 0 : reg));
525 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
526 result = plus_constant (base, INTVAL (orig));
528 result = gen_rtx_PLUS (Pmode, base, orig);
530 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
534 emit_move_insn (reg, result);
539 result = force_reg (GET_MODE (result), result);
546 else if (GET_CODE (orig) == MEM)
547 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
548 /* When the target is i386, this code prevents crashes due to the
549 compiler's ignorance on how to move the PIC base register to
550 other registers. (The reload phase sometimes introduces such
552 else if (GET_CODE (orig) == PLUS
553 && GET_CODE (XEXP (orig, 0)) == REG
554 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
556 /* Prevent the same register from being erroneously used
557 as both the base and index registers. */
558 && GET_CODE (XEXP (orig, 1)) == CONST
562 emit_move_insn (reg, XEXP (orig, 0));
563 XEXP (ptr_ref, 0) = reg;
568 /* Transform TARGET (a MEM), which is a function call target, to the
569 corresponding symbol_stub if necessary. Return a new MEM. */
572 machopic_indirect_call_target (rtx target)
574 if (GET_CODE (target) != MEM)
577 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
579 enum machine_mode mode = GET_MODE (XEXP (target, 0));
580 const char *name = XSTR (XEXP (target, 0), 0);
582 /* If the name is already defined, we need do nothing. */
583 if (name[0] == '!' && name[1] == 'T')
586 if (!machopic_name_defined_p (name))
588 const char *stub_name = machopic_stub_name (name);
590 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
591 RTX_UNCHANGING_P (target) = 1;
599 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
603 if (! MACHOPIC_INDIRECT)
606 /* First handle a simple SYMBOL_REF or LABEL_REF */
607 if (GET_CODE (orig) == LABEL_REF
608 || (GET_CODE (orig) == SYMBOL_REF
611 /* addr(foo) = &func+(foo-func) */
614 orig = machopic_indirect_data_reference (orig, reg);
616 if (GET_CODE (orig) == PLUS
617 && GET_CODE (XEXP (orig, 0)) == REG)
620 return force_reg (mode, orig);
622 emit_move_insn (reg, orig);
626 /* if dynamic-no-pic then use 0 as the pic base */
627 if (MACHO_DYNAMIC_NO_PIC_P)
628 pic_base = CONST0_RTX (Pmode);
630 pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
632 if (GET_CODE (orig) == MEM)
636 if (reload_in_progress)
639 reg = gen_reg_rtx (Pmode);
643 if (MACHO_DYNAMIC_NO_PIC_P
644 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
645 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
647 #if defined (TARGET_TOC) /* ppc */
648 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
649 rtx asym = XEXP (orig, 0);
652 emit_insn (gen_macho_high (temp_reg, asym));
653 mem = gen_rtx_MEM (GET_MODE (orig),
654 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
655 RTX_UNCHANGING_P (mem) = 1;
656 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
658 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
664 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
665 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
667 rtx offset = gen_rtx_CONST (Pmode,
668 gen_rtx_MINUS (Pmode,
671 #if defined (TARGET_TOC) /* i.e., PowerPC */
672 /* Generating a new reg may expose opportunities for
673 common subexpression elimination. */
674 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
679 sum = gen_rtx_HIGH (Pmode, offset);
680 if (! MACHO_DYNAMIC_NO_PIC_P)
681 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
683 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
685 mem = gen_rtx_MEM (GET_MODE (orig),
686 gen_rtx_LO_SUM (Pmode,
687 hi_sum_reg, offset));
688 RTX_UNCHANGING_P (mem) = 1;
689 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
690 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
695 emit_insn (gen_rtx_USE (VOIDmode,
697 PIC_OFFSET_TABLE_REGNUM)));
699 emit_insn (gen_rtx_SET (VOIDmode, reg,
701 gen_rtx_CONST (Pmode,
703 emit_insn (gen_rtx_SET (VOIDmode, reg,
704 gen_rtx_LO_SUM (Pmode, reg,
705 gen_rtx_CONST (Pmode, offset))));
706 pic_ref = gen_rtx_PLUS (Pmode,
707 pic_offset_table_rtx, reg);
711 #endif /* HAVE_lo_sum */
713 rtx pic = pic_offset_table_rtx;
714 if (GET_CODE (pic) != REG)
716 emit_move_insn (reg, pic);
720 emit_insn (gen_rtx_USE (VOIDmode,
722 PIC_OFFSET_TABLE_REGNUM)));
725 pic_ref = gen_rtx_PLUS (Pmode,
727 gen_rtx_CONST (Pmode,
728 gen_rtx_MINUS (Pmode,
733 #if !defined (TARGET_TOC)
734 emit_move_insn (reg, pic_ref);
735 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
737 RTX_UNCHANGING_P (pic_ref) = 1;
743 if (GET_CODE (orig) == SYMBOL_REF
744 || GET_CODE (orig) == LABEL_REF)
746 rtx offset = gen_rtx_CONST (Pmode,
747 gen_rtx_MINUS (Pmode,
749 #if defined (TARGET_TOC) /* i.e., PowerPC */
754 if (reload_in_progress)
757 reg = gen_reg_rtx (SImode);
762 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
763 (MACHO_DYNAMIC_NO_PIC_P)
764 ? gen_rtx_HIGH (Pmode, offset)
765 : gen_rtx_PLUS (Pmode,
766 pic_offset_table_rtx,
769 emit_insn (gen_rtx_SET (VOIDmode, reg,
770 gen_rtx_LO_SUM (Pmode,
771 hi_sum_reg, offset)));
773 RTX_UNCHANGING_P (pic_ref) = 1;
775 emit_insn (gen_rtx_SET (VOIDmode, reg,
776 gen_rtx_HIGH (Pmode, offset)));
777 emit_insn (gen_rtx_SET (VOIDmode, reg,
778 gen_rtx_LO_SUM (Pmode, reg, offset)));
779 pic_ref = gen_rtx_PLUS (Pmode,
780 pic_offset_table_rtx, reg);
781 RTX_UNCHANGING_P (pic_ref) = 1;
785 #endif /* HAVE_lo_sum */
787 if (GET_CODE (orig) == REG)
793 rtx pic = pic_offset_table_rtx;
794 if (GET_CODE (pic) != REG)
796 emit_move_insn (reg, pic);
800 emit_insn (gen_rtx_USE (VOIDmode,
801 pic_offset_table_rtx));
803 pic_ref = gen_rtx_PLUS (Pmode,
805 gen_rtx_CONST (Pmode,
806 gen_rtx_MINUS (Pmode,
812 if (GET_CODE (pic_ref) != REG)
816 emit_move_insn (reg, pic_ref);
821 return force_reg (mode, pic_ref);
830 else if (GET_CODE (orig) == SYMBOL_REF)
833 else if (GET_CODE (orig) == PLUS
834 && (GET_CODE (XEXP (orig, 0)) == MEM
835 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
836 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
837 && XEXP (orig, 0) != pic_offset_table_rtx
838 && GET_CODE (XEXP (orig, 1)) != REG)
842 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
844 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
845 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
846 Pmode, (base == reg ? 0 : reg));
847 if (GET_CODE (orig) == CONST_INT)
849 pic_ref = plus_constant (base, INTVAL (orig));
853 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
855 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
856 RTX_UNCHANGING_P (pic_ref) = 1;
858 if (reg && is_complex)
860 emit_move_insn (reg, pic_ref);
863 /* Likewise, should we set special REG_NOTEs here? */
866 else if (GET_CODE (orig) == CONST)
868 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
871 else if (GET_CODE (orig) == MEM
872 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
874 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
876 addr = gen_rtx_MEM (GET_MODE (orig), addr);
877 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
878 emit_move_insn (reg, addr);
887 machopic_finish (FILE *asm_out_file)
891 for (temp = machopic_stubs;
893 temp = TREE_CHAIN (temp))
895 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
896 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
900 if (! TREE_USED (temp))
903 sym_name = darwin_strip_name_encoding (sym_name);
905 sym = alloca (strlen (sym_name) + 2);
906 if (sym_name[0] == '*' || sym_name[0] == '&')
907 strcpy (sym, sym_name + 1);
908 else if (sym_name[0] == '-' || sym_name[0] == '+')
909 strcpy (sym, sym_name);
911 sym[0] = '_', strcpy (sym + 1, sym_name);
913 stub = alloca (strlen (stub_name) + 2);
914 if (stub_name[0] == '*' || stub_name[0] == '&')
915 strcpy (stub, stub_name + 1);
917 stub[0] = '_', strcpy (stub + 1, stub_name);
919 machopic_output_stub (asm_out_file, sym, stub);
922 for (temp = machopic_non_lazy_pointers;
924 temp = TREE_CHAIN (temp))
926 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
927 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
929 if (! TREE_USED (temp))
932 if (machopic_ident_defined_p (TREE_VALUE (temp)))
935 assemble_align (GET_MODE_ALIGNMENT (Pmode));
936 assemble_label (lazy_name);
937 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
938 GET_MODE_SIZE (Pmode),
939 GET_MODE_ALIGNMENT (Pmode), 1);
943 machopic_nl_symbol_ptr_section ();
944 assemble_name (asm_out_file, lazy_name);
945 fprintf (asm_out_file, ":\n");
947 fprintf (asm_out_file, "\t.indirect_symbol ");
948 assemble_name (asm_out_file, sym_name);
949 fprintf (asm_out_file, "\n");
951 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
952 GET_MODE_ALIGNMENT (Pmode), 1);
958 machopic_operand_p (rtx op)
960 if (MACHOPIC_JUST_INDIRECT)
962 while (GET_CODE (op) == CONST)
965 if (GET_CODE (op) == SYMBOL_REF)
966 return machopic_name_defined_p (XSTR (op, 0));
971 while (GET_CODE (op) == CONST)
974 if (GET_CODE (op) == MINUS
975 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
976 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
977 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
978 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
984 /* This function records whether a given name corresponds to a defined
985 or undefined function or variable, for machopic_classify_ident to
989 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
994 const char *orig_str;
998 /* Do the standard encoding things first. */
999 default_encode_section_info (decl, rtl, first);
1001 /* With the introduction of symbol_ref flags, some of the following
1002 code has become redundant and should be removed at some point. */
1004 if ((TREE_CODE (decl) == FUNCTION_DECL
1005 || TREE_CODE (decl) == VAR_DECL)
1006 && !DECL_EXTERNAL (decl)
1007 && ((TREE_STATIC (decl)
1008 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1009 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
1010 && DECL_INITIAL (decl) != error_mark_node)))
1013 if (TREE_CODE (decl) == FUNCTION_DECL)
1014 code = (defined ? 'T' : 't');
1015 else if (TREE_CODE (decl) == VAR_DECL)
1016 code = (defined ? 'D' : 'd');
1021 sym_ref = XEXP (rtl, 0);
1022 orig_str = XSTR (sym_ref, 0);
1023 len = strlen (orig_str) + 1;
1025 if (orig_str[0] == '!')
1027 /* Already encoded; see if we need to change it. */
1028 if (code == orig_str[1])
1030 /* Yes, tweak a copy of the name and put it in a new string. */
1031 new_str = alloca (len);
1032 memcpy (new_str, orig_str, len);
1034 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1038 /* Add the encoding. */
1040 new_str = alloca (new_len);
1045 memcpy (new_str + 4, orig_str, len);
1046 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1048 /* The non-lazy pointer list may have captured references to the
1049 old encoded name, change them. */
1050 if (TREE_CODE (decl) == VAR_DECL)
1051 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1053 update_stubs (XSTR (sym_ref, 0));
1056 /* Undo the effects of the above. */
1059 darwin_strip_name_encoding (const char *str)
1061 return str[0] == '!' ? str + 4 : str;
1064 /* Scan the list of non-lazy pointers and update any recorded names whose
1065 stripped name matches the argument. */
1068 update_non_lazy_ptrs (const char *name)
1070 const char *name1, *name2;
1073 name1 = darwin_strip_name_encoding (name);
1075 for (temp = machopic_non_lazy_pointers;
1077 temp = TREE_CHAIN (temp))
1079 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1081 if (*sym_name == '!')
1083 name2 = darwin_strip_name_encoding (sym_name);
1084 if (strcmp (name1, name2) == 0)
1086 /* FIXME: This breaks the identifier hash table. */
1087 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1088 = (unsigned char *) name;
1095 /* Scan the list of stubs and update any recorded names whose
1096 stripped name matches the argument. */
1099 update_stubs (const char *name)
1101 const char *name1, *name2;
1104 name1 = darwin_strip_name_encoding (name);
1106 for (temp = machopic_stubs;
1108 temp = TREE_CHAIN (temp))
1110 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1112 if (*sym_name == '!')
1114 name2 = darwin_strip_name_encoding (sym_name);
1115 if (strcmp (name1, name2) == 0)
1117 /* FIXME: This breaks the identifier hash table. */
1118 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1119 = (unsigned char *) name;
1127 machopic_select_section (tree exp, int reloc,
1128 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1130 void (*base_function)(void);
1132 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1133 base_function = readonly_data_section;
1134 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1135 base_function = const_data_section;
1137 base_function = data_section;
1139 if (TREE_CODE (exp) == STRING_CST
1140 && ((size_t) TREE_STRING_LENGTH (exp)
1141 == strlen (TREE_STRING_POINTER (exp)) + 1)
1142 && ! flag_writable_strings)
1144 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1145 && flag_merge_constants)
1147 tree size = TYPE_SIZE (TREE_TYPE (exp));
1149 if (TREE_CODE (size) == INTEGER_CST &&
1150 TREE_INT_CST_LOW (size) == 4 &&
1151 TREE_INT_CST_HIGH (size) == 0)
1152 literal4_section ();
1153 else if (TREE_CODE (size) == INTEGER_CST &&
1154 TREE_INT_CST_LOW (size) == 8 &&
1155 TREE_INT_CST_HIGH (size) == 0)
1156 literal8_section ();
1160 else if (TREE_CODE (exp) == CONSTRUCTOR
1162 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1163 && TYPE_NAME (TREE_TYPE (exp)))
1165 tree name = TYPE_NAME (TREE_TYPE (exp));
1166 if (TREE_CODE (name) == TYPE_DECL)
1167 name = DECL_NAME (name);
1168 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1169 objc_constant_string_object_section ();
1170 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1171 objc_string_object_section ();
1175 else if (TREE_CODE (exp) == VAR_DECL &&
1177 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1178 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1179 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1181 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1183 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1184 objc_cls_meth_section ();
1185 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1186 objc_inst_meth_section ();
1187 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1188 objc_cat_cls_meth_section ();
1189 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1190 objc_cat_inst_meth_section ();
1191 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1192 objc_class_vars_section ();
1193 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1194 objc_instance_vars_section ();
1195 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1196 objc_cat_cls_meth_section ();
1197 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1198 objc_class_names_section ();
1199 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1200 objc_meth_var_names_section ();
1201 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1202 objc_meth_var_types_section ();
1203 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1204 objc_cls_refs_section ();
1205 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1206 objc_class_section ();
1207 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1208 objc_meta_class_section ();
1209 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1210 objc_category_section ();
1211 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1212 objc_selector_refs_section ();
1213 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1214 objc_selector_fixup_section ();
1215 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1216 objc_symbols_section ();
1217 else if (!strncmp (name, "_OBJC_MODULES", 13))
1218 objc_module_info_section ();
1219 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1220 objc_image_info_section ();
1221 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1222 objc_cat_inst_meth_section ();
1223 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1224 objc_cat_cls_meth_section ();
1225 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1226 objc_cat_cls_meth_section ();
1227 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1228 objc_protocol_section ();
1236 /* This can be called with address expressions as "rtx".
1237 They must go in "const". */
1240 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1241 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1243 if (GET_MODE_SIZE (mode) == 8)
1244 literal8_section ();
1245 else if (GET_MODE_SIZE (mode) == 4
1246 && (GET_CODE (x) == CONST_INT
1247 || GET_CODE (x) == CONST_DOUBLE))
1248 literal4_section ();
1249 else if (MACHOPIC_INDIRECT
1250 && (GET_CODE (x) == SYMBOL_REF
1251 || GET_CODE (x) == CONST
1252 || GET_CODE (x) == LABEL_REF))
1253 const_data_section ();
1259 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1261 if (MACHOPIC_INDIRECT)
1262 mod_init_section ();
1264 constructor_section ();
1265 assemble_align (POINTER_SIZE);
1266 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1268 if (! MACHOPIC_INDIRECT)
1269 fprintf (asm_out_file, ".reference .constructors_used\n");
1273 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1275 if (MACHOPIC_INDIRECT)
1276 mod_term_section ();
1278 destructor_section ();
1279 assemble_align (POINTER_SIZE);
1280 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1282 if (! MACHOPIC_INDIRECT)
1283 fprintf (asm_out_file, ".reference .destructors_used\n");
1287 darwin_globalize_label (FILE *stream, const char *name)
1289 if (!!strncmp (name, "_OBJC_", 6))
1290 default_globalize_label (stream, name);
1293 /* Emit an assembler directive to set visibility for a symbol. The
1294 only supported visibilities are VISIBILITY_DEFAULT and
1295 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1296 extern". There is no MACH-O equivalent of ELF's
1297 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1300 darwin_assemble_visibility (tree decl, int vis)
1302 if (vis == VISIBILITY_DEFAULT)
1304 else if (vis == VISIBILITY_HIDDEN)
1306 fputs ("\t.private_extern ", asm_out_file);
1307 assemble_name (asm_out_file,
1308 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1309 fputs ("\n", asm_out_file);
1312 warning ("internal and protected visibility attributes not supported"
1313 "in this configuration; ignored");
1316 /* Output a difference of two labels that will be an assembly time
1317 constant if the two labels are local. (.long lab1-lab2 will be
1318 very different if lab1 is at the boundary between two sections; it
1319 will be relocated according to the second section, not the first,
1320 so one ends up with a difference between labels in different
1321 sections, which is bad in the dwarf2 eh context for instance.) */
1323 static int darwin_dwarf_label_counter;
1326 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1327 const char *lab1, const char *lab2)
1329 const char *p = lab1 + (lab1[0] == '*');
1330 int islocaldiff = (p[0] == 'L');
1333 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1335 fprintf (file, "\t%s\t", ".long");
1336 assemble_name (file, lab1);
1337 fprintf (file, "-");
1338 assemble_name (file, lab2);
1340 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1344 darwin_file_end (void)
1346 machopic_finish (asm_out_file);
1347 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1349 constructor_section ();
1350 destructor_section ();
1351 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1355 #include "gt-darwin.h"