1 /* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Apple Computer Inc.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
40 #include "langhooks.h"
43 static int machopic_data_defined_p
PARAMS ((const char *));
44 static void update_non_lazy_ptrs
PARAMS ((const char *));
45 static void update_stubs
PARAMS ((const char *));
48 name_needs_quotes (name
)
52 while ((c
= *name
++) != '\0')
59 * flag_pic = 1 ... generate only indirections
60 * flag_pic = 2 ... generate indirections and pure code
63 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
64 reference, which will not be changed. */
66 static GTY(()) tree machopic_defined_list
;
68 enum machopic_addr_class
69 machopic_classify_ident (ident
)
72 const char *name
= IDENTIFIER_POINTER (ident
);
73 int lprefix
= (((name
[0] == '*' || name
[0] == '&')
74 && (name
[1] == 'L' || (name
[1] == '"' && name
[2] == 'L')))
85 /* Here if no special encoding to be found. */
88 const char *name
= IDENTIFIER_POINTER (ident
);
89 int len
= strlen (name
);
91 if ((len
> 5 && !strcmp (name
+ len
- 5, "$stub"))
92 || (len
> 6 && !strcmp (name
+ len
- 6, "$stub\"")))
93 return MACHOPIC_DEFINED_FUNCTION
;
94 return MACHOPIC_DEFINED_DATA
;
97 for (temp
= machopic_defined_list
;
99 temp
= TREE_CHAIN (temp
))
101 if (ident
== TREE_VALUE (temp
))
102 return MACHOPIC_DEFINED_DATA
;
105 if (TREE_ASM_WRITTEN (ident
))
106 return MACHOPIC_DEFINED_DATA
;
108 return MACHOPIC_UNDEFINED
;
111 else if (name
[1] == 'D')
112 return MACHOPIC_DEFINED_DATA
;
114 else if (name
[1] == 'T')
115 return MACHOPIC_DEFINED_FUNCTION
;
117 /* It is possible that someone is holding a "stale" name, which has
118 since been defined. See if there is a "defined" name (i.e,
119 different from NAME only in having a '!D_' or a '!T_' instead of
120 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
121 that this identifier is defined. */
122 else if (name
[1] == 'd' || name
[1] == 't')
125 new_name
= (char *)alloca (strlen (name
) + 1);
126 strcpy (new_name
, name
);
127 new_name
[1] = (name
[1] == 'd') ? 'D' : 'T';
128 if (maybe_get_identifier (new_name
) != NULL
)
129 return (name
[1] == 'd') ? MACHOPIC_DEFINED_DATA
130 : MACHOPIC_DEFINED_FUNCTION
;
133 for (temp
= machopic_defined_list
; temp
!= NULL_TREE
; temp
= TREE_CHAIN (temp
))
135 if (ident
== TREE_VALUE (temp
))
138 return MACHOPIC_DEFINED_FUNCTION
;
140 return MACHOPIC_DEFINED_DATA
;
144 if (name
[1] == 't' || name
[1] == 'T')
147 return MACHOPIC_DEFINED_FUNCTION
;
149 return MACHOPIC_UNDEFINED_FUNCTION
;
154 return MACHOPIC_DEFINED_DATA
;
156 return MACHOPIC_UNDEFINED_DATA
;
161 enum machopic_addr_class
162 machopic_classify_name (name
)
165 return machopic_classify_ident (get_identifier (name
));
169 machopic_ident_defined_p (ident
)
172 switch (machopic_classify_ident (ident
))
174 case MACHOPIC_UNDEFINED
:
175 case MACHOPIC_UNDEFINED_DATA
:
176 case MACHOPIC_UNDEFINED_FUNCTION
:
184 machopic_data_defined_p (name
)
187 switch (machopic_classify_ident (get_identifier (name
)))
189 case MACHOPIC_DEFINED_DATA
:
197 machopic_name_defined_p (name
)
200 return machopic_ident_defined_p (get_identifier (name
));
204 machopic_define_ident (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 (name
)
216 machopic_define_ident (get_identifier (name
));
219 /* This is a static to make inline functions work. The rtx
220 representing the PIC base symbol always points to here. */
222 static char function_base
[32];
224 static int current_pic_label_num
;
227 machopic_function_base_name ()
229 static const char *name
= NULL
;
230 static const char *current_name
;
232 current_name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl
));
234 if (name
!= current_name
)
236 current_function_uses_pic_offset_table
= 1;
238 /* Save mucho space and time. Some of the C++ mangled names are over
239 700 characters long! Note that we produce a label containing a '-'
240 if the function we're compiling is an Objective-C method, as evinced
241 by the incredibly scientific test below. This is because code in
242 rs6000.c makes the same ugly test when loading the PIC reg. */
244 ++current_pic_label_num
;
245 if (*current_name
== '+' || *current_name
== '-')
246 sprintf (function_base
, "*\"L-%d$pb\"", current_pic_label_num
);
248 sprintf (function_base
, "*L%d$pb", current_pic_label_num
);
253 return function_base
;
256 static GTY(()) tree machopic_non_lazy_pointers
;
258 /* Return a non-lazy pointer name corresponding to the given name,
259 either by finding it in our list of pointer names, or by generating
263 machopic_non_lazy_ptr_name (name
)
266 const char *temp_name
;
267 tree temp
, ident
= get_identifier (name
);
269 for (temp
= machopic_non_lazy_pointers
;
271 temp
= TREE_CHAIN (temp
))
273 if (ident
== TREE_VALUE (temp
))
274 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
277 name
= darwin_strip_name_encoding (name
);
279 /* Try again, but comparing names this time. */
280 for (temp
= machopic_non_lazy_pointers
;
282 temp
= TREE_CHAIN (temp
))
284 if (TREE_VALUE (temp
))
286 temp_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
287 temp_name
= darwin_strip_name_encoding (temp_name
);
288 if (strcmp (name
, temp_name
) == 0)
289 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
297 buffer
= alloca (strlen (name
) + 20);
299 strcpy (buffer
, "&L");
301 strcat (buffer
, name
+1);
304 strcat (buffer
, "_");
305 strcat (buffer
, name
);
308 strcat (buffer
, "$non_lazy_ptr");
309 ptr_name
= get_identifier (buffer
);
311 machopic_non_lazy_pointers
312 = tree_cons (ptr_name
, ident
, machopic_non_lazy_pointers
);
314 TREE_USED (machopic_non_lazy_pointers
) = 0;
316 return IDENTIFIER_POINTER (ptr_name
);
320 static GTY(()) tree machopic_stubs
;
322 /* Return the name of the stub corresponding to the given name,
323 generating a new stub name if necessary. */
326 machopic_stub_name (name
)
329 tree temp
, ident
= get_identifier (name
);
332 for (temp
= machopic_stubs
;
334 temp
= TREE_CHAIN (temp
))
336 if (ident
== TREE_VALUE (temp
))
337 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
338 tname
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
339 if (strcmp (name
, tname
) == 0)
340 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
341 /* A library call name might not be section-encoded yet, so try
342 it against a stripped name. */
345 && strcmp (name
, tname
+ 4) == 0)
346 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
349 name
= darwin_strip_name_encoding (name
);
354 int needs_quotes
= name_needs_quotes (name
);
356 buffer
= alloca (strlen (name
) + 20);
359 strcpy (buffer
, "&\"L");
361 strcpy (buffer
, "&L");
364 strcat (buffer
, name
+1);
368 strcat (buffer
, "_");
369 strcat (buffer
, name
);
373 strcat (buffer
, "$stub\"");
375 strcat (buffer
, "$stub");
376 ptr_name
= get_identifier (buffer
);
378 machopic_stubs
= tree_cons (ptr_name
, ident
, machopic_stubs
);
379 TREE_USED (machopic_stubs
) = 0;
381 return IDENTIFIER_POINTER (ptr_name
);
386 machopic_validate_stub_or_non_lazy_ptr (name
, validate_stub
)
390 const char *real_name
;
391 tree temp
, ident
= get_identifier (name
), id2
;
393 for (temp
= (validate_stub
? machopic_stubs
: machopic_non_lazy_pointers
);
395 temp
= TREE_CHAIN (temp
))
396 if (ident
== TREE_PURPOSE (temp
))
398 /* Mark both the stub or non-lazy pointer as well as the
399 original symbol as being referenced. */
400 TREE_USED (temp
) = 1;
401 if (TREE_CODE (TREE_VALUE (temp
)) == IDENTIFIER_NODE
)
402 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp
)) = 1;
403 real_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
404 real_name
= darwin_strip_name_encoding (real_name
);
405 id2
= maybe_get_identifier (real_name
);
407 TREE_SYMBOL_REFERENCED (id2
) = 1;
411 /* Transform ORIG, which may be any data source, to the corresponding
412 source using indirections. */
415 machopic_indirect_data_reference (orig
, reg
)
420 if (! MACHOPIC_INDIRECT
)
423 if (GET_CODE (orig
) == SYMBOL_REF
)
425 const char *name
= XSTR (orig
, 0);
427 if (machopic_data_defined_p (name
))
429 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
430 rtx pic_base
= gen_rtx (SYMBOL_REF
, Pmode
,
431 machopic_function_base_name ());
432 rtx offset
= gen_rtx (CONST
, Pmode
,
433 gen_rtx (MINUS
, Pmode
, orig
, pic_base
));
436 #if defined (TARGET_TOC) /* i.e., PowerPC */
437 rtx hi_sum_reg
= reg
;
442 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
443 gen_rtx (PLUS
, Pmode
, pic_offset_table_rtx
,
444 gen_rtx (HIGH
, Pmode
, offset
))));
445 emit_insn (gen_rtx (SET
, Pmode
, reg
,
446 gen_rtx (LO_SUM
, Pmode
, hi_sum_reg
, offset
)));
450 #if defined (HAVE_lo_sum)
451 if (reg
== 0) abort ();
453 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
454 gen_rtx (HIGH
, Pmode
, offset
)));
455 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
456 gen_rtx (LO_SUM
, Pmode
, reg
, offset
)));
457 emit_insn (gen_rtx (USE
, VOIDmode
,
458 gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
460 orig
= gen_rtx (PLUS
, Pmode
, pic_offset_table_rtx
, reg
);
466 ptr_ref
= gen_rtx (SYMBOL_REF
, Pmode
,
467 machopic_non_lazy_ptr_name (name
));
469 ptr_ref
= gen_rtx_MEM (Pmode
, ptr_ref
);
470 RTX_UNCHANGING_P (ptr_ref
) = 1;
474 else if (GET_CODE (orig
) == CONST
)
478 /* legitimize both operands of the PLUS */
479 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
481 base
= machopic_indirect_data_reference (XEXP (XEXP (orig
, 0), 0),
483 orig
= machopic_indirect_data_reference (XEXP (XEXP (orig
, 0), 1),
484 (base
== reg
? 0 : reg
));
489 if (MACHOPIC_PURE
&& GET_CODE (orig
) == CONST_INT
)
490 result
= plus_constant (base
, INTVAL (orig
));
492 result
= gen_rtx (PLUS
, Pmode
, base
, orig
);
494 if (MACHOPIC_JUST_INDIRECT
&& GET_CODE (base
) == MEM
)
498 emit_move_insn (reg
, result
);
503 result
= force_reg (GET_MODE (result
), result
);
510 else if (GET_CODE (orig
) == MEM
)
511 XEXP (ptr_ref
, 0) = machopic_indirect_data_reference (XEXP (orig
, 0), reg
);
512 /* When the target is i386, this code prevents crashes due to the
513 compiler's ignorance on how to move the PIC base register to
514 other registers. (The reload phase sometimes introduces such
516 else if (GET_CODE (orig
) == PLUS
517 && GET_CODE (XEXP (orig
, 0)) == REG
518 && REGNO (XEXP (orig
, 0)) == PIC_OFFSET_TABLE_REGNUM
520 /* Prevent the same register from being erroneously used
521 as both the base and index registers. */
522 && GET_CODE (XEXP (orig
, 1)) == CONST
526 emit_move_insn (reg
, XEXP (orig
, 0));
527 XEXP (ptr_ref
, 0) = reg
;
532 /* Transform TARGET (a MEM), which is a function call target, to the
533 corresponding symbol_stub if necessary. Return a new MEM. */
536 machopic_indirect_call_target (target
)
539 if (GET_CODE (target
) != MEM
)
542 if (MACHOPIC_INDIRECT
&& GET_CODE (XEXP (target
, 0)) == SYMBOL_REF
)
544 enum machine_mode mode
= GET_MODE (XEXP (target
, 0));
545 const char *name
= XSTR (XEXP (target
, 0), 0);
547 /* If the name is already defined, we need do nothing. */
548 if (name
[0] == '!' && name
[1] == 'T')
551 if (!machopic_name_defined_p (name
))
553 const char *stub_name
= machopic_stub_name (name
);
555 XEXP (target
, 0) = gen_rtx (SYMBOL_REF
, mode
, stub_name
);
556 RTX_UNCHANGING_P (target
) = 1;
564 machopic_legitimize_pic_address (orig
, mode
, reg
)
566 enum machine_mode mode
;
573 /* First handle a simple SYMBOL_REF or LABEL_REF */
574 if (GET_CODE (orig
) == LABEL_REF
575 || (GET_CODE (orig
) == SYMBOL_REF
578 /* addr(foo) = &func+(foo-func) */
581 orig
= machopic_indirect_data_reference (orig
, reg
);
583 if (GET_CODE (orig
) == PLUS
584 && GET_CODE (XEXP (orig
, 0)) == REG
)
587 return force_reg (mode
, orig
);
589 emit_move_insn (reg
, orig
);
593 pic_base
= gen_rtx (SYMBOL_REF
, Pmode
, machopic_function_base_name ());
595 if (GET_CODE (orig
) == MEM
)
599 if (reload_in_progress
)
602 reg
= gen_reg_rtx (Pmode
);
606 if (GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
607 || GET_CODE (XEXP (orig
, 0)) == LABEL_REF
)
609 rtx offset
= gen_rtx (CONST
, Pmode
,
610 gen_rtx (MINUS
, Pmode
,
611 XEXP (orig
, 0), pic_base
));
612 #if defined (TARGET_TOC) /* i.e., PowerPC */
613 /* Generating a new reg may expose opportunities for
614 common subexpression elimination. */
616 (reload_in_progress
? reg
: gen_reg_rtx (SImode
));
618 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
619 gen_rtx (PLUS
, Pmode
,
620 pic_offset_table_rtx
,
621 gen_rtx (HIGH
, Pmode
, offset
))));
622 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
623 gen_rtx (MEM
, GET_MODE (orig
),
624 gen_rtx (LO_SUM
, Pmode
,
625 hi_sum_reg
, offset
))));
629 emit_insn (gen_rtx (USE
, VOIDmode
,
630 gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
632 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
633 gen_rtx (HIGH
, Pmode
,
634 gen_rtx (CONST
, Pmode
, offset
))));
635 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
636 gen_rtx (LO_SUM
, Pmode
, reg
,
637 gen_rtx (CONST
, Pmode
, offset
))));
638 pic_ref
= gen_rtx (PLUS
, Pmode
,
639 pic_offset_table_rtx
, reg
);
643 #endif /* HAVE_lo_sum */
645 rtx pic
= pic_offset_table_rtx
;
646 if (GET_CODE (pic
) != REG
)
648 emit_move_insn (reg
, pic
);
652 emit_insn (gen_rtx (USE
, VOIDmode
,
653 gen_rtx (REG
, Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
656 pic_ref
= gen_rtx (PLUS
, Pmode
,
658 gen_rtx (CONST
, Pmode
,
659 gen_rtx (MINUS
, Pmode
,
664 #if !defined (TARGET_TOC)
665 emit_move_insn (reg
, pic_ref
);
666 pic_ref
= gen_rtx (MEM
, GET_MODE (orig
), reg
);
668 RTX_UNCHANGING_P (pic_ref
) = 1;
674 if (GET_CODE (orig
) == SYMBOL_REF
675 || GET_CODE (orig
) == LABEL_REF
)
677 rtx offset
= gen_rtx (CONST
, Pmode
,
678 gen_rtx (MINUS
, Pmode
, orig
, pic_base
));
679 #if defined (TARGET_TOC) /* i.e., PowerPC */
684 if (reload_in_progress
)
687 reg
= gen_reg_rtx (SImode
);
692 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
693 gen_rtx (PLUS
, Pmode
,
694 pic_offset_table_rtx
,
695 gen_rtx (HIGH
, Pmode
, offset
))));
696 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
697 gen_rtx (LO_SUM
, Pmode
,
698 hi_sum_reg
, offset
)));
700 RTX_UNCHANGING_P (pic_ref
) = 1;
702 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
703 gen_rtx (HIGH
, Pmode
, offset
)));
704 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
705 gen_rtx (LO_SUM
, Pmode
, reg
, offset
)));
706 pic_ref
= gen_rtx (PLUS
, Pmode
,
707 pic_offset_table_rtx
, reg
);
708 RTX_UNCHANGING_P (pic_ref
) = 1;
712 #endif /* HAVE_lo_sum */
714 if (GET_CODE (orig
) == REG
)
720 rtx pic
= pic_offset_table_rtx
;
721 if (GET_CODE (pic
) != REG
)
723 emit_move_insn (reg
, pic
);
727 emit_insn (gen_rtx (USE
, VOIDmode
,
728 pic_offset_table_rtx
));
730 pic_ref
= gen_rtx (PLUS
, Pmode
,
732 gen_rtx (CONST
, Pmode
,
733 gen_rtx (MINUS
, Pmode
,
739 if (GET_CODE (pic_ref
) != REG
)
743 emit_move_insn (reg
, pic_ref
);
748 return force_reg (mode
, pic_ref
);
757 else if (GET_CODE (orig
) == SYMBOL_REF
)
760 else if (GET_CODE (orig
) == PLUS
761 && (GET_CODE (XEXP (orig
, 0)) == MEM
762 || GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
763 || GET_CODE (XEXP (orig
, 0)) == LABEL_REF
)
764 && XEXP (orig
, 0) != pic_offset_table_rtx
765 && GET_CODE (XEXP (orig
, 1)) != REG
)
769 int is_complex
= (GET_CODE (XEXP (orig
, 0)) == MEM
);
771 base
= machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
772 orig
= machopic_legitimize_pic_address (XEXP (orig
, 1),
773 Pmode
, (base
== reg
? 0 : reg
));
774 if (GET_CODE (orig
) == CONST_INT
)
776 pic_ref
= plus_constant (base
, INTVAL (orig
));
780 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
782 if (RTX_UNCHANGING_P (base
) && RTX_UNCHANGING_P (orig
))
783 RTX_UNCHANGING_P (pic_ref
) = 1;
785 if (reg
&& is_complex
)
787 emit_move_insn (reg
, pic_ref
);
790 /* Likewise, should we set special REG_NOTEs here? */
793 else if (GET_CODE (orig
) == CONST
)
795 return machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
798 else if (GET_CODE (orig
) == MEM
799 && GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
)
801 rtx addr
= machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
803 addr
= gen_rtx (MEM
, GET_MODE (orig
), addr
);
804 RTX_UNCHANGING_P (addr
) = RTX_UNCHANGING_P (orig
);
805 emit_move_insn (reg
, addr
);
814 machopic_finish (asm_out_file
)
819 for (temp
= machopic_stubs
;
821 temp
= TREE_CHAIN (temp
))
823 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
824 const char *stub_name
= IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
828 if (! TREE_USED (temp
))
831 /* If the symbol is actually defined, we don't need a stub. */
832 if (sym_name
[0] == '!' && sym_name
[1] == 'T')
835 sym_name
= darwin_strip_name_encoding (sym_name
);
837 sym
= alloca (strlen (sym_name
) + 2);
838 if (sym_name
[0] == '*' || sym_name
[0] == '&')
839 strcpy (sym
, sym_name
+ 1);
840 else if (sym_name
[0] == '-' || sym_name
[0] == '+')
841 strcpy (sym
, sym_name
);
843 sym
[0] = '_', strcpy (sym
+ 1, sym_name
);
845 stub
= alloca (strlen (stub_name
) + 2);
846 if (stub_name
[0] == '*' || stub_name
[0] == '&')
847 strcpy (stub
, stub_name
+ 1);
849 stub
[0] = '_', strcpy (stub
+ 1, stub_name
);
851 machopic_output_stub (asm_out_file
, sym
, stub
);
854 for (temp
= machopic_non_lazy_pointers
;
856 temp
= TREE_CHAIN (temp
))
858 const char *const sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
859 const char *const lazy_name
= IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
861 if (! TREE_USED (temp
))
864 if (machopic_ident_defined_p (TREE_VALUE (temp
)))
867 assemble_align (GET_MODE_ALIGNMENT (Pmode
));
868 assemble_label (lazy_name
);
869 assemble_integer (gen_rtx (SYMBOL_REF
, Pmode
, sym_name
),
870 GET_MODE_SIZE (Pmode
),
871 GET_MODE_ALIGNMENT (Pmode
), 1);
875 machopic_nl_symbol_ptr_section ();
876 assemble_name (asm_out_file
, lazy_name
);
877 fprintf (asm_out_file
, ":\n");
879 fprintf (asm_out_file
, "\t.indirect_symbol ");
880 assemble_name (asm_out_file
, sym_name
);
881 fprintf (asm_out_file
, "\n");
883 assemble_integer (const0_rtx
, GET_MODE_SIZE (Pmode
),
884 GET_MODE_ALIGNMENT (Pmode
), 1);
890 machopic_operand_p (op
)
893 if (MACHOPIC_JUST_INDIRECT
)
895 while (GET_CODE (op
) == CONST
)
898 if (GET_CODE (op
) == SYMBOL_REF
)
899 return machopic_name_defined_p (XSTR (op
, 0));
904 while (GET_CODE (op
) == CONST
)
907 if (GET_CODE (op
) == MINUS
908 && GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
909 && GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
910 && machopic_name_defined_p (XSTR (XEXP (op
, 0), 0))
911 && machopic_name_defined_p (XSTR (XEXP (op
, 1), 0)))
917 /* This function records whether a given name corresponds to a defined
918 or undefined function or variable, for machopic_classify_ident to
922 darwin_encode_section_info (decl
, first
)
924 int first ATTRIBUTE_UNUSED
;
929 const char *orig_str
;
933 if ((TREE_CODE (decl
) == FUNCTION_DECL
934 || TREE_CODE (decl
) == VAR_DECL
)
935 && !DECL_EXTERNAL (decl
)
936 && ((TREE_STATIC (decl
)
937 && (!DECL_COMMON (decl
) || !TREE_PUBLIC (decl
)))
938 || (DECL_INITIAL (decl
)
939 && DECL_INITIAL (decl
) != error_mark_node
)))
942 if (TREE_CODE (decl
) == FUNCTION_DECL
)
943 code
= (defined
? 'T' : 't');
944 else if (TREE_CODE (decl
) == VAR_DECL
)
945 code
= (defined
? 'D' : 'd');
950 sym_ref
= XEXP (DECL_RTL (decl
), 0);
951 orig_str
= XSTR (sym_ref
, 0);
952 len
= strlen (orig_str
) + 1;
954 if (orig_str
[0] == '!')
956 /* Already encoded; see if we need to change it. */
957 if (code
== orig_str
[1])
959 /* Yes, tweak a copy of the name and put it in a new string. */
960 new_str
= alloca (len
);
961 memcpy (new_str
, orig_str
, len
);
963 XSTR (sym_ref
, 0) = ggc_alloc_string (new_str
, len
);
967 /* Add the encoding. */
969 new_str
= alloca (new_len
);
974 memcpy (new_str
+ 4, orig_str
, len
);
975 XSTR (sym_ref
, 0) = ggc_alloc_string (new_str
, new_len
);
977 /* The non-lazy pointer list may have captured references to the
978 old encoded name, change them. */
979 if (TREE_CODE (decl
) == VAR_DECL
)
980 update_non_lazy_ptrs (XSTR (sym_ref
, 0));
982 update_stubs (XSTR (sym_ref
, 0));
985 /* Undo the effects of the above. */
988 darwin_strip_name_encoding (str
)
991 return str
[0] == '!' ? str
+ 4 : str
;
994 /* Scan the list of non-lazy pointers and update any recorded names whose
995 stripped name matches the argument. */
998 update_non_lazy_ptrs (name
)
1001 const char *name1
, *name2
;
1004 name1
= darwin_strip_name_encoding (name
);
1006 for (temp
= machopic_non_lazy_pointers
;
1008 temp
= TREE_CHAIN (temp
))
1010 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1012 if (*sym_name
== '!')
1014 name2
= darwin_strip_name_encoding (sym_name
);
1015 if (strcmp (name1
, name2
) == 0)
1017 IDENTIFIER_POINTER (TREE_VALUE (temp
)) = name
;
1024 /* Function NAME is being defined, and its label has just been output.
1025 If there's already a reference to a stub for this function, we can
1026 just emit the stub label now and we don't bother emitting the stub later. */
1029 machopic_output_possible_stub_label (file
, name
)
1036 /* Ensure we're looking at a section-encoded name. */
1037 if (name
[0] != '!' || (name
[1] != 't' && name
[1] != 'T'))
1040 for (temp
= machopic_stubs
;
1042 temp
= TREE_CHAIN (temp
))
1044 const char *sym_name
;
1046 sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1047 if (sym_name
[0] == '!' && sym_name
[1] == 'T'
1048 && ! strcmp (name
+2, sym_name
+2))
1050 ASM_OUTPUT_LABEL (file
, IDENTIFIER_POINTER (TREE_PURPOSE (temp
)));
1051 /* Avoid generating a stub for this. */
1052 TREE_USED (temp
) = 0;
1058 /* Scan the list of stubs and update any recorded names whose
1059 stripped name matches the argument. */
1065 const char *name1
, *name2
;
1068 name1
= darwin_strip_name_encoding (name
);
1070 for (temp
= machopic_stubs
;
1072 temp
= TREE_CHAIN (temp
))
1074 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1076 if (*sym_name
== '!')
1078 name2
= darwin_strip_name_encoding (sym_name
);
1079 if (strcmp (name1
, name2
) == 0)
1081 IDENTIFIER_POINTER (TREE_VALUE (temp
)) = name
;
1089 machopic_select_section (exp
, reloc
, align
)
1092 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
;
1094 if (TREE_CODE (exp
) == STRING_CST
)
1096 if (flag_writable_strings
)
1098 else if (TREE_STRING_LENGTH (exp
) !=
1099 strlen (TREE_STRING_POINTER (exp
)) + 1)
1100 readonly_data_section ();
1104 else if (TREE_CODE (exp
) == INTEGER_CST
1105 || TREE_CODE (exp
) == REAL_CST
)
1107 tree size
= TYPE_SIZE (TREE_TYPE (exp
));
1109 if (TREE_CODE (size
) == INTEGER_CST
&&
1110 TREE_INT_CST_LOW (size
) == 4 &&
1111 TREE_INT_CST_HIGH (size
) == 0)
1112 literal4_section ();
1113 else if (TREE_CODE (size
) == INTEGER_CST
&&
1114 TREE_INT_CST_LOW (size
) == 8 &&
1115 TREE_INT_CST_HIGH (size
) == 0)
1116 literal8_section ();
1118 readonly_data_section ();
1120 else if (TREE_CODE (exp
) == CONSTRUCTOR
1122 && TREE_CODE (TREE_TYPE (exp
)) == RECORD_TYPE
1123 && TYPE_NAME (TREE_TYPE (exp
)))
1125 tree name
= TYPE_NAME (TREE_TYPE (exp
));
1126 if (TREE_CODE (name
) == TYPE_DECL
)
1127 name
= DECL_NAME (name
);
1128 if (!strcmp (IDENTIFIER_POINTER (name
), "NSConstantString"))
1129 objc_constant_string_object_section ();
1130 else if (!strcmp (IDENTIFIER_POINTER (name
), "NXConstantString"))
1131 objc_string_object_section ();
1132 else if (TREE_READONLY (exp
) || TREE_CONSTANT (exp
))
1134 if (TREE_SIDE_EFFECTS (exp
) || (flag_pic
&& reloc
))
1135 const_data_section ();
1137 readonly_data_section ();
1142 else if (TREE_CODE (exp
) == VAR_DECL
&&
1144 TREE_CODE (DECL_NAME (exp
)) == IDENTIFIER_NODE
&&
1145 IDENTIFIER_POINTER (DECL_NAME (exp
)) &&
1146 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp
)), "_OBJC_", 6))
1148 const char *name
= IDENTIFIER_POINTER (DECL_NAME (exp
));
1150 if (!strncmp (name
, "_OBJC_CLASS_METHODS_", 20))
1151 objc_cls_meth_section ();
1152 else if (!strncmp (name
, "_OBJC_INSTANCE_METHODS_", 23))
1153 objc_inst_meth_section ();
1154 else if (!strncmp (name
, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1155 objc_cat_cls_meth_section ();
1156 else if (!strncmp (name
, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1157 objc_cat_inst_meth_section ();
1158 else if (!strncmp (name
, "_OBJC_CLASS_VARIABLES_", 22))
1159 objc_class_vars_section ();
1160 else if (!strncmp (name
, "_OBJC_INSTANCE_VARIABLES_", 25))
1161 objc_instance_vars_section ();
1162 else if (!strncmp (name
, "_OBJC_CLASS_PROTOCOLS_", 22))
1163 objc_cat_cls_meth_section ();
1164 else if (!strncmp (name
, "_OBJC_CLASS_NAME_", 17))
1165 objc_class_names_section ();
1166 else if (!strncmp (name
, "_OBJC_METH_VAR_NAME_", 20))
1167 objc_meth_var_names_section ();
1168 else if (!strncmp (name
, "_OBJC_METH_VAR_TYPE_", 20))
1169 objc_meth_var_types_section ();
1170 else if (!strncmp (name
, "_OBJC_CLASS_REFERENCES", 22))
1171 objc_cls_refs_section ();
1172 else if (!strncmp (name
, "_OBJC_CLASS_", 12))
1173 objc_class_section ();
1174 else if (!strncmp (name
, "_OBJC_METACLASS_", 16))
1175 objc_meta_class_section ();
1176 else if (!strncmp (name
, "_OBJC_CATEGORY_", 15))
1177 objc_category_section ();
1178 else if (!strncmp (name
, "_OBJC_SELECTOR_REFERENCES", 25))
1179 objc_selector_refs_section ();
1180 else if (!strncmp (name
, "_OBJC_SELECTOR_FIXUP", 20))
1181 objc_selector_fixup_section ();
1182 else if (!strncmp (name
, "_OBJC_SYMBOLS", 13))
1183 objc_symbols_section ();
1184 else if (!strncmp (name
, "_OBJC_MODULES", 13))
1185 objc_module_info_section ();
1186 else if (!strncmp (name
, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1187 objc_cat_inst_meth_section ();
1188 else if (!strncmp (name
, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1189 objc_cat_cls_meth_section ();
1190 else if (!strncmp (name
, "_OBJC_PROTOCOL_REFS_", 20))
1191 objc_cat_cls_meth_section ();
1192 else if (!strncmp (name
, "_OBJC_PROTOCOL_", 15))
1193 objc_protocol_section ();
1194 else if ((TREE_READONLY (exp
) || TREE_CONSTANT (exp
))
1195 && !TREE_SIDE_EFFECTS (exp
))
1197 if (flag_pic
&& reloc
)
1198 const_data_section ();
1200 readonly_data_section ();
1205 else if (TREE_READONLY (exp
) || TREE_CONSTANT (exp
))
1207 if (TREE_SIDE_EFFECTS (exp
) || (flag_pic
&& reloc
))
1208 const_data_section ();
1210 readonly_data_section ();
1216 /* This can be called with address expressions as "rtx".
1217 They must go in "const". */
1220 machopic_select_rtx_section (mode
, x
, align
)
1221 enum machine_mode mode
;
1223 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
;
1225 if (GET_MODE_SIZE (mode
) == 8)
1226 literal8_section ();
1227 else if (GET_MODE_SIZE (mode
) == 4
1228 && (GET_CODE (x
) == CONST_INT
1229 || GET_CODE (x
) == CONST_DOUBLE
))
1230 literal4_section ();
1236 machopic_asm_out_constructor (symbol
, priority
)
1238 int priority ATTRIBUTE_UNUSED
;
1241 mod_init_section ();
1243 constructor_section ();
1244 assemble_align (POINTER_SIZE
);
1245 assemble_integer (symbol
, POINTER_SIZE
/ BITS_PER_UNIT
, POINTER_SIZE
, 1);
1248 fprintf (asm_out_file
, ".reference .constructors_used\n");
1252 machopic_asm_out_destructor (symbol
, priority
)
1254 int priority ATTRIBUTE_UNUSED
;
1257 mod_term_section ();
1259 destructor_section ();
1260 assemble_align (POINTER_SIZE
);
1261 assemble_integer (symbol
, POINTER_SIZE
/ BITS_PER_UNIT
, POINTER_SIZE
, 1);
1264 fprintf (asm_out_file
, ".reference .destructors_used\n");
1268 darwin_globalize_label (stream
, name
)
1272 if (!!strncmp (name
, "_OBJC_", 6))
1273 default_globalize_label (stream
, name
);
1276 /* Output a difference of two labels that will be an assembly time
1277 constant if the two labels are local. (.long lab1-lab2 will be
1278 very different if lab1 is at the boundary between two sections; it
1279 will be relocated according to the second section, not the first,
1280 so one ends up with a difference between labels in different
1281 sections, which is bad in the dwarf2 eh context for instance.) */
1283 static int darwin_dwarf_label_counter
;
1286 darwin_asm_output_dwarf_delta (file
, size
, lab1
, lab2
)
1288 int size ATTRIBUTE_UNUSED
;
1289 const char *lab1
, *lab2
;
1291 const char *p
= lab1
+ (lab1
[0] == '*');
1292 int islocaldiff
= (p
[0] == 'L');
1295 fprintf (file
, "\t.set L$set$%d,", darwin_dwarf_label_counter
);
1297 fprintf (file
, "\t%s\t", ".long");
1298 assemble_name (file
, lab1
);
1299 fprintf (file
, "-");
1300 assemble_name (file
, lab2
);
1302 fprintf (file
, "\n\t.long L$set$%d", darwin_dwarf_label_counter
++);
1305 #include "gt-darwin.h"