darwin.c (machopic_output_possible_stub_label): Don't generate stub routines for...
[gcc.git] / gcc / config / darwin.c
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.
5
6 This file is part of GNU CC.
7
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.
12
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.
17
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. */
22
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"
41
42 #include "darwin-protos.h"
43
44 extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
45
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 *));
50
51 int
52 name_needs_quotes (name)
53 const char *name;
54 {
55 int c;
56 while ((c = *name++) != '\0')
57 if (! ISIDNUM (c))
58 return 1;
59 return 0;
60 }
61
62 /*
63 * flag_pic = 1 ... generate only indirections
64 * flag_pic = 2 ... generate indirections and pure code
65 */
66
67 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
68 reference, which will not be changed. */
69
70 static tree machopic_defined_list;
71
72 enum machopic_addr_class
73 machopic_classify_ident (ident)
74 tree ident;
75 {
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;
86
87 if (name[0] != '!')
88 {
89 /* Here if no special encoding to be found. */
90 if (lprefix)
91 {
92 const char *name = IDENTIFIER_POINTER (ident);
93 int len = strlen (name);
94
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;
99 }
100
101 for (temp = machopic_defined_list;
102 temp != NULL_TREE;
103 temp = TREE_CHAIN (temp))
104 {
105 if (ident == TREE_VALUE (temp))
106 return MACHOPIC_DEFINED_DATA;
107 }
108
109 if (TREE_ASM_WRITTEN (ident))
110 return MACHOPIC_DEFINED_DATA;
111
112 return MACHOPIC_UNDEFINED;
113 }
114
115 else if (name[1] == 'D')
116 return MACHOPIC_DEFINED_DATA;
117
118 else if (name[1] == 'T')
119 return MACHOPIC_DEFINED_FUNCTION;
120
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')
127 {
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;
135 }
136
137 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
138 {
139 if (ident == TREE_VALUE (temp))
140 {
141 if (name[1] == 'T')
142 return MACHOPIC_DEFINED_FUNCTION;
143 else
144 return MACHOPIC_DEFINED_DATA;
145 }
146 }
147
148 if (name[1] == 't' || name[1] == 'T')
149 {
150 if (lprefix)
151 return MACHOPIC_DEFINED_FUNCTION;
152 else
153 return MACHOPIC_UNDEFINED_FUNCTION;
154 }
155 else
156 {
157 if (lprefix)
158 return MACHOPIC_DEFINED_DATA;
159 else
160 return MACHOPIC_UNDEFINED_DATA;
161 }
162 }
163
164
165 enum machopic_addr_class
166 machopic_classify_name (name)
167 const char *name;
168 {
169 return machopic_classify_ident (get_identifier (name));
170 }
171
172 int
173 machopic_ident_defined_p (ident)
174 tree ident;
175 {
176 switch (machopic_classify_ident (ident))
177 {
178 case MACHOPIC_UNDEFINED:
179 case MACHOPIC_UNDEFINED_DATA:
180 case MACHOPIC_UNDEFINED_FUNCTION:
181 return 0;
182 default:
183 return 1;
184 }
185 }
186
187 static int
188 machopic_data_defined_p (name)
189 const char *name;
190 {
191 switch (machopic_classify_ident (get_identifier (name)))
192 {
193 case MACHOPIC_DEFINED_DATA:
194 return 1;
195 default:
196 return 0;
197 }
198 }
199
200 int
201 machopic_name_defined_p (name)
202 const char *name;
203 {
204 return machopic_ident_defined_p (get_identifier (name));
205 }
206
207 void
208 machopic_define_ident (ident)
209 tree ident;
210 {
211 if (!machopic_ident_defined_p (ident))
212 machopic_defined_list =
213 tree_cons (NULL_TREE, ident, machopic_defined_list);
214 }
215
216 void
217 machopic_define_name (name)
218 const char *name;
219 {
220 machopic_define_ident (get_identifier (name));
221 }
222
223 /* This is a static to make inline functions work. The rtx
224 representing the PIC base symbol always points to here. */
225
226 static char function_base[32];
227
228 static int current_pic_label_num;
229
230 char *
231 machopic_function_base_name ()
232 {
233 static const char *name = NULL;
234 static const char *current_name;
235
236 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
237
238 if (name != current_name)
239 {
240 current_function_uses_pic_offset_table = 1;
241
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. */
247
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);
253
254 name = current_name;
255 }
256
257 return function_base;
258 }
259
260 static tree machopic_non_lazy_pointers = NULL;
261
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. */
265
266 char *
267 machopic_non_lazy_ptr_name (name)
268 const char *name;
269 {
270 char *temp_name;
271 tree temp, ident = get_identifier (name);
272
273 for (temp = machopic_non_lazy_pointers;
274 temp != NULL_TREE;
275 temp = TREE_CHAIN (temp))
276 {
277 if (ident == TREE_VALUE (temp))
278 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279 }
280
281 STRIP_NAME_ENCODING (name, name);
282
283 /* Try again, but comparing names this time. */
284 for (temp = machopic_non_lazy_pointers;
285 temp != NULL_TREE;
286 temp = TREE_CHAIN (temp))
287 {
288 if (TREE_VALUE (temp))
289 {
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));
294 }
295 }
296
297 {
298 char *buffer;
299 tree ptr_name;
300
301 buffer = alloca (strlen (name) + 20);
302
303 strcpy (buffer, "&L");
304 if (name[0] == '*')
305 strcat (buffer, name+1);
306 else
307 {
308 strcat (buffer, "_");
309 strcat (buffer, name);
310 }
311
312 strcat (buffer, "$non_lazy_ptr");
313 ptr_name = get_identifier (buffer);
314
315 machopic_non_lazy_pointers
316 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
317
318 TREE_USED (machopic_non_lazy_pointers) = 0;
319
320 return IDENTIFIER_POINTER (ptr_name);
321 }
322 }
323
324 static tree machopic_stubs = 0;
325
326 /* Make sure the GC knows about our homemade lists. */
327
328 void
329 machopic_add_gc_roots ()
330 {
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);
334 }
335
336 /* Return the name of the stub corresponding to the given name,
337 generating a new stub name if necessary. */
338
339 char *
340 machopic_stub_name (name)
341 const char *name;
342 {
343 tree temp, ident = get_identifier (name);
344 const char *tname;
345
346 for (temp = machopic_stubs;
347 temp != NULL_TREE;
348 temp = TREE_CHAIN (temp))
349 {
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));
361 }
362
363 STRIP_NAME_ENCODING (name, name);
364
365 {
366 char *buffer;
367 tree ptr_name;
368 int needs_quotes = name_needs_quotes (name);
369
370 buffer = alloca (strlen (name) + 20);
371
372 if (needs_quotes)
373 strcpy (buffer, "&\"L");
374 else
375 strcpy (buffer, "&L");
376 if (name[0] == '*')
377 {
378 strcat (buffer, name+1);
379 }
380 else
381 {
382 strcat (buffer, "_");
383 strcat (buffer, name);
384 }
385
386 if (needs_quotes)
387 strcat (buffer, "$stub\"");
388 else
389 strcat (buffer, "$stub");
390 ptr_name = get_identifier (buffer);
391
392 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
393 TREE_USED (machopic_stubs) = 0;
394
395 return IDENTIFIER_POINTER (ptr_name);
396 }
397 }
398
399 void
400 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
401 const char *name;
402 int validate_stub;
403 {
404 char *real_name;
405 tree temp, ident = get_identifier (name), id2;
406
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))
411 {
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;
421 }
422 }
423
424 /* Transform ORIG, which may be any data source, to the corresponding
425 source using indirections. */
426
427 rtx
428 machopic_indirect_data_reference (orig, reg)
429 rtx orig, reg;
430 {
431 rtx ptr_ref = orig;
432
433 if (! MACHOPIC_INDIRECT)
434 return orig;
435
436 if (GET_CODE (orig) == SYMBOL_REF)
437 {
438 const char *name = XSTR (orig, 0);
439
440 if (machopic_data_defined_p (name))
441 {
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));
446
447 #if defined (TARGET_TOC) /* i.e., PowerPC */
448 rtx hi_sum_reg = reg;
449
450 if (reg == NULL)
451 abort ();
452
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)));
458
459 orig = reg;
460 #else
461 #if defined (HAVE_lo_sum)
462 if (reg == 0) abort ();
463
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)));
470
471 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
472 #endif
473 #endif
474 return orig;
475 }
476
477 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
478 machopic_non_lazy_ptr_name (name));
479
480 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
481 RTX_UNCHANGING_P (ptr_ref) = 1;
482
483 return ptr_ref;
484 }
485 else if (GET_CODE (orig) == CONST)
486 {
487 rtx base, result;
488
489 /* legitimize both operands of the PLUS */
490 if (GET_CODE (XEXP (orig, 0)) == PLUS)
491 {
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));
496 }
497 else
498 return orig;
499
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);
504
505 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
506 RTX_UNCHANGING_P (result) = 1;
507
508 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
509 {
510 if (reg)
511 {
512 emit_move_insn (reg, result);
513 result = reg;
514 }
515 else
516 {
517 result = force_reg (GET_MODE (result), result);
518 }
519 }
520
521 return result;
522
523 }
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)
539 {
540 emit_move_insn (reg, XEXP (orig, 0));
541 XEXP (ptr_ref, 0) = reg;
542 }
543 return ptr_ref;
544 }
545
546 /* Transform TARGET (a MEM), which is a function call target, to the
547 corresponding symbol_stub if necessary. Return a new MEM. */
548
549 rtx
550 machopic_indirect_call_target (target)
551 rtx target;
552 {
553 if (GET_CODE (target) != MEM)
554 return target;
555
556 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
557 {
558 enum machine_mode mode = GET_MODE (XEXP (target, 0));
559 const char *name = XSTR (XEXP (target, 0), 0);
560
561 /* If the name is already defined, we need do nothing. */
562 if (name[0] == '!' && name[1] == 'T')
563 return target;
564
565 if (!machopic_name_defined_p (name))
566 {
567 const char *stub_name = machopic_stub_name (name);
568
569 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
570 RTX_UNCHANGING_P (target) = 1;
571 }
572 }
573
574 return target;
575 }
576
577 rtx
578 machopic_legitimize_pic_address (orig, mode, reg)
579 rtx orig, reg;
580 enum machine_mode mode;
581 {
582 rtx pic_ref = orig;
583
584 if (! MACHOPIC_PURE)
585 return orig;
586
587 /* First handle a simple SYMBOL_REF or LABEL_REF */
588 if (GET_CODE (orig) == LABEL_REF
589 || (GET_CODE (orig) == SYMBOL_REF
590 ))
591 {
592 /* addr(foo) = &func+(foo-func) */
593 rtx pic_base;
594
595 orig = machopic_indirect_data_reference (orig, reg);
596
597 if (GET_CODE (orig) == PLUS
598 && GET_CODE (XEXP (orig, 0)) == REG)
599 {
600 if (reg == 0)
601 return force_reg (mode, orig);
602
603 emit_move_insn (reg, orig);
604 return reg;
605 }
606
607 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
608
609 if (GET_CODE (orig) == MEM)
610 {
611 if (reg == 0)
612 {
613 if (reload_in_progress)
614 abort ();
615 else
616 reg = gen_reg_rtx (Pmode);
617 }
618
619 #ifdef HAVE_lo_sum
620 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
621 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
622 {
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));
631
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;
641
642 #else
643 emit_insn (gen_rtx (USE, VOIDmode,
644 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
645
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
655 }
656 else
657 #endif /* HAVE_lo_sum */
658 {
659 rtx pic = pic_offset_table_rtx;
660 if (GET_CODE (pic) != REG)
661 {
662 emit_move_insn (reg, pic);
663 pic = reg;
664 }
665 #if 0
666 emit_insn (gen_rtx (USE, VOIDmode,
667 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
668 #endif
669
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)));
676 }
677
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
683 }
684 else
685 {
686
687 #ifdef HAVE_lo_sum
688 if (GET_CODE (orig) == SYMBOL_REF
689 || GET_CODE (orig) == LABEL_REF)
690 {
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;
695
696 if (reg == 0)
697 {
698 if (reload_in_progress)
699 abort ();
700 else
701 reg = gen_reg_rtx (SImode);
702 }
703
704 hi_sum_reg = reg;
705
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
722 }
723 else
724 #endif /* HAVE_lo_sum */
725 {
726 if (GET_CODE (orig) == REG)
727 {
728 return orig;
729 }
730 else
731 {
732 rtx pic = pic_offset_table_rtx;
733 if (GET_CODE (pic) != REG)
734 {
735 emit_move_insn (reg, pic);
736 pic = reg;
737 }
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)));
747 }
748 }
749 }
750
751 RTX_UNCHANGING_P (pic_ref) = 1;
752
753 if (GET_CODE (pic_ref) != REG)
754 {
755 if (reg != 0)
756 {
757 emit_move_insn (reg, pic_ref);
758 return reg;
759 }
760 else
761 {
762 return force_reg (mode, pic_ref);
763 }
764 }
765 else
766 {
767 return pic_ref;
768 }
769 }
770
771 else if (GET_CODE (orig) == SYMBOL_REF)
772 return orig;
773
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)
780
781 {
782 rtx base;
783 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
784
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)
789 {
790 pic_ref = plus_constant (base, INTVAL (orig));
791 is_complex = 1;
792 }
793 else
794 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
795
796 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
797 RTX_UNCHANGING_P (pic_ref) = 1;
798
799 if (reg && is_complex)
800 {
801 emit_move_insn (reg, pic_ref);
802 pic_ref = reg;
803 }
804 /* Likewise, should we set special REG_NOTEs here? */
805 }
806
807 else if (GET_CODE (orig) == CONST)
808 {
809 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
810 }
811
812 else if (GET_CODE (orig) == MEM
813 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
814 {
815 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
816
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;
821 }
822
823 return pic_ref;
824 }
825
826
827 void
828 machopic_finish (asm_out_file)
829 FILE *asm_out_file;
830 {
831 tree temp;
832
833 for (temp = machopic_stubs;
834 temp != NULL_TREE;
835 temp = TREE_CHAIN (temp))
836 {
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;
841
842 if (! TREE_USED (temp))
843 continue;
844
845 /* If the symbol is actually defined, we don't need a stub. */
846 if (sym_name[0] == '!' && sym_name[1] == 'T')
847 continue;
848
849 STRIP_NAME_ENCODING (sym_name, sym_name);
850
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);
858
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);
864
865 machopic_output_stub (asm_out_file, sym, stub);
866 }
867
868 for (temp = machopic_non_lazy_pointers;
869 temp != NULL_TREE;
870 temp = TREE_CHAIN (temp))
871 {
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
877
878 if (! TREE_USED (temp))
879 continue;
880
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
885 )
886 {
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);
893 }
894 else
895 {
896 machopic_nl_symbol_ptr_section ();
897 assemble_name (asm_out_file, lazy_name);
898 fprintf (asm_out_file, ":\n");
899
900 fprintf (asm_out_file, "\t.indirect_symbol ");
901 assemble_name (asm_out_file, sym_name);
902 fprintf (asm_out_file, "\n");
903
904 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
905 GET_MODE_ALIGNMENT (Pmode), 1);
906 }
907 }
908 }
909
910 int
911 machopic_operand_p (op)
912 rtx op;
913 {
914 if (MACHOPIC_JUST_INDIRECT)
915 {
916 while (GET_CODE (op) == CONST)
917 op = XEXP (op, 0);
918
919 if (GET_CODE (op) == SYMBOL_REF)
920 return machopic_name_defined_p (XSTR (op, 0));
921 else
922 return 0;
923 }
924
925 while (GET_CODE (op) == CONST)
926 op = XEXP (op, 0);
927
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;
934
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))
942 {
943 return 1;
944 }
945 #endif
946
947 return 0;
948 }
949
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. */
953
954 void
955 darwin_encode_section_info (decl)
956 tree decl;
957 {
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;
964
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;
973
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');
978
979 if (code == '\0')
980 return;
981
982 sym_ref = XEXP (DECL_RTL (decl), 0);
983 orig_str = XSTR (sym_ref, 0);
984 len = strlen (orig_str) + 1;
985
986 if (orig_str[0] == '!')
987 {
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);
996 }
997 else
998 {
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);
1008 }
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));
1015 }
1016
1017 /* Scan the list of non-lazy pointers and update any recorded names whose
1018 stripped name matches the argument. */
1019
1020 static void
1021 update_non_lazy_ptrs (name)
1022 const char *name;
1023 {
1024 const char *name1, *name2;
1025 tree temp;
1026
1027 STRIP_NAME_ENCODING (name1, name);
1028
1029 for (temp = machopic_non_lazy_pointers;
1030 temp != NULL_TREE;
1031 temp = TREE_CHAIN (temp))
1032 {
1033 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1034
1035 if (*sym_name == '!')
1036 {
1037 STRIP_NAME_ENCODING (name2, sym_name);
1038 if (strcmp (name1, name2) == 0)
1039 {
1040 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
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. */
1050
1051 void
1052 machopic_output_possible_stub_label (file, name)
1053 FILE *file;
1054 const char *name;
1055 {
1056 tree temp;
1057
1058
1059 /* Ensure we're looking at a section-encoded name. */
1060 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1061 return;
1062
1063 for (temp = machopic_stubs;
1064 temp != NULL_TREE;
1065 temp = TREE_CHAIN (temp))
1066 {
1067 const char *sym_name;
1068
1069 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1070 if (sym_name[0] == '!' && sym_name[1] == 'T'
1071 && ! strcmp (name+2, sym_name+2))
1072 {
1073 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1074 /* Avoid generating a stub for this. */
1075 TREE_USED (temp) = 0;
1076 break;
1077 }
1078 }
1079 }
1080
1081 /* Scan the list of stubs and update any recorded names whose
1082 stripped name matches the argument. */
1083
1084 static void
1085 update_stubs (name)
1086 const char *name;
1087 {
1088 const char *name1, *name2;
1089 tree temp;
1090
1091 STRIP_NAME_ENCODING (name1, name);
1092
1093 for (temp = machopic_stubs;
1094 temp != NULL_TREE;
1095 temp = TREE_CHAIN (temp))
1096 {
1097 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1098
1099 if (*sym_name == '!')
1100 {
1101 STRIP_NAME_ENCODING (name2, sym_name);
1102 if (strcmp (name1, name2) == 0)
1103 {
1104 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1105 break;
1106 }
1107 }
1108 }
1109 }
1110
1111 void
1112 machopic_asm_out_constructor (symbol, priority)
1113 rtx symbol;
1114 int priority ATTRIBUTE_UNUSED;
1115 {
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);
1122
1123 if (!flag_pic)
1124 fprintf (asm_out_file, ".reference .constructors_used\n");
1125 }
1126
1127 void
1128 machopic_asm_out_destructor (symbol, priority)
1129 rtx symbol;
1130 int priority ATTRIBUTE_UNUSED;
1131 {
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);
1138
1139 if (!flag_pic)
1140 fprintf (asm_out_file, ".reference .destructors_used\n");
1141 }