Daily bump.
[official-gcc.git] / gcc / config / darwin.c
blob6864f0c8288355fbd5b60eb06f852e0589bb5bc3
1 /* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001
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 STRIP_NAME_ENCODING (name, 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 STRIP_NAME_ENCODING (temp_name, 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 STRIP_NAME_ENCODING (name, 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 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
418 id2 = maybe_get_identifier (real_name);
419 if (id2)
420 TREE_SYMBOL_REFERENCED (id2) = 1;
424 /* Transform ORIG, which may be any data source, to the corresponding
425 source using indirections. */
428 machopic_indirect_data_reference (orig, reg)
429 rtx orig, reg;
431 rtx ptr_ref = orig;
433 if (! MACHOPIC_INDIRECT)
434 return orig;
436 if (GET_CODE (orig) == SYMBOL_REF)
438 const char *name = XSTR (orig, 0);
440 if (machopic_data_defined_p (name))
442 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
443 machopic_function_base_name ());
444 rtx offset = gen_rtx (CONST, Pmode,
445 gen_rtx (MINUS, Pmode, orig, pic_base));
447 #if defined (TARGET_TOC) /* i.e., PowerPC */
448 rtx hi_sum_reg = reg;
450 if (reg == NULL)
451 abort ();
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)));
459 orig = reg;
460 #else
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);
472 #endif
473 #endif
474 return orig;
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;
483 return ptr_ref;
485 else if (GET_CODE (orig) == CONST)
487 rtx base, result;
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),
493 reg);
494 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
495 (base == reg ? 0 : reg));
497 else
498 return orig;
500 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
501 result = plus_constant (base, INTVAL (orig));
502 else
503 result = gen_rtx (PLUS, Pmode, base, orig);
505 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
506 RTX_UNCHANGING_P (result) = 1;
508 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
510 if (reg)
512 emit_move_insn (reg, result);
513 result = reg;
515 else
517 result = force_reg (GET_MODE (result), result);
521 return result;
524 else if (GET_CODE (orig) == MEM)
525 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
526 /* When the target is i386, this code prevents crashes due to the
527 compiler's ignorance on how to move the PIC base register to
528 other registers. (The reload phase sometimes introduces such
529 insns.) */
530 else if (GET_CODE (orig) == PLUS
531 && GET_CODE (XEXP (orig, 0)) == REG
532 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
533 #ifdef I386
534 /* Prevent the same register from being erroneously used
535 as both the base and index registers. */
536 && GET_CODE (XEXP (orig, 1)) == CONST
537 #endif
538 && reg)
540 emit_move_insn (reg, XEXP (orig, 0));
541 XEXP (ptr_ref, 0) = reg;
543 return ptr_ref;
546 /* Transform TARGET (a MEM), which is a function call target, to the
547 corresponding symbol_stub if necessary. Return a new MEM. */
550 machopic_indirect_call_target (target)
551 rtx target;
553 if (GET_CODE (target) != MEM)
554 return target;
556 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
558 enum machine_mode mode = GET_MODE (XEXP (target, 0));
559 const char *name = XSTR (XEXP (target, 0), 0);
561 /* If the name is already defined, we need do nothing. */
562 if (name[0] == '!' && name[1] == 'T')
563 return target;
565 if (!machopic_name_defined_p (name))
567 const char *stub_name = machopic_stub_name (name);
569 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
570 RTX_UNCHANGING_P (target) = 1;
574 return target;
578 machopic_legitimize_pic_address (orig, mode, reg)
579 rtx orig, reg;
580 enum machine_mode mode;
582 rtx pic_ref = orig;
584 if (! MACHOPIC_PURE)
585 return orig;
587 /* First handle a simple SYMBOL_REF or LABEL_REF */
588 if (GET_CODE (orig) == LABEL_REF
589 || (GET_CODE (orig) == SYMBOL_REF
592 /* addr(foo) = &func+(foo-func) */
593 rtx pic_base;
595 orig = machopic_indirect_data_reference (orig, reg);
597 if (GET_CODE (orig) == PLUS
598 && GET_CODE (XEXP (orig, 0)) == REG)
600 if (reg == 0)
601 return force_reg (mode, orig);
603 emit_move_insn (reg, orig);
604 return reg;
607 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
609 if (GET_CODE (orig) == MEM)
611 if (reg == 0)
613 if (reload_in_progress)
614 abort ();
615 else
616 reg = gen_reg_rtx (Pmode);
619 #ifdef HAVE_lo_sum
620 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
621 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
623 rtx offset = gen_rtx (CONST, Pmode,
624 gen_rtx (MINUS, Pmode,
625 XEXP (orig, 0), pic_base));
626 #if defined (TARGET_TOC) /* i.e., PowerPC */
627 /* Generating a new reg may expose opportunities for
628 common subexpression elimination. */
629 rtx hi_sum_reg =
630 (reload_in_progress ? reg : gen_reg_rtx (SImode));
632 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
633 gen_rtx (PLUS, Pmode,
634 pic_offset_table_rtx,
635 gen_rtx (HIGH, Pmode, offset))));
636 emit_insn (gen_rtx (SET, VOIDmode, reg,
637 gen_rtx (MEM, GET_MODE (orig),
638 gen_rtx (LO_SUM, Pmode,
639 hi_sum_reg, offset))));
640 pic_ref = reg;
642 #else
643 emit_insn (gen_rtx (USE, VOIDmode,
644 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
646 emit_insn (gen_rtx (SET, VOIDmode, reg,
647 gen_rtx (HIGH, Pmode,
648 gen_rtx (CONST, Pmode, offset))));
649 emit_insn (gen_rtx (SET, VOIDmode, reg,
650 gen_rtx (LO_SUM, Pmode, reg,
651 gen_rtx (CONST, Pmode, offset))));
652 pic_ref = gen_rtx (PLUS, Pmode,
653 pic_offset_table_rtx, reg);
654 #endif
656 else
657 #endif /* HAVE_lo_sum */
659 rtx pic = pic_offset_table_rtx;
660 if (GET_CODE (pic) != REG)
662 emit_move_insn (reg, pic);
663 pic = reg;
665 #if 0
666 emit_insn (gen_rtx (USE, VOIDmode,
667 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
668 #endif
670 pic_ref = gen_rtx (PLUS, Pmode,
671 pic,
672 gen_rtx (CONST, Pmode,
673 gen_rtx (MINUS, Pmode,
674 XEXP (orig, 0),
675 pic_base)));
678 #if !defined (TARGET_TOC)
679 RTX_UNCHANGING_P (pic_ref) = 1;
680 emit_move_insn (reg, pic_ref);
681 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
682 #endif
684 else
687 #ifdef HAVE_lo_sum
688 if (GET_CODE (orig) == SYMBOL_REF
689 || GET_CODE (orig) == LABEL_REF)
691 rtx offset = gen_rtx (CONST, Pmode,
692 gen_rtx (MINUS, Pmode, orig, pic_base));
693 #if defined (TARGET_TOC) /* i.e., PowerPC */
694 rtx hi_sum_reg;
696 if (reg == 0)
698 if (reload_in_progress)
699 abort ();
700 else
701 reg = gen_reg_rtx (SImode);
704 hi_sum_reg = reg;
706 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
707 gen_rtx (PLUS, Pmode,
708 pic_offset_table_rtx,
709 gen_rtx (HIGH, Pmode, offset))));
710 emit_insn (gen_rtx (SET, VOIDmode, reg,
711 gen_rtx (LO_SUM, Pmode,
712 hi_sum_reg, offset)));
713 pic_ref = reg;
714 #else
715 emit_insn (gen_rtx (SET, VOIDmode, reg,
716 gen_rtx (HIGH, Pmode, offset)));
717 emit_insn (gen_rtx (SET, VOIDmode, reg,
718 gen_rtx (LO_SUM, Pmode, reg, offset)));
719 pic_ref = gen_rtx (PLUS, Pmode,
720 pic_offset_table_rtx, reg);
721 #endif
723 else
724 #endif /* HAVE_lo_sum */
726 if (GET_CODE (orig) == REG)
728 return orig;
730 else
732 rtx pic = pic_offset_table_rtx;
733 if (GET_CODE (pic) != REG)
735 emit_move_insn (reg, pic);
736 pic = reg;
738 #if 0
739 emit_insn (gen_rtx (USE, VOIDmode,
740 pic_offset_table_rtx));
741 #endif
742 pic_ref = gen_rtx (PLUS, Pmode,
743 pic,
744 gen_rtx (CONST, Pmode,
745 gen_rtx (MINUS, Pmode,
746 orig, pic_base)));
751 RTX_UNCHANGING_P (pic_ref) = 1;
753 if (GET_CODE (pic_ref) != REG)
755 if (reg != 0)
757 emit_move_insn (reg, pic_ref);
758 return reg;
760 else
762 return force_reg (mode, pic_ref);
765 else
767 return pic_ref;
771 else if (GET_CODE (orig) == SYMBOL_REF)
772 return orig;
774 else if (GET_CODE (orig) == PLUS
775 && (GET_CODE (XEXP (orig, 0)) == MEM
776 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
777 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
778 && XEXP (orig, 0) != pic_offset_table_rtx
779 && GET_CODE (XEXP (orig, 1)) != REG)
782 rtx base;
783 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
785 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
786 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
787 Pmode, (base == reg ? 0 : reg));
788 if (GET_CODE (orig) == CONST_INT)
790 pic_ref = plus_constant (base, INTVAL (orig));
791 is_complex = 1;
793 else
794 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
796 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
797 RTX_UNCHANGING_P (pic_ref) = 1;
799 if (reg && is_complex)
801 emit_move_insn (reg, pic_ref);
802 pic_ref = reg;
804 /* Likewise, should we set special REG_NOTEs here? */
807 else if (GET_CODE (orig) == CONST)
809 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
812 else if (GET_CODE (orig) == MEM
813 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
815 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
817 addr = gen_rtx (MEM, GET_MODE (orig), addr);
818 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
819 emit_move_insn (reg, addr);
820 pic_ref = reg;
823 return pic_ref;
827 void
828 machopic_finish (asm_out_file)
829 FILE *asm_out_file;
831 tree temp;
833 for (temp = machopic_stubs;
834 temp != NULL_TREE;
835 temp = TREE_CHAIN (temp))
837 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
838 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
839 char *sym;
840 char *stub;
842 if (! TREE_USED (temp))
843 continue;
845 /* If the symbol is actually defined, we don't need a stub. */
846 if (sym_name[0] == '!' && sym_name[1] == 'T')
847 continue;
849 STRIP_NAME_ENCODING (sym_name, sym_name);
851 sym = alloca (strlen (sym_name) + 2);
852 if (sym_name[0] == '*' || sym_name[0] == '&')
853 strcpy (sym, sym_name + 1);
854 else if (sym_name[0] == '-' || sym_name[0] == '+')
855 strcpy (sym, sym_name);
856 else
857 sym[0] = '_', strcpy (sym + 1, sym_name);
859 stub = alloca (strlen (stub_name) + 2);
860 if (stub_name[0] == '*' || stub_name[0] == '&')
861 strcpy (stub, stub_name + 1);
862 else
863 stub[0] = '_', strcpy (stub + 1, stub_name);
865 machopic_output_stub (asm_out_file, sym, stub);
868 for (temp = machopic_non_lazy_pointers;
869 temp != NULL_TREE;
870 temp = TREE_CHAIN (temp))
872 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
873 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
874 #if 0
875 tree decl = lookup_name_darwin (TREE_VALUE (temp));
876 #endif
878 if (! TREE_USED (temp))
879 continue;
881 if (machopic_ident_defined_p (TREE_VALUE (temp))
882 #if 0 /* add back when we have private externs */
883 || (decl && DECL_PRIVATE_EXTERN (decl))
884 #endif
887 data_section ();
888 assemble_align (GET_MODE_ALIGNMENT (Pmode));
889 assemble_label (lazy_name);
890 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
891 GET_MODE_SIZE (Pmode),
892 GET_MODE_ALIGNMENT (Pmode), 1);
894 else
896 machopic_nl_symbol_ptr_section ();
897 assemble_name (asm_out_file, lazy_name);
898 fprintf (asm_out_file, ":\n");
900 fprintf (asm_out_file, "\t.indirect_symbol ");
901 assemble_name (asm_out_file, sym_name);
902 fprintf (asm_out_file, "\n");
904 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
905 GET_MODE_ALIGNMENT (Pmode), 1);
910 int
911 machopic_operand_p (op)
912 rtx op;
914 if (MACHOPIC_JUST_INDIRECT)
916 while (GET_CODE (op) == CONST)
917 op = XEXP (op, 0);
919 if (GET_CODE (op) == SYMBOL_REF)
920 return machopic_name_defined_p (XSTR (op, 0));
921 else
922 return 0;
925 while (GET_CODE (op) == CONST)
926 op = XEXP (op, 0);
928 if (GET_CODE (op) == MINUS
929 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
930 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
931 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
932 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
933 return 1;
935 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
936 /* Without this statement, the compiler crashes while compiling enquire.c
937 when targetting PowerPC. It is not known why this code is not needed
938 when targetting other processors. */
939 else if (GET_CODE (op) == SYMBOL_REF
940 && (machopic_classify_name (XSTR (op, 0))
941 == MACHOPIC_DEFINED_FUNCTION))
943 return 1;
945 #endif
947 return 0;
950 /* This function records whether a given name corresponds to a defined
951 or undefined function or variable, for machopic_classify_ident to
952 use later. */
954 void
955 darwin_encode_section_info (decl)
956 tree decl;
958 char code = '\0';
959 int defined = 0;
960 rtx sym_ref;
961 const char *orig_str;
962 char *new_str;
963 size_t len, new_len;
965 if ((TREE_CODE (decl) == FUNCTION_DECL
966 || TREE_CODE (decl) == VAR_DECL)
967 && !DECL_EXTERNAL (decl)
968 && ((TREE_STATIC (decl)
969 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
970 || (DECL_INITIAL (decl)
971 && DECL_INITIAL (decl) != error_mark_node)))
972 defined = 1;
974 if (TREE_CODE (decl) == FUNCTION_DECL)
975 code = (defined ? 'T' : 't');
976 else if (TREE_CODE (decl) == VAR_DECL)
977 code = (defined ? 'D' : 'd');
979 if (code == '\0')
980 return;
982 sym_ref = XEXP (DECL_RTL (decl), 0);
983 orig_str = XSTR (sym_ref, 0);
984 len = strlen (orig_str) + 1;
986 if (orig_str[0] == '!')
988 /* Already encoded; see if we need to change it. */
989 if (code == orig_str[1])
990 return;
991 /* Yes, tweak a copy of the name and put it in a new string. */
992 new_str = alloca (len);
993 memcpy (new_str, orig_str, len);
994 new_str[1] = code;
995 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
997 else
999 /* Add the encoding. */
1000 new_len = len + 4;
1001 new_str = alloca (new_len);
1002 new_str[0] = '!';
1003 new_str[1] = code;
1004 new_str[2] = '_';
1005 new_str[3] = '_';
1006 memcpy (new_str + 4, orig_str, len);
1007 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1009 /* The non-lazy pointer list may have captured references to the
1010 old encoded name, change them. */
1011 if (TREE_CODE (decl) == VAR_DECL)
1012 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1013 else
1014 update_stubs (XSTR (sym_ref, 0));
1017 /* Scan the list of non-lazy pointers and update any recorded names whose
1018 stripped name matches the argument. */
1020 static void
1021 update_non_lazy_ptrs (name)
1022 const char *name;
1024 const char *name1, *name2;
1025 tree temp;
1027 STRIP_NAME_ENCODING (name1, name);
1029 for (temp = machopic_non_lazy_pointers;
1030 temp != NULL_TREE;
1031 temp = TREE_CHAIN (temp))
1033 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1035 if (*sym_name == '!')
1037 STRIP_NAME_ENCODING (name2, sym_name);
1038 if (strcmp (name1, name2) == 0)
1040 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1041 break;
1047 /* Function NAME is being defined, and its label has just been output.
1048 If there's already a reference to a stub for this function, we can
1049 just emit the stub label now and we don't bother emitting the stub later. */
1051 void
1052 machopic_output_possible_stub_label (file, name)
1053 FILE *file;
1054 const char *name;
1056 tree temp;
1059 /* Ensure we're looking at a section-encoded name. */
1060 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1061 return;
1063 for (temp = machopic_stubs;
1064 temp != NULL_TREE;
1065 temp = TREE_CHAIN (temp))
1067 const char *sym_name;
1069 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1070 if (sym_name[0] == '!' && sym_name[1] == 'T'
1071 && ! strcmp (name+2, sym_name+2))
1073 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1074 /* Avoid generating a stub for this. */
1075 TREE_USED (temp) = 0;
1076 break;
1081 /* Scan the list of stubs and update any recorded names whose
1082 stripped name matches the argument. */
1084 static void
1085 update_stubs (name)
1086 const char *name;
1088 const char *name1, *name2;
1089 tree temp;
1091 STRIP_NAME_ENCODING (name1, name);
1093 for (temp = machopic_stubs;
1094 temp != NULL_TREE;
1095 temp = TREE_CHAIN (temp))
1097 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1099 if (*sym_name == '!')
1101 STRIP_NAME_ENCODING (name2, sym_name);
1102 if (strcmp (name1, name2) == 0)
1104 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1105 break;
1111 void
1112 machopic_asm_out_constructor (symbol, priority)
1113 rtx symbol;
1114 int priority ATTRIBUTE_UNUSED;
1116 if (flag_pic)
1117 mod_init_section ();
1118 else
1119 constructor_section ();
1120 assemble_align (POINTER_SIZE);
1121 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1123 if (!flag_pic)
1124 fprintf (asm_out_file, ".reference .constructors_used\n");
1127 void
1128 machopic_asm_out_destructor (symbol, priority)
1129 rtx symbol;
1130 int priority ATTRIBUTE_UNUSED;
1132 if (flag_pic)
1133 mod_term_section ();
1134 else
1135 destructor_section ();
1136 assemble_align (POINTER_SIZE);
1137 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1139 if (!flag_pic)
1140 fprintf (asm_out_file, ".reference .destructors_used\n");