* config/sparc/sol2-bi.h: Handle TARGET_CPU_ultrasparc3.
[official-gcc.git] / gcc / config / darwin.c
blob1ac122376de162a441a902aafa695b712a470483
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)
11 any later version.
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. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "reload.h"
40 #include "function.h"
41 #include "ggc.h"
42 #include "langhooks.h"
43 #include "tm_p.h"
44 #include "errors.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 int
52 name_needs_quotes (const char *name)
54 int c;
55 while ((c = *name++) != '\0')
56 if (! ISIDNUM (c) && c != '.' && c != '$')
57 return 1;
58 return 0;
62 * flag_pic = 1 ... generate only indirections
63 * flag_pic = 2 ... generate indirections and pure code
66 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
67 reference, which will not be changed. */
69 static GTY(()) tree machopic_defined_list;
71 enum machopic_addr_class
72 machopic_classify_ident (tree ident)
74 const char *name = IDENTIFIER_POINTER (ident);
75 int lprefix = (((name[0] == '*' || name[0] == '&')
76 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
77 || ( name[0] == '_'
78 && name[1] == 'O'
79 && name[2] == 'B'
80 && name[3] == 'J'
81 && name[4] == 'C'
82 && name[5] == '_'));
83 tree temp;
85 /* The PIC base symbol is always defined. */
86 if (! strcmp (name, "<pic base>"))
87 return MACHOPIC_DEFINED_DATA;
89 if (name[0] != '!')
91 /* Here if no special encoding to be found. */
92 if (lprefix)
94 const char *name = IDENTIFIER_POINTER (ident);
95 int len = strlen (name);
97 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
98 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
99 return MACHOPIC_DEFINED_FUNCTION;
100 return MACHOPIC_DEFINED_DATA;
103 for (temp = machopic_defined_list;
104 temp != NULL_TREE;
105 temp = TREE_CHAIN (temp))
107 if (ident == TREE_VALUE (temp))
108 return MACHOPIC_DEFINED_DATA;
111 if (TREE_ASM_WRITTEN (ident))
112 return MACHOPIC_DEFINED_DATA;
114 return MACHOPIC_UNDEFINED;
117 else if (name[1] == 'D')
118 return MACHOPIC_DEFINED_DATA;
120 else if (name[1] == 'T')
121 return MACHOPIC_DEFINED_FUNCTION;
123 /* It is possible that someone is holding a "stale" name, which has
124 since been defined. See if there is a "defined" name (i.e,
125 different from NAME only in having a '!D_' or a '!T_' instead of
126 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
127 that this identifier is defined. */
128 else if (name[1] == 'd' || name[1] == 't')
130 char *new_name;
131 new_name = (char *)alloca (strlen (name) + 1);
132 strcpy (new_name, name);
133 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
134 if (maybe_get_identifier (new_name) != NULL)
135 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
136 : MACHOPIC_DEFINED_FUNCTION;
139 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
141 if (ident == TREE_VALUE (temp))
143 if (name[1] == 'T')
144 return MACHOPIC_DEFINED_FUNCTION;
145 else
146 return MACHOPIC_DEFINED_DATA;
150 if (name[1] == 't' || name[1] == 'T')
152 if (lprefix)
153 return MACHOPIC_DEFINED_FUNCTION;
154 else
155 return MACHOPIC_UNDEFINED_FUNCTION;
157 else
159 if (lprefix)
160 return MACHOPIC_DEFINED_DATA;
161 else
162 return MACHOPIC_UNDEFINED_DATA;
167 enum machopic_addr_class
168 machopic_classify_name (const char *name)
170 return machopic_classify_ident (get_identifier (name));
174 machopic_ident_defined_p (tree ident)
176 switch (machopic_classify_ident (ident))
178 case MACHOPIC_UNDEFINED:
179 case MACHOPIC_UNDEFINED_DATA:
180 case MACHOPIC_UNDEFINED_FUNCTION:
181 return 0;
182 default:
183 return 1;
187 static int
188 machopic_data_defined_p (const char *name)
190 switch (machopic_classify_ident (get_identifier (name)))
192 case MACHOPIC_DEFINED_DATA:
193 return 1;
194 default:
195 return 0;
200 machopic_name_defined_p (const char *name)
202 return machopic_ident_defined_p (get_identifier (name));
205 void
206 machopic_define_ident (tree ident)
208 if (!machopic_ident_defined_p (ident))
209 machopic_defined_list =
210 tree_cons (NULL_TREE, ident, machopic_defined_list);
213 void
214 machopic_define_name (const char *name)
216 machopic_define_ident (get_identifier (name));
219 static GTY(()) char * function_base;
221 const char *
222 machopic_function_base_name (void)
224 const char *current_name;
225 /* if dynamic-no-pic is on, we should not get here */
226 if (MACHO_DYNAMIC_NO_PIC_P)
227 abort ();
228 current_name =
229 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
231 if (function_base == NULL)
232 function_base =
233 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
235 current_function_uses_pic_offset_table = 1;
237 return function_base;
240 static GTY(()) const char * function_base_func_name;
241 static GTY(()) int current_pic_label_num;
243 void
244 machopic_output_function_base_name (FILE *file)
246 const char *current_name;
248 /* If dynamic-no-pic is on, we should not get here. */
249 if (MACHO_DYNAMIC_NO_PIC_P)
250 abort ();
251 current_name =
252 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
253 if (function_base_func_name != current_name)
255 ++current_pic_label_num;
256 function_base_func_name = current_name;
258 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
261 static GTY(()) tree machopic_non_lazy_pointers;
263 /* Return a non-lazy pointer name corresponding to the given name,
264 either by finding it in our list of pointer names, or by generating
265 a new one. */
267 static const char *
268 machopic_non_lazy_ptr_name (const char *name)
270 const char *temp_name;
271 tree temp, ident = get_identifier (name);
273 for (temp = machopic_non_lazy_pointers;
274 temp != NULL_TREE;
275 temp = TREE_CHAIN (temp))
277 if (ident == TREE_VALUE (temp))
278 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
281 name = darwin_strip_name_encoding (name);
283 /* Try again, but comparing names this time. */
284 for (temp = machopic_non_lazy_pointers;
285 temp != NULL_TREE;
286 temp = TREE_CHAIN (temp))
288 if (TREE_VALUE (temp))
290 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
291 temp_name = darwin_strip_name_encoding (temp_name);
292 if (strcmp (name, temp_name) == 0)
293 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
298 char *buffer;
299 int namelen = strlen (name);
300 int bufferlen = 0;
301 tree ptr_name;
303 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
305 strcpy (buffer, "&L");
306 bufferlen = 2;
307 if (name[0] == '*')
309 memcpy (buffer + bufferlen, name+1, namelen-1+1);
310 bufferlen += namelen-1;
312 else
314 buffer[bufferlen] = '_';
315 memcpy (buffer + bufferlen +1, name, namelen+1);
316 bufferlen += namelen +1;
319 memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
320 bufferlen += strlen("$non_lazy_ptr");
321 ptr_name = get_identifier (buffer);
323 machopic_non_lazy_pointers
324 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
326 TREE_USED (machopic_non_lazy_pointers) = 0;
328 return IDENTIFIER_POINTER (ptr_name);
332 static GTY(()) tree machopic_stubs;
334 /* Return the name of the stub corresponding to the given name,
335 generating a new stub name if necessary. */
337 const char *
338 machopic_stub_name (const char *name)
340 tree temp, ident = get_identifier (name);
341 const char *tname;
343 for (temp = machopic_stubs;
344 temp != NULL_TREE;
345 temp = TREE_CHAIN (temp))
347 if (ident == TREE_VALUE (temp))
348 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
350 if (strcmp (name, tname) == 0)
351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
352 /* A library call name might not be section-encoded yet, so try
353 it against a stripped name. */
354 if (name[0] != '!'
355 && tname[0] == '!'
356 && strcmp (name, tname + 4) == 0)
357 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
360 name = darwin_strip_name_encoding (name);
363 char *buffer;
364 int bufferlen = 0;
365 int namelen = strlen (name);
366 tree ptr_name;
367 int needs_quotes = name_needs_quotes (name);
369 buffer = alloca (namelen + 20);
371 if (needs_quotes)
373 strcpy (buffer, "&\"L");
374 bufferlen = strlen("&\"L");
376 else
378 strcpy (buffer, "&L");
379 bufferlen = strlen("&L");
382 if (name[0] == '*')
384 memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
385 bufferlen += namelen - 1;
387 else
389 buffer[bufferlen] = '_';
390 memcpy (buffer + bufferlen +1, name, namelen+1);
391 bufferlen += namelen +1;
394 if (needs_quotes)
396 memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
397 bufferlen += strlen("$stub\"");
399 else
401 memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
402 bufferlen += strlen("$stub");
404 ptr_name = get_identifier (buffer);
406 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
407 TREE_USED (machopic_stubs) = 0;
409 return IDENTIFIER_POINTER (ptr_name);
413 void
414 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
416 const char *real_name;
417 tree temp, ident = get_identifier (name), id2;
419 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
420 temp != NULL_TREE;
421 temp = TREE_CHAIN (temp))
422 if (ident == TREE_PURPOSE (temp))
424 /* Mark both the stub or non-lazy pointer as well as the
425 original symbol as being referenced. */
426 TREE_USED (temp) = 1;
427 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
428 mark_referenced (TREE_VALUE (temp));
429 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
430 real_name = darwin_strip_name_encoding (real_name);
431 id2 = maybe_get_identifier (real_name);
432 if (id2)
433 mark_referenced (id2);
437 /* Transform ORIG, which may be any data source, to the corresponding
438 source using indirections. */
441 machopic_indirect_data_reference (rtx orig, rtx reg)
443 rtx ptr_ref = orig;
445 if (! MACHOPIC_INDIRECT)
446 return orig;
448 if (GET_CODE (orig) == SYMBOL_REF)
450 const char *name = XSTR (orig, 0);
451 int defined = machopic_data_defined_p (name);
453 if (defined && MACHO_DYNAMIC_NO_PIC_P)
455 #if defined (TARGET_TOC)
456 emit_insn (gen_macho_high (reg, orig));
457 emit_insn (gen_macho_low (reg, reg, orig));
458 #else
459 /* some other cpu -- writeme! */
460 abort ();
461 #endif
462 return reg;
464 else if (defined)
466 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
467 rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
468 machopic_function_base_name ());
469 rtx offset = gen_rtx_CONST (Pmode,
470 gen_rtx_MINUS (Pmode, orig, pic_base));
471 #endif
473 #if defined (TARGET_TOC) /* i.e., PowerPC */
474 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
476 if (reg == NULL)
477 abort ();
479 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
480 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
481 gen_rtx_HIGH (Pmode, offset))));
482 emit_insn (gen_rtx_SET (Pmode, reg,
483 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
485 orig = reg;
486 #else
487 #if defined (HAVE_lo_sum)
488 if (reg == 0) abort ();
490 emit_insn (gen_rtx_SET (VOIDmode, reg,
491 gen_rtx_HIGH (Pmode, offset)));
492 emit_insn (gen_rtx_SET (VOIDmode, reg,
493 gen_rtx_LO_SUM (Pmode, reg, offset)));
494 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
496 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
497 #endif
498 #endif
499 return orig;
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;
508 return ptr_ref;
510 else if (GET_CODE (orig) == CONST)
512 rtx base, result;
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),
518 reg);
519 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
520 (base == reg ? 0 : reg));
522 else
523 return orig;
525 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
526 result = plus_constant (base, INTVAL (orig));
527 else
528 result = gen_rtx_PLUS (Pmode, base, orig);
530 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
532 if (reg)
534 emit_move_insn (reg, result);
535 result = reg;
537 else
539 result = force_reg (GET_MODE (result), result);
543 return 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
551 insns.) */
552 else if (GET_CODE (orig) == PLUS
553 && GET_CODE (XEXP (orig, 0)) == REG
554 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
555 #ifdef I386
556 /* Prevent the same register from being erroneously used
557 as both the base and index registers. */
558 && GET_CODE (XEXP (orig, 1)) == CONST
559 #endif
560 && reg)
562 emit_move_insn (reg, XEXP (orig, 0));
563 XEXP (ptr_ref, 0) = reg;
565 return ptr_ref;
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)
575 return target;
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')
584 return target;
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;
595 return target;
599 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
601 rtx pic_ref = orig;
603 if (! MACHOPIC_INDIRECT)
604 return orig;
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) */
612 rtx pic_base;
614 orig = machopic_indirect_data_reference (orig, reg);
616 if (GET_CODE (orig) == PLUS
617 && GET_CODE (XEXP (orig, 0)) == REG)
619 if (reg == 0)
620 return force_reg (mode, orig);
622 emit_move_insn (reg, orig);
623 return reg;
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);
629 else
630 pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
632 if (GET_CODE (orig) == MEM)
634 if (reg == 0)
636 if (reload_in_progress)
637 abort ();
638 else
639 reg = gen_reg_rtx (Pmode);
642 #ifdef HAVE_lo_sum
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);
650 rtx mem;
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));
657 #else
658 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
659 abort ();
660 #endif
661 pic_ref = reg;
663 else
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),
670 pic_base));
671 #if defined (TARGET_TOC) /* i.e., PowerPC */
672 /* Generating a new reg may expose opportunities for
673 common subexpression elimination. */
674 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
675 rtx mem;
676 rtx insn;
677 rtx sum;
679 sum = gen_rtx_HIGH (Pmode, offset);
680 if (! MACHO_DYNAMIC_NO_PIC_P)
681 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
683 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
685 mem = gen_rtx_MEM (GET_MODE (orig),
686 gen_rtx_LO_SUM (Pmode,
687 hi_sum_reg, offset));
688 RTX_UNCHANGING_P (mem) = 1;
689 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
690 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
691 REG_NOTES (insn));
693 pic_ref = reg;
694 #else
695 emit_insn (gen_rtx_USE (VOIDmode,
696 gen_rtx_REG (Pmode,
697 PIC_OFFSET_TABLE_REGNUM)));
699 emit_insn (gen_rtx_SET (VOIDmode, reg,
700 gen_rtx_HIGH (Pmode,
701 gen_rtx_CONST (Pmode,
702 offset))));
703 emit_insn (gen_rtx_SET (VOIDmode, reg,
704 gen_rtx_LO_SUM (Pmode, reg,
705 gen_rtx_CONST (Pmode, offset))));
706 pic_ref = gen_rtx_PLUS (Pmode,
707 pic_offset_table_rtx, reg);
708 #endif
710 else
711 #endif /* HAVE_lo_sum */
713 rtx pic = pic_offset_table_rtx;
714 if (GET_CODE (pic) != REG)
716 emit_move_insn (reg, pic);
717 pic = reg;
719 #if 0
720 emit_insn (gen_rtx_USE (VOIDmode,
721 gen_rtx_REG (Pmode,
722 PIC_OFFSET_TABLE_REGNUM)));
723 #endif
725 pic_ref = gen_rtx_PLUS (Pmode,
726 pic,
727 gen_rtx_CONST (Pmode,
728 gen_rtx_MINUS (Pmode,
729 XEXP (orig, 0),
730 pic_base)));
733 #if !defined (TARGET_TOC)
734 emit_move_insn (reg, pic_ref);
735 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
736 #endif
737 RTX_UNCHANGING_P (pic_ref) = 1;
739 else
742 #ifdef HAVE_lo_sum
743 if (GET_CODE (orig) == SYMBOL_REF
744 || GET_CODE (orig) == LABEL_REF)
746 rtx offset = gen_rtx_CONST (Pmode,
747 gen_rtx_MINUS (Pmode,
748 orig, pic_base));
749 #if defined (TARGET_TOC) /* i.e., PowerPC */
750 rtx hi_sum_reg;
752 if (reg == 0)
754 if (reload_in_progress)
755 abort ();
756 else
757 reg = gen_reg_rtx (SImode);
760 hi_sum_reg = reg;
762 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
763 (MACHO_DYNAMIC_NO_PIC_P)
764 ? gen_rtx_HIGH (Pmode, offset)
765 : gen_rtx_PLUS (Pmode,
766 pic_offset_table_rtx,
767 gen_rtx_HIGH (Pmode,
768 offset))));
769 emit_insn (gen_rtx_SET (VOIDmode, reg,
770 gen_rtx_LO_SUM (Pmode,
771 hi_sum_reg, offset)));
772 pic_ref = reg;
773 RTX_UNCHANGING_P (pic_ref) = 1;
774 #else
775 emit_insn (gen_rtx_SET (VOIDmode, reg,
776 gen_rtx_HIGH (Pmode, offset)));
777 emit_insn (gen_rtx_SET (VOIDmode, reg,
778 gen_rtx_LO_SUM (Pmode, reg, offset)));
779 pic_ref = gen_rtx_PLUS (Pmode,
780 pic_offset_table_rtx, reg);
781 RTX_UNCHANGING_P (pic_ref) = 1;
782 #endif
784 else
785 #endif /* HAVE_lo_sum */
787 if (GET_CODE (orig) == REG)
789 return orig;
791 else
793 rtx pic = pic_offset_table_rtx;
794 if (GET_CODE (pic) != REG)
796 emit_move_insn (reg, pic);
797 pic = reg;
799 #if 0
800 emit_insn (gen_rtx_USE (VOIDmode,
801 pic_offset_table_rtx));
802 #endif
803 pic_ref = gen_rtx_PLUS (Pmode,
804 pic,
805 gen_rtx_CONST (Pmode,
806 gen_rtx_MINUS (Pmode,
807 orig, pic_base)));
812 if (GET_CODE (pic_ref) != REG)
814 if (reg != 0)
816 emit_move_insn (reg, pic_ref);
817 return reg;
819 else
821 return force_reg (mode, pic_ref);
824 else
826 return pic_ref;
830 else if (GET_CODE (orig) == SYMBOL_REF)
831 return orig;
833 else if (GET_CODE (orig) == PLUS
834 && (GET_CODE (XEXP (orig, 0)) == MEM
835 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
836 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
837 && XEXP (orig, 0) != pic_offset_table_rtx
838 && GET_CODE (XEXP (orig, 1)) != REG)
841 rtx base;
842 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
844 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
845 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
846 Pmode, (base == reg ? 0 : reg));
847 if (GET_CODE (orig) == CONST_INT)
849 pic_ref = plus_constant (base, INTVAL (orig));
850 is_complex = 1;
852 else
853 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
855 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
856 RTX_UNCHANGING_P (pic_ref) = 1;
858 if (reg && is_complex)
860 emit_move_insn (reg, pic_ref);
861 pic_ref = reg;
863 /* Likewise, should we set special REG_NOTEs here? */
866 else if (GET_CODE (orig) == CONST)
868 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
871 else if (GET_CODE (orig) == MEM
872 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
874 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
876 addr = gen_rtx_MEM (GET_MODE (orig), addr);
877 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
878 emit_move_insn (reg, addr);
879 pic_ref = reg;
882 return pic_ref;
886 void
887 machopic_finish (FILE *asm_out_file)
889 tree temp;
891 for (temp = machopic_stubs;
892 temp != NULL_TREE;
893 temp = TREE_CHAIN (temp))
895 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
896 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
897 char *sym;
898 char *stub;
900 if (! TREE_USED (temp))
901 continue;
903 /* If the symbol is actually defined, we don't need a stub. */
904 if (sym_name[0] == '!' && sym_name[1] == 'T')
905 continue;
907 sym_name = darwin_strip_name_encoding (sym_name);
909 sym = alloca (strlen (sym_name) + 2);
910 if (sym_name[0] == '*' || sym_name[0] == '&')
911 strcpy (sym, sym_name + 1);
912 else if (sym_name[0] == '-' || sym_name[0] == '+')
913 strcpy (sym, sym_name);
914 else
915 sym[0] = '_', strcpy (sym + 1, sym_name);
917 stub = alloca (strlen (stub_name) + 2);
918 if (stub_name[0] == '*' || stub_name[0] == '&')
919 strcpy (stub, stub_name + 1);
920 else
921 stub[0] = '_', strcpy (stub + 1, stub_name);
923 machopic_output_stub (asm_out_file, sym, stub);
926 for (temp = machopic_non_lazy_pointers;
927 temp != NULL_TREE;
928 temp = TREE_CHAIN (temp))
930 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
931 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
933 if (! TREE_USED (temp))
934 continue;
936 if (machopic_ident_defined_p (TREE_VALUE (temp)))
938 data_section ();
939 assemble_align (GET_MODE_ALIGNMENT (Pmode));
940 assemble_label (lazy_name);
941 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
942 GET_MODE_SIZE (Pmode),
943 GET_MODE_ALIGNMENT (Pmode), 1);
945 else
947 machopic_nl_symbol_ptr_section ();
948 assemble_name (asm_out_file, lazy_name);
949 fprintf (asm_out_file, ":\n");
951 fprintf (asm_out_file, "\t.indirect_symbol ");
952 assemble_name (asm_out_file, sym_name);
953 fprintf (asm_out_file, "\n");
955 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
956 GET_MODE_ALIGNMENT (Pmode), 1);
962 machopic_operand_p (rtx op)
964 if (MACHOPIC_JUST_INDIRECT)
966 while (GET_CODE (op) == CONST)
967 op = XEXP (op, 0);
969 if (GET_CODE (op) == SYMBOL_REF)
970 return machopic_name_defined_p (XSTR (op, 0));
971 else
972 return 0;
975 while (GET_CODE (op) == CONST)
976 op = XEXP (op, 0);
978 if (GET_CODE (op) == MINUS
979 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
980 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
981 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
982 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
983 return 1;
985 return 0;
988 /* This function records whether a given name corresponds to a defined
989 or undefined function or variable, for machopic_classify_ident to
990 use later. */
992 void
993 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
995 char code = '\0';
996 int defined = 0;
997 rtx sym_ref;
998 const char *orig_str;
999 char *new_str;
1000 size_t len, new_len;
1002 /* Do the standard encoding things first. */
1003 default_encode_section_info (decl, rtl, first);
1005 /* With the introduction of symbol_ref flags, some of the following
1006 code has become redundant and should be removed at some point. */
1008 if ((TREE_CODE (decl) == FUNCTION_DECL
1009 || TREE_CODE (decl) == VAR_DECL)
1010 && !DECL_EXTERNAL (decl)
1011 && ((TREE_STATIC (decl)
1012 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1013 || (DECL_INITIAL (decl)
1014 && DECL_INITIAL (decl) != error_mark_node)))
1015 defined = 1;
1017 if (TREE_CODE (decl) == FUNCTION_DECL)
1018 code = (defined ? 'T' : 't');
1019 else if (TREE_CODE (decl) == VAR_DECL)
1020 code = (defined ? 'D' : 'd');
1022 if (code == '\0')
1023 return;
1025 sym_ref = XEXP (rtl, 0);
1026 orig_str = XSTR (sym_ref, 0);
1027 len = strlen (orig_str) + 1;
1029 if (orig_str[0] == '!')
1031 /* Already encoded; see if we need to change it. */
1032 if (code == orig_str[1])
1033 return;
1034 /* Yes, tweak a copy of the name and put it in a new string. */
1035 new_str = alloca (len);
1036 memcpy (new_str, orig_str, len);
1037 new_str[1] = code;
1038 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1040 else
1042 /* Add the encoding. */
1043 new_len = len + 4;
1044 new_str = alloca (new_len);
1045 new_str[0] = '!';
1046 new_str[1] = code;
1047 new_str[2] = '_';
1048 new_str[3] = '_';
1049 memcpy (new_str + 4, orig_str, len);
1050 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1052 /* The non-lazy pointer list may have captured references to the
1053 old encoded name, change them. */
1054 if (TREE_CODE (decl) == VAR_DECL)
1055 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1056 else
1057 update_stubs (XSTR (sym_ref, 0));
1060 /* Undo the effects of the above. */
1062 const char *
1063 darwin_strip_name_encoding (const char *str)
1065 return str[0] == '!' ? str + 4 : str;
1068 /* Scan the list of non-lazy pointers and update any recorded names whose
1069 stripped name matches the argument. */
1071 static void
1072 update_non_lazy_ptrs (const char *name)
1074 const char *name1, *name2;
1075 tree temp;
1077 name1 = darwin_strip_name_encoding (name);
1079 for (temp = machopic_non_lazy_pointers;
1080 temp != NULL_TREE;
1081 temp = TREE_CHAIN (temp))
1083 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1085 if (*sym_name == '!')
1087 name2 = darwin_strip_name_encoding (sym_name);
1088 if (strcmp (name1, name2) == 0)
1090 /* FIXME: This breaks the identifier hash table. */
1091 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1092 = (unsigned char *) name;
1093 break;
1099 /* Function NAME is being defined, and its label has just been output.
1100 If there's already a reference to a stub for this function, we can
1101 just emit the stub label now and we don't bother emitting the stub later. */
1103 void
1104 machopic_output_possible_stub_label (FILE *file, const char *name)
1106 tree temp;
1108 /* Ensure we're looking at a section-encoded name. */
1109 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1110 return;
1112 for (temp = machopic_stubs;
1113 temp != NULL_TREE;
1114 temp = TREE_CHAIN (temp))
1116 const char *sym_name;
1118 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1119 if (sym_name[0] == '!' && (sym_name[1] == 'T' || sym_name[1] == 't')
1120 && ! strcmp (name+2, sym_name+2))
1122 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1123 /* Avoid generating a stub for this. */
1124 TREE_USED (temp) = 0;
1125 break;
1130 /* Scan the list of stubs and update any recorded names whose
1131 stripped name matches the argument. */
1133 static void
1134 update_stubs (const char *name)
1136 const char *name1, *name2;
1137 tree temp;
1139 name1 = darwin_strip_name_encoding (name);
1141 for (temp = machopic_stubs;
1142 temp != NULL_TREE;
1143 temp = TREE_CHAIN (temp))
1145 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1147 if (*sym_name == '!')
1149 name2 = darwin_strip_name_encoding (sym_name);
1150 if (strcmp (name1, name2) == 0)
1152 /* FIXME: This breaks the identifier hash table. */
1153 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1154 = (unsigned char *) name;
1155 break;
1161 void
1162 machopic_select_section (tree exp, int reloc,
1163 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1165 void (*base_function)(void);
1167 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1168 base_function = readonly_data_section;
1169 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1170 base_function = const_data_section;
1171 else
1172 base_function = data_section;
1174 if (TREE_CODE (exp) == STRING_CST
1175 && ((size_t) TREE_STRING_LENGTH (exp)
1176 == strlen (TREE_STRING_POINTER (exp)) + 1)
1177 && ! flag_writable_strings)
1178 cstring_section ();
1179 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1180 && flag_merge_constants)
1182 tree size = TYPE_SIZE (TREE_TYPE (exp));
1184 if (TREE_CODE (size) == INTEGER_CST &&
1185 TREE_INT_CST_LOW (size) == 4 &&
1186 TREE_INT_CST_HIGH (size) == 0)
1187 literal4_section ();
1188 else if (TREE_CODE (size) == INTEGER_CST &&
1189 TREE_INT_CST_LOW (size) == 8 &&
1190 TREE_INT_CST_HIGH (size) == 0)
1191 literal8_section ();
1192 else
1193 base_function ();
1195 else if (TREE_CODE (exp) == CONSTRUCTOR
1196 && TREE_TYPE (exp)
1197 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1198 && TYPE_NAME (TREE_TYPE (exp)))
1200 tree name = TYPE_NAME (TREE_TYPE (exp));
1201 if (TREE_CODE (name) == TYPE_DECL)
1202 name = DECL_NAME (name);
1203 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1204 objc_constant_string_object_section ();
1205 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1206 objc_string_object_section ();
1207 else
1208 base_function ();
1210 else if (TREE_CODE (exp) == VAR_DECL &&
1211 DECL_NAME (exp) &&
1212 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1213 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1214 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1216 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1218 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1219 objc_cls_meth_section ();
1220 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1221 objc_inst_meth_section ();
1222 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1223 objc_cat_cls_meth_section ();
1224 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1225 objc_cat_inst_meth_section ();
1226 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1227 objc_class_vars_section ();
1228 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1229 objc_instance_vars_section ();
1230 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1231 objc_cat_cls_meth_section ();
1232 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1233 objc_class_names_section ();
1234 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1235 objc_meth_var_names_section ();
1236 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1237 objc_meth_var_types_section ();
1238 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1239 objc_cls_refs_section ();
1240 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1241 objc_class_section ();
1242 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1243 objc_meta_class_section ();
1244 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1245 objc_category_section ();
1246 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1247 objc_selector_refs_section ();
1248 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1249 objc_selector_fixup_section ();
1250 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1251 objc_symbols_section ();
1252 else if (!strncmp (name, "_OBJC_MODULES", 13))
1253 objc_module_info_section ();
1254 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1255 objc_image_info_section ();
1256 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1257 objc_cat_inst_meth_section ();
1258 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1259 objc_cat_cls_meth_section ();
1260 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1261 objc_cat_cls_meth_section ();
1262 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1263 objc_protocol_section ();
1264 else
1265 base_function ();
1267 else
1268 base_function ();
1271 /* This can be called with address expressions as "rtx".
1272 They must go in "const". */
1274 void
1275 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1276 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1278 if (GET_MODE_SIZE (mode) == 8)
1279 literal8_section ();
1280 else if (GET_MODE_SIZE (mode) == 4
1281 && (GET_CODE (x) == CONST_INT
1282 || GET_CODE (x) == CONST_DOUBLE))
1283 literal4_section ();
1284 else if (MACHOPIC_INDIRECT
1285 && (GET_CODE (x) == SYMBOL_REF
1286 || GET_CODE (x) == CONST
1287 || GET_CODE (x) == LABEL_REF))
1288 const_data_section ();
1289 else
1290 const_section ();
1293 void
1294 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1296 if (MACHOPIC_INDIRECT)
1297 mod_init_section ();
1298 else
1299 constructor_section ();
1300 assemble_align (POINTER_SIZE);
1301 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1303 if (! MACHOPIC_INDIRECT)
1304 fprintf (asm_out_file, ".reference .constructors_used\n");
1307 void
1308 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1310 if (MACHOPIC_INDIRECT)
1311 mod_term_section ();
1312 else
1313 destructor_section ();
1314 assemble_align (POINTER_SIZE);
1315 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1317 if (! MACHOPIC_INDIRECT)
1318 fprintf (asm_out_file, ".reference .destructors_used\n");
1321 void
1322 darwin_globalize_label (FILE *stream, const char *name)
1324 if (!!strncmp (name, "_OBJC_", 6))
1325 default_globalize_label (stream, name);
1328 /* Emit an assembler directive to set visibility for a symbol. The
1329 only supported visibilities are VISIBILITY_DEFAULT and
1330 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1331 extern". There is no MACH-O equivalent of ELF's
1332 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1334 void
1335 darwin_assemble_visibility (tree decl, int vis)
1337 if (vis == VISIBILITY_DEFAULT)
1339 else if (vis == VISIBILITY_HIDDEN)
1341 fputs ("\t.private_extern ", asm_out_file);
1342 assemble_name (asm_out_file,
1343 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1344 fputs ("\n", asm_out_file);
1346 else
1347 warning ("internal and protected visibility attributes not supported"
1348 "in this configuration; ignored");
1351 /* Output a difference of two labels that will be an assembly time
1352 constant if the two labels are local. (.long lab1-lab2 will be
1353 very different if lab1 is at the boundary between two sections; it
1354 will be relocated according to the second section, not the first,
1355 so one ends up with a difference between labels in different
1356 sections, which is bad in the dwarf2 eh context for instance.) */
1358 static int darwin_dwarf_label_counter;
1360 void
1361 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1362 const char *lab1, const char *lab2)
1364 const char *p = lab1 + (lab1[0] == '*');
1365 int islocaldiff = (p[0] == 'L');
1367 if (islocaldiff)
1368 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1369 else
1370 fprintf (file, "\t%s\t", ".long");
1371 assemble_name (file, lab1);
1372 fprintf (file, "-");
1373 assemble_name (file, lab2);
1374 if (islocaldiff)
1375 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1378 void
1379 darwin_file_end (void)
1381 machopic_finish (asm_out_file);
1382 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1384 constructor_section ();
1385 destructor_section ();
1386 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1390 #include "gt-darwin.h"