* tm.texi: Fix markup.
[official-gcc.git] / gcc / config / darwin.c
bloba3c382cee69439f2cb363cf7148ffeab23230df0
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 *));
49 int
50 name_needs_quotes (name)
51 const char *name;
53 int c;
54 while ((c = *name++) != '\0')
55 if (!isalnum (c) && c != '_')
56 return 1;
57 return 0;
60 /*
61 * flag_pic = 1 ... generate only indirections
62 * flag_pic = 2 ... generate indirections and pure code
65 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
66 reference, which will not be changed. */
68 static tree machopic_defined_list;
70 enum machopic_addr_class
71 machopic_classify_ident (ident)
72 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 if (name[0] != '!')
87 /* Here if no special encoding to be found. */
88 if (lprefix)
90 const char *name = IDENTIFIER_POINTER (ident);
91 int len = strlen (name);
93 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
94 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
95 return MACHOPIC_DEFINED_FUNCTION;
96 return MACHOPIC_DEFINED_DATA;
99 for (temp = machopic_defined_list;
100 temp != NULL_TREE;
101 temp = TREE_CHAIN (temp))
103 if (ident == TREE_VALUE (temp))
104 return MACHOPIC_DEFINED_DATA;
107 if (TREE_ASM_WRITTEN (ident))
108 return MACHOPIC_DEFINED_DATA;
110 return MACHOPIC_UNDEFINED;
113 else if (name[1] == 'D')
114 return MACHOPIC_DEFINED_DATA;
116 else if (name[1] == 'T')
117 return MACHOPIC_DEFINED_FUNCTION;
119 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
121 if (ident == TREE_VALUE (temp))
123 if (name[1] == 'T')
124 return MACHOPIC_DEFINED_FUNCTION;
125 else
126 return MACHOPIC_DEFINED_DATA;
130 if (name[1] == 't' || name[1] == 'T')
132 if (lprefix)
133 return MACHOPIC_DEFINED_FUNCTION;
134 else
135 return MACHOPIC_UNDEFINED_FUNCTION;
137 else
139 if (lprefix)
140 return MACHOPIC_DEFINED_DATA;
141 else
142 return MACHOPIC_UNDEFINED_DATA;
147 enum machopic_addr_class
148 machopic_classify_name (name)
149 const char *name;
151 return machopic_classify_ident (get_identifier (name));
155 machopic_ident_defined_p (ident)
156 tree ident;
158 switch (machopic_classify_ident (ident))
160 case MACHOPIC_UNDEFINED:
161 case MACHOPIC_UNDEFINED_DATA:
162 case MACHOPIC_UNDEFINED_FUNCTION:
163 return 0;
164 default:
165 return 1;
169 static int
170 machopic_data_defined_p (name)
171 const char *name;
173 switch (machopic_classify_ident (get_identifier (name)))
175 case MACHOPIC_DEFINED_DATA:
176 return 1;
177 default:
178 return 0;
183 machopic_name_defined_p (name)
184 const char *name;
186 return machopic_ident_defined_p (get_identifier (name));
189 void
190 machopic_define_ident (ident)
191 tree ident;
193 if (!machopic_ident_defined_p (ident))
194 machopic_defined_list =
195 tree_cons (NULL_TREE, ident, machopic_defined_list);
198 void
199 machopic_define_name (name)
200 const char *name;
202 machopic_define_ident (get_identifier (name));
205 /* This is a static to make inline functions work. The rtx
206 representing the PIC base symbol always points to here. */
208 static char function_base[32];
210 static int current_pic_label_num;
212 char *
213 machopic_function_base_name ()
215 static char *name = NULL;
216 static const char *current_name;
218 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
220 if (name != current_name)
222 current_function_uses_pic_offset_table = 1;
224 /* Save mucho space and time. Some of the C++ mangled names are over
225 700 characters long! Note that we produce a label containing a '-'
226 if the function we're compiling is an Objective-C method, as evinced
227 by the incredibly scientific test below. This is because code in
228 rs6000.c makes the same ugly test when loading the PIC reg. */
230 ++current_pic_label_num;
231 if (*current_name == '+' || *current_name == '-')
232 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
233 else
234 sprintf (function_base, "*L%d$pb", current_pic_label_num);
236 name = current_name;
239 return function_base;
242 static tree machopic_non_lazy_pointers = NULL;
244 /* Return a non-lazy pointer name corresponding to the given name,
245 either by finding it in our list of pointer names, or by generating
246 a new one. */
248 char *
249 machopic_non_lazy_ptr_name (name)
250 const char *name;
252 char *temp_name;
253 tree temp, ident = get_identifier (name);
255 for (temp = machopic_non_lazy_pointers;
256 temp != NULL_TREE;
257 temp = TREE_CHAIN (temp))
259 if (ident == TREE_VALUE (temp))
260 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
263 STRIP_NAME_ENCODING (name, name);
265 /* Try again, but comparing names this time. */
266 for (temp = machopic_non_lazy_pointers;
267 temp != NULL_TREE;
268 temp = TREE_CHAIN (temp))
270 if (TREE_VALUE (temp))
272 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
273 STRIP_NAME_ENCODING (temp_name, temp_name);
274 if (strcmp (name, temp_name) == 0)
275 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
280 char *buffer;
281 tree ptr_name;
283 buffer = alloca (strlen (name) + 20);
285 strcpy (buffer, "&L");
286 if (name[0] == '*')
287 strcat (buffer, name+1);
288 else
290 strcat (buffer, "_");
291 strcat (buffer, name);
294 strcat (buffer, "$non_lazy_ptr");
295 ptr_name = get_identifier (buffer);
297 machopic_non_lazy_pointers
298 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
300 TREE_USED (machopic_non_lazy_pointers) = 0;
302 return IDENTIFIER_POINTER (ptr_name);
306 static tree machopic_stubs = 0;
308 /* Make sure the GC knows about our homemade lists. */
310 void
311 machopic_add_gc_roots ()
313 ggc_add_tree_root (&machopic_defined_list, 1);
314 ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
315 ggc_add_tree_root (&machopic_stubs, 1);
318 /* Return the name of the stub corresponding to the given name,
319 generating a new stub name if necessary. */
321 char *
322 machopic_stub_name (name)
323 const char *name;
325 tree temp, ident = get_identifier (name);
327 for (temp = machopic_stubs;
328 temp != NULL_TREE;
329 temp = TREE_CHAIN (temp))
331 if (ident == TREE_VALUE (temp))
332 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
335 STRIP_NAME_ENCODING (name, name);
338 char *buffer;
339 tree ptr_name;
340 int needs_quotes = name_needs_quotes (name);
342 buffer = alloca (strlen (name) + 20);
344 if (needs_quotes)
345 strcpy (buffer, "&\"L");
346 else
347 strcpy (buffer, "&L");
348 if (name[0] == '*')
350 strcat (buffer, name+1);
352 else
354 strcat (buffer, "_");
355 strcat (buffer, name);
358 if (needs_quotes)
359 strcat (buffer, "$stub\"");
360 else
361 strcat (buffer, "$stub");
362 ptr_name = get_identifier (buffer);
364 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
365 TREE_USED (machopic_stubs) = 0;
367 return IDENTIFIER_POINTER (ptr_name);
371 void
372 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
373 const char *name;
374 int validate_stub;
376 char *real_name;
377 tree temp, ident = get_identifier (name), id2;
379 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
380 temp != NULL_TREE;
381 temp = TREE_CHAIN (temp))
382 if (ident == TREE_PURPOSE (temp))
384 /* Mark both the stub or non-lazy pointer as well as the
385 original symbol as being referenced. */
386 TREE_USED (temp) = 1;
387 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
388 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
389 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
390 id2 = maybe_get_identifier (real_name);
391 if (id2)
392 TREE_SYMBOL_REFERENCED (id2) = 1;
396 /* Transform ORIG, which may be any data source, to the corresponding
397 source using indirections. */
400 machopic_indirect_data_reference (orig, reg)
401 rtx orig, reg;
403 rtx ptr_ref = orig;
405 if (! MACHOPIC_INDIRECT)
406 return orig;
408 if (GET_CODE (orig) == SYMBOL_REF)
410 const char *name = XSTR (orig, 0);
412 if (machopic_data_defined_p (name))
414 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
415 machopic_function_base_name ());
416 rtx offset = gen_rtx (CONST, Pmode,
417 gen_rtx (MINUS, Pmode, orig, pic_base));
419 #if defined (TARGET_TOC) /* i.e., PowerPC */
420 rtx hi_sum_reg = reg;
422 if (reg == NULL)
423 abort ();
425 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
426 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
427 gen_rtx (HIGH, Pmode, offset))));
428 emit_insn (gen_rtx (SET, Pmode, reg,
429 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
431 orig = reg;
432 #else
433 #if defined (HAVE_lo_sum)
434 if (reg == 0) abort ();
436 emit_insn (gen_rtx (SET, VOIDmode, reg,
437 gen_rtx (HIGH, Pmode, offset)));
438 emit_insn (gen_rtx (SET, VOIDmode, reg,
439 gen_rtx (LO_SUM, Pmode, reg, offset)));
440 emit_insn (gen_rtx (USE, VOIDmode,
441 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
443 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
444 #endif
445 #endif
446 return orig;
449 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
450 machopic_non_lazy_ptr_name (name));
452 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
453 RTX_UNCHANGING_P (ptr_ref) = 1;
455 return ptr_ref;
457 else if (GET_CODE (orig) == CONST)
459 rtx base, result;
461 /* legitimize both operands of the PLUS */
462 if (GET_CODE (XEXP (orig, 0)) == PLUS)
464 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
465 reg);
466 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
467 (base == reg ? 0 : reg));
469 else
470 return orig;
472 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
473 result = plus_constant (base, INTVAL (orig));
474 else
475 result = gen_rtx (PLUS, Pmode, base, orig);
477 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
478 RTX_UNCHANGING_P (result) = 1;
480 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
482 if (reg)
484 emit_move_insn (reg, result);
485 result = reg;
487 else
489 result = force_reg (GET_MODE (result), result);
493 return result;
496 else if (GET_CODE (orig) == MEM)
497 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
498 /* When the target is i386, this code prevents crashes due to the
499 compiler's ignorance on how to move the PIC base register to
500 other registers. (The reload phase sometimes introduces such
501 insns.) */
502 else if (GET_CODE (orig) == PLUS
503 && GET_CODE (XEXP (orig, 0)) == REG
504 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
505 #ifdef I386
506 /* Prevent the same register from being erroneously used
507 as both the base and index registers. */
508 && GET_CODE (XEXP (orig, 1)) == CONST
509 #endif
510 && reg)
512 emit_move_insn (reg, XEXP (orig, 0));
513 XEXP (ptr_ref, 0) = reg;
515 return ptr_ref;
518 /* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
520 extern "C" { int f(); }
521 struct X { int f(); int g(); };
522 int X::f() { ::f(); }
523 int X::g() { ::f(); f();}
525 This is hairy. Both calls to "::f()" need to be indirect (i.e., to
526 appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
527 GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
528 defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
529 returns TRUE when called with "f", which means that
530 MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
531 indirect one as it should.
533 Our quick-n-dirty solution to this is to call the following
534 FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
535 FNAME -- the name of the function which we're calling -- is NOT a
536 mangled C++ name, AND if the current function being compiled is a
537 method, and if so, use an "external" or "indirect" call.
539 Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
540 has already indicated that the target is NOT indirect.
542 This conservative solution will sometimes make indirect calls where
543 it might have been possible to make direct ones.
545 FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
546 which in turns means we should create a stub for an indirect call.
549 static int is_cplusplus = -1;
551 static int
552 func_name_maybe_scoped (fname)
553 const char *fname;
556 if (is_cplusplus < 0)
557 is_cplusplus = (strcmp (lang_identify (), "cplusplus") == 0);
559 if (is_cplusplus)
561 /* If we have a method, then check whether the function we're trying to
562 call is a "C" function. If so, we should use an indirect call.
564 It turns out to be hard to tell whether "we have a method", since
565 static member functions have a TREE_CODE of FUNCTION_TYPE, as do
566 namespace-level non-member functions. So here, we always look for
567 an extern-"C"-like name, and make stubs for them no matter the
568 calling context. This is temporary, and leaves nagging suspicion
569 that improvements should be possible here. (I.e., I suspect that
570 it can still sometimes make stubs where it needn't.) */
572 /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
574 /* If fname is of the form "f__1X" or "f__Fv", it's C++. */
575 while (*fname == '_') ++fname; /* skip leading underscores */
576 while (*fname != 0)
578 if (fname[0] == '_' && fname[1] == '_'
579 && (fname[2] == 'F' || (fname[2] >= '0' && fname[2] <= '9')))
580 return 0;
581 ++fname;
583 /* Not a C++ mangled name: must be "C", in which case play safe. */
584 return 1;
587 return 0;
590 /* Transform TARGET (a MEM), which is a function call target, to the
591 corresponding symbol_stub if necessary. Return a new MEM. */
594 machopic_indirect_call_target (target)
595 rtx target;
597 if (GET_CODE (target) != MEM)
598 return target;
600 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
602 enum machine_mode mode = GET_MODE (XEXP (target, 0));
603 const char *name = XSTR (XEXP (target, 0), 0);
605 if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name))
607 const char *stub_name = machopic_stub_name (name);
609 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
610 RTX_UNCHANGING_P (target) = 1;
614 return target;
618 machopic_legitimize_pic_address (orig, mode, reg)
619 rtx orig, reg;
620 enum machine_mode mode;
622 rtx pic_ref = orig;
624 if (! MACHOPIC_PURE)
625 return orig;
627 /* First handle a simple SYMBOL_REF or LABEL_REF */
628 if (GET_CODE (orig) == LABEL_REF
629 || (GET_CODE (orig) == SYMBOL_REF
632 /* addr(foo) = &func+(foo-func) */
633 rtx pic_base;
635 orig = machopic_indirect_data_reference (orig, reg);
637 if (GET_CODE (orig) == PLUS
638 && GET_CODE (XEXP (orig, 0)) == REG)
640 if (reg == 0)
641 return force_reg (mode, orig);
643 emit_move_insn (reg, orig);
644 return reg;
647 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
649 if (GET_CODE (orig) == MEM)
651 if (reg == 0)
653 if (reload_in_progress)
654 abort ();
655 else
656 reg = gen_reg_rtx (Pmode);
659 #ifdef HAVE_lo_sum
660 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
661 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
663 rtx offset = gen_rtx (CONST, Pmode,
664 gen_rtx (MINUS, Pmode,
665 XEXP (orig, 0), pic_base));
666 #if defined (TARGET_TOC) /* i.e., PowerPC */
667 /* Generating a new reg may expose opportunities for
668 common subexpression elimination. */
669 rtx hi_sum_reg =
670 (reload_in_progress ? reg : gen_reg_rtx (SImode));
672 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
673 gen_rtx (PLUS, Pmode,
674 pic_offset_table_rtx,
675 gen_rtx (HIGH, Pmode, offset))));
676 emit_insn (gen_rtx (SET, VOIDmode, reg,
677 gen_rtx (MEM, GET_MODE (orig),
678 gen_rtx (LO_SUM, Pmode,
679 hi_sum_reg, offset))));
680 pic_ref = reg;
682 #else
683 emit_insn (gen_rtx (USE, VOIDmode,
684 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
686 emit_insn (gen_rtx (SET, VOIDmode, reg,
687 gen_rtx (HIGH, Pmode,
688 gen_rtx (CONST, Pmode, offset))));
689 emit_insn (gen_rtx (SET, VOIDmode, reg,
690 gen_rtx (LO_SUM, Pmode, reg,
691 gen_rtx (CONST, Pmode, offset))));
692 pic_ref = gen_rtx (PLUS, Pmode,
693 pic_offset_table_rtx, reg);
694 #endif
696 else
697 #endif /* HAVE_lo_sum */
699 rtx pic = pic_offset_table_rtx;
700 if (GET_CODE (pic) != REG)
702 emit_move_insn (reg, pic);
703 pic = reg;
705 #if 0
706 emit_insn (gen_rtx (USE, VOIDmode,
707 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
708 #endif
710 pic_ref = gen_rtx (PLUS, Pmode,
711 pic,
712 gen_rtx (CONST, Pmode,
713 gen_rtx (MINUS, Pmode,
714 XEXP (orig, 0),
715 pic_base)));
718 #if !defined (TARGET_TOC)
719 RTX_UNCHANGING_P (pic_ref) = 1;
720 emit_move_insn (reg, pic_ref);
721 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
722 #endif
724 else
727 #ifdef HAVE_lo_sum
728 if (GET_CODE (orig) == SYMBOL_REF
729 || GET_CODE (orig) == LABEL_REF)
731 rtx offset = gen_rtx (CONST, Pmode,
732 gen_rtx (MINUS, Pmode, orig, pic_base));
733 #if defined (TARGET_TOC) /* i.e., PowerPC */
734 rtx hi_sum_reg;
736 if (reg == 0)
738 if (reload_in_progress)
739 abort ();
740 else
741 reg = gen_reg_rtx (SImode);
744 hi_sum_reg = reg;
746 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
747 gen_rtx (PLUS, Pmode,
748 pic_offset_table_rtx,
749 gen_rtx (HIGH, Pmode, offset))));
750 emit_insn (gen_rtx (SET, VOIDmode, reg,
751 gen_rtx (LO_SUM, Pmode,
752 hi_sum_reg, offset)));
753 pic_ref = reg;
754 #else
755 emit_insn (gen_rtx (SET, VOIDmode, reg,
756 gen_rtx (HIGH, Pmode, offset)));
757 emit_insn (gen_rtx (SET, VOIDmode, reg,
758 gen_rtx (LO_SUM, Pmode, reg, offset)));
759 pic_ref = gen_rtx (PLUS, Pmode,
760 pic_offset_table_rtx, reg);
761 #endif
763 else
764 #endif /* HAVE_lo_sum */
766 if (GET_CODE (orig) == REG)
768 return orig;
770 else
772 rtx pic = pic_offset_table_rtx;
773 if (GET_CODE (pic) != REG)
775 emit_move_insn (reg, pic);
776 pic = reg;
778 #if 0
779 emit_insn (gen_rtx (USE, VOIDmode,
780 pic_offset_table_rtx));
781 #endif
782 pic_ref = gen_rtx (PLUS, Pmode,
783 pic,
784 gen_rtx (CONST, Pmode,
785 gen_rtx (MINUS, Pmode,
786 orig, pic_base)));
791 RTX_UNCHANGING_P (pic_ref) = 1;
793 if (GET_CODE (pic_ref) != REG)
795 if (reg != 0)
797 emit_move_insn (reg, pic_ref);
798 return reg;
800 else
802 return force_reg (mode, pic_ref);
805 else
807 return pic_ref;
811 else if (GET_CODE (orig) == SYMBOL_REF)
812 return orig;
814 else if (GET_CODE (orig) == PLUS
815 && (GET_CODE (XEXP (orig, 0)) == MEM
816 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
817 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
818 && XEXP (orig, 0) != pic_offset_table_rtx
819 && GET_CODE (XEXP (orig, 1)) != REG)
822 rtx base;
823 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
825 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
826 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
827 Pmode, (base == reg ? 0 : reg));
828 if (GET_CODE (orig) == CONST_INT)
830 pic_ref = plus_constant (base, INTVAL (orig));
831 is_complex = 1;
833 else
834 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
836 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
837 RTX_UNCHANGING_P (pic_ref) = 1;
839 if (reg && is_complex)
841 emit_move_insn (reg, pic_ref);
842 pic_ref = reg;
844 /* Likewise, should we set special REG_NOTEs here? */
847 else if (GET_CODE (orig) == CONST)
849 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
852 else if (GET_CODE (orig) == MEM
853 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
855 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
857 addr = gen_rtx (MEM, GET_MODE (orig), addr);
858 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
859 emit_move_insn (reg, addr);
860 pic_ref = reg;
863 return pic_ref;
867 void
868 machopic_finish (asm_out_file)
869 FILE *asm_out_file;
871 tree temp;
873 for (temp = machopic_stubs;
874 temp != NULL_TREE;
875 temp = TREE_CHAIN (temp))
877 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
878 char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
879 char *sym;
880 char *stub;
882 if (! TREE_USED (temp))
883 continue;
885 STRIP_NAME_ENCODING (sym_name, sym_name);
887 sym = alloca (strlen (sym_name) + 2);
888 if (sym_name[0] == '*' || sym_name[0] == '&')
889 strcpy (sym, sym_name + 1);
890 else if (sym_name[0] == '-' || sym_name[0] == '+')
891 strcpy (sym, sym_name);
892 else
893 sym[0] = '_', strcpy (sym + 1, sym_name);
895 stub = alloca (strlen (stub_name) + 2);
896 if (stub_name[0] == '*' || stub_name[0] == '&')
897 strcpy (stub, stub_name + 1);
898 else
899 stub[0] = '_', strcpy (stub + 1, stub_name);
901 machopic_output_stub (asm_out_file, sym, stub);
904 for (temp = machopic_non_lazy_pointers;
905 temp != NULL_TREE;
906 temp = TREE_CHAIN (temp))
908 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
909 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
910 #if 0
911 tree decl = lookup_name_darwin (TREE_VALUE (temp));
912 #endif
914 if (! TREE_USED (temp))
915 continue;
917 if (machopic_ident_defined_p (TREE_VALUE (temp))
918 #if 0 /* add back when we have private externs */
919 || (decl && DECL_PRIVATE_EXTERN (decl))
920 #endif
923 data_section ();
924 assemble_align (UNITS_PER_WORD * BITS_PER_UNIT);
925 assemble_label (lazy_name);
926 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
927 GET_MODE_SIZE (Pmode), 1);
929 else
931 machopic_nl_symbol_ptr_section ();
932 assemble_name (asm_out_file, lazy_name);
933 fprintf (asm_out_file, ":\n");
935 fprintf (asm_out_file, "\t.indirect_symbol ");
936 assemble_name (asm_out_file, sym_name);
937 fprintf (asm_out_file, "\n");
939 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1);
944 int
945 machopic_operand_p (op)
946 rtx op;
948 if (MACHOPIC_JUST_INDIRECT)
950 while (GET_CODE (op) == CONST)
951 op = XEXP (op, 0);
953 if (GET_CODE (op) == SYMBOL_REF)
954 return machopic_name_defined_p (XSTR (op, 0));
955 else
956 return 0;
959 while (GET_CODE (op) == CONST)
960 op = XEXP (op, 0);
962 if (GET_CODE (op) == MINUS
963 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
964 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
965 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
966 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
967 return 1;
969 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
970 /* Without this statement, the compiler crashes while compiling enquire.c
971 when targetting PowerPC. It is not known why this code is not needed
972 when targetting other processors. */
973 else if (GET_CODE (op) == SYMBOL_REF
974 && (machopic_classify_name (XSTR (op, 0))
975 == MACHOPIC_DEFINED_FUNCTION))
977 return 1;
979 #endif
981 return 0;
984 /* This function records whether a given name corresponds to a defined
985 or undefined function or variable, for machopic_classify_ident to
986 use later. */
988 void
989 darwin_encode_section_info (decl)
990 tree decl;
992 char code = '\0';
993 int defined = 0;
994 rtx sym_ref;
995 char *orig_str, *new_str;
996 size_t len, new_len;
998 if ((TREE_CODE (decl) == FUNCTION_DECL
999 || TREE_CODE (decl) == VAR_DECL)
1000 && ((TREE_STATIC (decl)
1001 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1002 || DECL_INITIAL (decl)))
1003 defined = 1;
1005 if (TREE_CODE (decl) == FUNCTION_DECL)
1006 code = (defined ? 'T' : 't');
1007 else if (TREE_CODE (decl) == VAR_DECL)
1008 code = (defined ? 'D' : 'd');
1010 if (code == '\0')
1011 return;
1013 sym_ref = XEXP (DECL_RTL (decl), 0);
1014 orig_str = XSTR (sym_ref, 0);
1015 len = strlen (orig_str) + 1;
1017 if (orig_str[0] == '!')
1019 /* Already encoded; see if we need to change it. */
1020 if (code == orig_str[1])
1021 return;
1022 /* Yes, tweak a copy of the name and put it in a new string. */
1023 new_str = alloca (len);
1024 memcpy (new_str, orig_str, len);
1025 new_str[1] = code;
1026 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1027 /* The non-lazy pointer list may have captured references to the
1028 old encoded name, change them. */
1029 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1031 else
1033 /* Add the encoding. */
1034 new_len = len + 4;
1035 new_str = alloca (new_len);
1036 new_str[0] = '!';
1037 new_str[1] = code;
1038 new_str[2] = '_';
1039 new_str[3] = '_';
1040 memcpy (new_str + 4, orig_str, len);
1041 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1045 /* Scan the list of non-lazy pointers and update any recorded names whose
1046 stripped name matches the argument. */
1048 static void
1049 update_non_lazy_ptrs (name)
1050 const char *name;
1052 char *name1, *name2;
1053 tree temp;
1055 STRIP_NAME_ENCODING (name1, name);
1057 for (temp = machopic_non_lazy_pointers;
1058 temp != NULL_TREE;
1059 temp = TREE_CHAIN (temp))
1061 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1063 if (*sym_name == '!')
1065 STRIP_NAME_ENCODING (name2, sym_name);
1066 if (strcmp (name1, name2) == 0)
1068 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1069 break;