Restore definition of STRUCT_VALUE_REGNUM,
[official-gcc.git] / gcc / config / darwin.c
blobcaf812055887bf134fdcbd46f386ab8ebe957c9f
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 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
123 if (ident == TREE_VALUE (temp))
125 if (name[1] == 'T')
126 return MACHOPIC_DEFINED_FUNCTION;
127 else
128 return MACHOPIC_DEFINED_DATA;
132 if (name[1] == 't' || name[1] == 'T')
134 if (lprefix)
135 return MACHOPIC_DEFINED_FUNCTION;
136 else
137 return MACHOPIC_UNDEFINED_FUNCTION;
139 else
141 if (lprefix)
142 return MACHOPIC_DEFINED_DATA;
143 else
144 return MACHOPIC_UNDEFINED_DATA;
149 enum machopic_addr_class
150 machopic_classify_name (name)
151 const char *name;
153 return machopic_classify_ident (get_identifier (name));
157 machopic_ident_defined_p (ident)
158 tree ident;
160 switch (machopic_classify_ident (ident))
162 case MACHOPIC_UNDEFINED:
163 case MACHOPIC_UNDEFINED_DATA:
164 case MACHOPIC_UNDEFINED_FUNCTION:
165 return 0;
166 default:
167 return 1;
171 static int
172 machopic_data_defined_p (name)
173 const char *name;
175 switch (machopic_classify_ident (get_identifier (name)))
177 case MACHOPIC_DEFINED_DATA:
178 return 1;
179 default:
180 return 0;
185 machopic_name_defined_p (name)
186 const char *name;
188 return machopic_ident_defined_p (get_identifier (name));
191 void
192 machopic_define_ident (ident)
193 tree ident;
195 if (!machopic_ident_defined_p (ident))
196 machopic_defined_list =
197 tree_cons (NULL_TREE, ident, machopic_defined_list);
200 void
201 machopic_define_name (name)
202 const char *name;
204 machopic_define_ident (get_identifier (name));
207 /* This is a static to make inline functions work. The rtx
208 representing the PIC base symbol always points to here. */
210 static char function_base[32];
212 static int current_pic_label_num;
214 char *
215 machopic_function_base_name ()
217 static const char *name = NULL;
218 static const char *current_name;
220 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
222 if (name != current_name)
224 current_function_uses_pic_offset_table = 1;
226 /* Save mucho space and time. Some of the C++ mangled names are over
227 700 characters long! Note that we produce a label containing a '-'
228 if the function we're compiling is an Objective-C method, as evinced
229 by the incredibly scientific test below. This is because code in
230 rs6000.c makes the same ugly test when loading the PIC reg. */
232 ++current_pic_label_num;
233 if (*current_name == '+' || *current_name == '-')
234 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
235 else
236 sprintf (function_base, "*L%d$pb", current_pic_label_num);
238 name = current_name;
241 return function_base;
244 static tree machopic_non_lazy_pointers = NULL;
246 /* Return a non-lazy pointer name corresponding to the given name,
247 either by finding it in our list of pointer names, or by generating
248 a new one. */
250 char *
251 machopic_non_lazy_ptr_name (name)
252 const char *name;
254 char *temp_name;
255 tree temp, ident = get_identifier (name);
257 for (temp = machopic_non_lazy_pointers;
258 temp != NULL_TREE;
259 temp = TREE_CHAIN (temp))
261 if (ident == TREE_VALUE (temp))
262 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
265 STRIP_NAME_ENCODING (name, name);
267 /* Try again, but comparing names this time. */
268 for (temp = machopic_non_lazy_pointers;
269 temp != NULL_TREE;
270 temp = TREE_CHAIN (temp))
272 if (TREE_VALUE (temp))
274 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
275 STRIP_NAME_ENCODING (temp_name, temp_name);
276 if (strcmp (name, temp_name) == 0)
277 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
282 char *buffer;
283 tree ptr_name;
285 buffer = alloca (strlen (name) + 20);
287 strcpy (buffer, "&L");
288 if (name[0] == '*')
289 strcat (buffer, name+1);
290 else
292 strcat (buffer, "_");
293 strcat (buffer, name);
296 strcat (buffer, "$non_lazy_ptr");
297 ptr_name = get_identifier (buffer);
299 machopic_non_lazy_pointers
300 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
302 TREE_USED (machopic_non_lazy_pointers) = 0;
304 return IDENTIFIER_POINTER (ptr_name);
308 static tree machopic_stubs = 0;
310 /* Make sure the GC knows about our homemade lists. */
312 void
313 machopic_add_gc_roots ()
315 ggc_add_tree_root (&machopic_defined_list, 1);
316 ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
317 ggc_add_tree_root (&machopic_stubs, 1);
320 /* Return the name of the stub corresponding to the given name,
321 generating a new stub name if necessary. */
323 char *
324 machopic_stub_name (name)
325 const char *name;
327 tree temp, ident = get_identifier (name);
328 const char *tname;
330 for (temp = machopic_stubs;
331 temp != NULL_TREE;
332 temp = TREE_CHAIN (temp))
334 if (ident == TREE_VALUE (temp))
335 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
336 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
337 if (strcmp (name, tname) == 0)
338 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
339 /* A library call name might not be section-encoded yet, so try
340 it against a stripped name. */
341 if (name[0] != '!'
342 && tname[0] == '!'
343 && strcmp (name, tname + 4) == 0)
344 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
347 STRIP_NAME_ENCODING (name, name);
350 char *buffer;
351 tree ptr_name;
352 int needs_quotes = name_needs_quotes (name);
354 buffer = alloca (strlen (name) + 20);
356 if (needs_quotes)
357 strcpy (buffer, "&\"L");
358 else
359 strcpy (buffer, "&L");
360 if (name[0] == '*')
362 strcat (buffer, name+1);
364 else
366 strcat (buffer, "_");
367 strcat (buffer, name);
370 if (needs_quotes)
371 strcat (buffer, "$stub\"");
372 else
373 strcat (buffer, "$stub");
374 ptr_name = get_identifier (buffer);
376 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
377 TREE_USED (machopic_stubs) = 0;
379 return IDENTIFIER_POINTER (ptr_name);
383 void
384 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
385 const char *name;
386 int validate_stub;
388 char *real_name;
389 tree temp, ident = get_identifier (name), id2;
391 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
392 temp != NULL_TREE;
393 temp = TREE_CHAIN (temp))
394 if (ident == TREE_PURPOSE (temp))
396 /* Mark both the stub or non-lazy pointer as well as the
397 original symbol as being referenced. */
398 TREE_USED (temp) = 1;
399 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
400 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
401 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
402 id2 = maybe_get_identifier (real_name);
403 if (id2)
404 TREE_SYMBOL_REFERENCED (id2) = 1;
408 /* Transform ORIG, which may be any data source, to the corresponding
409 source using indirections. */
412 machopic_indirect_data_reference (orig, reg)
413 rtx orig, reg;
415 rtx ptr_ref = orig;
417 if (! MACHOPIC_INDIRECT)
418 return orig;
420 if (GET_CODE (orig) == SYMBOL_REF)
422 const char *name = XSTR (orig, 0);
424 if (machopic_data_defined_p (name))
426 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
427 machopic_function_base_name ());
428 rtx offset = gen_rtx (CONST, Pmode,
429 gen_rtx (MINUS, Pmode, orig, pic_base));
431 #if defined (TARGET_TOC) /* i.e., PowerPC */
432 rtx hi_sum_reg = reg;
434 if (reg == NULL)
435 abort ();
437 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
438 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
439 gen_rtx (HIGH, Pmode, offset))));
440 emit_insn (gen_rtx (SET, Pmode, reg,
441 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
443 orig = reg;
444 #else
445 #if defined (HAVE_lo_sum)
446 if (reg == 0) abort ();
448 emit_insn (gen_rtx (SET, VOIDmode, reg,
449 gen_rtx (HIGH, Pmode, offset)));
450 emit_insn (gen_rtx (SET, VOIDmode, reg,
451 gen_rtx (LO_SUM, Pmode, reg, offset)));
452 emit_insn (gen_rtx (USE, VOIDmode,
453 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
455 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
456 #endif
457 #endif
458 return orig;
461 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
462 machopic_non_lazy_ptr_name (name));
464 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
465 RTX_UNCHANGING_P (ptr_ref) = 1;
467 return ptr_ref;
469 else if (GET_CODE (orig) == CONST)
471 rtx base, result;
473 /* legitimize both operands of the PLUS */
474 if (GET_CODE (XEXP (orig, 0)) == PLUS)
476 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
477 reg);
478 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
479 (base == reg ? 0 : reg));
481 else
482 return orig;
484 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
485 result = plus_constant (base, INTVAL (orig));
486 else
487 result = gen_rtx (PLUS, Pmode, base, orig);
489 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
490 RTX_UNCHANGING_P (result) = 1;
492 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
494 if (reg)
496 emit_move_insn (reg, result);
497 result = reg;
499 else
501 result = force_reg (GET_MODE (result), result);
505 return result;
508 else if (GET_CODE (orig) == MEM)
509 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
510 /* When the target is i386, this code prevents crashes due to the
511 compiler's ignorance on how to move the PIC base register to
512 other registers. (The reload phase sometimes introduces such
513 insns.) */
514 else if (GET_CODE (orig) == PLUS
515 && GET_CODE (XEXP (orig, 0)) == REG
516 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
517 #ifdef I386
518 /* Prevent the same register from being erroneously used
519 as both the base and index registers. */
520 && GET_CODE (XEXP (orig, 1)) == CONST
521 #endif
522 && reg)
524 emit_move_insn (reg, XEXP (orig, 0));
525 XEXP (ptr_ref, 0) = reg;
527 return ptr_ref;
530 /* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
532 extern "C" { int f(); }
533 struct X { int f(); int g(); };
534 int X::f() { ::f(); }
535 int X::g() { ::f(); f();}
537 This is hairy. Both calls to "::f()" need to be indirect (i.e., to
538 appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
539 GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
540 defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
541 returns TRUE when called with "f", which means that
542 MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
543 indirect one as it should.
545 Our quick-n-dirty solution to this is to call the following
546 FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
547 FNAME -- the name of the function which we're calling -- is NOT a
548 mangled C++ name, AND if the current function being compiled is a
549 method, and if so, use an "external" or "indirect" call.
551 Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
552 has already indicated that the target is NOT indirect.
554 This conservative solution will sometimes make indirect calls where
555 it might have been possible to make direct ones.
557 FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
558 which in turns means we should create a stub for an indirect call.
561 static int is_cplusplus = -1;
563 static int
564 func_name_maybe_scoped (fname)
565 const char *fname;
568 if (is_cplusplus < 0)
569 is_cplusplus = (strcmp (lang_hooks.name, "GNU C++") == 0);
571 if (is_cplusplus)
573 /* If we have a method, then check whether the function we're trying to
574 call is a "C" function. If so, we should use an indirect call.
576 It turns out to be hard to tell whether "we have a method", since
577 static member functions have a TREE_CODE of FUNCTION_TYPE, as do
578 namespace-level non-member functions. So here, we always look for
579 an extern-"C"-like name, and make stubs for them no matter the
580 calling context. This is temporary, and leaves nagging suspicion
581 that improvements should be possible here. (I.e., I suspect that
582 it can still sometimes make stubs where it needn't.) */
584 /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
586 /* If fname is of the form "f__1X" or "f__Fv", it's C++. */
587 while (*fname == '_') ++fname; /* skip leading underscores */
588 while (*fname != 0)
590 if (fname[0] == '_' && fname[1] == '_'
591 && (fname[2] == 'F' || ISDIGIT (fname[2])))
592 return 0;
593 ++fname;
595 /* Not a C++ mangled name: must be "C", in which case play safe. */
596 return 1;
599 return 0;
602 /* Transform TARGET (a MEM), which is a function call target, to the
603 corresponding symbol_stub if necessary. Return a new MEM. */
606 machopic_indirect_call_target (target)
607 rtx target;
609 if (GET_CODE (target) != MEM)
610 return target;
612 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
614 enum machine_mode mode = GET_MODE (XEXP (target, 0));
615 const char *name = XSTR (XEXP (target, 0), 0);
617 if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name))
619 const char *stub_name = machopic_stub_name (name);
621 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
622 RTX_UNCHANGING_P (target) = 1;
626 return target;
630 machopic_legitimize_pic_address (orig, mode, reg)
631 rtx orig, reg;
632 enum machine_mode mode;
634 rtx pic_ref = orig;
636 if (! MACHOPIC_PURE)
637 return orig;
639 /* First handle a simple SYMBOL_REF or LABEL_REF */
640 if (GET_CODE (orig) == LABEL_REF
641 || (GET_CODE (orig) == SYMBOL_REF
644 /* addr(foo) = &func+(foo-func) */
645 rtx pic_base;
647 orig = machopic_indirect_data_reference (orig, reg);
649 if (GET_CODE (orig) == PLUS
650 && GET_CODE (XEXP (orig, 0)) == REG)
652 if (reg == 0)
653 return force_reg (mode, orig);
655 emit_move_insn (reg, orig);
656 return reg;
659 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
661 if (GET_CODE (orig) == MEM)
663 if (reg == 0)
665 if (reload_in_progress)
666 abort ();
667 else
668 reg = gen_reg_rtx (Pmode);
671 #ifdef HAVE_lo_sum
672 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
673 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
675 rtx offset = gen_rtx (CONST, Pmode,
676 gen_rtx (MINUS, Pmode,
677 XEXP (orig, 0), pic_base));
678 #if defined (TARGET_TOC) /* i.e., PowerPC */
679 /* Generating a new reg may expose opportunities for
680 common subexpression elimination. */
681 rtx hi_sum_reg =
682 (reload_in_progress ? reg : gen_reg_rtx (SImode));
684 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
685 gen_rtx (PLUS, Pmode,
686 pic_offset_table_rtx,
687 gen_rtx (HIGH, Pmode, offset))));
688 emit_insn (gen_rtx (SET, VOIDmode, reg,
689 gen_rtx (MEM, GET_MODE (orig),
690 gen_rtx (LO_SUM, Pmode,
691 hi_sum_reg, offset))));
692 pic_ref = reg;
694 #else
695 emit_insn (gen_rtx (USE, VOIDmode,
696 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
698 emit_insn (gen_rtx (SET, VOIDmode, reg,
699 gen_rtx (HIGH, Pmode,
700 gen_rtx (CONST, Pmode, offset))));
701 emit_insn (gen_rtx (SET, VOIDmode, reg,
702 gen_rtx (LO_SUM, Pmode, reg,
703 gen_rtx (CONST, Pmode, offset))));
704 pic_ref = gen_rtx (PLUS, Pmode,
705 pic_offset_table_rtx, reg);
706 #endif
708 else
709 #endif /* HAVE_lo_sum */
711 rtx pic = pic_offset_table_rtx;
712 if (GET_CODE (pic) != REG)
714 emit_move_insn (reg, pic);
715 pic = reg;
717 #if 0
718 emit_insn (gen_rtx (USE, VOIDmode,
719 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
720 #endif
722 pic_ref = gen_rtx (PLUS, Pmode,
723 pic,
724 gen_rtx (CONST, Pmode,
725 gen_rtx (MINUS, Pmode,
726 XEXP (orig, 0),
727 pic_base)));
730 #if !defined (TARGET_TOC)
731 RTX_UNCHANGING_P (pic_ref) = 1;
732 emit_move_insn (reg, pic_ref);
733 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
734 #endif
736 else
739 #ifdef HAVE_lo_sum
740 if (GET_CODE (orig) == SYMBOL_REF
741 || GET_CODE (orig) == LABEL_REF)
743 rtx offset = gen_rtx (CONST, Pmode,
744 gen_rtx (MINUS, Pmode, orig, pic_base));
745 #if defined (TARGET_TOC) /* i.e., PowerPC */
746 rtx hi_sum_reg;
748 if (reg == 0)
750 if (reload_in_progress)
751 abort ();
752 else
753 reg = gen_reg_rtx (SImode);
756 hi_sum_reg = reg;
758 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
759 gen_rtx (PLUS, Pmode,
760 pic_offset_table_rtx,
761 gen_rtx (HIGH, Pmode, offset))));
762 emit_insn (gen_rtx (SET, VOIDmode, reg,
763 gen_rtx (LO_SUM, Pmode,
764 hi_sum_reg, offset)));
765 pic_ref = reg;
766 #else
767 emit_insn (gen_rtx (SET, VOIDmode, reg,
768 gen_rtx (HIGH, Pmode, offset)));
769 emit_insn (gen_rtx (SET, VOIDmode, reg,
770 gen_rtx (LO_SUM, Pmode, reg, offset)));
771 pic_ref = gen_rtx (PLUS, Pmode,
772 pic_offset_table_rtx, reg);
773 #endif
775 else
776 #endif /* HAVE_lo_sum */
778 if (GET_CODE (orig) == REG)
780 return orig;
782 else
784 rtx pic = pic_offset_table_rtx;
785 if (GET_CODE (pic) != REG)
787 emit_move_insn (reg, pic);
788 pic = reg;
790 #if 0
791 emit_insn (gen_rtx (USE, VOIDmode,
792 pic_offset_table_rtx));
793 #endif
794 pic_ref = gen_rtx (PLUS, Pmode,
795 pic,
796 gen_rtx (CONST, Pmode,
797 gen_rtx (MINUS, Pmode,
798 orig, pic_base)));
803 RTX_UNCHANGING_P (pic_ref) = 1;
805 if (GET_CODE (pic_ref) != REG)
807 if (reg != 0)
809 emit_move_insn (reg, pic_ref);
810 return reg;
812 else
814 return force_reg (mode, pic_ref);
817 else
819 return pic_ref;
823 else if (GET_CODE (orig) == SYMBOL_REF)
824 return orig;
826 else if (GET_CODE (orig) == PLUS
827 && (GET_CODE (XEXP (orig, 0)) == MEM
828 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
829 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
830 && XEXP (orig, 0) != pic_offset_table_rtx
831 && GET_CODE (XEXP (orig, 1)) != REG)
834 rtx base;
835 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
837 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
838 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
839 Pmode, (base == reg ? 0 : reg));
840 if (GET_CODE (orig) == CONST_INT)
842 pic_ref = plus_constant (base, INTVAL (orig));
843 is_complex = 1;
845 else
846 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
848 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
849 RTX_UNCHANGING_P (pic_ref) = 1;
851 if (reg && is_complex)
853 emit_move_insn (reg, pic_ref);
854 pic_ref = reg;
856 /* Likewise, should we set special REG_NOTEs here? */
859 else if (GET_CODE (orig) == CONST)
861 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
864 else if (GET_CODE (orig) == MEM
865 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
867 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
869 addr = gen_rtx (MEM, GET_MODE (orig), addr);
870 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
871 emit_move_insn (reg, addr);
872 pic_ref = reg;
875 return pic_ref;
879 void
880 machopic_finish (asm_out_file)
881 FILE *asm_out_file;
883 tree temp;
885 for (temp = machopic_stubs;
886 temp != NULL_TREE;
887 temp = TREE_CHAIN (temp))
889 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
890 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
891 char *sym;
892 char *stub;
894 if (! TREE_USED (temp))
895 continue;
897 STRIP_NAME_ENCODING (sym_name, sym_name);
899 sym = alloca (strlen (sym_name) + 2);
900 if (sym_name[0] == '*' || sym_name[0] == '&')
901 strcpy (sym, sym_name + 1);
902 else if (sym_name[0] == '-' || sym_name[0] == '+')
903 strcpy (sym, sym_name);
904 else
905 sym[0] = '_', strcpy (sym + 1, sym_name);
907 stub = alloca (strlen (stub_name) + 2);
908 if (stub_name[0] == '*' || stub_name[0] == '&')
909 strcpy (stub, stub_name + 1);
910 else
911 stub[0] = '_', strcpy (stub + 1, stub_name);
913 machopic_output_stub (asm_out_file, sym, stub);
916 for (temp = machopic_non_lazy_pointers;
917 temp != NULL_TREE;
918 temp = TREE_CHAIN (temp))
920 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
921 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
922 #if 0
923 tree decl = lookup_name_darwin (TREE_VALUE (temp));
924 #endif
926 if (! TREE_USED (temp))
927 continue;
929 if (machopic_ident_defined_p (TREE_VALUE (temp))
930 #if 0 /* add back when we have private externs */
931 || (decl && DECL_PRIVATE_EXTERN (decl))
932 #endif
935 data_section ();
936 assemble_align (GET_MODE_ALIGNMENT (Pmode));
937 assemble_label (lazy_name);
938 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
939 GET_MODE_SIZE (Pmode),
940 GET_MODE_ALIGNMENT (Pmode), 1);
942 else
944 machopic_nl_symbol_ptr_section ();
945 assemble_name (asm_out_file, lazy_name);
946 fprintf (asm_out_file, ":\n");
948 fprintf (asm_out_file, "\t.indirect_symbol ");
949 assemble_name (asm_out_file, sym_name);
950 fprintf (asm_out_file, "\n");
952 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
953 GET_MODE_ALIGNMENT (Pmode), 1);
958 int
959 machopic_operand_p (op)
960 rtx op;
962 if (MACHOPIC_JUST_INDIRECT)
964 while (GET_CODE (op) == CONST)
965 op = XEXP (op, 0);
967 if (GET_CODE (op) == SYMBOL_REF)
968 return machopic_name_defined_p (XSTR (op, 0));
969 else
970 return 0;
973 while (GET_CODE (op) == CONST)
974 op = XEXP (op, 0);
976 if (GET_CODE (op) == MINUS
977 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
978 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
979 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
980 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
981 return 1;
983 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
984 /* Without this statement, the compiler crashes while compiling enquire.c
985 when targetting PowerPC. It is not known why this code is not needed
986 when targetting other processors. */
987 else if (GET_CODE (op) == SYMBOL_REF
988 && (machopic_classify_name (XSTR (op, 0))
989 == MACHOPIC_DEFINED_FUNCTION))
991 return 1;
993 #endif
995 return 0;
998 /* This function records whether a given name corresponds to a defined
999 or undefined function or variable, for machopic_classify_ident to
1000 use later. */
1002 void
1003 darwin_encode_section_info (decl)
1004 tree decl;
1006 char code = '\0';
1007 int defined = 0;
1008 rtx sym_ref;
1009 const char *orig_str;
1010 char *new_str;
1011 size_t len, new_len;
1013 if ((TREE_CODE (decl) == FUNCTION_DECL
1014 || TREE_CODE (decl) == VAR_DECL)
1015 && !DECL_EXTERNAL (decl)
1016 && ((TREE_STATIC (decl)
1017 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1018 || (DECL_INITIAL (decl)
1019 && DECL_INITIAL (decl) != error_mark_node)))
1020 defined = 1;
1022 if (TREE_CODE (decl) == FUNCTION_DECL)
1023 code = (defined ? 'T' : 't');
1024 else if (TREE_CODE (decl) == VAR_DECL)
1025 code = (defined ? 'D' : 'd');
1027 if (code == '\0')
1028 return;
1030 sym_ref = XEXP (DECL_RTL (decl), 0);
1031 orig_str = XSTR (sym_ref, 0);
1032 len = strlen (orig_str) + 1;
1034 if (orig_str[0] == '!')
1036 /* Already encoded; see if we need to change it. */
1037 if (code == orig_str[1])
1038 return;
1039 /* Yes, tweak a copy of the name and put it in a new string. */
1040 new_str = alloca (len);
1041 memcpy (new_str, orig_str, len);
1042 new_str[1] = code;
1043 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1045 else
1047 /* Add the encoding. */
1048 new_len = len + 4;
1049 new_str = alloca (new_len);
1050 new_str[0] = '!';
1051 new_str[1] = code;
1052 new_str[2] = '_';
1053 new_str[3] = '_';
1054 memcpy (new_str + 4, orig_str, len);
1055 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1057 /* The non-lazy pointer list may have captured references to the
1058 old encoded name, change them. */
1059 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1060 update_stubs (XSTR (sym_ref, 0));
1063 /* Scan the list of non-lazy pointers and update any recorded names whose
1064 stripped name matches the argument. */
1066 static void
1067 update_non_lazy_ptrs (name)
1068 const char *name;
1070 const char *name1, *name2;
1071 tree temp;
1073 STRIP_NAME_ENCODING (name1, name);
1075 for (temp = machopic_non_lazy_pointers;
1076 temp != NULL_TREE;
1077 temp = TREE_CHAIN (temp))
1079 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1081 if (*sym_name == '!')
1083 STRIP_NAME_ENCODING (name2, sym_name);
1084 if (strcmp (name1, name2) == 0)
1086 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1087 break;
1094 /* Scan the list of stubs and update any recorded names whose
1095 stripped name matches the argument. */
1097 static void
1098 update_stubs (name)
1099 const char *name;
1101 const char *name1, *name2;
1102 tree temp;
1104 STRIP_NAME_ENCODING (name1, name);
1106 for (temp = machopic_stubs;
1107 temp != NULL_TREE;
1108 temp = TREE_CHAIN (temp))
1110 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1112 if (*sym_name == '!')
1114 STRIP_NAME_ENCODING (name2, sym_name);
1115 if (strcmp (name1, name2) == 0)
1117 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1118 break;
1124 void
1125 machopic_asm_out_constructor (symbol, priority)
1126 rtx symbol;
1127 int priority ATTRIBUTE_UNUSED;
1129 if (flag_pic)
1130 mod_init_section ();
1131 else
1132 constructor_section ();
1133 assemble_align (POINTER_SIZE);
1134 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1136 if (!flag_pic)
1137 fprintf (asm_out_file, ".reference .constructors_used\n");
1140 void
1141 machopic_asm_out_destructor (symbol, priority)
1142 rtx symbol;
1143 int priority ATTRIBUTE_UNUSED;
1145 if (flag_pic)
1146 mod_term_section ();
1147 else
1148 destructor_section ();
1149 assemble_align (POINTER_SIZE);
1150 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1152 if (!flag_pic)
1153 fprintf (asm_out_file, ".reference .destructors_used\n");