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"
45 static int machopic_data_defined_p (const char *);
46 static void update_non_lazy_ptrs (const char *);
47 static void update_stubs (const char *);
48 static const char *machopic_non_lazy_ptr_name (const char*);
51 name_needs_quotes (const char *name)
54 while ((c = *name++) != '\0')
55 if (! ISIDNUM (c) && c != '.' && c != '$')
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 (tree ident)
73 const char *name = IDENTIFIER_POINTER (ident);
74 int lprefix = (((name[0] == '*' || name[0] == '&')
75 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
84 /* The PIC base symbol is always defined. */
85 if (! strcmp (name, "<pic base>"))
86 return MACHOPIC_DEFINED_DATA;
90 /* Here if no special encoding to be found. */
93 const char *name = IDENTIFIER_POINTER (ident);
94 int len = strlen (name);
96 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
97 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
98 return MACHOPIC_DEFINED_FUNCTION;
99 return MACHOPIC_DEFINED_DATA;
102 for (temp = machopic_defined_list;
104 temp = TREE_CHAIN (temp))
106 if (ident == TREE_VALUE (temp))
107 return MACHOPIC_DEFINED_DATA;
110 if (TREE_ASM_WRITTEN (ident))
111 return MACHOPIC_DEFINED_DATA;
113 return MACHOPIC_UNDEFINED;
116 else if (name[1] == 'D')
117 return MACHOPIC_DEFINED_DATA;
119 else if (name[1] == 'T')
120 return MACHOPIC_DEFINED_FUNCTION;
122 /* It is possible that someone is holding a "stale" name, which has
123 since been defined. See if there is a "defined" name (i.e,
124 different from NAME only in having a '!D_' or a '!T_' instead of
125 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
126 that this identifier is defined. */
127 else if (name[1] == 'd' || name[1] == 't')
130 new_name = (char *)alloca (strlen (name) + 1);
131 strcpy (new_name, name);
132 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
133 if (maybe_get_identifier (new_name) != NULL)
134 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
135 : MACHOPIC_DEFINED_FUNCTION;
138 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
140 if (ident == TREE_VALUE (temp))
143 return MACHOPIC_DEFINED_FUNCTION;
145 return MACHOPIC_DEFINED_DATA;
149 if (name[1] == 't' || name[1] == 'T')
152 return MACHOPIC_DEFINED_FUNCTION;
154 return MACHOPIC_UNDEFINED_FUNCTION;
159 return MACHOPIC_DEFINED_DATA;
161 return MACHOPIC_UNDEFINED_DATA;
166 enum machopic_addr_class
167 machopic_classify_name (const char *name)
169 return machopic_classify_ident (get_identifier (name));
173 machopic_ident_defined_p (tree ident)
175 switch (machopic_classify_ident (ident))
177 case MACHOPIC_UNDEFINED:
178 case MACHOPIC_UNDEFINED_DATA:
179 case MACHOPIC_UNDEFINED_FUNCTION:
187 machopic_data_defined_p (const char *name)
189 switch (machopic_classify_ident (get_identifier (name)))
191 case MACHOPIC_DEFINED_DATA:
199 machopic_name_defined_p (const char *name)
201 return machopic_ident_defined_p (get_identifier (name));
205 machopic_define_ident (tree ident)
207 if (!machopic_ident_defined_p (ident))
208 machopic_defined_list =
209 tree_cons (NULL_TREE, ident, machopic_defined_list);
213 machopic_define_name (const char *name)
215 machopic_define_ident (get_identifier (name));
218 static GTY(()) char * function_base;
221 machopic_function_base_name (void)
223 const char *current_name;
224 /* if dynamic-no-pic is on, we should not get here */
225 if (MACHO_DYNAMIC_NO_PIC_P)
228 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
230 if (function_base == NULL)
232 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
234 current_function_uses_pic_offset_table = 1;
236 return function_base;
239 static GTY(()) const char * function_base_func_name;
240 static GTY(()) int current_pic_label_num;
243 machopic_output_function_base_name (FILE *file)
245 const char *current_name;
247 /* If dynamic-no-pic is on, we should not get here. */
248 if (MACHO_DYNAMIC_NO_PIC_P)
251 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
252 if (function_base_func_name != current_name)
254 ++current_pic_label_num;
255 function_base_func_name = current_name;
257 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
260 static GTY(()) tree machopic_non_lazy_pointers;
262 /* Return a non-lazy pointer name corresponding to the given name,
263 either by finding it in our list of pointer names, or by generating
267 machopic_non_lazy_ptr_name (const char *name)
269 const char *temp_name;
270 tree temp, ident = get_identifier (name);
272 for (temp = machopic_non_lazy_pointers;
274 temp = TREE_CHAIN (temp))
276 if (ident == TREE_VALUE (temp))
277 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
280 name = darwin_strip_name_encoding (name);
282 /* Try again, but comparing names this time. */
283 for (temp = machopic_non_lazy_pointers;
285 temp = TREE_CHAIN (temp))
287 if (TREE_VALUE (temp))
289 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
290 temp_name = darwin_strip_name_encoding (temp_name);
291 if (strcmp (name, temp_name) == 0)
292 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
298 int namelen = strlen (name);
302 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
304 strcpy (buffer, "&L");
308 memcpy (buffer + bufferlen, name+1, namelen-1+1);
309 bufferlen += namelen-1;
313 buffer[bufferlen] = '_';
314 memcpy (buffer + bufferlen +1, name, namelen+1);
315 bufferlen += namelen +1;
318 memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
319 bufferlen += strlen("$non_lazy_ptr");
320 ptr_name = get_identifier (buffer);
322 machopic_non_lazy_pointers
323 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
325 TREE_USED (machopic_non_lazy_pointers) = 0;
327 return IDENTIFIER_POINTER (ptr_name);
331 static GTY(()) tree machopic_stubs;
333 /* Return the name of the stub corresponding to the given name,
334 generating a new stub name if necessary. */
337 machopic_stub_name (const char *name)
339 tree temp, ident = get_identifier (name);
342 for (temp = machopic_stubs;
344 temp = TREE_CHAIN (temp))
346 if (ident == TREE_VALUE (temp))
347 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
348 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
349 if (strcmp (name, tname) == 0)
350 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
351 /* A library call name might not be section-encoded yet, so try
352 it against a stripped name. */
355 && strcmp (name, tname + 4) == 0)
356 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
359 name = darwin_strip_name_encoding (name);
364 int namelen = strlen (name);
366 int needs_quotes = name_needs_quotes (name);
368 buffer = alloca (namelen + 20);
372 strcpy (buffer, "&\"L");
373 bufferlen = strlen("&\"L");
377 strcpy (buffer, "&L");
378 bufferlen = strlen("&L");
383 memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
384 bufferlen += namelen - 1;
388 buffer[bufferlen] = '_';
389 memcpy (buffer + bufferlen +1, name, namelen+1);
390 bufferlen += namelen +1;
395 memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
396 bufferlen += strlen("$stub\"");
400 memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
401 bufferlen += strlen("$stub");
403 ptr_name = get_identifier (buffer);
405 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
406 TREE_USED (machopic_stubs) = 0;
408 return IDENTIFIER_POINTER (ptr_name);
413 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
415 const char *real_name;
416 tree temp, ident = get_identifier (name), id2;
418 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
420 temp = TREE_CHAIN (temp))
421 if (ident == TREE_PURPOSE (temp))
423 /* Mark both the stub or non-lazy pointer as well as the
424 original symbol as being referenced. */
425 TREE_USED (temp) = 1;
426 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
427 mark_referenced (TREE_VALUE (temp));
428 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
429 real_name = darwin_strip_name_encoding (real_name);
430 id2 = maybe_get_identifier (real_name);
432 mark_referenced (id2);
436 /* Transform ORIG, which may be any data source, to the corresponding
437 source using indirections. */
440 machopic_indirect_data_reference (rtx orig, rtx reg)
444 if (! MACHOPIC_INDIRECT)
447 if (GET_CODE (orig) == SYMBOL_REF)
449 const char *name = XSTR (orig, 0);
450 int defined = machopic_data_defined_p (name);
452 if (defined && MACHO_DYNAMIC_NO_PIC_P)
454 #if defined (TARGET_TOC)
455 emit_insn (gen_macho_high (reg, orig));
456 emit_insn (gen_macho_low (reg, reg, orig));
458 /* some other cpu -- writeme! */
465 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
466 rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
467 machopic_function_base_name ());
468 rtx offset = gen_rtx_CONST (Pmode,
469 gen_rtx_MINUS (Pmode, orig, pic_base));
472 #if defined (TARGET_TOC) /* i.e., PowerPC */
473 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
478 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
479 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
480 gen_rtx_HIGH (Pmode, offset))));
481 emit_insn (gen_rtx_SET (Pmode, reg,
482 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
486 #if defined (HAVE_lo_sum)
487 if (reg == 0) abort ();
489 emit_insn (gen_rtx_SET (VOIDmode, reg,
490 gen_rtx_HIGH (Pmode, offset)));
491 emit_insn (gen_rtx_SET (VOIDmode, reg,
492 gen_rtx_LO_SUM (Pmode, reg, offset)));
493 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
495 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
501 ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
502 machopic_non_lazy_ptr_name (name));
504 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
505 RTX_UNCHANGING_P (ptr_ref) = 1;
509 else if (GET_CODE (orig) == CONST)
513 /* legitimize both operands of the PLUS */
514 if (GET_CODE (XEXP (orig, 0)) == PLUS)
516 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
518 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
519 (base == reg ? 0 : reg));
524 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
525 result = plus_constant (base, INTVAL (orig));
527 result = gen_rtx_PLUS (Pmode, base, orig);
529 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
533 emit_move_insn (reg, result);
538 result = force_reg (GET_MODE (result), result);
545 else if (GET_CODE (orig) == MEM)
546 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
547 /* When the target is i386, this code prevents crashes due to the
548 compiler's ignorance on how to move the PIC base register to
549 other registers. (The reload phase sometimes introduces such
551 else if (GET_CODE (orig) == PLUS
552 && GET_CODE (XEXP (orig, 0)) == REG
553 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
555 /* Prevent the same register from being erroneously used
556 as both the base and index registers. */
557 && GET_CODE (XEXP (orig, 1)) == CONST
561 emit_move_insn (reg, XEXP (orig, 0));
562 XEXP (ptr_ref, 0) = reg;
567 /* Transform TARGET (a MEM), which is a function call target, to the
568 corresponding symbol_stub if necessary. Return a new MEM. */
571 machopic_indirect_call_target (rtx target)
573 if (GET_CODE (target) != MEM)
576 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
578 enum machine_mode mode = GET_MODE (XEXP (target, 0));
579 const char *name = XSTR (XEXP (target, 0), 0);
581 /* If the name is already defined, we need do nothing. */
582 if (name[0] == '!' && name[1] == 'T')
585 if (!machopic_name_defined_p (name))
587 const char *stub_name = machopic_stub_name (name);
589 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
590 RTX_UNCHANGING_P (target) = 1;
598 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
602 if (! MACHOPIC_INDIRECT)
605 /* First handle a simple SYMBOL_REF or LABEL_REF */
606 if (GET_CODE (orig) == LABEL_REF
607 || (GET_CODE (orig) == SYMBOL_REF
610 /* addr(foo) = &func+(foo-func) */
613 orig = machopic_indirect_data_reference (orig, reg);
615 if (GET_CODE (orig) == PLUS
616 && GET_CODE (XEXP (orig, 0)) == REG)
619 return force_reg (mode, orig);
621 emit_move_insn (reg, orig);
625 /* if dynamic-no-pic then use 0 as the pic base */
626 if (MACHO_DYNAMIC_NO_PIC_P)
627 pic_base = CONST0_RTX (Pmode);
629 pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
631 if (GET_CODE (orig) == MEM)
635 if (reload_in_progress)
638 reg = gen_reg_rtx (Pmode);
642 if (MACHO_DYNAMIC_NO_PIC_P
643 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
644 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
646 #if defined (TARGET_TOC) /* ppc */
647 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
648 rtx asym = XEXP (orig, 0);
651 emit_insn (gen_macho_high (temp_reg, asym));
652 mem = gen_rtx_MEM (GET_MODE (orig),
653 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
654 RTX_UNCHANGING_P (mem) = 1;
655 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
657 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
663 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
664 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
666 rtx offset = gen_rtx_CONST (Pmode,
667 gen_rtx_MINUS (Pmode,
670 #if defined (TARGET_TOC) /* i.e., PowerPC */
671 /* Generating a new reg may expose opportunities for
672 common subexpression elimination. */
673 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
678 sum = gen_rtx_HIGH (Pmode, offset);
679 if (! MACHO_DYNAMIC_NO_PIC_P)
680 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
682 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
684 mem = gen_rtx_MEM (GET_MODE (orig),
685 gen_rtx_LO_SUM (Pmode,
686 hi_sum_reg, offset));
687 RTX_UNCHANGING_P (mem) = 1;
688 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
689 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
694 emit_insn (gen_rtx_USE (VOIDmode,
696 PIC_OFFSET_TABLE_REGNUM)));
698 emit_insn (gen_rtx_SET (VOIDmode, reg,
700 gen_rtx_CONST (Pmode,
702 emit_insn (gen_rtx_SET (VOIDmode, reg,
703 gen_rtx_LO_SUM (Pmode, reg,
704 gen_rtx_CONST (Pmode, offset))));
705 pic_ref = gen_rtx_PLUS (Pmode,
706 pic_offset_table_rtx, reg);
710 #endif /* HAVE_lo_sum */
712 rtx pic = pic_offset_table_rtx;
713 if (GET_CODE (pic) != REG)
715 emit_move_insn (reg, pic);
719 emit_insn (gen_rtx_USE (VOIDmode,
721 PIC_OFFSET_TABLE_REGNUM)));
724 pic_ref = gen_rtx_PLUS (Pmode,
726 gen_rtx_CONST (Pmode,
727 gen_rtx_MINUS (Pmode,
732 #if !defined (TARGET_TOC)
733 emit_move_insn (reg, pic_ref);
734 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
736 RTX_UNCHANGING_P (pic_ref) = 1;
742 if (GET_CODE (orig) == SYMBOL_REF
743 || GET_CODE (orig) == LABEL_REF)
745 rtx offset = gen_rtx_CONST (Pmode,
746 gen_rtx_MINUS (Pmode,
748 #if defined (TARGET_TOC) /* i.e., PowerPC */
753 if (reload_in_progress)
756 reg = gen_reg_rtx (SImode);
761 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
762 (MACHO_DYNAMIC_NO_PIC_P)
763 ? gen_rtx_HIGH (Pmode, offset)
764 : gen_rtx_PLUS (Pmode,
765 pic_offset_table_rtx,
768 emit_insn (gen_rtx_SET (VOIDmode, reg,
769 gen_rtx_LO_SUM (Pmode,
770 hi_sum_reg, offset)));
772 RTX_UNCHANGING_P (pic_ref) = 1;
774 emit_insn (gen_rtx_SET (VOIDmode, reg,
775 gen_rtx_HIGH (Pmode, offset)));
776 emit_insn (gen_rtx_SET (VOIDmode, reg,
777 gen_rtx_LO_SUM (Pmode, reg, offset)));
778 pic_ref = gen_rtx_PLUS (Pmode,
779 pic_offset_table_rtx, reg);
780 RTX_UNCHANGING_P (pic_ref) = 1;
784 #endif /* HAVE_lo_sum */
786 if (GET_CODE (orig) == REG)
792 rtx pic = pic_offset_table_rtx;
793 if (GET_CODE (pic) != REG)
795 emit_move_insn (reg, pic);
799 emit_insn (gen_rtx_USE (VOIDmode,
800 pic_offset_table_rtx));
802 pic_ref = gen_rtx_PLUS (Pmode,
804 gen_rtx_CONST (Pmode,
805 gen_rtx_MINUS (Pmode,
811 if (GET_CODE (pic_ref) != REG)
815 emit_move_insn (reg, pic_ref);
820 return force_reg (mode, pic_ref);
829 else if (GET_CODE (orig) == SYMBOL_REF)
832 else if (GET_CODE (orig) == PLUS
833 && (GET_CODE (XEXP (orig, 0)) == MEM
834 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
835 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
836 && XEXP (orig, 0) != pic_offset_table_rtx
837 && GET_CODE (XEXP (orig, 1)) != REG)
841 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
843 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
844 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
845 Pmode, (base == reg ? 0 : reg));
846 if (GET_CODE (orig) == CONST_INT)
848 pic_ref = plus_constant (base, INTVAL (orig));
852 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
854 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
855 RTX_UNCHANGING_P (pic_ref) = 1;
857 if (reg && is_complex)
859 emit_move_insn (reg, pic_ref);
862 /* Likewise, should we set special REG_NOTEs here? */
865 else if (GET_CODE (orig) == CONST)
867 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
870 else if (GET_CODE (orig) == MEM
871 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
873 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
875 addr = gen_rtx_MEM (GET_MODE (orig), addr);
876 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
877 emit_move_insn (reg, addr);
886 machopic_finish (FILE *asm_out_file)
890 for (temp = machopic_stubs;
892 temp = TREE_CHAIN (temp))
894 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
895 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
899 if (! TREE_USED (temp))
902 /* If the symbol is actually defined, we don't need a stub. */
903 if (sym_name[0] == '!' && sym_name[1] == 'T')
906 sym_name = darwin_strip_name_encoding (sym_name);
908 sym = alloca (strlen (sym_name) + 2);
909 if (sym_name[0] == '*' || sym_name[0] == '&')
910 strcpy (sym, sym_name + 1);
911 else if (sym_name[0] == '-' || sym_name[0] == '+')
912 strcpy (sym, sym_name);
914 sym[0] = '_', strcpy (sym + 1, sym_name);
916 stub = alloca (strlen (stub_name) + 2);
917 if (stub_name[0] == '*' || stub_name[0] == '&')
918 strcpy (stub, stub_name + 1);
920 stub[0] = '_', strcpy (stub + 1, stub_name);
922 machopic_output_stub (asm_out_file, sym, stub);
925 for (temp = machopic_non_lazy_pointers;
927 temp = TREE_CHAIN (temp))
929 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
930 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
932 if (! TREE_USED (temp))
935 if (machopic_ident_defined_p (TREE_VALUE (temp)))
938 assemble_align (GET_MODE_ALIGNMENT (Pmode));
939 assemble_label (lazy_name);
940 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
941 GET_MODE_SIZE (Pmode),
942 GET_MODE_ALIGNMENT (Pmode), 1);
946 machopic_nl_symbol_ptr_section ();
947 assemble_name (asm_out_file, lazy_name);
948 fprintf (asm_out_file, ":\n");
950 fprintf (asm_out_file, "\t.indirect_symbol ");
951 assemble_name (asm_out_file, sym_name);
952 fprintf (asm_out_file, "\n");
954 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
955 GET_MODE_ALIGNMENT (Pmode), 1);
961 machopic_operand_p (rtx op)
963 if (MACHOPIC_JUST_INDIRECT)
965 while (GET_CODE (op) == CONST)
968 if (GET_CODE (op) == SYMBOL_REF)
969 return machopic_name_defined_p (XSTR (op, 0));
974 while (GET_CODE (op) == CONST)
977 if (GET_CODE (op) == MINUS
978 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
979 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
980 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
981 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
987 /* This function records whether a given name corresponds to a defined
988 or undefined function or variable, for machopic_classify_ident to
992 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
997 const char *orig_str;
1001 /* Do the standard encoding things first. */
1002 default_encode_section_info (decl, rtl, first);
1004 /* With the introduction of symbol_ref flags, some of the following
1005 code has become redundant and should be removed at some point. */
1007 if ((TREE_CODE (decl) == FUNCTION_DECL
1008 || TREE_CODE (decl) == VAR_DECL)
1009 && !DECL_EXTERNAL (decl)
1010 && ((TREE_STATIC (decl)
1011 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1012 || (DECL_INITIAL (decl)
1013 && DECL_INITIAL (decl) != error_mark_node)))
1016 if (TREE_CODE (decl) == FUNCTION_DECL)
1017 code = (defined ? 'T' : 't');
1018 else if (TREE_CODE (decl) == VAR_DECL)
1019 code = (defined ? 'D' : 'd');
1024 sym_ref = XEXP (rtl, 0);
1025 orig_str = XSTR (sym_ref, 0);
1026 len = strlen (orig_str) + 1;
1028 if (orig_str[0] == '!')
1030 /* Already encoded; see if we need to change it. */
1031 if (code == orig_str[1])
1033 /* Yes, tweak a copy of the name and put it in a new string. */
1034 new_str = alloca (len);
1035 memcpy (new_str, orig_str, len);
1037 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1041 /* Add the encoding. */
1043 new_str = alloca (new_len);
1048 memcpy (new_str + 4, orig_str, len);
1049 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1051 /* The non-lazy pointer list may have captured references to the
1052 old encoded name, change them. */
1053 if (TREE_CODE (decl) == VAR_DECL)
1054 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1056 update_stubs (XSTR (sym_ref, 0));
1059 /* Undo the effects of the above. */
1062 darwin_strip_name_encoding (const char *str)
1064 return str[0] == '!' ? str + 4 : str;
1067 /* Scan the list of non-lazy pointers and update any recorded names whose
1068 stripped name matches the argument. */
1071 update_non_lazy_ptrs (const char *name)
1073 const char *name1, *name2;
1076 name1 = darwin_strip_name_encoding (name);
1078 for (temp = machopic_non_lazy_pointers;
1080 temp = TREE_CHAIN (temp))
1082 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1084 if (*sym_name == '!')
1086 name2 = darwin_strip_name_encoding (sym_name);
1087 if (strcmp (name1, name2) == 0)
1089 /* FIXME: This breaks the identifier hash table. */
1090 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1091 = (unsigned char *) name;
1098 /* Function NAME is being defined, and its label has just been output.
1099 If there's already a reference to a stub for this function, we can
1100 just emit the stub label now and we don't bother emitting the stub later. */
1103 machopic_output_possible_stub_label (FILE *file, const char *name)
1107 /* Ensure we're looking at a section-encoded name. */
1108 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1111 for (temp = machopic_stubs;
1113 temp = TREE_CHAIN (temp))
1115 const char *sym_name;
1117 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1118 if (sym_name[0] == '!' && sym_name[1] == 'T'
1119 && ! strcmp (name+2, sym_name+2))
1121 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1122 /* Avoid generating a stub for this. */
1123 TREE_USED (temp) = 0;
1129 /* Scan the list of stubs and update any recorded names whose
1130 stripped name matches the argument. */
1133 update_stubs (const char *name)
1135 const char *name1, *name2;
1138 name1 = darwin_strip_name_encoding (name);
1140 for (temp = machopic_stubs;
1142 temp = TREE_CHAIN (temp))
1144 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1146 if (*sym_name == '!')
1148 name2 = darwin_strip_name_encoding (sym_name);
1149 if (strcmp (name1, name2) == 0)
1151 /* FIXME: This breaks the identifier hash table. */
1152 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1153 = (unsigned char *) name;
1161 machopic_select_section (tree exp, int reloc,
1162 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1164 void (*base_function)(void);
1166 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1167 base_function = readonly_data_section;
1168 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1169 base_function = const_data_section;
1171 base_function = data_section;
1173 if (TREE_CODE (exp) == STRING_CST
1174 && ((size_t) TREE_STRING_LENGTH (exp)
1175 == strlen (TREE_STRING_POINTER (exp)) + 1)
1176 && ! flag_writable_strings)
1178 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1179 && flag_merge_constants)
1181 tree size = TYPE_SIZE (TREE_TYPE (exp));
1183 if (TREE_CODE (size) == INTEGER_CST &&
1184 TREE_INT_CST_LOW (size) == 4 &&
1185 TREE_INT_CST_HIGH (size) == 0)
1186 literal4_section ();
1187 else if (TREE_CODE (size) == INTEGER_CST &&
1188 TREE_INT_CST_LOW (size) == 8 &&
1189 TREE_INT_CST_HIGH (size) == 0)
1190 literal8_section ();
1194 else if (TREE_CODE (exp) == CONSTRUCTOR
1196 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1197 && TYPE_NAME (TREE_TYPE (exp)))
1199 tree name = TYPE_NAME (TREE_TYPE (exp));
1200 if (TREE_CODE (name) == TYPE_DECL)
1201 name = DECL_NAME (name);
1202 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1203 objc_constant_string_object_section ();
1204 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1205 objc_string_object_section ();
1209 else if (TREE_CODE (exp) == VAR_DECL &&
1211 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1212 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1213 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1215 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1217 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1218 objc_cls_meth_section ();
1219 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1220 objc_inst_meth_section ();
1221 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1222 objc_cat_cls_meth_section ();
1223 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1224 objc_cat_inst_meth_section ();
1225 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1226 objc_class_vars_section ();
1227 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1228 objc_instance_vars_section ();
1229 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1230 objc_cat_cls_meth_section ();
1231 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1232 objc_class_names_section ();
1233 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1234 objc_meth_var_names_section ();
1235 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1236 objc_meth_var_types_section ();
1237 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1238 objc_cls_refs_section ();
1239 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1240 objc_class_section ();
1241 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1242 objc_meta_class_section ();
1243 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1244 objc_category_section ();
1245 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1246 objc_selector_refs_section ();
1247 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1248 objc_selector_fixup_section ();
1249 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1250 objc_symbols_section ();
1251 else if (!strncmp (name, "_OBJC_MODULES", 13))
1252 objc_module_info_section ();
1253 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1254 objc_image_info_section ();
1255 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1256 objc_cat_inst_meth_section ();
1257 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1258 objc_cat_cls_meth_section ();
1259 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1260 objc_cat_cls_meth_section ();
1261 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1262 objc_protocol_section ();
1270 /* This can be called with address expressions as "rtx".
1271 They must go in "const". */
1274 machopic_select_rtx_section (enum machine_mode mode, rtx x,
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 ();
1283 else if (MACHOPIC_INDIRECT
1284 && (GET_CODE (x) == SYMBOL_REF
1285 || GET_CODE (x) == CONST
1286 || GET_CODE (x) == LABEL_REF))
1287 const_data_section ();
1293 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1295 if (MACHOPIC_INDIRECT)
1296 mod_init_section ();
1298 constructor_section ();
1299 assemble_align (POINTER_SIZE);
1300 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1302 if (! MACHOPIC_INDIRECT)
1303 fprintf (asm_out_file, ".reference .constructors_used\n");
1307 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1309 if (MACHOPIC_INDIRECT)
1310 mod_term_section ();
1312 destructor_section ();
1313 assemble_align (POINTER_SIZE);
1314 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1316 if (! MACHOPIC_INDIRECT)
1317 fprintf (asm_out_file, ".reference .destructors_used\n");
1321 darwin_globalize_label (FILE *stream, const char *name)
1323 if (!!strncmp (name, "_OBJC_", 6))
1324 default_globalize_label (stream, name);
1327 /* Output a difference of two labels that will be an assembly time
1328 constant if the two labels are local. (.long lab1-lab2 will be
1329 very different if lab1 is at the boundary between two sections; it
1330 will be relocated according to the second section, not the first,
1331 so one ends up with a difference between labels in different
1332 sections, which is bad in the dwarf2 eh context for instance.) */
1334 static int darwin_dwarf_label_counter;
1337 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1338 const char *lab1, const char *lab2)
1340 const char *p = lab1 + (lab1[0] == '*');
1341 int islocaldiff = (p[0] == 'L');
1344 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1346 fprintf (file, "\t%s\t", ".long");
1347 assemble_name (file, lab1);
1348 fprintf (file, "-");
1349 assemble_name (file, lab2);
1351 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1355 darwin_file_end (void)
1357 machopic_finish (asm_out_file);
1358 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1360 constructor_section ();
1361 destructor_section ();
1362 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1366 #include "gt-darwin.h"