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 *);
50 name_needs_quotes (const char *name)
53 while ((c = *name++) != '\0')
60 * flag_pic = 1 ... generate only indirections
61 * flag_pic = 2 ... generate indirections and pure code
64 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
65 reference, which will not be changed. */
67 static GTY(()) tree machopic_defined_list;
69 enum machopic_addr_class
70 machopic_classify_ident (tree ident)
72 const char *name = IDENTIFIER_POINTER (ident);
73 int lprefix = (((name[0] == '*' || name[0] == '&')
74 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
83 /* The PIC base symbol is always defined. */
84 if (! strcmp (name, "<pic base>"))
85 return MACHOPIC_DEFINED_DATA;
89 /* Here if no special encoding to be found. */
92 const char *name = IDENTIFIER_POINTER (ident);
93 int len = strlen (name);
95 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
96 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
97 return MACHOPIC_DEFINED_FUNCTION;
98 return MACHOPIC_DEFINED_DATA;
101 for (temp = machopic_defined_list;
103 temp = TREE_CHAIN (temp))
105 if (ident == TREE_VALUE (temp))
106 return MACHOPIC_DEFINED_DATA;
109 if (TREE_ASM_WRITTEN (ident))
110 return MACHOPIC_DEFINED_DATA;
112 return MACHOPIC_UNDEFINED;
115 else if (name[1] == 'D')
116 return MACHOPIC_DEFINED_DATA;
118 else if (name[1] == 'T')
119 return MACHOPIC_DEFINED_FUNCTION;
121 /* It is possible that someone is holding a "stale" name, which has
122 since been defined. See if there is a "defined" name (i.e,
123 different from NAME only in having a '!D_' or a '!T_' instead of
124 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
125 that this identifier is defined. */
126 else if (name[1] == 'd' || name[1] == 't')
129 new_name = (char *)alloca (strlen (name) + 1);
130 strcpy (new_name, name);
131 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
132 if (maybe_get_identifier (new_name) != NULL)
133 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
134 : MACHOPIC_DEFINED_FUNCTION;
137 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
139 if (ident == TREE_VALUE (temp))
142 return MACHOPIC_DEFINED_FUNCTION;
144 return MACHOPIC_DEFINED_DATA;
148 if (name[1] == 't' || name[1] == 'T')
151 return MACHOPIC_DEFINED_FUNCTION;
153 return MACHOPIC_UNDEFINED_FUNCTION;
158 return MACHOPIC_DEFINED_DATA;
160 return MACHOPIC_UNDEFINED_DATA;
165 enum machopic_addr_class
166 machopic_classify_name (const char *name)
168 return machopic_classify_ident (get_identifier (name));
172 machopic_ident_defined_p (tree ident)
174 switch (machopic_classify_ident (ident))
176 case MACHOPIC_UNDEFINED:
177 case MACHOPIC_UNDEFINED_DATA:
178 case MACHOPIC_UNDEFINED_FUNCTION:
186 machopic_data_defined_p (const char *name)
188 switch (machopic_classify_ident (get_identifier (name)))
190 case MACHOPIC_DEFINED_DATA:
198 machopic_name_defined_p (const char *name)
200 return machopic_ident_defined_p (get_identifier (name));
204 machopic_define_ident (tree ident)
206 if (!machopic_ident_defined_p (ident))
207 machopic_defined_list =
208 tree_cons (NULL_TREE, ident, machopic_defined_list);
212 machopic_define_name (const char *name)
214 machopic_define_ident (get_identifier (name));
217 static GTY(()) char * function_base;
220 machopic_function_base_name (void)
222 const char *current_name;
223 /* if dynamic-no-pic is on, we should not get here */
224 if (MACHO_DYNAMIC_NO_PIC_P)
227 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
229 if (function_base == NULL)
231 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
233 current_function_uses_pic_offset_table = 1;
235 return function_base;
238 static GTY(()) const char * function_base_func_name;
239 static GTY(()) int current_pic_label_num;
242 machopic_output_function_base_name (FILE *file)
244 const char *current_name;
246 /* If dynamic-no-pic is on, we should not get here. */
247 if (MACHO_DYNAMIC_NO_PIC_P)
250 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
251 if (function_base_func_name != current_name)
253 ++current_pic_label_num;
254 function_base_func_name = current_name;
256 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
259 static GTY(()) tree machopic_non_lazy_pointers;
261 /* Return a non-lazy pointer name corresponding to the given name,
262 either by finding it in our list of pointer names, or by generating
266 machopic_non_lazy_ptr_name (const char *name)
268 const char *temp_name;
269 tree temp, ident = get_identifier (name);
271 for (temp = machopic_non_lazy_pointers;
273 temp = TREE_CHAIN (temp))
275 if (ident == TREE_VALUE (temp))
276 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279 name = darwin_strip_name_encoding (name);
281 /* Try again, but comparing names this time. */
282 for (temp = machopic_non_lazy_pointers;
284 temp = TREE_CHAIN (temp))
286 if (TREE_VALUE (temp))
288 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
289 temp_name = darwin_strip_name_encoding (temp_name);
290 if (strcmp (name, temp_name) == 0)
291 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
297 int namelen = strlen (name);
301 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
303 strcpy (buffer, "&L");
307 memcpy (buffer + bufferlen +1, name+1, namelen-1+1);
308 bufferlen += namelen-1;
312 buffer[bufferlen] = '_';
313 memcpy (buffer + bufferlen+1 +1, name, namelen+1);
314 bufferlen += namelen;
317 memcpy (buffer + bufferlen +1, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
318 bufferlen += strlen("$non_lazy_ptr");
319 ptr_name = get_identifier (buffer);
321 machopic_non_lazy_pointers
322 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
324 TREE_USED (machopic_non_lazy_pointers) = 0;
326 return IDENTIFIER_POINTER (ptr_name);
330 static GTY(()) tree machopic_stubs;
332 /* Return the name of the stub corresponding to the given name,
333 generating a new stub name if necessary. */
336 machopic_stub_name (const char *name)
338 tree temp, ident = get_identifier (name);
341 for (temp = machopic_stubs;
343 temp = TREE_CHAIN (temp))
345 if (ident == TREE_VALUE (temp))
346 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
347 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
348 if (strcmp (name, tname) == 0)
349 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
350 /* A library call name might not be section-encoded yet, so try
351 it against a stripped name. */
354 && strcmp (name, tname + 4) == 0)
355 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
358 name = darwin_strip_name_encoding (name);
363 int namelen = strlen (name);
365 int needs_quotes = name_needs_quotes (name);
367 buffer = alloca (namelen + 20);
371 strcpy (buffer, "&\"L");
372 bufferlen = strlen("&\"L");
376 strcpy (buffer, "&L");
377 bufferlen = strlen("&L");
382 memcpy (buffer + bufferlen +1, name+1, namelen - 1 +1);
383 bufferlen += namelen - 1;
387 buffer[bufferlen] = '_';
388 memcpy (buffer + bufferlen+1 +1, name, namelen+1);
389 bufferlen += namelen;
394 memcpy (buffer + bufferlen +1, "$stub\"", strlen("$stub\""));
395 bufferlen += strlen("$stub\"");
399 memcpy (buffer + bufferlen +1, "$stub", strlen("$stub"));
400 bufferlen += strlen("$stub");
402 ptr_name = get_identifier (buffer);
404 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
405 TREE_USED (machopic_stubs) = 0;
407 return IDENTIFIER_POINTER (ptr_name);
412 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
414 const char *real_name;
415 tree temp, ident = get_identifier (name), id2;
417 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
419 temp = TREE_CHAIN (temp))
420 if (ident == TREE_PURPOSE (temp))
422 /* Mark both the stub or non-lazy pointer as well as the
423 original symbol as being referenced. */
424 TREE_USED (temp) = 1;
425 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
426 mark_referenced (TREE_VALUE (temp));
427 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
428 real_name = darwin_strip_name_encoding (real_name);
429 id2 = maybe_get_identifier (real_name);
431 mark_referenced (id2);
435 /* Transform ORIG, which may be any data source, to the corresponding
436 source using indirections. */
439 machopic_indirect_data_reference (rtx orig, rtx reg)
443 if (! MACHOPIC_INDIRECT)
446 if (GET_CODE (orig) == SYMBOL_REF)
448 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 = reg;
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,
494 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
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,
669 XEXP (orig, 0), pic_base));
670 #if defined (TARGET_TOC) /* i.e., PowerPC */
671 /* Generating a new reg may expose opportunities for
672 common subexpression elimination. */
674 (reload_in_progress ? reg : gen_reg_rtx (SImode));
676 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
677 gen_rtx (PLUS, Pmode,
678 pic_offset_table_rtx,
679 gen_rtx (HIGH, Pmode, offset))));
680 emit_insn (gen_rtx (SET, VOIDmode, reg,
681 gen_rtx (MEM, GET_MODE (orig),
682 gen_rtx (LO_SUM, Pmode,
683 hi_sum_reg, offset))));
687 emit_insn (gen_rtx (USE, VOIDmode,
688 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
690 emit_insn (gen_rtx (SET, VOIDmode, reg,
691 gen_rtx (HIGH, Pmode,
692 gen_rtx (CONST, Pmode, offset))));
693 emit_insn (gen_rtx (SET, VOIDmode, reg,
694 gen_rtx (LO_SUM, Pmode, reg,
695 gen_rtx (CONST, Pmode, offset))));
696 pic_ref = gen_rtx (PLUS, Pmode,
697 pic_offset_table_rtx, reg);
701 #endif /* HAVE_lo_sum */
703 rtx pic = pic_offset_table_rtx;
704 if (GET_CODE (pic) != REG)
706 emit_move_insn (reg, pic);
710 emit_insn (gen_rtx (USE, VOIDmode,
711 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
714 pic_ref = gen_rtx (PLUS, Pmode,
716 gen_rtx (CONST, Pmode,
717 gen_rtx (MINUS, Pmode,
722 #if !defined (TARGET_TOC)
723 emit_move_insn (reg, pic_ref);
724 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
726 RTX_UNCHANGING_P (pic_ref) = 1;
732 if (GET_CODE (orig) == SYMBOL_REF
733 || GET_CODE (orig) == LABEL_REF)
735 rtx offset = gen_rtx (CONST, Pmode,
736 gen_rtx (MINUS, Pmode, orig, pic_base));
737 #if defined (TARGET_TOC) /* i.e., PowerPC */
742 if (reload_in_progress)
745 reg = gen_reg_rtx (SImode);
750 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
751 (MACHO_DYNAMIC_NO_PIC_P)
752 ? gen_rtx (HIGH, Pmode, offset)
753 : gen_rtx (PLUS, Pmode,
754 pic_offset_table_rtx,
755 gen_rtx (HIGH, Pmode, offset))));
756 emit_insn (gen_rtx (SET, VOIDmode, reg,
757 gen_rtx (LO_SUM, Pmode,
758 hi_sum_reg, offset)));
760 RTX_UNCHANGING_P (pic_ref) = 1;
762 emit_insn (gen_rtx (SET, VOIDmode, reg,
763 gen_rtx (HIGH, Pmode, offset)));
764 emit_insn (gen_rtx (SET, VOIDmode, reg,
765 gen_rtx (LO_SUM, Pmode, reg, offset)));
766 pic_ref = gen_rtx (PLUS, Pmode,
767 pic_offset_table_rtx, reg);
768 RTX_UNCHANGING_P (pic_ref) = 1;
772 #endif /* HAVE_lo_sum */
774 if (GET_CODE (orig) == REG)
780 rtx pic = pic_offset_table_rtx;
781 if (GET_CODE (pic) != REG)
783 emit_move_insn (reg, pic);
787 emit_insn (gen_rtx (USE, VOIDmode,
788 pic_offset_table_rtx));
790 pic_ref = gen_rtx (PLUS, Pmode,
792 gen_rtx (CONST, Pmode,
793 gen_rtx (MINUS, Pmode,
799 if (GET_CODE (pic_ref) != REG)
803 emit_move_insn (reg, pic_ref);
808 return force_reg (mode, pic_ref);
817 else if (GET_CODE (orig) == SYMBOL_REF)
820 else if (GET_CODE (orig) == PLUS
821 && (GET_CODE (XEXP (orig, 0)) == MEM
822 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
823 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
824 && XEXP (orig, 0) != pic_offset_table_rtx
825 && GET_CODE (XEXP (orig, 1)) != REG)
829 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
831 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
832 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
833 Pmode, (base == reg ? 0 : reg));
834 if (GET_CODE (orig) == CONST_INT)
836 pic_ref = plus_constant (base, INTVAL (orig));
840 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
842 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
843 RTX_UNCHANGING_P (pic_ref) = 1;
845 if (reg && is_complex)
847 emit_move_insn (reg, pic_ref);
850 /* Likewise, should we set special REG_NOTEs here? */
853 else if (GET_CODE (orig) == CONST)
855 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
858 else if (GET_CODE (orig) == MEM
859 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
861 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
863 addr = gen_rtx (MEM, GET_MODE (orig), addr);
864 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
865 emit_move_insn (reg, addr);
874 machopic_finish (FILE *asm_out_file)
878 for (temp = machopic_stubs;
880 temp = TREE_CHAIN (temp))
882 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
883 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
887 if (! TREE_USED (temp))
890 /* If the symbol is actually defined, we don't need a stub. */
891 if (sym_name[0] == '!' && sym_name[1] == 'T')
894 sym_name = darwin_strip_name_encoding (sym_name);
896 sym = alloca (strlen (sym_name) + 2);
897 if (sym_name[0] == '*' || sym_name[0] == '&')
898 strcpy (sym, sym_name + 1);
899 else if (sym_name[0] == '-' || sym_name[0] == '+')
900 strcpy (sym, sym_name);
902 sym[0] = '_', strcpy (sym + 1, sym_name);
904 stub = alloca (strlen (stub_name) + 2);
905 if (stub_name[0] == '*' || stub_name[0] == '&')
906 strcpy (stub, stub_name + 1);
908 stub[0] = '_', strcpy (stub + 1, stub_name);
910 machopic_output_stub (asm_out_file, sym, stub);
913 for (temp = machopic_non_lazy_pointers;
915 temp = TREE_CHAIN (temp))
917 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
918 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
920 if (! TREE_USED (temp))
923 if (machopic_ident_defined_p (TREE_VALUE (temp)))
926 assemble_align (GET_MODE_ALIGNMENT (Pmode));
927 assemble_label (lazy_name);
928 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
929 GET_MODE_SIZE (Pmode),
930 GET_MODE_ALIGNMENT (Pmode), 1);
934 machopic_nl_symbol_ptr_section ();
935 assemble_name (asm_out_file, lazy_name);
936 fprintf (asm_out_file, ":\n");
938 fprintf (asm_out_file, "\t.indirect_symbol ");
939 assemble_name (asm_out_file, sym_name);
940 fprintf (asm_out_file, "\n");
942 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
943 GET_MODE_ALIGNMENT (Pmode), 1);
949 machopic_operand_p (rtx op)
951 if (MACHOPIC_JUST_INDIRECT)
953 while (GET_CODE (op) == CONST)
956 if (GET_CODE (op) == SYMBOL_REF)
957 return machopic_name_defined_p (XSTR (op, 0));
962 while (GET_CODE (op) == CONST)
965 if (GET_CODE (op) == MINUS
966 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
967 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
968 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
969 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
975 /* This function records whether a given name corresponds to a defined
976 or undefined function or variable, for machopic_classify_ident to
980 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
985 const char *orig_str;
989 /* Do the standard encoding things first. */
990 default_encode_section_info (decl, rtl, first);
992 /* With the introduction of symbol_ref flags, some of the following
993 code has become redundant and should be removed at some point. */
995 if ((TREE_CODE (decl) == FUNCTION_DECL
996 || TREE_CODE (decl) == VAR_DECL)
997 && !DECL_EXTERNAL (decl)
998 && ((TREE_STATIC (decl)
999 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1000 || (DECL_INITIAL (decl)
1001 && DECL_INITIAL (decl) != error_mark_node)))
1004 if (TREE_CODE (decl) == FUNCTION_DECL)
1005 code = (defined ? 'T' : 't');
1006 else if (TREE_CODE (decl) == VAR_DECL)
1007 code = (defined ? 'D' : 'd');
1012 sym_ref = XEXP (rtl, 0);
1013 orig_str = XSTR (sym_ref, 0);
1014 len = strlen (orig_str) + 1;
1016 if (orig_str[0] == '!')
1018 /* Already encoded; see if we need to change it. */
1019 if (code == orig_str[1])
1021 /* Yes, tweak a copy of the name and put it in a new string. */
1022 new_str = alloca (len);
1023 memcpy (new_str, orig_str, len);
1025 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1029 /* Add the encoding. */
1031 new_str = alloca (new_len);
1036 memcpy (new_str + 4, orig_str, len);
1037 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1039 /* The non-lazy pointer list may have captured references to the
1040 old encoded name, change them. */
1041 if (TREE_CODE (decl) == VAR_DECL)
1042 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1044 update_stubs (XSTR (sym_ref, 0));
1047 /* Undo the effects of the above. */
1050 darwin_strip_name_encoding (const char *str)
1052 return str[0] == '!' ? str + 4 : str;
1055 /* Scan the list of non-lazy pointers and update any recorded names whose
1056 stripped name matches the argument. */
1059 update_non_lazy_ptrs (const char *name)
1061 const char *name1, *name2;
1064 name1 = darwin_strip_name_encoding (name);
1066 for (temp = machopic_non_lazy_pointers;
1068 temp = TREE_CHAIN (temp))
1070 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1072 if (*sym_name == '!')
1074 name2 = darwin_strip_name_encoding (sym_name);
1075 if (strcmp (name1, name2) == 0)
1077 /* FIXME: This breaks the identifier hash table. */
1078 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1079 = (unsigned char *) name;
1086 /* Function NAME is being defined, and its label has just been output.
1087 If there's already a reference to a stub for this function, we can
1088 just emit the stub label now and we don't bother emitting the stub later. */
1091 machopic_output_possible_stub_label (FILE *file, const char *name)
1096 /* Ensure we're looking at a section-encoded name. */
1097 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1100 for (temp = machopic_stubs;
1102 temp = TREE_CHAIN (temp))
1104 const char *sym_name;
1106 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1107 if (sym_name[0] == '!' && sym_name[1] == 'T'
1108 && ! strcmp (name+2, sym_name+2))
1110 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1111 /* Avoid generating a stub for this. */
1112 TREE_USED (temp) = 0;
1118 /* Scan the list of stubs and update any recorded names whose
1119 stripped name matches the argument. */
1122 update_stubs (const char *name)
1124 const char *name1, *name2;
1127 name1 = darwin_strip_name_encoding (name);
1129 for (temp = machopic_stubs;
1131 temp = TREE_CHAIN (temp))
1133 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1135 if (*sym_name == '!')
1137 name2 = darwin_strip_name_encoding (sym_name);
1138 if (strcmp (name1, name2) == 0)
1140 /* FIXME: This breaks the identifier hash table. */
1141 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1142 = (unsigned char *) name;
1150 machopic_select_section (tree exp, int reloc,
1151 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1153 void (*base_function)(void);
1155 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1156 base_function = readonly_data_section;
1157 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1158 base_function = const_data_section;
1160 base_function = data_section;
1162 if (TREE_CODE (exp) == STRING_CST
1163 && ((size_t) TREE_STRING_LENGTH (exp)
1164 == strlen (TREE_STRING_POINTER (exp)) + 1)
1165 && ! flag_writable_strings)
1167 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1168 && flag_merge_constants)
1170 tree size = TYPE_SIZE (TREE_TYPE (exp));
1172 if (TREE_CODE (size) == INTEGER_CST &&
1173 TREE_INT_CST_LOW (size) == 4 &&
1174 TREE_INT_CST_HIGH (size) == 0)
1175 literal4_section ();
1176 else if (TREE_CODE (size) == INTEGER_CST &&
1177 TREE_INT_CST_LOW (size) == 8 &&
1178 TREE_INT_CST_HIGH (size) == 0)
1179 literal8_section ();
1183 else if (TREE_CODE (exp) == CONSTRUCTOR
1185 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1186 && TYPE_NAME (TREE_TYPE (exp)))
1188 tree name = TYPE_NAME (TREE_TYPE (exp));
1189 if (TREE_CODE (name) == TYPE_DECL)
1190 name = DECL_NAME (name);
1191 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1192 objc_constant_string_object_section ();
1193 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1194 objc_string_object_section ();
1198 else if (TREE_CODE (exp) == VAR_DECL &&
1200 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1201 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1202 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1204 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1206 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1207 objc_cls_meth_section ();
1208 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1209 objc_inst_meth_section ();
1210 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1211 objc_cat_cls_meth_section ();
1212 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1213 objc_cat_inst_meth_section ();
1214 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1215 objc_class_vars_section ();
1216 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1217 objc_instance_vars_section ();
1218 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1219 objc_cat_cls_meth_section ();
1220 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1221 objc_class_names_section ();
1222 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1223 objc_meth_var_names_section ();
1224 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1225 objc_meth_var_types_section ();
1226 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1227 objc_cls_refs_section ();
1228 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1229 objc_class_section ();
1230 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1231 objc_meta_class_section ();
1232 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1233 objc_category_section ();
1234 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1235 objc_selector_refs_section ();
1236 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1237 objc_selector_fixup_section ();
1238 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1239 objc_symbols_section ();
1240 else if (!strncmp (name, "_OBJC_MODULES", 13))
1241 objc_module_info_section ();
1242 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1243 objc_image_info_section ();
1244 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1245 objc_cat_inst_meth_section ();
1246 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1247 objc_cat_cls_meth_section ();
1248 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1249 objc_cat_cls_meth_section ();
1250 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1251 objc_protocol_section ();
1259 /* This can be called with address expressions as "rtx".
1260 They must go in "const". */
1263 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1264 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1266 if (GET_MODE_SIZE (mode) == 8)
1267 literal8_section ();
1268 else if (GET_MODE_SIZE (mode) == 4
1269 && (GET_CODE (x) == CONST_INT
1270 || GET_CODE (x) == CONST_DOUBLE))
1271 literal4_section ();
1272 else if (MACHOPIC_INDIRECT
1273 && (GET_CODE (x) == SYMBOL_REF
1274 || GET_CODE (x) == CONST
1275 || GET_CODE (x) == LABEL_REF))
1276 const_data_section ();
1282 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1285 if (MACHOPIC_INDIRECT)
1286 mod_init_section ();
1288 constructor_section ();
1289 assemble_align (POINTER_SIZE);
1290 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1293 if (! MACHOPIC_INDIRECT)
1294 fprintf (asm_out_file, ".reference .constructors_used\n");
1298 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1301 if (MACHOPIC_INDIRECT)
1302 mod_term_section ();
1304 destructor_section ();
1305 assemble_align (POINTER_SIZE);
1306 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1308 if (! MACHOPIC_INDIRECT)
1309 fprintf (asm_out_file, ".reference .destructors_used\n");
1313 darwin_globalize_label (FILE *stream, const char *name)
1315 if (!!strncmp (name, "_OBJC_", 6))
1316 default_globalize_label (stream, name);
1319 /* Output a difference of two labels that will be an assembly time
1320 constant if the two labels are local. (.long lab1-lab2 will be
1321 very different if lab1 is at the boundary between two sections; it
1322 will be relocated according to the second section, not the first,
1323 so one ends up with a difference between labels in different
1324 sections, which is bad in the dwarf2 eh context for instance.) */
1326 static int darwin_dwarf_label_counter;
1329 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1330 const char *lab1, const char *lab2)
1332 const char *p = lab1 + (lab1[0] == '*');
1333 int islocaldiff = (p[0] == 'L');
1336 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1338 fprintf (file, "\t%s\t", ".long");
1339 assemble_name (file, lab1);
1340 fprintf (file, "-");
1341 assemble_name (file, lab2);
1343 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1347 darwin_file_end (void)
1349 machopic_finish (asm_out_file);
1350 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1352 constructor_section ();
1353 destructor_section ();
1354 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1358 #include "gt-darwin.h"