1 /* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004
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*);
51 /* Earliest operating system for which generated code is targeted, as string
52 and as integer. The string form is "10.0", "10.1", etc. The corresponding
53 numeric versions are 1000, 1010, etc. This number is used for feature
54 tests of the form "enable_this_feature = macosx_version_min_required >= n",
55 so 0 is a conservative default. */
57 const char *darwin_macosx_version_name;
58 unsigned int macosx_version_min_required = 0;
60 /* Parse -macosx= option. */
62 static struct darwin_macosx_vers {
64 unsigned int vers_num;
65 } darwin_macosx_vers_tbl[] = {
77 void darwin_parse_macosx_version_name (void)
79 if (darwin_macosx_version_name)
81 struct darwin_macosx_vers *v = darwin_macosx_vers_tbl;
83 && strcmp (darwin_macosx_version_name, v->vers_str) != 0)
87 macosx_version_min_required = v->vers_num;
89 warning ("-macosx=%s: unrecognized version", darwin_macosx_version_name);
94 name_needs_quotes (const char *name)
97 while ((c = *name++) != '\0')
98 if (! ISIDNUM (c) && c != '.' && c != '$')
104 * flag_pic = 1 ... generate only indirections
105 * flag_pic = 2 ... generate indirections and pure code
108 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
109 reference, which will not be changed. */
111 static GTY(()) tree machopic_defined_list;
113 enum machopic_addr_class
114 machopic_classify_ident (tree ident)
116 const char *name = IDENTIFIER_POINTER (ident);
117 int lprefix = (((name[0] == '*' || name[0] == '&')
118 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
127 /* The PIC base symbol is always defined. */
128 if (! strcmp (name, "<pic base>"))
129 return MACHOPIC_DEFINED_DATA;
133 /* Here if no special encoding to be found. */
136 const char *name = IDENTIFIER_POINTER (ident);
137 int len = strlen (name);
139 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
140 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
141 return MACHOPIC_DEFINED_FUNCTION;
142 return MACHOPIC_DEFINED_DATA;
145 for (temp = machopic_defined_list;
147 temp = TREE_CHAIN (temp))
149 if (ident == TREE_VALUE (temp))
150 return MACHOPIC_DEFINED_DATA;
153 if (TREE_ASM_WRITTEN (ident))
154 return MACHOPIC_DEFINED_DATA;
156 return MACHOPIC_UNDEFINED;
159 else if (name[1] == 'D')
160 return MACHOPIC_DEFINED_DATA;
162 else if (name[1] == 'T')
163 return MACHOPIC_DEFINED_FUNCTION;
165 /* It is possible that someone is holding a "stale" name, which has
166 since been defined. See if there is a "defined" name (i.e,
167 different from NAME only in having a '!D_' or a '!T_' instead of
168 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
169 that this identifier is defined. */
170 else if (name[1] == 'd' || name[1] == 't')
173 new_name = (char *)alloca (strlen (name) + 1);
174 strcpy (new_name, name);
175 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
176 if (maybe_get_identifier (new_name) != NULL)
177 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
178 : MACHOPIC_DEFINED_FUNCTION;
181 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
183 if (ident == TREE_VALUE (temp))
186 return MACHOPIC_DEFINED_FUNCTION;
188 return MACHOPIC_DEFINED_DATA;
192 if (name[1] == 't' || name[1] == 'T')
195 return MACHOPIC_DEFINED_FUNCTION;
197 return MACHOPIC_UNDEFINED_FUNCTION;
202 return MACHOPIC_DEFINED_DATA;
204 return MACHOPIC_UNDEFINED_DATA;
209 enum machopic_addr_class
210 machopic_classify_name (const char *name)
212 return machopic_classify_ident (get_identifier (name));
216 machopic_ident_defined_p (tree ident)
218 switch (machopic_classify_ident (ident))
220 case MACHOPIC_UNDEFINED:
221 case MACHOPIC_UNDEFINED_DATA:
222 case MACHOPIC_UNDEFINED_FUNCTION:
230 machopic_data_defined_p (const char *name)
232 switch (machopic_classify_ident (get_identifier (name)))
234 case MACHOPIC_DEFINED_DATA:
242 machopic_name_defined_p (const char *name)
244 return machopic_ident_defined_p (get_identifier (name));
248 machopic_define_ident (tree ident)
250 if (!machopic_ident_defined_p (ident))
251 machopic_defined_list =
252 tree_cons (NULL_TREE, ident, machopic_defined_list);
256 machopic_define_name (const char *name)
258 machopic_define_ident (get_identifier (name));
261 static GTY(()) char * function_base;
264 machopic_function_base_name (void)
266 const char *current_name;
267 /* if dynamic-no-pic is on, we should not get here */
268 if (MACHO_DYNAMIC_NO_PIC_P)
271 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
273 if (function_base == NULL)
275 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
277 current_function_uses_pic_offset_table = 1;
279 return function_base;
282 static GTY(()) const char * function_base_func_name;
283 static GTY(()) int current_pic_label_num;
286 machopic_output_function_base_name (FILE *file)
288 const char *current_name;
290 /* If dynamic-no-pic is on, we should not get here. */
291 if (MACHO_DYNAMIC_NO_PIC_P)
294 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
295 if (function_base_func_name != current_name)
297 ++current_pic_label_num;
298 function_base_func_name = current_name;
300 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
303 static GTY(()) tree machopic_non_lazy_pointers;
305 /* Return a non-lazy pointer name corresponding to the given name,
306 either by finding it in our list of pointer names, or by generating
310 machopic_non_lazy_ptr_name (const char *name)
312 const char *temp_name;
313 tree temp, ident = get_identifier (name);
315 for (temp = machopic_non_lazy_pointers;
317 temp = TREE_CHAIN (temp))
319 if (ident == TREE_VALUE (temp))
320 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
323 name = darwin_strip_name_encoding (name);
325 /* Try again, but comparing names this time. */
326 for (temp = machopic_non_lazy_pointers;
328 temp = TREE_CHAIN (temp))
330 if (TREE_VALUE (temp))
332 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
333 temp_name = darwin_strip_name_encoding (temp_name);
334 if (strcmp (name, temp_name) == 0)
335 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
341 int namelen = strlen (name);
345 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
347 strcpy (buffer, "&L");
351 memcpy (buffer + bufferlen, name+1, namelen-1+1);
352 bufferlen += namelen-1;
356 buffer[bufferlen] = '_';
357 memcpy (buffer + bufferlen +1, name, namelen+1);
358 bufferlen += namelen +1;
361 memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
362 bufferlen += strlen("$non_lazy_ptr");
363 ptr_name = get_identifier (buffer);
365 machopic_non_lazy_pointers
366 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
368 TREE_USED (machopic_non_lazy_pointers) = 0;
370 return IDENTIFIER_POINTER (ptr_name);
374 static GTY(()) tree machopic_stubs;
376 /* Return the name of the stub corresponding to the given name,
377 generating a new stub name if necessary. */
380 machopic_stub_name (const char *name)
382 tree temp, ident = get_identifier (name);
385 for (temp = machopic_stubs;
387 temp = TREE_CHAIN (temp))
389 if (ident == TREE_VALUE (temp))
390 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
391 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
392 if (strcmp (name, tname) == 0)
393 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
394 /* A library call name might not be section-encoded yet, so try
395 it against a stripped name. */
398 && strcmp (name, tname + 4) == 0)
399 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
402 name = darwin_strip_name_encoding (name);
407 int namelen = strlen (name);
409 int needs_quotes = name_needs_quotes (name);
411 buffer = alloca (namelen + 20);
415 strcpy (buffer, "&\"L");
416 bufferlen = strlen("&\"L");
420 strcpy (buffer, "&L");
421 bufferlen = strlen("&L");
426 memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
427 bufferlen += namelen - 1;
431 buffer[bufferlen] = '_';
432 memcpy (buffer + bufferlen +1, name, namelen+1);
433 bufferlen += namelen +1;
438 memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
439 bufferlen += strlen("$stub\"");
443 memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
444 bufferlen += strlen("$stub");
446 ptr_name = get_identifier (buffer);
448 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
449 TREE_USED (machopic_stubs) = 0;
451 return IDENTIFIER_POINTER (ptr_name);
456 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
458 const char *real_name;
459 tree temp, ident = get_identifier (name), id2;
461 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
463 temp = TREE_CHAIN (temp))
464 if (ident == TREE_PURPOSE (temp))
466 /* Mark both the stub or non-lazy pointer as well as the
467 original symbol as being referenced. */
468 TREE_USED (temp) = 1;
469 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
470 mark_referenced (TREE_VALUE (temp));
471 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
472 real_name = darwin_strip_name_encoding (real_name);
473 id2 = maybe_get_identifier (real_name);
475 mark_referenced (id2);
479 /* Transform ORIG, which may be any data source, to the corresponding
480 source using indirections. */
483 machopic_indirect_data_reference (rtx orig, rtx reg)
487 if (! MACHOPIC_INDIRECT)
490 if (GET_CODE (orig) == SYMBOL_REF)
492 const char *name = XSTR (orig, 0);
493 int defined = machopic_data_defined_p (name);
495 if (defined && MACHO_DYNAMIC_NO_PIC_P)
497 #if defined (TARGET_TOC)
498 emit_insn (gen_macho_high (reg, orig));
499 emit_insn (gen_macho_low (reg, reg, orig));
501 /* some other cpu -- writeme! */
508 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
509 rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
510 machopic_function_base_name ());
511 rtx offset = gen_rtx_CONST (Pmode,
512 gen_rtx_MINUS (Pmode, orig, pic_base));
515 #if defined (TARGET_TOC) /* i.e., PowerPC */
516 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
521 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
522 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
523 gen_rtx_HIGH (Pmode, offset))));
524 emit_insn (gen_rtx_SET (Pmode, reg,
525 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
529 #if defined (HAVE_lo_sum)
530 if (reg == 0) abort ();
532 emit_insn (gen_rtx_SET (VOIDmode, reg,
533 gen_rtx_HIGH (Pmode, offset)));
534 emit_insn (gen_rtx_SET (VOIDmode, reg,
535 gen_rtx_LO_SUM (Pmode, reg, offset)));
536 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
538 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
544 ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
545 machopic_non_lazy_ptr_name (name));
547 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
548 RTX_UNCHANGING_P (ptr_ref) = 1;
552 else if (GET_CODE (orig) == CONST)
556 /* legitimize both operands of the PLUS */
557 if (GET_CODE (XEXP (orig, 0)) == PLUS)
559 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
561 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
562 (base == reg ? 0 : reg));
567 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
568 result = plus_constant (base, INTVAL (orig));
570 result = gen_rtx_PLUS (Pmode, base, orig);
572 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
576 emit_move_insn (reg, result);
581 result = force_reg (GET_MODE (result), result);
588 else if (GET_CODE (orig) == MEM)
589 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
590 /* When the target is i386, this code prevents crashes due to the
591 compiler's ignorance on how to move the PIC base register to
592 other registers. (The reload phase sometimes introduces such
594 else if (GET_CODE (orig) == PLUS
595 && GET_CODE (XEXP (orig, 0)) == REG
596 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
598 /* Prevent the same register from being erroneously used
599 as both the base and index registers. */
600 && GET_CODE (XEXP (orig, 1)) == CONST
604 emit_move_insn (reg, XEXP (orig, 0));
605 XEXP (ptr_ref, 0) = reg;
610 /* Transform TARGET (a MEM), which is a function call target, to the
611 corresponding symbol_stub if necessary. Return a new MEM. */
614 machopic_indirect_call_target (rtx target)
616 if (GET_CODE (target) != MEM)
619 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
621 enum machine_mode mode = GET_MODE (XEXP (target, 0));
622 const char *name = XSTR (XEXP (target, 0), 0);
624 /* If the name is already defined, we need do nothing. */
625 if (name[0] == '!' && name[1] == 'T')
628 if (!machopic_name_defined_p (name))
630 const char *stub_name = machopic_stub_name (name);
632 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
633 RTX_UNCHANGING_P (target) = 1;
641 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
645 if (! MACHOPIC_INDIRECT)
648 /* First handle a simple SYMBOL_REF or LABEL_REF */
649 if (GET_CODE (orig) == LABEL_REF
650 || (GET_CODE (orig) == SYMBOL_REF
653 /* addr(foo) = &func+(foo-func) */
656 orig = machopic_indirect_data_reference (orig, reg);
658 if (GET_CODE (orig) == PLUS
659 && GET_CODE (XEXP (orig, 0)) == REG)
662 return force_reg (mode, orig);
664 emit_move_insn (reg, orig);
668 /* if dynamic-no-pic then use 0 as the pic base */
669 if (MACHO_DYNAMIC_NO_PIC_P)
670 pic_base = CONST0_RTX (Pmode);
672 pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
674 if (GET_CODE (orig) == MEM)
678 if (reload_in_progress)
681 reg = gen_reg_rtx (Pmode);
685 if (MACHO_DYNAMIC_NO_PIC_P
686 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
687 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
689 #if defined (TARGET_TOC) /* ppc */
690 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
691 rtx asym = XEXP (orig, 0);
694 emit_insn (gen_macho_high (temp_reg, asym));
695 mem = gen_rtx_MEM (GET_MODE (orig),
696 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
697 RTX_UNCHANGING_P (mem) = 1;
698 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
700 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
706 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
707 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
709 rtx offset = gen_rtx_CONST (Pmode,
710 gen_rtx_MINUS (Pmode,
713 #if defined (TARGET_TOC) /* i.e., PowerPC */
714 /* Generating a new reg may expose opportunities for
715 common subexpression elimination. */
716 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
721 sum = gen_rtx_HIGH (Pmode, offset);
722 if (! MACHO_DYNAMIC_NO_PIC_P)
723 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
725 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
727 mem = gen_rtx_MEM (GET_MODE (orig),
728 gen_rtx_LO_SUM (Pmode,
729 hi_sum_reg, offset));
730 RTX_UNCHANGING_P (mem) = 1;
731 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
732 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
737 emit_insn (gen_rtx_USE (VOIDmode,
739 PIC_OFFSET_TABLE_REGNUM)));
741 emit_insn (gen_rtx_SET (VOIDmode, reg,
743 gen_rtx_CONST (Pmode,
745 emit_insn (gen_rtx_SET (VOIDmode, reg,
746 gen_rtx_LO_SUM (Pmode, reg,
747 gen_rtx_CONST (Pmode, offset))));
748 pic_ref = gen_rtx_PLUS (Pmode,
749 pic_offset_table_rtx, reg);
753 #endif /* HAVE_lo_sum */
755 rtx pic = pic_offset_table_rtx;
756 if (GET_CODE (pic) != REG)
758 emit_move_insn (reg, pic);
762 emit_insn (gen_rtx_USE (VOIDmode,
764 PIC_OFFSET_TABLE_REGNUM)));
767 pic_ref = gen_rtx_PLUS (Pmode,
769 gen_rtx_CONST (Pmode,
770 gen_rtx_MINUS (Pmode,
775 #if !defined (TARGET_TOC)
776 emit_move_insn (reg, pic_ref);
777 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
779 RTX_UNCHANGING_P (pic_ref) = 1;
785 if (GET_CODE (orig) == SYMBOL_REF
786 || GET_CODE (orig) == LABEL_REF)
788 rtx offset = gen_rtx_CONST (Pmode,
789 gen_rtx_MINUS (Pmode,
791 #if defined (TARGET_TOC) /* i.e., PowerPC */
796 if (reload_in_progress)
799 reg = gen_reg_rtx (SImode);
804 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
805 (MACHO_DYNAMIC_NO_PIC_P)
806 ? gen_rtx_HIGH (Pmode, offset)
807 : gen_rtx_PLUS (Pmode,
808 pic_offset_table_rtx,
811 emit_insn (gen_rtx_SET (VOIDmode, reg,
812 gen_rtx_LO_SUM (Pmode,
813 hi_sum_reg, offset)));
815 RTX_UNCHANGING_P (pic_ref) = 1;
817 emit_insn (gen_rtx_SET (VOIDmode, reg,
818 gen_rtx_HIGH (Pmode, offset)));
819 emit_insn (gen_rtx_SET (VOIDmode, reg,
820 gen_rtx_LO_SUM (Pmode, reg, offset)));
821 pic_ref = gen_rtx_PLUS (Pmode,
822 pic_offset_table_rtx, reg);
823 RTX_UNCHANGING_P (pic_ref) = 1;
827 #endif /* HAVE_lo_sum */
829 if (GET_CODE (orig) == REG)
835 rtx pic = pic_offset_table_rtx;
836 if (GET_CODE (pic) != REG)
838 emit_move_insn (reg, pic);
842 emit_insn (gen_rtx_USE (VOIDmode,
843 pic_offset_table_rtx));
845 pic_ref = gen_rtx_PLUS (Pmode,
847 gen_rtx_CONST (Pmode,
848 gen_rtx_MINUS (Pmode,
854 if (GET_CODE (pic_ref) != REG)
858 emit_move_insn (reg, pic_ref);
863 return force_reg (mode, pic_ref);
872 else if (GET_CODE (orig) == SYMBOL_REF)
875 else if (GET_CODE (orig) == PLUS
876 && (GET_CODE (XEXP (orig, 0)) == MEM
877 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
878 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
879 && XEXP (orig, 0) != pic_offset_table_rtx
880 && GET_CODE (XEXP (orig, 1)) != REG)
884 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
886 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
887 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
888 Pmode, (base == reg ? 0 : reg));
889 if (GET_CODE (orig) == CONST_INT)
891 pic_ref = plus_constant (base, INTVAL (orig));
895 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
897 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
898 RTX_UNCHANGING_P (pic_ref) = 1;
900 if (reg && is_complex)
902 emit_move_insn (reg, pic_ref);
905 /* Likewise, should we set special REG_NOTEs here? */
908 else if (GET_CODE (orig) == CONST)
910 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
913 else if (GET_CODE (orig) == MEM
914 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
916 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
918 addr = gen_rtx_MEM (GET_MODE (orig), addr);
919 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
920 emit_move_insn (reg, addr);
929 machopic_finish (FILE *asm_out_file)
933 for (temp = machopic_stubs;
935 temp = TREE_CHAIN (temp))
937 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
938 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
942 if (! TREE_USED (temp))
945 /* If the symbol is actually defined, we don't need a stub. */
946 if (sym_name[0] == '!' && sym_name[1] == 'T')
949 sym_name = darwin_strip_name_encoding (sym_name);
951 sym = alloca (strlen (sym_name) + 2);
952 if (sym_name[0] == '*' || sym_name[0] == '&')
953 strcpy (sym, sym_name + 1);
954 else if (sym_name[0] == '-' || sym_name[0] == '+')
955 strcpy (sym, sym_name);
957 sym[0] = '_', strcpy (sym + 1, sym_name);
959 stub = alloca (strlen (stub_name) + 2);
960 if (stub_name[0] == '*' || stub_name[0] == '&')
961 strcpy (stub, stub_name + 1);
963 stub[0] = '_', strcpy (stub + 1, stub_name);
965 machopic_output_stub (asm_out_file, sym, stub);
968 for (temp = machopic_non_lazy_pointers;
970 temp = TREE_CHAIN (temp))
972 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
973 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
975 if (! TREE_USED (temp))
978 if (machopic_ident_defined_p (TREE_VALUE (temp)))
981 assemble_align (GET_MODE_ALIGNMENT (Pmode));
982 assemble_label (lazy_name);
983 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
984 GET_MODE_SIZE (Pmode),
985 GET_MODE_ALIGNMENT (Pmode), 1);
989 machopic_nl_symbol_ptr_section ();
990 assemble_name (asm_out_file, lazy_name);
991 fprintf (asm_out_file, ":\n");
993 fprintf (asm_out_file, "\t.indirect_symbol ");
994 assemble_name (asm_out_file, sym_name);
995 fprintf (asm_out_file, "\n");
997 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
998 GET_MODE_ALIGNMENT (Pmode), 1);
1004 machopic_operand_p (rtx op)
1006 if (MACHOPIC_JUST_INDIRECT)
1008 while (GET_CODE (op) == CONST)
1011 if (GET_CODE (op) == SYMBOL_REF)
1012 return machopic_name_defined_p (XSTR (op, 0));
1017 while (GET_CODE (op) == CONST)
1020 if (GET_CODE (op) == MINUS
1021 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1022 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1023 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
1024 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
1030 /* This function records whether a given name corresponds to a defined
1031 or undefined function or variable, for machopic_classify_ident to
1035 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
1040 const char *orig_str;
1042 size_t len, new_len;
1044 /* Do the standard encoding things first. */
1045 default_encode_section_info (decl, rtl, first);
1047 /* With the introduction of symbol_ref flags, some of the following
1048 code has become redundant and should be removed at some point. */
1050 if ((TREE_CODE (decl) == FUNCTION_DECL
1051 || TREE_CODE (decl) == VAR_DECL)
1052 && !DECL_EXTERNAL (decl)
1053 && ((TREE_STATIC (decl)
1054 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1055 || (DECL_INITIAL (decl)
1056 && DECL_INITIAL (decl) != error_mark_node)))
1059 if (TREE_CODE (decl) == FUNCTION_DECL)
1060 code = (defined ? 'T' : 't');
1061 else if (TREE_CODE (decl) == VAR_DECL)
1062 code = (defined ? 'D' : 'd');
1067 sym_ref = XEXP (rtl, 0);
1068 orig_str = XSTR (sym_ref, 0);
1069 len = strlen (orig_str) + 1;
1071 if (orig_str[0] == '!')
1073 /* Already encoded; see if we need to change it. */
1074 if (code == orig_str[1])
1076 /* Yes, tweak a copy of the name and put it in a new string. */
1077 new_str = alloca (len);
1078 memcpy (new_str, orig_str, len);
1080 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1084 /* Add the encoding. */
1086 new_str = alloca (new_len);
1091 memcpy (new_str + 4, orig_str, len);
1092 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1094 /* The non-lazy pointer list may have captured references to the
1095 old encoded name, change them. */
1096 if (TREE_CODE (decl) == VAR_DECL)
1097 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1099 update_stubs (XSTR (sym_ref, 0));
1102 /* Undo the effects of the above. */
1105 darwin_strip_name_encoding (const char *str)
1107 return str[0] == '!' ? str + 4 : str;
1110 /* Scan the list of non-lazy pointers and update any recorded names whose
1111 stripped name matches the argument. */
1114 update_non_lazy_ptrs (const char *name)
1116 const char *name1, *name2;
1119 name1 = darwin_strip_name_encoding (name);
1121 for (temp = machopic_non_lazy_pointers;
1123 temp = TREE_CHAIN (temp))
1125 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1127 if (*sym_name == '!')
1129 name2 = darwin_strip_name_encoding (sym_name);
1130 if (strcmp (name1, name2) == 0)
1132 /* FIXME: This breaks the identifier hash table. */
1133 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1134 = (unsigned char *) name;
1141 /* Function NAME is being defined, and its label has just been output.
1142 If there's already a reference to a stub for this function, we can
1143 just emit the stub label now and we don't bother emitting the stub later. */
1146 machopic_output_possible_stub_label (FILE *file, const char *name)
1150 /* Ensure we're looking at a section-encoded name. */
1151 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1154 for (temp = machopic_stubs;
1156 temp = TREE_CHAIN (temp))
1158 const char *sym_name;
1160 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1161 if (sym_name[0] == '!' && (sym_name[1] == 'T' || sym_name[1] == 't')
1162 && ! strcmp (name+2, sym_name+2))
1164 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1165 /* Avoid generating a stub for this. */
1166 TREE_USED (temp) = 0;
1172 /* Scan the list of stubs and update any recorded names whose
1173 stripped name matches the argument. */
1176 update_stubs (const char *name)
1178 const char *name1, *name2;
1181 name1 = darwin_strip_name_encoding (name);
1183 for (temp = machopic_stubs;
1185 temp = TREE_CHAIN (temp))
1187 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1189 if (*sym_name == '!')
1191 name2 = darwin_strip_name_encoding (sym_name);
1192 if (strcmp (name1, name2) == 0)
1194 /* FIXME: This breaks the identifier hash table. */
1195 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1196 = (unsigned char *) name;
1204 machopic_select_section (tree exp, int reloc,
1205 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1207 void (*base_function)(void);
1209 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1210 base_function = readonly_data_section;
1211 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1212 base_function = const_data_section;
1214 base_function = data_section;
1216 if (TREE_CODE (exp) == STRING_CST
1217 && ((size_t) TREE_STRING_LENGTH (exp)
1218 == strlen (TREE_STRING_POINTER (exp)) + 1)
1219 && ! flag_writable_strings)
1221 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1222 && flag_merge_constants)
1224 tree size = TYPE_SIZE (TREE_TYPE (exp));
1226 if (TREE_CODE (size) == INTEGER_CST &&
1227 TREE_INT_CST_LOW (size) == 4 &&
1228 TREE_INT_CST_HIGH (size) == 0)
1229 literal4_section ();
1230 else if (TREE_CODE (size) == INTEGER_CST &&
1231 TREE_INT_CST_LOW (size) == 8 &&
1232 TREE_INT_CST_HIGH (size) == 0)
1233 literal8_section ();
1237 else if (TREE_CODE (exp) == CONSTRUCTOR
1239 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1240 && TYPE_NAME (TREE_TYPE (exp)))
1242 tree name = TYPE_NAME (TREE_TYPE (exp));
1243 if (TREE_CODE (name) == TYPE_DECL)
1244 name = DECL_NAME (name);
1245 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1246 objc_constant_string_object_section ();
1247 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1248 objc_string_object_section ();
1252 else if (TREE_CODE (exp) == VAR_DECL &&
1254 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1255 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1256 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1258 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1260 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1261 objc_cls_meth_section ();
1262 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1263 objc_inst_meth_section ();
1264 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1265 objc_cat_cls_meth_section ();
1266 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1267 objc_cat_inst_meth_section ();
1268 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1269 objc_class_vars_section ();
1270 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1271 objc_instance_vars_section ();
1272 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1273 objc_cat_cls_meth_section ();
1274 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1275 objc_class_names_section ();
1276 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1277 objc_meth_var_names_section ();
1278 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1279 objc_meth_var_types_section ();
1280 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1281 objc_cls_refs_section ();
1282 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1283 objc_class_section ();
1284 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1285 objc_meta_class_section ();
1286 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1287 objc_category_section ();
1288 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1289 objc_selector_refs_section ();
1290 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1291 objc_selector_fixup_section ();
1292 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1293 objc_symbols_section ();
1294 else if (!strncmp (name, "_OBJC_MODULES", 13))
1295 objc_module_info_section ();
1296 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1297 objc_image_info_section ();
1298 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1299 objc_cat_inst_meth_section ();
1300 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1301 objc_cat_cls_meth_section ();
1302 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1303 objc_cat_cls_meth_section ();
1304 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1305 objc_protocol_section ();
1313 /* This can be called with address expressions as "rtx".
1314 They must go in "const". */
1317 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1318 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1320 if (GET_MODE_SIZE (mode) == 8)
1321 literal8_section ();
1322 else if (GET_MODE_SIZE (mode) == 4
1323 && (GET_CODE (x) == CONST_INT
1324 || GET_CODE (x) == CONST_DOUBLE))
1325 literal4_section ();
1326 else if (MACHOPIC_INDIRECT
1327 && (GET_CODE (x) == SYMBOL_REF
1328 || GET_CODE (x) == CONST
1329 || GET_CODE (x) == LABEL_REF))
1330 const_data_section ();
1336 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1338 if (MACHOPIC_INDIRECT)
1339 mod_init_section ();
1341 constructor_section ();
1342 assemble_align (POINTER_SIZE);
1343 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1345 if (! MACHOPIC_INDIRECT)
1346 fprintf (asm_out_file, ".reference .constructors_used\n");
1350 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1352 if (MACHOPIC_INDIRECT)
1353 mod_term_section ();
1355 destructor_section ();
1356 assemble_align (POINTER_SIZE);
1357 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1359 if (! MACHOPIC_INDIRECT)
1360 fprintf (asm_out_file, ".reference .destructors_used\n");
1364 darwin_globalize_label (FILE *stream, const char *name)
1366 if (!!strncmp (name, "_OBJC_", 6))
1367 default_globalize_label (stream, name);
1370 /* Emit an assembler directive to set visibility for a symbol. The
1371 only supported visibilities are VISIBILITY_DEFAULT and
1372 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1373 extern". There is no MACH-O equivalent of ELF's
1374 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1377 darwin_assemble_visibility (tree decl, int vis)
1379 if (vis == VISIBILITY_DEFAULT)
1381 else if (vis == VISIBILITY_HIDDEN)
1383 fputs ("\t.private_extern ", asm_out_file);
1384 assemble_name (asm_out_file,
1385 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1386 fputs ("\n", asm_out_file);
1389 warning ("internal and protected visibility attributes not supported"
1390 "in this configuration; ignored");
1393 /* Output a difference of two labels that will be an assembly time
1394 constant if the two labels are local. (.long lab1-lab2 will be
1395 very different if lab1 is at the boundary between two sections; it
1396 will be relocated according to the second section, not the first,
1397 so one ends up with a difference between labels in different
1398 sections, which is bad in the dwarf2 eh context for instance.) */
1400 static int darwin_dwarf_label_counter;
1403 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1404 const char *lab1, const char *lab2)
1406 const char *p = lab1 + (lab1[0] == '*');
1407 int islocaldiff = (p[0] == 'L');
1410 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1412 fprintf (file, "\t%s\t", ".long");
1413 assemble_name (file, lab1);
1414 fprintf (file, "-");
1415 assemble_name (file, lab2);
1417 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1421 darwin_file_end (void)
1423 machopic_finish (asm_out_file);
1424 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1426 constructor_section ();
1427 destructor_section ();
1428 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1432 #include "gt-darwin.h"