oops - omitted in previous delta
[official-gcc.git] / gcc / config / darwin.c
bloba46d46b7d5fff8addfd29d1eb7a4c5c7fbf003c4
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"
41 #include "darwin-protos.h"
43 extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
45 static int machopic_data_defined_p PARAMS ((const char *));
46 static int func_name_maybe_scoped PARAMS ((const char *));
47 static void update_non_lazy_ptrs PARAMS ((const char *));
48 static void update_stubs PARAMS ((const char *));
50 int
51 name_needs_quotes (name)
52 const char *name;
54 int c;
55 while ((c = *name++) != '\0')
56 if (!isalnum (c) && c != '_')
57 return 1;
58 return 0;
61 /*
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 tree machopic_defined_list;
71 enum machopic_addr_class
72 machopic_classify_ident (ident)
73 tree ident;
75 const char *name = IDENTIFIER_POINTER (ident);
76 int lprefix = (((name[0] == '*' || name[0] == '&')
77 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
78 || ( name[0] == '_'
79 && name[1] == 'O'
80 && name[2] == 'B'
81 && name[3] == 'J'
82 && name[4] == 'C'
83 && name[5] == '_'));
84 tree temp;
86 if (name[0] != '!')
88 /* Here if no special encoding to be found. */
89 if (lprefix)
91 const char *name = IDENTIFIER_POINTER (ident);
92 int len = strlen (name);
94 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
95 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
96 return MACHOPIC_DEFINED_FUNCTION;
97 return MACHOPIC_DEFINED_DATA;
100 for (temp = machopic_defined_list;
101 temp != NULL_TREE;
102 temp = TREE_CHAIN (temp))
104 if (ident == TREE_VALUE (temp))
105 return MACHOPIC_DEFINED_DATA;
108 if (TREE_ASM_WRITTEN (ident))
109 return MACHOPIC_DEFINED_DATA;
111 return MACHOPIC_UNDEFINED;
114 else if (name[1] == 'D')
115 return MACHOPIC_DEFINED_DATA;
117 else if (name[1] == 'T')
118 return MACHOPIC_DEFINED_FUNCTION;
120 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
122 if (ident == TREE_VALUE (temp))
124 if (name[1] == 'T')
125 return MACHOPIC_DEFINED_FUNCTION;
126 else
127 return MACHOPIC_DEFINED_DATA;
131 if (name[1] == 't' || name[1] == 'T')
133 if (lprefix)
134 return MACHOPIC_DEFINED_FUNCTION;
135 else
136 return MACHOPIC_UNDEFINED_FUNCTION;
138 else
140 if (lprefix)
141 return MACHOPIC_DEFINED_DATA;
142 else
143 return MACHOPIC_UNDEFINED_DATA;
148 enum machopic_addr_class
149 machopic_classify_name (name)
150 const char *name;
152 return machopic_classify_ident (get_identifier (name));
156 machopic_ident_defined_p (ident)
157 tree ident;
159 switch (machopic_classify_ident (ident))
161 case MACHOPIC_UNDEFINED:
162 case MACHOPIC_UNDEFINED_DATA:
163 case MACHOPIC_UNDEFINED_FUNCTION:
164 return 0;
165 default:
166 return 1;
170 static int
171 machopic_data_defined_p (name)
172 const char *name;
174 switch (machopic_classify_ident (get_identifier (name)))
176 case MACHOPIC_DEFINED_DATA:
177 return 1;
178 default:
179 return 0;
184 machopic_name_defined_p (name)
185 const char *name;
187 return machopic_ident_defined_p (get_identifier (name));
190 void
191 machopic_define_ident (ident)
192 tree ident;
194 if (!machopic_ident_defined_p (ident))
195 machopic_defined_list =
196 tree_cons (NULL_TREE, ident, machopic_defined_list);
199 void
200 machopic_define_name (name)
201 const char *name;
203 machopic_define_ident (get_identifier (name));
206 /* This is a static to make inline functions work. The rtx
207 representing the PIC base symbol always points to here. */
209 static char function_base[32];
211 static int current_pic_label_num;
213 char *
214 machopic_function_base_name ()
216 static const char *name = NULL;
217 static const char *current_name;
219 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
221 if (name != current_name)
223 current_function_uses_pic_offset_table = 1;
225 /* Save mucho space and time. Some of the C++ mangled names are over
226 700 characters long! Note that we produce a label containing a '-'
227 if the function we're compiling is an Objective-C method, as evinced
228 by the incredibly scientific test below. This is because code in
229 rs6000.c makes the same ugly test when loading the PIC reg. */
231 ++current_pic_label_num;
232 if (*current_name == '+' || *current_name == '-')
233 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
234 else
235 sprintf (function_base, "*L%d$pb", current_pic_label_num);
237 name = current_name;
240 return function_base;
243 static tree machopic_non_lazy_pointers = NULL;
245 /* Return a non-lazy pointer name corresponding to the given name,
246 either by finding it in our list of pointer names, or by generating
247 a new one. */
249 char *
250 machopic_non_lazy_ptr_name (name)
251 const char *name;
253 char *temp_name;
254 tree temp, ident = get_identifier (name);
256 for (temp = machopic_non_lazy_pointers;
257 temp != NULL_TREE;
258 temp = TREE_CHAIN (temp))
260 if (ident == TREE_VALUE (temp))
261 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
264 STRIP_NAME_ENCODING (name, name);
266 /* Try again, but comparing names this time. */
267 for (temp = machopic_non_lazy_pointers;
268 temp != NULL_TREE;
269 temp = TREE_CHAIN (temp))
271 if (TREE_VALUE (temp))
273 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
274 STRIP_NAME_ENCODING (temp_name, temp_name);
275 if (strcmp (name, temp_name) == 0)
276 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
281 char *buffer;
282 tree ptr_name;
284 buffer = alloca (strlen (name) + 20);
286 strcpy (buffer, "&L");
287 if (name[0] == '*')
288 strcat (buffer, name+1);
289 else
291 strcat (buffer, "_");
292 strcat (buffer, name);
295 strcat (buffer, "$non_lazy_ptr");
296 ptr_name = get_identifier (buffer);
298 machopic_non_lazy_pointers
299 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
301 TREE_USED (machopic_non_lazy_pointers) = 0;
303 return IDENTIFIER_POINTER (ptr_name);
307 static tree machopic_stubs = 0;
309 /* Make sure the GC knows about our homemade lists. */
311 void
312 machopic_add_gc_roots ()
314 ggc_add_tree_root (&machopic_defined_list, 1);
315 ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
316 ggc_add_tree_root (&machopic_stubs, 1);
319 /* Return the name of the stub corresponding to the given name,
320 generating a new stub name if necessary. */
322 char *
323 machopic_stub_name (name)
324 const char *name;
326 tree temp, ident = get_identifier (name);
327 const char *tname;
329 for (temp = machopic_stubs;
330 temp != NULL_TREE;
331 temp = TREE_CHAIN (temp))
333 if (ident == TREE_VALUE (temp))
334 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
335 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
336 if (strcmp (name, tname) == 0)
337 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
338 /* A library call name might not be section-encoded yet, so try
339 it against a stripped name. */
340 if (name[0] != '!'
341 && tname[0] == '!'
342 && strcmp (name, tname + 4) == 0)
343 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
346 STRIP_NAME_ENCODING (name, name);
349 char *buffer;
350 tree ptr_name;
351 int needs_quotes = name_needs_quotes (name);
353 buffer = alloca (strlen (name) + 20);
355 if (needs_quotes)
356 strcpy (buffer, "&\"L");
357 else
358 strcpy (buffer, "&L");
359 if (name[0] == '*')
361 strcat (buffer, name+1);
363 else
365 strcat (buffer, "_");
366 strcat (buffer, name);
369 if (needs_quotes)
370 strcat (buffer, "$stub\"");
371 else
372 strcat (buffer, "$stub");
373 ptr_name = get_identifier (buffer);
375 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
376 TREE_USED (machopic_stubs) = 0;
378 return IDENTIFIER_POINTER (ptr_name);
382 void
383 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
384 const char *name;
385 int validate_stub;
387 char *real_name;
388 tree temp, ident = get_identifier (name), id2;
390 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
391 temp != NULL_TREE;
392 temp = TREE_CHAIN (temp))
393 if (ident == TREE_PURPOSE (temp))
395 /* Mark both the stub or non-lazy pointer as well as the
396 original symbol as being referenced. */
397 TREE_USED (temp) = 1;
398 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
399 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
400 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
401 id2 = maybe_get_identifier (real_name);
402 if (id2)
403 TREE_SYMBOL_REFERENCED (id2) = 1;
407 /* Transform ORIG, which may be any data source, to the corresponding
408 source using indirections. */
411 machopic_indirect_data_reference (orig, reg)
412 rtx orig, reg;
414 rtx ptr_ref = orig;
416 if (! MACHOPIC_INDIRECT)
417 return orig;
419 if (GET_CODE (orig) == SYMBOL_REF)
421 const char *name = XSTR (orig, 0);
423 if (machopic_data_defined_p (name))
425 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
426 machopic_function_base_name ());
427 rtx offset = gen_rtx (CONST, Pmode,
428 gen_rtx (MINUS, Pmode, orig, pic_base));
430 #if defined (TARGET_TOC) /* i.e., PowerPC */
431 rtx hi_sum_reg = reg;
433 if (reg == NULL)
434 abort ();
436 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
437 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
438 gen_rtx (HIGH, Pmode, offset))));
439 emit_insn (gen_rtx (SET, Pmode, reg,
440 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
442 orig = reg;
443 #else
444 #if defined (HAVE_lo_sum)
445 if (reg == 0) abort ();
447 emit_insn (gen_rtx (SET, VOIDmode, reg,
448 gen_rtx (HIGH, Pmode, offset)));
449 emit_insn (gen_rtx (SET, VOIDmode, reg,
450 gen_rtx (LO_SUM, Pmode, reg, offset)));
451 emit_insn (gen_rtx (USE, VOIDmode,
452 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
454 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
455 #endif
456 #endif
457 return orig;
460 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
461 machopic_non_lazy_ptr_name (name));
463 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
464 RTX_UNCHANGING_P (ptr_ref) = 1;
466 return ptr_ref;
468 else if (GET_CODE (orig) == CONST)
470 rtx base, result;
472 /* legitimize both operands of the PLUS */
473 if (GET_CODE (XEXP (orig, 0)) == PLUS)
475 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
476 reg);
477 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
478 (base == reg ? 0 : reg));
480 else
481 return orig;
483 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
484 result = plus_constant (base, INTVAL (orig));
485 else
486 result = gen_rtx (PLUS, Pmode, base, orig);
488 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
489 RTX_UNCHANGING_P (result) = 1;
491 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
493 if (reg)
495 emit_move_insn (reg, result);
496 result = reg;
498 else
500 result = force_reg (GET_MODE (result), result);
504 return result;
507 else if (GET_CODE (orig) == MEM)
508 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
509 /* When the target is i386, this code prevents crashes due to the
510 compiler's ignorance on how to move the PIC base register to
511 other registers. (The reload phase sometimes introduces such
512 insns.) */
513 else if (GET_CODE (orig) == PLUS
514 && GET_CODE (XEXP (orig, 0)) == REG
515 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
516 #ifdef I386
517 /* Prevent the same register from being erroneously used
518 as both the base and index registers. */
519 && GET_CODE (XEXP (orig, 1)) == CONST
520 #endif
521 && reg)
523 emit_move_insn (reg, XEXP (orig, 0));
524 XEXP (ptr_ref, 0) = reg;
526 return ptr_ref;
529 /* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
531 extern "C" { int f(); }
532 struct X { int f(); int g(); };
533 int X::f() { ::f(); }
534 int X::g() { ::f(); f();}
536 This is hairy. Both calls to "::f()" need to be indirect (i.e., to
537 appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
538 GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
539 defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
540 returns TRUE when called with "f", which means that
541 MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
542 indirect one as it should.
544 Our quick-n-dirty solution to this is to call the following
545 FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
546 FNAME -- the name of the function which we're calling -- is NOT a
547 mangled C++ name, AND if the current function being compiled is a
548 method, and if so, use an "external" or "indirect" call.
550 Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
551 has already indicated that the target is NOT indirect.
553 This conservative solution will sometimes make indirect calls where
554 it might have been possible to make direct ones.
556 FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
557 which in turns means we should create a stub for an indirect call.
560 static int is_cplusplus = -1;
562 static int
563 func_name_maybe_scoped (fname)
564 const char *fname;
567 if (is_cplusplus < 0)
568 is_cplusplus = (strcmp (lang_identify (), "cplusplus") == 0);
570 if (is_cplusplus)
572 /* If we have a method, then check whether the function we're trying to
573 call is a "C" function. If so, we should use an indirect call.
575 It turns out to be hard to tell whether "we have a method", since
576 static member functions have a TREE_CODE of FUNCTION_TYPE, as do
577 namespace-level non-member functions. So here, we always look for
578 an extern-"C"-like name, and make stubs for them no matter the
579 calling context. This is temporary, and leaves nagging suspicion
580 that improvements should be possible here. (I.e., I suspect that
581 it can still sometimes make stubs where it needn't.) */
583 /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
585 /* If fname is of the form "f__1X" or "f__Fv", it's C++. */
586 while (*fname == '_') ++fname; /* skip leading underscores */
587 while (*fname != 0)
589 if (fname[0] == '_' && fname[1] == '_'
590 && (fname[2] == 'F' || (fname[2] >= '0' && fname[2] <= '9')))
591 return 0;
592 ++fname;
594 /* Not a C++ mangled name: must be "C", in which case play safe. */
595 return 1;
598 return 0;
601 /* Transform TARGET (a MEM), which is a function call target, to the
602 corresponding symbol_stub if necessary. Return a new MEM. */
605 machopic_indirect_call_target (target)
606 rtx target;
608 if (GET_CODE (target) != MEM)
609 return target;
611 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
613 enum machine_mode mode = GET_MODE (XEXP (target, 0));
614 const char *name = XSTR (XEXP (target, 0), 0);
616 if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name))
618 const char *stub_name = machopic_stub_name (name);
620 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
621 RTX_UNCHANGING_P (target) = 1;
625 return target;
629 machopic_legitimize_pic_address (orig, mode, reg)
630 rtx orig, reg;
631 enum machine_mode mode;
633 rtx pic_ref = orig;
635 if (! MACHOPIC_PURE)
636 return orig;
638 /* First handle a simple SYMBOL_REF or LABEL_REF */
639 if (GET_CODE (orig) == LABEL_REF
640 || (GET_CODE (orig) == SYMBOL_REF
643 /* addr(foo) = &func+(foo-func) */
644 rtx pic_base;
646 orig = machopic_indirect_data_reference (orig, reg);
648 if (GET_CODE (orig) == PLUS
649 && GET_CODE (XEXP (orig, 0)) == REG)
651 if (reg == 0)
652 return force_reg (mode, orig);
654 emit_move_insn (reg, orig);
655 return reg;
658 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
660 if (GET_CODE (orig) == MEM)
662 if (reg == 0)
664 if (reload_in_progress)
665 abort ();
666 else
667 reg = gen_reg_rtx (Pmode);
670 #ifdef HAVE_lo_sum
671 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
672 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
674 rtx offset = gen_rtx (CONST, Pmode,
675 gen_rtx (MINUS, Pmode,
676 XEXP (orig, 0), pic_base));
677 #if defined (TARGET_TOC) /* i.e., PowerPC */
678 /* Generating a new reg may expose opportunities for
679 common subexpression elimination. */
680 rtx hi_sum_reg =
681 (reload_in_progress ? reg : gen_reg_rtx (SImode));
683 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
684 gen_rtx (PLUS, Pmode,
685 pic_offset_table_rtx,
686 gen_rtx (HIGH, Pmode, offset))));
687 emit_insn (gen_rtx (SET, VOIDmode, reg,
688 gen_rtx (MEM, GET_MODE (orig),
689 gen_rtx (LO_SUM, Pmode,
690 hi_sum_reg, offset))));
691 pic_ref = reg;
693 #else
694 emit_insn (gen_rtx (USE, VOIDmode,
695 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
697 emit_insn (gen_rtx (SET, VOIDmode, reg,
698 gen_rtx (HIGH, Pmode,
699 gen_rtx (CONST, Pmode, offset))));
700 emit_insn (gen_rtx (SET, VOIDmode, reg,
701 gen_rtx (LO_SUM, Pmode, reg,
702 gen_rtx (CONST, Pmode, offset))));
703 pic_ref = gen_rtx (PLUS, Pmode,
704 pic_offset_table_rtx, reg);
705 #endif
707 else
708 #endif /* HAVE_lo_sum */
710 rtx pic = pic_offset_table_rtx;
711 if (GET_CODE (pic) != REG)
713 emit_move_insn (reg, pic);
714 pic = reg;
716 #if 0
717 emit_insn (gen_rtx (USE, VOIDmode,
718 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
719 #endif
721 pic_ref = gen_rtx (PLUS, Pmode,
722 pic,
723 gen_rtx (CONST, Pmode,
724 gen_rtx (MINUS, Pmode,
725 XEXP (orig, 0),
726 pic_base)));
729 #if !defined (TARGET_TOC)
730 RTX_UNCHANGING_P (pic_ref) = 1;
731 emit_move_insn (reg, pic_ref);
732 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
733 #endif
735 else
738 #ifdef HAVE_lo_sum
739 if (GET_CODE (orig) == SYMBOL_REF
740 || GET_CODE (orig) == LABEL_REF)
742 rtx offset = gen_rtx (CONST, Pmode,
743 gen_rtx (MINUS, Pmode, orig, pic_base));
744 #if defined (TARGET_TOC) /* i.e., PowerPC */
745 rtx hi_sum_reg;
747 if (reg == 0)
749 if (reload_in_progress)
750 abort ();
751 else
752 reg = gen_reg_rtx (SImode);
755 hi_sum_reg = reg;
757 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
758 gen_rtx (PLUS, Pmode,
759 pic_offset_table_rtx,
760 gen_rtx (HIGH, Pmode, offset))));
761 emit_insn (gen_rtx (SET, VOIDmode, reg,
762 gen_rtx (LO_SUM, Pmode,
763 hi_sum_reg, offset)));
764 pic_ref = reg;
765 #else
766 emit_insn (gen_rtx (SET, VOIDmode, reg,
767 gen_rtx (HIGH, Pmode, offset)));
768 emit_insn (gen_rtx (SET, VOIDmode, reg,
769 gen_rtx (LO_SUM, Pmode, reg, offset)));
770 pic_ref = gen_rtx (PLUS, Pmode,
771 pic_offset_table_rtx, reg);
772 #endif
774 else
775 #endif /* HAVE_lo_sum */
777 if (GET_CODE (orig) == REG)
779 return orig;
781 else
783 rtx pic = pic_offset_table_rtx;
784 if (GET_CODE (pic) != REG)
786 emit_move_insn (reg, pic);
787 pic = reg;
789 #if 0
790 emit_insn (gen_rtx (USE, VOIDmode,
791 pic_offset_table_rtx));
792 #endif
793 pic_ref = gen_rtx (PLUS, Pmode,
794 pic,
795 gen_rtx (CONST, Pmode,
796 gen_rtx (MINUS, Pmode,
797 orig, pic_base)));
802 RTX_UNCHANGING_P (pic_ref) = 1;
804 if (GET_CODE (pic_ref) != REG)
806 if (reg != 0)
808 emit_move_insn (reg, pic_ref);
809 return reg;
811 else
813 return force_reg (mode, pic_ref);
816 else
818 return pic_ref;
822 else if (GET_CODE (orig) == SYMBOL_REF)
823 return orig;
825 else if (GET_CODE (orig) == PLUS
826 && (GET_CODE (XEXP (orig, 0)) == MEM
827 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
828 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
829 && XEXP (orig, 0) != pic_offset_table_rtx
830 && GET_CODE (XEXP (orig, 1)) != REG)
833 rtx base;
834 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
836 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
837 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
838 Pmode, (base == reg ? 0 : reg));
839 if (GET_CODE (orig) == CONST_INT)
841 pic_ref = plus_constant (base, INTVAL (orig));
842 is_complex = 1;
844 else
845 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
847 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
848 RTX_UNCHANGING_P (pic_ref) = 1;
850 if (reg && is_complex)
852 emit_move_insn (reg, pic_ref);
853 pic_ref = reg;
855 /* Likewise, should we set special REG_NOTEs here? */
858 else if (GET_CODE (orig) == CONST)
860 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
863 else if (GET_CODE (orig) == MEM
864 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
866 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
868 addr = gen_rtx (MEM, GET_MODE (orig), addr);
869 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
870 emit_move_insn (reg, addr);
871 pic_ref = reg;
874 return pic_ref;
878 void
879 machopic_finish (asm_out_file)
880 FILE *asm_out_file;
882 tree temp;
884 for (temp = machopic_stubs;
885 temp != NULL_TREE;
886 temp = TREE_CHAIN (temp))
888 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
889 char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
890 char *sym;
891 char *stub;
893 if (! TREE_USED (temp))
894 continue;
896 STRIP_NAME_ENCODING (sym_name, sym_name);
898 sym = alloca (strlen (sym_name) + 2);
899 if (sym_name[0] == '*' || sym_name[0] == '&')
900 strcpy (sym, sym_name + 1);
901 else if (sym_name[0] == '-' || sym_name[0] == '+')
902 strcpy (sym, sym_name);
903 else
904 sym[0] = '_', strcpy (sym + 1, sym_name);
906 stub = alloca (strlen (stub_name) + 2);
907 if (stub_name[0] == '*' || stub_name[0] == '&')
908 strcpy (stub, stub_name + 1);
909 else
910 stub[0] = '_', strcpy (stub + 1, stub_name);
912 machopic_output_stub (asm_out_file, sym, stub);
915 for (temp = machopic_non_lazy_pointers;
916 temp != NULL_TREE;
917 temp = TREE_CHAIN (temp))
919 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
920 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
921 #if 0
922 tree decl = lookup_name_darwin (TREE_VALUE (temp));
923 #endif
925 if (! TREE_USED (temp))
926 continue;
928 if (machopic_ident_defined_p (TREE_VALUE (temp))
929 #if 0 /* add back when we have private externs */
930 || (decl && DECL_PRIVATE_EXTERN (decl))
931 #endif
934 data_section ();
935 assemble_align (GET_MODE_ALIGNMENT (Pmode));
936 assemble_label (lazy_name);
937 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
938 GET_MODE_SIZE (Pmode),
939 GET_MODE_ALIGNMENT (Pmode), 1);
941 else
943 machopic_nl_symbol_ptr_section ();
944 assemble_name (asm_out_file, lazy_name);
945 fprintf (asm_out_file, ":\n");
947 fprintf (asm_out_file, "\t.indirect_symbol ");
948 assemble_name (asm_out_file, sym_name);
949 fprintf (asm_out_file, "\n");
951 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
952 GET_MODE_ALIGNMENT (Pmode), 1);
957 int
958 machopic_operand_p (op)
959 rtx op;
961 if (MACHOPIC_JUST_INDIRECT)
963 while (GET_CODE (op) == CONST)
964 op = XEXP (op, 0);
966 if (GET_CODE (op) == SYMBOL_REF)
967 return machopic_name_defined_p (XSTR (op, 0));
968 else
969 return 0;
972 while (GET_CODE (op) == CONST)
973 op = XEXP (op, 0);
975 if (GET_CODE (op) == MINUS
976 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
977 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
978 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
979 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
980 return 1;
982 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
983 /* Without this statement, the compiler crashes while compiling enquire.c
984 when targetting PowerPC. It is not known why this code is not needed
985 when targetting other processors. */
986 else if (GET_CODE (op) == SYMBOL_REF
987 && (machopic_classify_name (XSTR (op, 0))
988 == MACHOPIC_DEFINED_FUNCTION))
990 return 1;
992 #endif
994 return 0;
997 /* This function records whether a given name corresponds to a defined
998 or undefined function or variable, for machopic_classify_ident to
999 use later. */
1001 void
1002 darwin_encode_section_info (decl)
1003 tree decl;
1005 char code = '\0';
1006 int defined = 0;
1007 rtx sym_ref;
1008 const char *orig_str;
1009 char *new_str;
1010 size_t len, new_len;
1012 if ((TREE_CODE (decl) == FUNCTION_DECL
1013 || TREE_CODE (decl) == VAR_DECL)
1014 && !DECL_EXTERNAL (decl)
1015 && ((TREE_STATIC (decl)
1016 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1017 || DECL_INITIAL (decl)))
1018 defined = 1;
1020 if (TREE_CODE (decl) == FUNCTION_DECL)
1021 code = (defined ? 'T' : 't');
1022 else if (TREE_CODE (decl) == VAR_DECL)
1023 code = (defined ? 'D' : 'd');
1025 if (code == '\0')
1026 return;
1028 sym_ref = XEXP (DECL_RTL (decl), 0);
1029 orig_str = XSTR (sym_ref, 0);
1030 len = strlen (orig_str) + 1;
1032 if (orig_str[0] == '!')
1034 /* Already encoded; see if we need to change it. */
1035 if (code == orig_str[1])
1036 return;
1037 /* Yes, tweak a copy of the name and put it in a new string. */
1038 new_str = alloca (len);
1039 memcpy (new_str, orig_str, len);
1040 new_str[1] = code;
1041 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1043 else
1045 /* Add the encoding. */
1046 new_len = len + 4;
1047 new_str = alloca (new_len);
1048 new_str[0] = '!';
1049 new_str[1] = code;
1050 new_str[2] = '_';
1051 new_str[3] = '_';
1052 memcpy (new_str + 4, orig_str, len);
1053 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1055 /* The non-lazy pointer list may have captured references to the
1056 old encoded name, change them. */
1057 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1058 update_stubs (XSTR (sym_ref, 0));
1061 /* Scan the list of non-lazy pointers and update any recorded names whose
1062 stripped name matches the argument. */
1064 static void
1065 update_non_lazy_ptrs (name)
1066 const char *name;
1068 char *name1, *name2;
1069 tree temp;
1071 STRIP_NAME_ENCODING (name1, name);
1073 for (temp = machopic_non_lazy_pointers;
1074 temp != NULL_TREE;
1075 temp = TREE_CHAIN (temp))
1077 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1079 if (*sym_name == '!')
1081 STRIP_NAME_ENCODING (name2, sym_name);
1082 if (strcmp (name1, name2) == 0)
1084 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1085 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 char *name1, *name2;
1100 tree temp;
1102 STRIP_NAME_ENCODING (name1, 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 STRIP_NAME_ENCODING (name2, sym_name);
1113 if (strcmp (name1, name2) == 0)
1115 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1116 break;
1122 void
1123 machopic_asm_out_constructor (symbol, priority)
1124 rtx symbol;
1125 int priority ATTRIBUTE_UNUSED;
1127 if (flag_pic)
1128 mod_init_section ();
1129 else
1130 constructor_section ();
1131 assemble_align (POINTER_SIZE);
1132 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1134 if (!flag_pic)
1135 fprintf (asm_out_file, ".reference .constructors_used\n");
1138 void
1139 machopic_asm_out_destructor (symbol, priority)
1140 rtx symbol;
1141 int priority ATTRIBUTE_UNUSED;
1143 if (flag_pic)
1144 mod_term_section ();
1145 else
1146 destructor_section ();
1147 assemble_align (POINTER_SIZE);
1148 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1150 if (!flag_pic)
1151 fprintf (asm_out_file, ".reference .destructors_used\n");