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 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. */
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
));
299 buffer
= alloca (strlen (name
) + 20);
301 strcpy (buffer
, "&L");
303 strcat (buffer
, name
+1);
306 strcat (buffer
, "_");
307 strcat (buffer
, name
);
310 strcat (buffer
, "$non_lazy_ptr");
311 ptr_name
= get_identifier (buffer
);
313 machopic_non_lazy_pointers
314 = tree_cons (ptr_name
, ident
, machopic_non_lazy_pointers
);
316 TREE_USED (machopic_non_lazy_pointers
) = 0;
318 return IDENTIFIER_POINTER (ptr_name
);
322 static GTY(()) tree machopic_stubs
;
324 /* Return the name of the stub corresponding to the given name,
325 generating a new stub name if necessary. */
328 machopic_stub_name (const char *name
)
330 tree temp
, ident
= get_identifier (name
);
333 for (temp
= machopic_stubs
;
335 temp
= TREE_CHAIN (temp
))
337 if (ident
== TREE_VALUE (temp
))
338 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
339 tname
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
340 if (strcmp (name
, tname
) == 0)
341 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
342 /* A library call name might not be section-encoded yet, so try
343 it against a stripped name. */
346 && strcmp (name
, tname
+ 4) == 0)
347 return IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
350 name
= darwin_strip_name_encoding (name
);
355 int needs_quotes
= name_needs_quotes (name
);
357 buffer
= alloca (strlen (name
) + 20);
360 strcpy (buffer
, "&\"L");
362 strcpy (buffer
, "&L");
365 strcat (buffer
, name
+1);
369 strcat (buffer
, "_");
370 strcat (buffer
, name
);
374 strcat (buffer
, "$stub\"");
376 strcat (buffer
, "$stub");
377 ptr_name
= get_identifier (buffer
);
379 machopic_stubs
= tree_cons (ptr_name
, ident
, machopic_stubs
);
380 TREE_USED (machopic_stubs
) = 0;
382 return IDENTIFIER_POINTER (ptr_name
);
387 machopic_validate_stub_or_non_lazy_ptr (const char *name
, int validate_stub
)
389 const char *real_name
;
390 tree temp
, ident
= get_identifier (name
), id2
;
392 for (temp
= (validate_stub
? machopic_stubs
: machopic_non_lazy_pointers
);
394 temp
= TREE_CHAIN (temp
))
395 if (ident
== TREE_PURPOSE (temp
))
397 /* Mark both the stub or non-lazy pointer as well as the
398 original symbol as being referenced. */
399 TREE_USED (temp
) = 1;
400 if (TREE_CODE (TREE_VALUE (temp
)) == IDENTIFIER_NODE
)
401 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp
)) = 1;
402 real_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
403 real_name
= darwin_strip_name_encoding (real_name
);
404 id2
= maybe_get_identifier (real_name
);
406 TREE_SYMBOL_REFERENCED (id2
) = 1;
410 /* Transform ORIG, which may be any data source, to the corresponding
411 source using indirections. */
414 machopic_indirect_data_reference (rtx orig
, rtx reg
)
418 if (! MACHOPIC_INDIRECT
)
421 if (GET_CODE (orig
) == SYMBOL_REF
)
423 const char *name
= XSTR (orig
, 0);
425 int defined
= machopic_data_defined_p (name
);
427 if (defined
&& MACHO_DYNAMIC_NO_PIC_P
)
429 #if defined (TARGET_TOC)
430 emit_insn (gen_macho_high (reg
, orig
));
431 emit_insn (gen_macho_low (reg
, reg
, orig
));
433 /* some other cpu -- writeme! */
440 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
441 rtx pic_base
= gen_rtx (SYMBOL_REF
, Pmode
,
442 machopic_function_base_name ());
443 rtx offset
= gen_rtx (CONST
, Pmode
,
444 gen_rtx (MINUS
, Pmode
, orig
, pic_base
));
447 #if defined (TARGET_TOC) /* i.e., PowerPC */
448 rtx hi_sum_reg
= reg
;
453 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
454 gen_rtx (PLUS
, Pmode
, pic_offset_table_rtx
,
455 gen_rtx (HIGH
, Pmode
, offset
))));
456 emit_insn (gen_rtx (SET
, Pmode
, reg
,
457 gen_rtx (LO_SUM
, Pmode
, hi_sum_reg
, offset
)));
461 #if defined (HAVE_lo_sum)
462 if (reg
== 0) abort ();
464 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
465 gen_rtx (HIGH
, Pmode
, offset
)));
466 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
467 gen_rtx (LO_SUM
, Pmode
, reg
, offset
)));
468 emit_insn (gen_rtx (USE
, VOIDmode
,
469 gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
471 orig
= gen_rtx (PLUS
, Pmode
, pic_offset_table_rtx
, reg
);
477 ptr_ref
= gen_rtx (SYMBOL_REF
, Pmode
,
478 machopic_non_lazy_ptr_name (name
));
480 ptr_ref
= gen_rtx_MEM (Pmode
, ptr_ref
);
481 RTX_UNCHANGING_P (ptr_ref
) = 1;
485 else if (GET_CODE (orig
) == CONST
)
489 /* legitimize both operands of the PLUS */
490 if (GET_CODE (XEXP (orig
, 0)) == PLUS
)
492 base
= machopic_indirect_data_reference (XEXP (XEXP (orig
, 0), 0),
494 orig
= machopic_indirect_data_reference (XEXP (XEXP (orig
, 0), 1),
495 (base
== reg
? 0 : reg
));
500 if (MACHOPIC_PURE
&& GET_CODE (orig
) == CONST_INT
)
501 result
= plus_constant (base
, INTVAL (orig
));
503 result
= gen_rtx (PLUS
, Pmode
, base
, orig
);
505 if (MACHOPIC_JUST_INDIRECT
&& GET_CODE (base
) == MEM
)
509 emit_move_insn (reg
, result
);
514 result
= force_reg (GET_MODE (result
), result
);
521 else if (GET_CODE (orig
) == MEM
)
522 XEXP (ptr_ref
, 0) = machopic_indirect_data_reference (XEXP (orig
, 0), reg
);
523 /* When the target is i386, this code prevents crashes due to the
524 compiler's ignorance on how to move the PIC base register to
525 other registers. (The reload phase sometimes introduces such
527 else if (GET_CODE (orig
) == PLUS
528 && GET_CODE (XEXP (orig
, 0)) == REG
529 && REGNO (XEXP (orig
, 0)) == PIC_OFFSET_TABLE_REGNUM
531 /* Prevent the same register from being erroneously used
532 as both the base and index registers. */
533 && GET_CODE (XEXP (orig
, 1)) == CONST
537 emit_move_insn (reg
, XEXP (orig
, 0));
538 XEXP (ptr_ref
, 0) = reg
;
543 /* Transform TARGET (a MEM), which is a function call target, to the
544 corresponding symbol_stub if necessary. Return a new MEM. */
547 machopic_indirect_call_target (rtx target
)
549 if (GET_CODE (target
) != MEM
)
552 if (MACHOPIC_INDIRECT
&& GET_CODE (XEXP (target
, 0)) == SYMBOL_REF
)
554 enum machine_mode mode
= GET_MODE (XEXP (target
, 0));
555 const char *name
= XSTR (XEXP (target
, 0), 0);
557 /* If the name is already defined, we need do nothing. */
558 if (name
[0] == '!' && name
[1] == 'T')
561 if (!machopic_name_defined_p (name
))
563 const char *stub_name
= machopic_stub_name (name
);
565 XEXP (target
, 0) = gen_rtx (SYMBOL_REF
, mode
, stub_name
);
566 RTX_UNCHANGING_P (target
) = 1;
574 machopic_legitimize_pic_address (rtx orig
, enum machine_mode mode
, rtx reg
)
578 if (! MACHOPIC_INDIRECT
)
581 /* First handle a simple SYMBOL_REF or LABEL_REF */
582 if (GET_CODE (orig
) == LABEL_REF
583 || (GET_CODE (orig
) == SYMBOL_REF
586 /* addr(foo) = &func+(foo-func) */
589 orig
= machopic_indirect_data_reference (orig
, reg
);
591 if (GET_CODE (orig
) == PLUS
592 && GET_CODE (XEXP (orig
, 0)) == REG
)
595 return force_reg (mode
, orig
);
597 emit_move_insn (reg
, orig
);
601 /* if dynamic-no-pic then use 0 as the pic base */
602 if (MACHO_DYNAMIC_NO_PIC_P
)
603 pic_base
= CONST0_RTX (Pmode
);
605 pic_base
= gen_rtx (SYMBOL_REF
, Pmode
, machopic_function_base_name ());
607 if (GET_CODE (orig
) == MEM
)
611 if (reload_in_progress
)
614 reg
= gen_reg_rtx (Pmode
);
618 if (MACHO_DYNAMIC_NO_PIC_P
619 && (GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
620 || GET_CODE (XEXP (orig
, 0)) == LABEL_REF
))
622 #if defined (TARGET_TOC) /* ppc */
623 rtx temp_reg
= (no_new_pseudos
) ? reg
: gen_reg_rtx (Pmode
);
624 rtx asym
= XEXP (orig
, 0);
627 emit_insn (gen_macho_high (temp_reg
, asym
));
628 mem
= gen_rtx_MEM (GET_MODE (orig
),
629 gen_rtx (LO_SUM
, Pmode
, temp_reg
, asym
));
630 RTX_UNCHANGING_P (mem
) = 1;
631 emit_insn (gen_rtx (SET
, VOIDmode
, reg
, mem
));
633 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
639 if (GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
640 || GET_CODE (XEXP (orig
, 0)) == LABEL_REF
)
642 rtx offset
= gen_rtx (CONST
, Pmode
,
643 gen_rtx (MINUS
, Pmode
,
644 XEXP (orig
, 0), pic_base
));
645 #if defined (TARGET_TOC) /* i.e., PowerPC */
646 /* Generating a new reg may expose opportunities for
647 common subexpression elimination. */
649 (reload_in_progress
? reg
: gen_reg_rtx (SImode
));
651 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
652 gen_rtx (PLUS
, Pmode
,
653 pic_offset_table_rtx
,
654 gen_rtx (HIGH
, Pmode
, offset
))));
655 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
656 gen_rtx (MEM
, GET_MODE (orig
),
657 gen_rtx (LO_SUM
, Pmode
,
658 hi_sum_reg
, offset
))));
662 emit_insn (gen_rtx (USE
, VOIDmode
,
663 gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
665 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
666 gen_rtx (HIGH
, Pmode
,
667 gen_rtx (CONST
, Pmode
, offset
))));
668 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
669 gen_rtx (LO_SUM
, Pmode
, reg
,
670 gen_rtx (CONST
, Pmode
, offset
))));
671 pic_ref
= gen_rtx (PLUS
, Pmode
,
672 pic_offset_table_rtx
, reg
);
676 #endif /* HAVE_lo_sum */
678 rtx pic
= pic_offset_table_rtx
;
679 if (GET_CODE (pic
) != REG
)
681 emit_move_insn (reg
, pic
);
685 emit_insn (gen_rtx (USE
, VOIDmode
,
686 gen_rtx (REG
, Pmode
, PIC_OFFSET_TABLE_REGNUM
)));
689 pic_ref
= gen_rtx (PLUS
, Pmode
,
691 gen_rtx (CONST
, Pmode
,
692 gen_rtx (MINUS
, Pmode
,
697 #if !defined (TARGET_TOC)
698 emit_move_insn (reg
, pic_ref
);
699 pic_ref
= gen_rtx (MEM
, GET_MODE (orig
), reg
);
701 RTX_UNCHANGING_P (pic_ref
) = 1;
707 if (GET_CODE (orig
) == SYMBOL_REF
708 || GET_CODE (orig
) == LABEL_REF
)
710 rtx offset
= gen_rtx (CONST
, Pmode
,
711 gen_rtx (MINUS
, Pmode
, orig
, pic_base
));
712 #if defined (TARGET_TOC) /* i.e., PowerPC */
717 if (reload_in_progress
)
720 reg
= gen_reg_rtx (SImode
);
725 emit_insn (gen_rtx (SET
, Pmode
, hi_sum_reg
,
726 (MACHO_DYNAMIC_NO_PIC_P
)
727 ? gen_rtx (HIGH
, Pmode
, offset
)
728 : gen_rtx (PLUS
, Pmode
,
729 pic_offset_table_rtx
,
730 gen_rtx (HIGH
, Pmode
, offset
))));
731 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
732 gen_rtx (LO_SUM
, Pmode
,
733 hi_sum_reg
, offset
)));
735 RTX_UNCHANGING_P (pic_ref
) = 1;
737 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
738 gen_rtx (HIGH
, Pmode
, offset
)));
739 emit_insn (gen_rtx (SET
, VOIDmode
, reg
,
740 gen_rtx (LO_SUM
, Pmode
, reg
, offset
)));
741 pic_ref
= gen_rtx (PLUS
, Pmode
,
742 pic_offset_table_rtx
, reg
);
743 RTX_UNCHANGING_P (pic_ref
) = 1;
747 #endif /* HAVE_lo_sum */
749 if (GET_CODE (orig
) == REG
)
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
,
763 pic_offset_table_rtx
));
765 pic_ref
= gen_rtx (PLUS
, Pmode
,
767 gen_rtx (CONST
, Pmode
,
768 gen_rtx (MINUS
, Pmode
,
774 if (GET_CODE (pic_ref
) != REG
)
778 emit_move_insn (reg
, pic_ref
);
783 return force_reg (mode
, pic_ref
);
792 else if (GET_CODE (orig
) == SYMBOL_REF
)
795 else if (GET_CODE (orig
) == PLUS
796 && (GET_CODE (XEXP (orig
, 0)) == MEM
797 || GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
798 || GET_CODE (XEXP (orig
, 0)) == LABEL_REF
)
799 && XEXP (orig
, 0) != pic_offset_table_rtx
800 && GET_CODE (XEXP (orig
, 1)) != REG
)
804 int is_complex
= (GET_CODE (XEXP (orig
, 0)) == MEM
);
806 base
= machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
807 orig
= machopic_legitimize_pic_address (XEXP (orig
, 1),
808 Pmode
, (base
== reg
? 0 : reg
));
809 if (GET_CODE (orig
) == CONST_INT
)
811 pic_ref
= plus_constant (base
, INTVAL (orig
));
815 pic_ref
= gen_rtx (PLUS
, Pmode
, base
, orig
);
817 if (RTX_UNCHANGING_P (base
) && RTX_UNCHANGING_P (orig
))
818 RTX_UNCHANGING_P (pic_ref
) = 1;
820 if (reg
&& is_complex
)
822 emit_move_insn (reg
, pic_ref
);
825 /* Likewise, should we set special REG_NOTEs here? */
828 else if (GET_CODE (orig
) == CONST
)
830 return machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
833 else if (GET_CODE (orig
) == MEM
834 && GET_CODE (XEXP (orig
, 0)) == SYMBOL_REF
)
836 rtx addr
= machopic_legitimize_pic_address (XEXP (orig
, 0), Pmode
, reg
);
838 addr
= gen_rtx (MEM
, GET_MODE (orig
), addr
);
839 RTX_UNCHANGING_P (addr
) = RTX_UNCHANGING_P (orig
);
840 emit_move_insn (reg
, addr
);
849 machopic_finish (FILE *asm_out_file
)
853 for (temp
= machopic_stubs
;
855 temp
= TREE_CHAIN (temp
))
857 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
858 const char *stub_name
= IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
862 if (! TREE_USED (temp
))
865 /* If the symbol is actually defined, we don't need a stub. */
866 if (sym_name
[0] == '!' && sym_name
[1] == 'T')
869 sym_name
= darwin_strip_name_encoding (sym_name
);
871 sym
= alloca (strlen (sym_name
) + 2);
872 if (sym_name
[0] == '*' || sym_name
[0] == '&')
873 strcpy (sym
, sym_name
+ 1);
874 else if (sym_name
[0] == '-' || sym_name
[0] == '+')
875 strcpy (sym
, sym_name
);
877 sym
[0] = '_', strcpy (sym
+ 1, sym_name
);
879 stub
= alloca (strlen (stub_name
) + 2);
880 if (stub_name
[0] == '*' || stub_name
[0] == '&')
881 strcpy (stub
, stub_name
+ 1);
883 stub
[0] = '_', strcpy (stub
+ 1, stub_name
);
885 machopic_output_stub (asm_out_file
, sym
, stub
);
888 for (temp
= machopic_non_lazy_pointers
;
890 temp
= TREE_CHAIN (temp
))
892 const char *const sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
893 const char *const lazy_name
= IDENTIFIER_POINTER (TREE_PURPOSE (temp
));
895 if (! TREE_USED (temp
))
898 if (machopic_ident_defined_p (TREE_VALUE (temp
)))
901 assemble_align (GET_MODE_ALIGNMENT (Pmode
));
902 assemble_label (lazy_name
);
903 assemble_integer (gen_rtx (SYMBOL_REF
, Pmode
, sym_name
),
904 GET_MODE_SIZE (Pmode
),
905 GET_MODE_ALIGNMENT (Pmode
), 1);
909 machopic_nl_symbol_ptr_section ();
910 assemble_name (asm_out_file
, lazy_name
);
911 fprintf (asm_out_file
, ":\n");
913 fprintf (asm_out_file
, "\t.indirect_symbol ");
914 assemble_name (asm_out_file
, sym_name
);
915 fprintf (asm_out_file
, "\n");
917 assemble_integer (const0_rtx
, GET_MODE_SIZE (Pmode
),
918 GET_MODE_ALIGNMENT (Pmode
), 1);
924 machopic_operand_p (rtx op
)
926 if (MACHOPIC_JUST_INDIRECT
)
928 while (GET_CODE (op
) == CONST
)
931 if (GET_CODE (op
) == SYMBOL_REF
)
932 return machopic_name_defined_p (XSTR (op
, 0));
937 while (GET_CODE (op
) == CONST
)
940 if (GET_CODE (op
) == MINUS
941 && GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
942 && GET_CODE (XEXP (op
, 1)) == SYMBOL_REF
943 && machopic_name_defined_p (XSTR (XEXP (op
, 0), 0))
944 && machopic_name_defined_p (XSTR (XEXP (op
, 1), 0)))
950 /* This function records whether a given name corresponds to a defined
951 or undefined function or variable, for machopic_classify_ident to
955 darwin_encode_section_info (tree decl
, rtx rtl
, int first ATTRIBUTE_UNUSED
)
960 const char *orig_str
;
964 /* Do the standard encoding things first. */
965 default_encode_section_info (decl
, rtl
, first
);
967 /* With the introduction of symbol_ref flags, some of the following
968 code has become redundant and should be removed at some point. */
970 if ((TREE_CODE (decl
) == FUNCTION_DECL
971 || TREE_CODE (decl
) == VAR_DECL
)
972 && !DECL_EXTERNAL (decl
)
973 && ((TREE_STATIC (decl
)
974 && (!DECL_COMMON (decl
) || !TREE_PUBLIC (decl
)))
975 || (DECL_INITIAL (decl
)
976 && DECL_INITIAL (decl
) != error_mark_node
)))
979 if (TREE_CODE (decl
) == FUNCTION_DECL
)
980 code
= (defined
? 'T' : 't');
981 else if (TREE_CODE (decl
) == VAR_DECL
)
982 code
= (defined
? 'D' : 'd');
987 sym_ref
= XEXP (rtl
, 0);
988 orig_str
= XSTR (sym_ref
, 0);
989 len
= strlen (orig_str
) + 1;
991 if (orig_str
[0] == '!')
993 /* Already encoded; see if we need to change it. */
994 if (code
== orig_str
[1])
996 /* Yes, tweak a copy of the name and put it in a new string. */
997 new_str
= alloca (len
);
998 memcpy (new_str
, orig_str
, len
);
1000 XSTR (sym_ref
, 0) = ggc_alloc_string (new_str
, len
);
1004 /* Add the encoding. */
1006 new_str
= alloca (new_len
);
1011 memcpy (new_str
+ 4, orig_str
, len
);
1012 XSTR (sym_ref
, 0) = ggc_alloc_string (new_str
, new_len
);
1014 /* The non-lazy pointer list may have captured references to the
1015 old encoded name, change them. */
1016 if (TREE_CODE (decl
) == VAR_DECL
)
1017 update_non_lazy_ptrs (XSTR (sym_ref
, 0));
1019 update_stubs (XSTR (sym_ref
, 0));
1022 /* Undo the effects of the above. */
1025 darwin_strip_name_encoding (const char *str
)
1027 return str
[0] == '!' ? str
+ 4 : str
;
1030 /* Scan the list of non-lazy pointers and update any recorded names whose
1031 stripped name matches the argument. */
1034 update_non_lazy_ptrs (const char *name
)
1036 const char *name1
, *name2
;
1039 name1
= darwin_strip_name_encoding (name
);
1041 for (temp
= machopic_non_lazy_pointers
;
1043 temp
= TREE_CHAIN (temp
))
1045 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1047 if (*sym_name
== '!')
1049 name2
= darwin_strip_name_encoding (sym_name
);
1050 if (strcmp (name1
, name2
) == 0)
1052 /* FIXME: This breaks the identifier hash table. */
1053 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp
))->identifier
.id
.str
1054 = (unsigned char *) name
;
1061 /* Function NAME is being defined, and its label has just been output.
1062 If there's already a reference to a stub for this function, we can
1063 just emit the stub label now and we don't bother emitting the stub later. */
1066 machopic_output_possible_stub_label (FILE *file
, const char *name
)
1071 /* Ensure we're looking at a section-encoded name. */
1072 if (name
[0] != '!' || (name
[1] != 't' && name
[1] != 'T'))
1075 for (temp
= machopic_stubs
;
1077 temp
= TREE_CHAIN (temp
))
1079 const char *sym_name
;
1081 sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1082 if (sym_name
[0] == '!' && sym_name
[1] == 'T'
1083 && ! strcmp (name
+2, sym_name
+2))
1085 ASM_OUTPUT_LABEL (file
, IDENTIFIER_POINTER (TREE_PURPOSE (temp
)));
1086 /* Avoid generating a stub for this. */
1087 TREE_USED (temp
) = 0;
1093 /* Scan the list of stubs and update any recorded names whose
1094 stripped name matches the argument. */
1097 update_stubs (const char *name
)
1099 const char *name1
, *name2
;
1102 name1
= darwin_strip_name_encoding (name
);
1104 for (temp
= machopic_stubs
;
1106 temp
= TREE_CHAIN (temp
))
1108 const char *sym_name
= IDENTIFIER_POINTER (TREE_VALUE (temp
));
1110 if (*sym_name
== '!')
1112 name2
= darwin_strip_name_encoding (sym_name
);
1113 if (strcmp (name1
, name2
) == 0)
1115 /* FIXME: This breaks the identifier hash table. */
1116 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp
))->identifier
.id
.str
1117 = (unsigned char *) name
;
1125 machopic_select_section (tree exp
, int reloc
,
1126 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
1128 void (*base_function
)(void);
1130 if (decl_readonly_section_1 (exp
, reloc
, MACHOPIC_INDIRECT
))
1131 base_function
= readonly_data_section
;
1132 else if (TREE_READONLY (exp
) || TREE_CONSTANT (exp
))
1133 base_function
= const_data_section
;
1135 base_function
= data_section
;
1137 if (TREE_CODE (exp
) == STRING_CST
1138 && ((size_t) TREE_STRING_LENGTH (exp
)
1139 == strlen (TREE_STRING_POINTER (exp
)) + 1)
1140 && ! flag_writable_strings
)
1142 else if ((TREE_CODE (exp
) == INTEGER_CST
|| TREE_CODE (exp
) == REAL_CST
)
1143 && flag_merge_constants
)
1145 tree size
= TYPE_SIZE (TREE_TYPE (exp
));
1147 if (TREE_CODE (size
) == INTEGER_CST
&&
1148 TREE_INT_CST_LOW (size
) == 4 &&
1149 TREE_INT_CST_HIGH (size
) == 0)
1150 literal4_section ();
1151 else if (TREE_CODE (size
) == INTEGER_CST
&&
1152 TREE_INT_CST_LOW (size
) == 8 &&
1153 TREE_INT_CST_HIGH (size
) == 0)
1154 literal8_section ();
1158 else if (TREE_CODE (exp
) == CONSTRUCTOR
1160 && TREE_CODE (TREE_TYPE (exp
)) == RECORD_TYPE
1161 && TYPE_NAME (TREE_TYPE (exp
)))
1163 tree name
= TYPE_NAME (TREE_TYPE (exp
));
1164 if (TREE_CODE (name
) == TYPE_DECL
)
1165 name
= DECL_NAME (name
);
1166 if (!strcmp (IDENTIFIER_POINTER (name
), "NSConstantString"))
1167 objc_constant_string_object_section ();
1168 else if (!strcmp (IDENTIFIER_POINTER (name
), "NXConstantString"))
1169 objc_string_object_section ();
1173 else if (TREE_CODE (exp
) == VAR_DECL
&&
1175 TREE_CODE (DECL_NAME (exp
)) == IDENTIFIER_NODE
&&
1176 IDENTIFIER_POINTER (DECL_NAME (exp
)) &&
1177 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp
)), "_OBJC_", 6))
1179 const char *name
= IDENTIFIER_POINTER (DECL_NAME (exp
));
1181 if (!strncmp (name
, "_OBJC_CLASS_METHODS_", 20))
1182 objc_cls_meth_section ();
1183 else if (!strncmp (name
, "_OBJC_INSTANCE_METHODS_", 23))
1184 objc_inst_meth_section ();
1185 else if (!strncmp (name
, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1186 objc_cat_cls_meth_section ();
1187 else if (!strncmp (name
, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1188 objc_cat_inst_meth_section ();
1189 else if (!strncmp (name
, "_OBJC_CLASS_VARIABLES_", 22))
1190 objc_class_vars_section ();
1191 else if (!strncmp (name
, "_OBJC_INSTANCE_VARIABLES_", 25))
1192 objc_instance_vars_section ();
1193 else if (!strncmp (name
, "_OBJC_CLASS_PROTOCOLS_", 22))
1194 objc_cat_cls_meth_section ();
1195 else if (!strncmp (name
, "_OBJC_CLASS_NAME_", 17))
1196 objc_class_names_section ();
1197 else if (!strncmp (name
, "_OBJC_METH_VAR_NAME_", 20))
1198 objc_meth_var_names_section ();
1199 else if (!strncmp (name
, "_OBJC_METH_VAR_TYPE_", 20))
1200 objc_meth_var_types_section ();
1201 else if (!strncmp (name
, "_OBJC_CLASS_REFERENCES", 22))
1202 objc_cls_refs_section ();
1203 else if (!strncmp (name
, "_OBJC_CLASS_", 12))
1204 objc_class_section ();
1205 else if (!strncmp (name
, "_OBJC_METACLASS_", 16))
1206 objc_meta_class_section ();
1207 else if (!strncmp (name
, "_OBJC_CATEGORY_", 15))
1208 objc_category_section ();
1209 else if (!strncmp (name
, "_OBJC_SELECTOR_REFERENCES", 25))
1210 objc_selector_refs_section ();
1211 else if (!strncmp (name
, "_OBJC_SELECTOR_FIXUP", 20))
1212 objc_selector_fixup_section ();
1213 else if (!strncmp (name
, "_OBJC_SYMBOLS", 13))
1214 objc_symbols_section ();
1215 else if (!strncmp (name
, "_OBJC_MODULES", 13))
1216 objc_module_info_section ();
1217 else if (!strncmp (name
, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1218 objc_cat_inst_meth_section ();
1219 else if (!strncmp (name
, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1220 objc_cat_cls_meth_section ();
1221 else if (!strncmp (name
, "_OBJC_PROTOCOL_REFS_", 20))
1222 objc_cat_cls_meth_section ();
1223 else if (!strncmp (name
, "_OBJC_PROTOCOL_", 15))
1224 objc_protocol_section ();
1232 /* This can be called with address expressions as "rtx".
1233 They must go in "const". */
1236 machopic_select_rtx_section (enum machine_mode mode
, rtx x
,
1237 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
1239 if (GET_MODE_SIZE (mode
) == 8)
1240 literal8_section ();
1241 else if (GET_MODE_SIZE (mode
) == 4
1242 && (GET_CODE (x
) == CONST_INT
1243 || GET_CODE (x
) == CONST_DOUBLE
))
1244 literal4_section ();
1245 else if (MACHOPIC_INDIRECT
1246 && (GET_CODE (x
) == SYMBOL_REF
1247 || GET_CODE (x
) == CONST
1248 || GET_CODE (x
) == LABEL_REF
))
1249 const_data_section ();
1255 machopic_asm_out_constructor (rtx symbol
, int priority ATTRIBUTE_UNUSED
)
1258 if (MACHOPIC_INDIRECT
)
1259 mod_init_section ();
1261 constructor_section ();
1262 assemble_align (POINTER_SIZE
);
1263 assemble_integer (symbol
, POINTER_SIZE
/ BITS_PER_UNIT
, POINTER_SIZE
, 1);
1266 if (! MACHOPIC_INDIRECT
)
1267 fprintf (asm_out_file
, ".reference .constructors_used\n");
1271 machopic_asm_out_destructor (rtx symbol
, int priority ATTRIBUTE_UNUSED
)
1274 if (MACHOPIC_INDIRECT
)
1275 mod_term_section ();
1277 destructor_section ();
1278 assemble_align (POINTER_SIZE
);
1279 assemble_integer (symbol
, POINTER_SIZE
/ BITS_PER_UNIT
, POINTER_SIZE
, 1);
1281 if (! MACHOPIC_INDIRECT
)
1282 fprintf (asm_out_file
, ".reference .destructors_used\n");
1286 darwin_globalize_label (FILE *stream
, const char *name
)
1288 if (!!strncmp (name
, "_OBJC_", 6))
1289 default_globalize_label (stream
, name
);
1292 /* Output a difference of two labels that will be an assembly time
1293 constant if the two labels are local. (.long lab1-lab2 will be
1294 very different if lab1 is at the boundary between two sections; it
1295 will be relocated according to the second section, not the first,
1296 so one ends up with a difference between labels in different
1297 sections, which is bad in the dwarf2 eh context for instance.) */
1299 static int darwin_dwarf_label_counter
;
1302 darwin_asm_output_dwarf_delta (FILE *file
, int size ATTRIBUTE_UNUSED
,
1303 const char *lab1
, const char *lab2
)
1305 const char *p
= lab1
+ (lab1
[0] == '*');
1306 int islocaldiff
= (p
[0] == 'L');
1309 fprintf (file
, "\t.set L$set$%d,", darwin_dwarf_label_counter
);
1311 fprintf (file
, "\t%s\t", ".long");
1312 assemble_name (file
, lab1
);
1313 fprintf (file
, "-");
1314 assemble_name (file
, lab2
);
1316 fprintf (file
, "\n\t.long L$set$%d", darwin_dwarf_label_counter
++);
1320 darwin_file_end (void)
1322 machopic_finish (asm_out_file
);
1323 if (strcmp (lang_hooks
.name
, "GNU C++") == 0)
1325 constructor_section ();
1326 destructor_section ();
1327 ASM_OUTPUT_ALIGN (asm_out_file
, 1);
1331 #include "gt-darwin.h"