stl_bvector.h (swap(_Bit_reference,_Bit_reference)): Move/rename...
[official-gcc.git] / gcc / config / darwin.c
blob3b9ee8c3cbc382e27db142a091378d9b06b7b7b7
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)
11 any later version.
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. */
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "tree.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "function.h"
39 #include "ggc.h"
40 #include "langhooks.h"
42 #include "darwin-protos.h"
44 extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
46 static int machopic_data_defined_p PARAMS ((const char *));
47 static int func_name_maybe_scoped PARAMS ((const char *));
48 static void update_non_lazy_ptrs PARAMS ((const char *));
49 static void update_stubs PARAMS ((const char *));
51 int
52 name_needs_quotes (name)
53 const char *name;
55 int c;
56 while ((c = *name++) != '\0')
57 if (! ISIDNUM (c))
58 return 1;
59 return 0;
62 /*
63 * flag_pic = 1 ... generate only indirections
64 * flag_pic = 2 ... generate indirections and pure code
67 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
68 reference, which will not be changed. */
70 static tree machopic_defined_list;
72 enum machopic_addr_class
73 machopic_classify_ident (ident)
74 tree ident;
76 const char *name = IDENTIFIER_POINTER (ident);
77 int lprefix = (((name[0] == '*' || name[0] == '&')
78 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
79 || ( name[0] == '_'
80 && name[1] == 'O'
81 && name[2] == 'B'
82 && name[3] == 'J'
83 && name[4] == 'C'
84 && name[5] == '_'));
85 tree temp;
87 if (name[0] != '!')
89 /* Here if no special encoding to be found. */
90 if (lprefix)
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;
102 temp != NULL_TREE;
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')
128 char *new_name;
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))
141 if (name[1] == 'T')
142 return MACHOPIC_DEFINED_FUNCTION;
143 else
144 return MACHOPIC_DEFINED_DATA;
148 if (name[1] == 't' || name[1] == 'T')
150 if (lprefix)
151 return MACHOPIC_DEFINED_FUNCTION;
152 else
153 return MACHOPIC_UNDEFINED_FUNCTION;
155 else
157 if (lprefix)
158 return MACHOPIC_DEFINED_DATA;
159 else
160 return MACHOPIC_UNDEFINED_DATA;
165 enum machopic_addr_class
166 machopic_classify_name (name)
167 const char *name;
169 return machopic_classify_ident (get_identifier (name));
173 machopic_ident_defined_p (ident)
174 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 (name)
189 const char *name;
191 switch (machopic_classify_ident (get_identifier (name)))
193 case MACHOPIC_DEFINED_DATA:
194 return 1;
195 default:
196 return 0;
201 machopic_name_defined_p (name)
202 const char *name;
204 return machopic_ident_defined_p (get_identifier (name));
207 void
208 machopic_define_ident (ident)
209 tree ident;
211 if (!machopic_ident_defined_p (ident))
212 machopic_defined_list =
213 tree_cons (NULL_TREE, ident, machopic_defined_list);
216 void
217 machopic_define_name (name)
218 const char *name;
220 machopic_define_ident (get_identifier (name));
223 /* This is a static to make inline functions work. The rtx
224 representing the PIC base symbol always points to here. */
226 static char function_base[32];
228 static int current_pic_label_num;
230 char *
231 machopic_function_base_name ()
233 static const char *name = NULL;
234 static const char *current_name;
236 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
238 if (name != current_name)
240 current_function_uses_pic_offset_table = 1;
242 /* Save mucho space and time. Some of the C++ mangled names are over
243 700 characters long! Note that we produce a label containing a '-'
244 if the function we're compiling is an Objective-C method, as evinced
245 by the incredibly scientific test below. This is because code in
246 rs6000.c makes the same ugly test when loading the PIC reg. */
248 ++current_pic_label_num;
249 if (*current_name == '+' || *current_name == '-')
250 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
251 else
252 sprintf (function_base, "*L%d$pb", current_pic_label_num);
254 name = current_name;
257 return function_base;
260 static tree machopic_non_lazy_pointers = NULL;
262 /* Return a non-lazy pointer name corresponding to the given name,
263 either by finding it in our list of pointer names, or by generating
264 a new one. */
266 char *
267 machopic_non_lazy_ptr_name (name)
268 const char *name;
270 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 tree ptr_name;
301 buffer = alloca (strlen (name) + 20);
303 strcpy (buffer, "&L");
304 if (name[0] == '*')
305 strcat (buffer, name+1);
306 else
308 strcat (buffer, "_");
309 strcat (buffer, name);
312 strcat (buffer, "$non_lazy_ptr");
313 ptr_name = get_identifier (buffer);
315 machopic_non_lazy_pointers
316 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
318 TREE_USED (machopic_non_lazy_pointers) = 0;
320 return IDENTIFIER_POINTER (ptr_name);
324 static tree machopic_stubs = 0;
326 /* Make sure the GC knows about our homemade lists. */
328 void
329 machopic_add_gc_roots ()
331 ggc_add_tree_root (&machopic_defined_list, 1);
332 ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
333 ggc_add_tree_root (&machopic_stubs, 1);
336 /* Return the name of the stub corresponding to the given name,
337 generating a new stub name if necessary. */
339 char *
340 machopic_stub_name (name)
341 const char *name;
343 tree temp, ident = get_identifier (name);
344 const char *tname;
346 for (temp = machopic_stubs;
347 temp != NULL_TREE;
348 temp = TREE_CHAIN (temp))
350 if (ident == TREE_VALUE (temp))
351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
352 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
353 if (strcmp (name, tname) == 0)
354 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
355 /* A library call name might not be section-encoded yet, so try
356 it against a stripped name. */
357 if (name[0] != '!'
358 && tname[0] == '!'
359 && strcmp (name, tname + 4) == 0)
360 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
363 name = darwin_strip_name_encoding (name);
366 char *buffer;
367 tree ptr_name;
368 int needs_quotes = name_needs_quotes (name);
370 buffer = alloca (strlen (name) + 20);
372 if (needs_quotes)
373 strcpy (buffer, "&\"L");
374 else
375 strcpy (buffer, "&L");
376 if (name[0] == '*')
378 strcat (buffer, name+1);
380 else
382 strcat (buffer, "_");
383 strcat (buffer, name);
386 if (needs_quotes)
387 strcat (buffer, "$stub\"");
388 else
389 strcat (buffer, "$stub");
390 ptr_name = get_identifier (buffer);
392 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
393 TREE_USED (machopic_stubs) = 0;
395 return IDENTIFIER_POINTER (ptr_name);
399 void
400 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
401 const char *name;
402 int validate_stub;
404 char *real_name;
405 tree temp, ident = get_identifier (name), id2;
407 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
408 temp != NULL_TREE;
409 temp = TREE_CHAIN (temp))
410 if (ident == TREE_PURPOSE (temp))
412 /* Mark both the stub or non-lazy pointer as well as the
413 original symbol as being referenced. */
414 TREE_USED (temp) = 1;
415 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
416 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
417 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
418 real_name = darwin_strip_name_encoding (real_name);
419 id2 = maybe_get_identifier (real_name);
420 if (id2)
421 TREE_SYMBOL_REFERENCED (id2) = 1;
425 /* Transform ORIG, which may be any data source, to the corresponding
426 source using indirections. */
429 machopic_indirect_data_reference (orig, reg)
430 rtx orig, reg;
432 rtx ptr_ref = orig;
434 if (! MACHOPIC_INDIRECT)
435 return orig;
437 if (GET_CODE (orig) == SYMBOL_REF)
439 const char *name = XSTR (orig, 0);
441 if (machopic_data_defined_p (name))
443 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
444 machopic_function_base_name ());
445 rtx offset = gen_rtx (CONST, Pmode,
446 gen_rtx (MINUS, Pmode, orig, pic_base));
448 #if defined (TARGET_TOC) /* i.e., PowerPC */
449 rtx hi_sum_reg = reg;
451 if (reg == NULL)
452 abort ();
454 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
455 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
456 gen_rtx (HIGH, Pmode, offset))));
457 emit_insn (gen_rtx (SET, Pmode, reg,
458 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
460 orig = reg;
461 #else
462 #if defined (HAVE_lo_sum)
463 if (reg == 0) abort ();
465 emit_insn (gen_rtx (SET, VOIDmode, reg,
466 gen_rtx (HIGH, Pmode, offset)));
467 emit_insn (gen_rtx (SET, VOIDmode, reg,
468 gen_rtx (LO_SUM, Pmode, reg, offset)));
469 emit_insn (gen_rtx (USE, VOIDmode,
470 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
472 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
473 #endif
474 #endif
475 return orig;
478 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
479 machopic_non_lazy_ptr_name (name));
481 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
482 RTX_UNCHANGING_P (ptr_ref) = 1;
484 return ptr_ref;
486 else if (GET_CODE (orig) == CONST)
488 rtx base, result;
490 /* legitimize both operands of the PLUS */
491 if (GET_CODE (XEXP (orig, 0)) == PLUS)
493 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
494 reg);
495 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
496 (base == reg ? 0 : reg));
498 else
499 return orig;
501 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
502 result = plus_constant (base, INTVAL (orig));
503 else
504 result = gen_rtx (PLUS, Pmode, base, orig);
506 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
507 RTX_UNCHANGING_P (result) = 1;
509 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
511 if (reg)
513 emit_move_insn (reg, result);
514 result = reg;
516 else
518 result = force_reg (GET_MODE (result), result);
522 return result;
525 else if (GET_CODE (orig) == MEM)
526 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
527 /* When the target is i386, this code prevents crashes due to the
528 compiler's ignorance on how to move the PIC base register to
529 other registers. (The reload phase sometimes introduces such
530 insns.) */
531 else if (GET_CODE (orig) == PLUS
532 && GET_CODE (XEXP (orig, 0)) == REG
533 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
534 #ifdef I386
535 /* Prevent the same register from being erroneously used
536 as both the base and index registers. */
537 && GET_CODE (XEXP (orig, 1)) == CONST
538 #endif
539 && reg)
541 emit_move_insn (reg, XEXP (orig, 0));
542 XEXP (ptr_ref, 0) = reg;
544 return ptr_ref;
547 /* Transform TARGET (a MEM), which is a function call target, to the
548 corresponding symbol_stub if necessary. Return a new MEM. */
551 machopic_indirect_call_target (target)
552 rtx target;
554 if (GET_CODE (target) != MEM)
555 return target;
557 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
559 enum machine_mode mode = GET_MODE (XEXP (target, 0));
560 const char *name = XSTR (XEXP (target, 0), 0);
562 /* If the name is already defined, we need do nothing. */
563 if (name[0] == '!' && name[1] == 'T')
564 return target;
566 if (!machopic_name_defined_p (name))
568 const char *stub_name = machopic_stub_name (name);
570 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
571 RTX_UNCHANGING_P (target) = 1;
575 return target;
579 machopic_legitimize_pic_address (orig, mode, reg)
580 rtx orig, reg;
581 enum machine_mode mode;
583 rtx pic_ref = orig;
585 if (! MACHOPIC_PURE)
586 return orig;
588 /* First handle a simple SYMBOL_REF or LABEL_REF */
589 if (GET_CODE (orig) == LABEL_REF
590 || (GET_CODE (orig) == SYMBOL_REF
593 /* addr(foo) = &func+(foo-func) */
594 rtx pic_base;
596 orig = machopic_indirect_data_reference (orig, reg);
598 if (GET_CODE (orig) == PLUS
599 && GET_CODE (XEXP (orig, 0)) == REG)
601 if (reg == 0)
602 return force_reg (mode, orig);
604 emit_move_insn (reg, orig);
605 return reg;
608 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
610 if (GET_CODE (orig) == MEM)
612 if (reg == 0)
614 if (reload_in_progress)
615 abort ();
616 else
617 reg = gen_reg_rtx (Pmode);
620 #ifdef HAVE_lo_sum
621 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
622 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
624 rtx offset = gen_rtx (CONST, Pmode,
625 gen_rtx (MINUS, Pmode,
626 XEXP (orig, 0), pic_base));
627 #if defined (TARGET_TOC) /* i.e., PowerPC */
628 /* Generating a new reg may expose opportunities for
629 common subexpression elimination. */
630 rtx hi_sum_reg =
631 (reload_in_progress ? reg : gen_reg_rtx (SImode));
633 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
634 gen_rtx (PLUS, Pmode,
635 pic_offset_table_rtx,
636 gen_rtx (HIGH, Pmode, offset))));
637 emit_insn (gen_rtx (SET, VOIDmode, reg,
638 gen_rtx (MEM, GET_MODE (orig),
639 gen_rtx (LO_SUM, Pmode,
640 hi_sum_reg, offset))));
641 pic_ref = reg;
643 #else
644 emit_insn (gen_rtx (USE, VOIDmode,
645 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
647 emit_insn (gen_rtx (SET, VOIDmode, reg,
648 gen_rtx (HIGH, Pmode,
649 gen_rtx (CONST, Pmode, offset))));
650 emit_insn (gen_rtx (SET, VOIDmode, reg,
651 gen_rtx (LO_SUM, Pmode, reg,
652 gen_rtx (CONST, Pmode, offset))));
653 pic_ref = gen_rtx (PLUS, Pmode,
654 pic_offset_table_rtx, reg);
655 #endif
657 else
658 #endif /* HAVE_lo_sum */
660 rtx pic = pic_offset_table_rtx;
661 if (GET_CODE (pic) != REG)
663 emit_move_insn (reg, pic);
664 pic = reg;
666 #if 0
667 emit_insn (gen_rtx (USE, VOIDmode,
668 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
669 #endif
671 pic_ref = gen_rtx (PLUS, Pmode,
672 pic,
673 gen_rtx (CONST, Pmode,
674 gen_rtx (MINUS, Pmode,
675 XEXP (orig, 0),
676 pic_base)));
679 #if !defined (TARGET_TOC)
680 RTX_UNCHANGING_P (pic_ref) = 1;
681 emit_move_insn (reg, pic_ref);
682 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
683 #endif
685 else
688 #ifdef HAVE_lo_sum
689 if (GET_CODE (orig) == SYMBOL_REF
690 || GET_CODE (orig) == LABEL_REF)
692 rtx offset = gen_rtx (CONST, Pmode,
693 gen_rtx (MINUS, Pmode, orig, pic_base));
694 #if defined (TARGET_TOC) /* i.e., PowerPC */
695 rtx hi_sum_reg;
697 if (reg == 0)
699 if (reload_in_progress)
700 abort ();
701 else
702 reg = gen_reg_rtx (SImode);
705 hi_sum_reg = reg;
707 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
708 gen_rtx (PLUS, Pmode,
709 pic_offset_table_rtx,
710 gen_rtx (HIGH, Pmode, offset))));
711 emit_insn (gen_rtx (SET, VOIDmode, reg,
712 gen_rtx (LO_SUM, Pmode,
713 hi_sum_reg, offset)));
714 pic_ref = reg;
715 #else
716 emit_insn (gen_rtx (SET, VOIDmode, reg,
717 gen_rtx (HIGH, Pmode, offset)));
718 emit_insn (gen_rtx (SET, VOIDmode, reg,
719 gen_rtx (LO_SUM, Pmode, reg, offset)));
720 pic_ref = gen_rtx (PLUS, Pmode,
721 pic_offset_table_rtx, reg);
722 #endif
724 else
725 #endif /* HAVE_lo_sum */
727 if (GET_CODE (orig) == REG)
729 return orig;
731 else
733 rtx pic = pic_offset_table_rtx;
734 if (GET_CODE (pic) != REG)
736 emit_move_insn (reg, pic);
737 pic = reg;
739 #if 0
740 emit_insn (gen_rtx (USE, VOIDmode,
741 pic_offset_table_rtx));
742 #endif
743 pic_ref = gen_rtx (PLUS, Pmode,
744 pic,
745 gen_rtx (CONST, Pmode,
746 gen_rtx (MINUS, Pmode,
747 orig, pic_base)));
752 RTX_UNCHANGING_P (pic_ref) = 1;
754 if (GET_CODE (pic_ref) != REG)
756 if (reg != 0)
758 emit_move_insn (reg, pic_ref);
759 return reg;
761 else
763 return force_reg (mode, pic_ref);
766 else
768 return pic_ref;
772 else if (GET_CODE (orig) == SYMBOL_REF)
773 return orig;
775 else if (GET_CODE (orig) == PLUS
776 && (GET_CODE (XEXP (orig, 0)) == MEM
777 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
778 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
779 && XEXP (orig, 0) != pic_offset_table_rtx
780 && GET_CODE (XEXP (orig, 1)) != REG)
783 rtx base;
784 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
786 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
787 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
788 Pmode, (base == reg ? 0 : reg));
789 if (GET_CODE (orig) == CONST_INT)
791 pic_ref = plus_constant (base, INTVAL (orig));
792 is_complex = 1;
794 else
795 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
797 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
798 RTX_UNCHANGING_P (pic_ref) = 1;
800 if (reg && is_complex)
802 emit_move_insn (reg, pic_ref);
803 pic_ref = reg;
805 /* Likewise, should we set special REG_NOTEs here? */
808 else if (GET_CODE (orig) == CONST)
810 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
813 else if (GET_CODE (orig) == MEM
814 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
816 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
818 addr = gen_rtx (MEM, GET_MODE (orig), addr);
819 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
820 emit_move_insn (reg, addr);
821 pic_ref = reg;
824 return pic_ref;
828 void
829 machopic_finish (asm_out_file)
830 FILE *asm_out_file;
832 tree temp;
834 for (temp = machopic_stubs;
835 temp != NULL_TREE;
836 temp = TREE_CHAIN (temp))
838 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
839 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
840 char *sym;
841 char *stub;
843 if (! TREE_USED (temp))
844 continue;
846 /* If the symbol is actually defined, we don't need a stub. */
847 if (sym_name[0] == '!' && sym_name[1] == 'T')
848 continue;
850 sym_name = darwin_strip_name_encoding (sym_name);
852 sym = alloca (strlen (sym_name) + 2);
853 if (sym_name[0] == '*' || sym_name[0] == '&')
854 strcpy (sym, sym_name + 1);
855 else if (sym_name[0] == '-' || sym_name[0] == '+')
856 strcpy (sym, sym_name);
857 else
858 sym[0] = '_', strcpy (sym + 1, sym_name);
860 stub = alloca (strlen (stub_name) + 2);
861 if (stub_name[0] == '*' || stub_name[0] == '&')
862 strcpy (stub, stub_name + 1);
863 else
864 stub[0] = '_', strcpy (stub + 1, stub_name);
866 machopic_output_stub (asm_out_file, sym, stub);
869 for (temp = machopic_non_lazy_pointers;
870 temp != NULL_TREE;
871 temp = TREE_CHAIN (temp))
873 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
874 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
875 #if 0
876 tree decl = lookup_name_darwin (TREE_VALUE (temp));
877 #endif
879 if (! TREE_USED (temp))
880 continue;
882 if (machopic_ident_defined_p (TREE_VALUE (temp))
883 #if 0 /* add back when we have private externs */
884 || (decl && DECL_PRIVATE_EXTERN (decl))
885 #endif
888 data_section ();
889 assemble_align (GET_MODE_ALIGNMENT (Pmode));
890 assemble_label (lazy_name);
891 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
892 GET_MODE_SIZE (Pmode),
893 GET_MODE_ALIGNMENT (Pmode), 1);
895 else
897 machopic_nl_symbol_ptr_section ();
898 assemble_name (asm_out_file, lazy_name);
899 fprintf (asm_out_file, ":\n");
901 fprintf (asm_out_file, "\t.indirect_symbol ");
902 assemble_name (asm_out_file, sym_name);
903 fprintf (asm_out_file, "\n");
905 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
906 GET_MODE_ALIGNMENT (Pmode), 1);
911 int
912 machopic_operand_p (op)
913 rtx op;
915 if (MACHOPIC_JUST_INDIRECT)
917 while (GET_CODE (op) == CONST)
918 op = XEXP (op, 0);
920 if (GET_CODE (op) == SYMBOL_REF)
921 return machopic_name_defined_p (XSTR (op, 0));
922 else
923 return 0;
926 while (GET_CODE (op) == CONST)
927 op = XEXP (op, 0);
929 if (GET_CODE (op) == MINUS
930 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
931 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
932 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
933 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
934 return 1;
936 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
937 /* Without this statement, the compiler crashes while compiling enquire.c
938 when targetting PowerPC. It is not known why this code is not needed
939 when targetting other processors. */
940 else if (GET_CODE (op) == SYMBOL_REF
941 && (machopic_classify_name (XSTR (op, 0))
942 == MACHOPIC_DEFINED_FUNCTION))
944 return 1;
946 #endif
948 return 0;
951 /* This function records whether a given name corresponds to a defined
952 or undefined function or variable, for machopic_classify_ident to
953 use later. */
955 void
956 darwin_encode_section_info (decl, first)
957 tree decl;
958 int first ATTRIBUTE_UNUSED;
960 char code = '\0';
961 int defined = 0;
962 rtx sym_ref;
963 const char *orig_str;
964 char *new_str;
965 size_t len, new_len;
967 if ((TREE_CODE (decl) == FUNCTION_DECL
968 || TREE_CODE (decl) == VAR_DECL)
969 && !DECL_EXTERNAL (decl)
970 && ((TREE_STATIC (decl)
971 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
972 || (DECL_INITIAL (decl)
973 && DECL_INITIAL (decl) != error_mark_node)))
974 defined = 1;
976 if (TREE_CODE (decl) == FUNCTION_DECL)
977 code = (defined ? 'T' : 't');
978 else if (TREE_CODE (decl) == VAR_DECL)
979 code = (defined ? 'D' : 'd');
981 if (code == '\0')
982 return;
984 sym_ref = XEXP (DECL_RTL (decl), 0);
985 orig_str = XSTR (sym_ref, 0);
986 len = strlen (orig_str) + 1;
988 if (orig_str[0] == '!')
990 /* Already encoded; see if we need to change it. */
991 if (code == orig_str[1])
992 return;
993 /* Yes, tweak a copy of the name and put it in a new string. */
994 new_str = alloca (len);
995 memcpy (new_str, orig_str, len);
996 new_str[1] = code;
997 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
999 else
1001 /* Add the encoding. */
1002 new_len = len + 4;
1003 new_str = alloca (new_len);
1004 new_str[0] = '!';
1005 new_str[1] = code;
1006 new_str[2] = '_';
1007 new_str[3] = '_';
1008 memcpy (new_str + 4, orig_str, len);
1009 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1011 /* The non-lazy pointer list may have captured references to the
1012 old encoded name, change them. */
1013 if (TREE_CODE (decl) == VAR_DECL)
1014 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1015 else
1016 update_stubs (XSTR (sym_ref, 0));
1019 /* Undo the effects of the above. */
1021 const char *
1022 darwin_strip_name_encoding (str)
1023 const char *str;
1025 return str[0] == '!' ? str + 4 : str;
1028 /* Scan the list of non-lazy pointers and update any recorded names whose
1029 stripped name matches the argument. */
1031 static void
1032 update_non_lazy_ptrs (name)
1033 const char *name;
1035 const char *name1, *name2;
1036 tree temp;
1038 name1 = darwin_strip_name_encoding (name);
1040 for (temp = machopic_non_lazy_pointers;
1041 temp != NULL_TREE;
1042 temp = TREE_CHAIN (temp))
1044 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1046 if (*sym_name == '!')
1048 name2 = darwin_strip_name_encoding (sym_name);
1049 if (strcmp (name1, name2) == 0)
1051 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1052 break;
1058 /* Function NAME is being defined, and its label has just been output.
1059 If there's already a reference to a stub for this function, we can
1060 just emit the stub label now and we don't bother emitting the stub later. */
1062 void
1063 machopic_output_possible_stub_label (file, name)
1064 FILE *file;
1065 const char *name;
1067 tree temp;
1070 /* Ensure we're looking at a section-encoded name. */
1071 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1072 return;
1074 for (temp = machopic_stubs;
1075 temp != NULL_TREE;
1076 temp = TREE_CHAIN (temp))
1078 const char *sym_name;
1080 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1081 if (sym_name[0] == '!' && sym_name[1] == 'T'
1082 && ! strcmp (name+2, sym_name+2))
1084 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1085 /* Avoid generating a stub for this. */
1086 TREE_USED (temp) = 0;
1087 break;
1092 /* Scan the list of stubs and update any recorded names whose
1093 stripped name matches the argument. */
1095 static void
1096 update_stubs (name)
1097 const char *name;
1099 const char *name1, *name2;
1100 tree temp;
1102 name1 = darwin_strip_name_encoding (name);
1104 for (temp = machopic_stubs;
1105 temp != NULL_TREE;
1106 temp = TREE_CHAIN (temp))
1108 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 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1116 break;
1122 void
1123 machopic_select_section (exp, reloc, align)
1124 tree exp;
1125 int reloc;
1126 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1128 if (TREE_CODE (exp) == STRING_CST)
1130 if (flag_writable_strings)
1131 data_section ();
1132 else if (TREE_STRING_LENGTH (exp) !=
1133 strlen (TREE_STRING_POINTER (exp)) + 1)
1134 readonly_data_section ();
1135 else
1136 cstring_section ();
1138 else if (TREE_CODE (exp) == INTEGER_CST
1139 || TREE_CODE (exp) == REAL_CST)
1141 tree size = TYPE_SIZE (TREE_TYPE (exp));
1143 if (TREE_CODE (size) == INTEGER_CST &&
1144 TREE_INT_CST_LOW (size) == 4 &&
1145 TREE_INT_CST_HIGH (size) == 0)
1146 literal4_section ();
1147 else if (TREE_CODE (size) == INTEGER_CST &&
1148 TREE_INT_CST_LOW (size) == 8 &&
1149 TREE_INT_CST_HIGH (size) == 0)
1150 literal8_section ();
1151 else
1152 readonly_data_section ();
1154 else if (TREE_CODE (exp) == CONSTRUCTOR
1155 && TREE_TYPE (exp)
1156 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1157 && TYPE_NAME (TREE_TYPE (exp)))
1159 tree name = TYPE_NAME (TREE_TYPE (exp));
1160 if (TREE_CODE (name) == TYPE_DECL)
1161 name = DECL_NAME (name);
1162 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1163 objc_constant_string_object_section ();
1164 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1165 objc_string_object_section ();
1166 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1168 if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1169 const_data_section ();
1170 else
1171 readonly_data_section ();
1173 else
1174 data_section ();
1176 else if (TREE_CODE (exp) == VAR_DECL &&
1177 DECL_NAME (exp) &&
1178 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1179 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1180 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1182 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1184 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1185 objc_cls_meth_section ();
1186 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1187 objc_inst_meth_section ();
1188 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1189 objc_cat_cls_meth_section ();
1190 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1191 objc_cat_inst_meth_section ();
1192 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1193 objc_class_vars_section ();
1194 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1195 objc_instance_vars_section ();
1196 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1197 objc_cat_cls_meth_section ();
1198 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1199 objc_class_names_section ();
1200 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1201 objc_meth_var_names_section ();
1202 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1203 objc_meth_var_types_section ();
1204 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1205 objc_cls_refs_section ();
1206 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1207 objc_class_section ();
1208 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1209 objc_meta_class_section ();
1210 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1211 objc_category_section ();
1212 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1213 objc_selector_refs_section ();
1214 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1215 objc_selector_fixup_section ();
1216 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1217 objc_symbols_section ();
1218 else if (!strncmp (name, "_OBJC_MODULES", 13))
1219 objc_module_info_section ();
1220 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1221 objc_cat_inst_meth_section ();
1222 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1223 objc_cat_cls_meth_section ();
1224 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1225 objc_cat_cls_meth_section ();
1226 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1227 objc_protocol_section ();
1228 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1229 && !TREE_SIDE_EFFECTS (exp))
1231 if (flag_pic && reloc)
1232 const_data_section ();
1233 else
1234 readonly_data_section ();
1236 else
1237 data_section ();
1239 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1241 if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1242 const_data_section ();
1243 else
1244 readonly_data_section ();
1246 else
1247 data_section ();
1250 /* This can be called with address expressions as "rtx".
1251 They must go in "const". */
1253 void
1254 machopic_select_rtx_section (mode, x, align)
1255 enum machine_mode mode;
1256 rtx x;
1257 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1259 if (GET_MODE_SIZE (mode) == 8)
1260 literal8_section ();
1261 else if (GET_MODE_SIZE (mode) == 4
1262 && (GET_CODE (x) == CONST_INT
1263 || GET_CODE (x) == CONST_DOUBLE))
1264 literal4_section ();
1265 else
1266 const_section ();
1269 void
1270 machopic_asm_out_constructor (symbol, priority)
1271 rtx symbol;
1272 int priority ATTRIBUTE_UNUSED;
1274 if (flag_pic)
1275 mod_init_section ();
1276 else
1277 constructor_section ();
1278 assemble_align (POINTER_SIZE);
1279 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1281 if (!flag_pic)
1282 fprintf (asm_out_file, ".reference .constructors_used\n");
1285 void
1286 machopic_asm_out_destructor (symbol, priority)
1287 rtx symbol;
1288 int priority ATTRIBUTE_UNUSED;
1290 if (flag_pic)
1291 mod_term_section ();
1292 else
1293 destructor_section ();
1294 assemble_align (POINTER_SIZE);
1295 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1297 if (!flag_pic)
1298 fprintf (asm_out_file, ".reference .destructors_used\n");