Merge from pch-branch up to tag pch-commit-20020603.
[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, 2002
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 GTY(()) 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 GTY(()) tree machopic_non_lazy_pointers;
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 name = darwin_strip_name_encoding (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 temp_name = darwin_strip_name_encoding (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 GTY(()) tree machopic_stubs;
325
326 /* Return the name of the stub corresponding to the given name,
327 generating a new stub name if necessary. */
328
329 char *
330 machopic_stub_name (name)
331 const char *name;
332 {
333 tree temp, ident = get_identifier (name);
334 const char *tname;
335
336 for (temp = machopic_stubs;
337 temp != NULL_TREE;
338 temp = TREE_CHAIN (temp))
339 {
340 if (ident == TREE_VALUE (temp))
341 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
342 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
343 if (strcmp (name, tname) == 0)
344 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
345 /* A library call name might not be section-encoded yet, so try
346 it against a stripped name. */
347 if (name[0] != '!'
348 && tname[0] == '!'
349 && strcmp (name, tname + 4) == 0)
350 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
351 }
352
353 name = darwin_strip_name_encoding (name);
354
355 {
356 char *buffer;
357 tree ptr_name;
358 int needs_quotes = name_needs_quotes (name);
359
360 buffer = alloca (strlen (name) + 20);
361
362 if (needs_quotes)
363 strcpy (buffer, "&\"L");
364 else
365 strcpy (buffer, "&L");
366 if (name[0] == '*')
367 {
368 strcat (buffer, name+1);
369 }
370 else
371 {
372 strcat (buffer, "_");
373 strcat (buffer, name);
374 }
375
376 if (needs_quotes)
377 strcat (buffer, "$stub\"");
378 else
379 strcat (buffer, "$stub");
380 ptr_name = get_identifier (buffer);
381
382 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
383 TREE_USED (machopic_stubs) = 0;
384
385 return IDENTIFIER_POINTER (ptr_name);
386 }
387 }
388
389 void
390 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
391 const char *name;
392 int validate_stub;
393 {
394 char *real_name;
395 tree temp, ident = get_identifier (name), id2;
396
397 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
398 temp != NULL_TREE;
399 temp = TREE_CHAIN (temp))
400 if (ident == TREE_PURPOSE (temp))
401 {
402 /* Mark both the stub or non-lazy pointer as well as the
403 original symbol as being referenced. */
404 TREE_USED (temp) = 1;
405 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
406 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
407 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
408 real_name = darwin_strip_name_encoding (real_name);
409 id2 = maybe_get_identifier (real_name);
410 if (id2)
411 TREE_SYMBOL_REFERENCED (id2) = 1;
412 }
413 }
414
415 /* Transform ORIG, which may be any data source, to the corresponding
416 source using indirections. */
417
418 rtx
419 machopic_indirect_data_reference (orig, reg)
420 rtx orig, reg;
421 {
422 rtx ptr_ref = orig;
423
424 if (! MACHOPIC_INDIRECT)
425 return orig;
426
427 if (GET_CODE (orig) == SYMBOL_REF)
428 {
429 const char *name = XSTR (orig, 0);
430
431 if (machopic_data_defined_p (name))
432 {
433 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
434 machopic_function_base_name ());
435 rtx offset = gen_rtx (CONST, Pmode,
436 gen_rtx (MINUS, Pmode, orig, pic_base));
437
438 #if defined (TARGET_TOC) /* i.e., PowerPC */
439 rtx hi_sum_reg = reg;
440
441 if (reg == NULL)
442 abort ();
443
444 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
445 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
446 gen_rtx (HIGH, Pmode, offset))));
447 emit_insn (gen_rtx (SET, Pmode, reg,
448 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
449
450 orig = reg;
451 #else
452 #if defined (HAVE_lo_sum)
453 if (reg == 0) abort ();
454
455 emit_insn (gen_rtx (SET, VOIDmode, reg,
456 gen_rtx (HIGH, Pmode, offset)));
457 emit_insn (gen_rtx (SET, VOIDmode, reg,
458 gen_rtx (LO_SUM, Pmode, reg, offset)));
459 emit_insn (gen_rtx (USE, VOIDmode,
460 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
461
462 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
463 #endif
464 #endif
465 return orig;
466 }
467
468 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
469 machopic_non_lazy_ptr_name (name));
470
471 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
472 RTX_UNCHANGING_P (ptr_ref) = 1;
473
474 return ptr_ref;
475 }
476 else if (GET_CODE (orig) == CONST)
477 {
478 rtx base, result;
479
480 /* legitimize both operands of the PLUS */
481 if (GET_CODE (XEXP (orig, 0)) == PLUS)
482 {
483 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
484 reg);
485 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
486 (base == reg ? 0 : reg));
487 }
488 else
489 return orig;
490
491 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
492 result = plus_constant (base, INTVAL (orig));
493 else
494 result = gen_rtx (PLUS, Pmode, base, orig);
495
496 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
497 RTX_UNCHANGING_P (result) = 1;
498
499 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
500 {
501 if (reg)
502 {
503 emit_move_insn (reg, result);
504 result = reg;
505 }
506 else
507 {
508 result = force_reg (GET_MODE (result), result);
509 }
510 }
511
512 return result;
513
514 }
515 else if (GET_CODE (orig) == MEM)
516 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
517 /* When the target is i386, this code prevents crashes due to the
518 compiler's ignorance on how to move the PIC base register to
519 other registers. (The reload phase sometimes introduces such
520 insns.) */
521 else if (GET_CODE (orig) == PLUS
522 && GET_CODE (XEXP (orig, 0)) == REG
523 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
524 #ifdef I386
525 /* Prevent the same register from being erroneously used
526 as both the base and index registers. */
527 && GET_CODE (XEXP (orig, 1)) == CONST
528 #endif
529 && reg)
530 {
531 emit_move_insn (reg, XEXP (orig, 0));
532 XEXP (ptr_ref, 0) = reg;
533 }
534 return ptr_ref;
535 }
536
537 /* Transform TARGET (a MEM), which is a function call target, to the
538 corresponding symbol_stub if necessary. Return a new MEM. */
539
540 rtx
541 machopic_indirect_call_target (target)
542 rtx target;
543 {
544 if (GET_CODE (target) != MEM)
545 return target;
546
547 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
548 {
549 enum machine_mode mode = GET_MODE (XEXP (target, 0));
550 const char *name = XSTR (XEXP (target, 0), 0);
551
552 /* If the name is already defined, we need do nothing. */
553 if (name[0] == '!' && name[1] == 'T')
554 return target;
555
556 if (!machopic_name_defined_p (name))
557 {
558 const char *stub_name = machopic_stub_name (name);
559
560 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
561 RTX_UNCHANGING_P (target) = 1;
562 }
563 }
564
565 return target;
566 }
567
568 rtx
569 machopic_legitimize_pic_address (orig, mode, reg)
570 rtx orig, reg;
571 enum machine_mode mode;
572 {
573 rtx pic_ref = orig;
574
575 if (! MACHOPIC_PURE)
576 return orig;
577
578 /* First handle a simple SYMBOL_REF or LABEL_REF */
579 if (GET_CODE (orig) == LABEL_REF
580 || (GET_CODE (orig) == SYMBOL_REF
581 ))
582 {
583 /* addr(foo) = &func+(foo-func) */
584 rtx pic_base;
585
586 orig = machopic_indirect_data_reference (orig, reg);
587
588 if (GET_CODE (orig) == PLUS
589 && GET_CODE (XEXP (orig, 0)) == REG)
590 {
591 if (reg == 0)
592 return force_reg (mode, orig);
593
594 emit_move_insn (reg, orig);
595 return reg;
596 }
597
598 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
599
600 if (GET_CODE (orig) == MEM)
601 {
602 if (reg == 0)
603 {
604 if (reload_in_progress)
605 abort ();
606 else
607 reg = gen_reg_rtx (Pmode);
608 }
609
610 #ifdef HAVE_lo_sum
611 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
612 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
613 {
614 rtx offset = gen_rtx (CONST, Pmode,
615 gen_rtx (MINUS, Pmode,
616 XEXP (orig, 0), pic_base));
617 #if defined (TARGET_TOC) /* i.e., PowerPC */
618 /* Generating a new reg may expose opportunities for
619 common subexpression elimination. */
620 rtx hi_sum_reg =
621 (reload_in_progress ? reg : gen_reg_rtx (SImode));
622
623 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
624 gen_rtx (PLUS, Pmode,
625 pic_offset_table_rtx,
626 gen_rtx (HIGH, Pmode, offset))));
627 emit_insn (gen_rtx (SET, VOIDmode, reg,
628 gen_rtx (MEM, GET_MODE (orig),
629 gen_rtx (LO_SUM, Pmode,
630 hi_sum_reg, offset))));
631 pic_ref = reg;
632
633 #else
634 emit_insn (gen_rtx (USE, VOIDmode,
635 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
636
637 emit_insn (gen_rtx (SET, VOIDmode, reg,
638 gen_rtx (HIGH, Pmode,
639 gen_rtx (CONST, Pmode, offset))));
640 emit_insn (gen_rtx (SET, VOIDmode, reg,
641 gen_rtx (LO_SUM, Pmode, reg,
642 gen_rtx (CONST, Pmode, offset))));
643 pic_ref = gen_rtx (PLUS, Pmode,
644 pic_offset_table_rtx, reg);
645 #endif
646 }
647 else
648 #endif /* HAVE_lo_sum */
649 {
650 rtx pic = pic_offset_table_rtx;
651 if (GET_CODE (pic) != REG)
652 {
653 emit_move_insn (reg, pic);
654 pic = reg;
655 }
656 #if 0
657 emit_insn (gen_rtx (USE, VOIDmode,
658 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
659 #endif
660
661 pic_ref = gen_rtx (PLUS, Pmode,
662 pic,
663 gen_rtx (CONST, Pmode,
664 gen_rtx (MINUS, Pmode,
665 XEXP (orig, 0),
666 pic_base)));
667 }
668
669 #if !defined (TARGET_TOC)
670 RTX_UNCHANGING_P (pic_ref) = 1;
671 emit_move_insn (reg, pic_ref);
672 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
673 #endif
674 }
675 else
676 {
677
678 #ifdef HAVE_lo_sum
679 if (GET_CODE (orig) == SYMBOL_REF
680 || GET_CODE (orig) == LABEL_REF)
681 {
682 rtx offset = gen_rtx (CONST, Pmode,
683 gen_rtx (MINUS, Pmode, orig, pic_base));
684 #if defined (TARGET_TOC) /* i.e., PowerPC */
685 rtx hi_sum_reg;
686
687 if (reg == 0)
688 {
689 if (reload_in_progress)
690 abort ();
691 else
692 reg = gen_reg_rtx (SImode);
693 }
694
695 hi_sum_reg = reg;
696
697 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
698 gen_rtx (PLUS, Pmode,
699 pic_offset_table_rtx,
700 gen_rtx (HIGH, Pmode, offset))));
701 emit_insn (gen_rtx (SET, VOIDmode, reg,
702 gen_rtx (LO_SUM, Pmode,
703 hi_sum_reg, offset)));
704 pic_ref = reg;
705 #else
706 emit_insn (gen_rtx (SET, VOIDmode, reg,
707 gen_rtx (HIGH, Pmode, offset)));
708 emit_insn (gen_rtx (SET, VOIDmode, reg,
709 gen_rtx (LO_SUM, Pmode, reg, offset)));
710 pic_ref = gen_rtx (PLUS, Pmode,
711 pic_offset_table_rtx, reg);
712 #endif
713 }
714 else
715 #endif /* HAVE_lo_sum */
716 {
717 if (GET_CODE (orig) == REG)
718 {
719 return orig;
720 }
721 else
722 {
723 rtx pic = pic_offset_table_rtx;
724 if (GET_CODE (pic) != REG)
725 {
726 emit_move_insn (reg, pic);
727 pic = reg;
728 }
729 #if 0
730 emit_insn (gen_rtx (USE, VOIDmode,
731 pic_offset_table_rtx));
732 #endif
733 pic_ref = gen_rtx (PLUS, Pmode,
734 pic,
735 gen_rtx (CONST, Pmode,
736 gen_rtx (MINUS, Pmode,
737 orig, pic_base)));
738 }
739 }
740 }
741
742 RTX_UNCHANGING_P (pic_ref) = 1;
743
744 if (GET_CODE (pic_ref) != REG)
745 {
746 if (reg != 0)
747 {
748 emit_move_insn (reg, pic_ref);
749 return reg;
750 }
751 else
752 {
753 return force_reg (mode, pic_ref);
754 }
755 }
756 else
757 {
758 return pic_ref;
759 }
760 }
761
762 else if (GET_CODE (orig) == SYMBOL_REF)
763 return orig;
764
765 else if (GET_CODE (orig) == PLUS
766 && (GET_CODE (XEXP (orig, 0)) == MEM
767 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
768 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
769 && XEXP (orig, 0) != pic_offset_table_rtx
770 && GET_CODE (XEXP (orig, 1)) != REG)
771
772 {
773 rtx base;
774 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
775
776 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
777 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
778 Pmode, (base == reg ? 0 : reg));
779 if (GET_CODE (orig) == CONST_INT)
780 {
781 pic_ref = plus_constant (base, INTVAL (orig));
782 is_complex = 1;
783 }
784 else
785 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
786
787 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
788 RTX_UNCHANGING_P (pic_ref) = 1;
789
790 if (reg && is_complex)
791 {
792 emit_move_insn (reg, pic_ref);
793 pic_ref = reg;
794 }
795 /* Likewise, should we set special REG_NOTEs here? */
796 }
797
798 else if (GET_CODE (orig) == CONST)
799 {
800 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
801 }
802
803 else if (GET_CODE (orig) == MEM
804 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
805 {
806 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
807
808 addr = gen_rtx (MEM, GET_MODE (orig), addr);
809 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
810 emit_move_insn (reg, addr);
811 pic_ref = reg;
812 }
813
814 return pic_ref;
815 }
816
817
818 void
819 machopic_finish (asm_out_file)
820 FILE *asm_out_file;
821 {
822 tree temp;
823
824 for (temp = machopic_stubs;
825 temp != NULL_TREE;
826 temp = TREE_CHAIN (temp))
827 {
828 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
829 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
830 char *sym;
831 char *stub;
832
833 if (! TREE_USED (temp))
834 continue;
835
836 /* If the symbol is actually defined, we don't need a stub. */
837 if (sym_name[0] == '!' && sym_name[1] == 'T')
838 continue;
839
840 sym_name = darwin_strip_name_encoding (sym_name);
841
842 sym = alloca (strlen (sym_name) + 2);
843 if (sym_name[0] == '*' || sym_name[0] == '&')
844 strcpy (sym, sym_name + 1);
845 else if (sym_name[0] == '-' || sym_name[0] == '+')
846 strcpy (sym, sym_name);
847 else
848 sym[0] = '_', strcpy (sym + 1, sym_name);
849
850 stub = alloca (strlen (stub_name) + 2);
851 if (stub_name[0] == '*' || stub_name[0] == '&')
852 strcpy (stub, stub_name + 1);
853 else
854 stub[0] = '_', strcpy (stub + 1, stub_name);
855
856 machopic_output_stub (asm_out_file, sym, stub);
857 }
858
859 for (temp = machopic_non_lazy_pointers;
860 temp != NULL_TREE;
861 temp = TREE_CHAIN (temp))
862 {
863 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
864 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
865 #if 0
866 tree decl = lookup_name_darwin (TREE_VALUE (temp));
867 #endif
868
869 if (! TREE_USED (temp))
870 continue;
871
872 if (machopic_ident_defined_p (TREE_VALUE (temp))
873 #if 0 /* add back when we have private externs */
874 || (decl && DECL_PRIVATE_EXTERN (decl))
875 #endif
876 )
877 {
878 data_section ();
879 assemble_align (GET_MODE_ALIGNMENT (Pmode));
880 assemble_label (lazy_name);
881 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
882 GET_MODE_SIZE (Pmode),
883 GET_MODE_ALIGNMENT (Pmode), 1);
884 }
885 else
886 {
887 machopic_nl_symbol_ptr_section ();
888 assemble_name (asm_out_file, lazy_name);
889 fprintf (asm_out_file, ":\n");
890
891 fprintf (asm_out_file, "\t.indirect_symbol ");
892 assemble_name (asm_out_file, sym_name);
893 fprintf (asm_out_file, "\n");
894
895 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
896 GET_MODE_ALIGNMENT (Pmode), 1);
897 }
898 }
899 }
900
901 int
902 machopic_operand_p (op)
903 rtx op;
904 {
905 if (MACHOPIC_JUST_INDIRECT)
906 {
907 while (GET_CODE (op) == CONST)
908 op = XEXP (op, 0);
909
910 if (GET_CODE (op) == SYMBOL_REF)
911 return machopic_name_defined_p (XSTR (op, 0));
912 else
913 return 0;
914 }
915
916 while (GET_CODE (op) == CONST)
917 op = XEXP (op, 0);
918
919 if (GET_CODE (op) == MINUS
920 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
921 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
922 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
923 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
924 return 1;
925
926 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
927 /* Without this statement, the compiler crashes while compiling enquire.c
928 when targetting PowerPC. It is not known why this code is not needed
929 when targetting other processors. */
930 else if (GET_CODE (op) == SYMBOL_REF
931 && (machopic_classify_name (XSTR (op, 0))
932 == MACHOPIC_DEFINED_FUNCTION))
933 {
934 return 1;
935 }
936 #endif
937
938 return 0;
939 }
940
941 /* This function records whether a given name corresponds to a defined
942 or undefined function or variable, for machopic_classify_ident to
943 use later. */
944
945 void
946 darwin_encode_section_info (decl, first)
947 tree decl;
948 int first ATTRIBUTE_UNUSED;
949 {
950 char code = '\0';
951 int defined = 0;
952 rtx sym_ref;
953 const char *orig_str;
954 char *new_str;
955 size_t len, new_len;
956
957 if ((TREE_CODE (decl) == FUNCTION_DECL
958 || TREE_CODE (decl) == VAR_DECL)
959 && !DECL_EXTERNAL (decl)
960 && ((TREE_STATIC (decl)
961 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
962 || (DECL_INITIAL (decl)
963 && DECL_INITIAL (decl) != error_mark_node)))
964 defined = 1;
965
966 if (TREE_CODE (decl) == FUNCTION_DECL)
967 code = (defined ? 'T' : 't');
968 else if (TREE_CODE (decl) == VAR_DECL)
969 code = (defined ? 'D' : 'd');
970
971 if (code == '\0')
972 return;
973
974 sym_ref = XEXP (DECL_RTL (decl), 0);
975 orig_str = XSTR (sym_ref, 0);
976 len = strlen (orig_str) + 1;
977
978 if (orig_str[0] == '!')
979 {
980 /* Already encoded; see if we need to change it. */
981 if (code == orig_str[1])
982 return;
983 /* Yes, tweak a copy of the name and put it in a new string. */
984 new_str = alloca (len);
985 memcpy (new_str, orig_str, len);
986 new_str[1] = code;
987 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
988 }
989 else
990 {
991 /* Add the encoding. */
992 new_len = len + 4;
993 new_str = alloca (new_len);
994 new_str[0] = '!';
995 new_str[1] = code;
996 new_str[2] = '_';
997 new_str[3] = '_';
998 memcpy (new_str + 4, orig_str, len);
999 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1000 }
1001 /* The non-lazy pointer list may have captured references to the
1002 old encoded name, change them. */
1003 if (TREE_CODE (decl) == VAR_DECL)
1004 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1005 else
1006 update_stubs (XSTR (sym_ref, 0));
1007 }
1008
1009 /* Undo the effects of the above. */
1010
1011 const char *
1012 darwin_strip_name_encoding (str)
1013 const char *str;
1014 {
1015 return str[0] == '!' ? str + 4 : str;
1016 }
1017
1018 /* Scan the list of non-lazy pointers and update any recorded names whose
1019 stripped name matches the argument. */
1020
1021 static void
1022 update_non_lazy_ptrs (name)
1023 const char *name;
1024 {
1025 const char *name1, *name2;
1026 tree temp;
1027
1028 name1 = darwin_strip_name_encoding (name);
1029
1030 for (temp = machopic_non_lazy_pointers;
1031 temp != NULL_TREE;
1032 temp = TREE_CHAIN (temp))
1033 {
1034 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1035
1036 if (*sym_name == '!')
1037 {
1038 name2 = darwin_strip_name_encoding (sym_name);
1039 if (strcmp (name1, name2) == 0)
1040 {
1041 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1042 break;
1043 }
1044 }
1045 }
1046 }
1047
1048 /* Function NAME is being defined, and its label has just been output.
1049 If there's already a reference to a stub for this function, we can
1050 just emit the stub label now and we don't bother emitting the stub later. */
1051
1052 void
1053 machopic_output_possible_stub_label (file, name)
1054 FILE *file;
1055 const char *name;
1056 {
1057 tree temp;
1058
1059
1060 /* Ensure we're looking at a section-encoded name. */
1061 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1062 return;
1063
1064 for (temp = machopic_stubs;
1065 temp != NULL_TREE;
1066 temp = TREE_CHAIN (temp))
1067 {
1068 const char *sym_name;
1069
1070 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1071 if (sym_name[0] == '!' && sym_name[1] == 'T'
1072 && ! strcmp (name+2, sym_name+2))
1073 {
1074 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1075 /* Avoid generating a stub for this. */
1076 TREE_USED (temp) = 0;
1077 break;
1078 }
1079 }
1080 }
1081
1082 /* Scan the list of stubs and update any recorded names whose
1083 stripped name matches the argument. */
1084
1085 static void
1086 update_stubs (name)
1087 const char *name;
1088 {
1089 const char *name1, *name2;
1090 tree temp;
1091
1092 name1 = darwin_strip_name_encoding (name);
1093
1094 for (temp = machopic_stubs;
1095 temp != NULL_TREE;
1096 temp = TREE_CHAIN (temp))
1097 {
1098 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1099
1100 if (*sym_name == '!')
1101 {
1102 name2 = darwin_strip_name_encoding (sym_name);
1103 if (strcmp (name1, name2) == 0)
1104 {
1105 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1106 break;
1107 }
1108 }
1109 }
1110 }
1111
1112 void
1113 machopic_select_section (exp, reloc, align)
1114 tree exp;
1115 int reloc;
1116 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1117 {
1118 if (TREE_CODE (exp) == STRING_CST)
1119 {
1120 if (flag_writable_strings)
1121 data_section ();
1122 else if (TREE_STRING_LENGTH (exp) !=
1123 strlen (TREE_STRING_POINTER (exp)) + 1)
1124 readonly_data_section ();
1125 else
1126 cstring_section ();
1127 }
1128 else if (TREE_CODE (exp) == INTEGER_CST
1129 || TREE_CODE (exp) == REAL_CST)
1130 {
1131 tree size = TYPE_SIZE (TREE_TYPE (exp));
1132
1133 if (TREE_CODE (size) == INTEGER_CST &&
1134 TREE_INT_CST_LOW (size) == 4 &&
1135 TREE_INT_CST_HIGH (size) == 0)
1136 literal4_section ();
1137 else if (TREE_CODE (size) == INTEGER_CST &&
1138 TREE_INT_CST_LOW (size) == 8 &&
1139 TREE_INT_CST_HIGH (size) == 0)
1140 literal8_section ();
1141 else
1142 readonly_data_section ();
1143 }
1144 else if (TREE_CODE (exp) == CONSTRUCTOR
1145 && TREE_TYPE (exp)
1146 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1147 && TYPE_NAME (TREE_TYPE (exp)))
1148 {
1149 tree name = TYPE_NAME (TREE_TYPE (exp));
1150 if (TREE_CODE (name) == TYPE_DECL)
1151 name = DECL_NAME (name);
1152 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1153 objc_constant_string_object_section ();
1154 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1155 objc_string_object_section ();
1156 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1157 {
1158 if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1159 const_data_section ();
1160 else
1161 readonly_data_section ();
1162 }
1163 else
1164 data_section ();
1165 }
1166 else if (TREE_CODE (exp) == VAR_DECL &&
1167 DECL_NAME (exp) &&
1168 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1169 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1170 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1171 {
1172 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1173
1174 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1175 objc_cls_meth_section ();
1176 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1177 objc_inst_meth_section ();
1178 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1179 objc_cat_cls_meth_section ();
1180 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1181 objc_cat_inst_meth_section ();
1182 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1183 objc_class_vars_section ();
1184 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1185 objc_instance_vars_section ();
1186 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1187 objc_cat_cls_meth_section ();
1188 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1189 objc_class_names_section ();
1190 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1191 objc_meth_var_names_section ();
1192 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1193 objc_meth_var_types_section ();
1194 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1195 objc_cls_refs_section ();
1196 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1197 objc_class_section ();
1198 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1199 objc_meta_class_section ();
1200 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1201 objc_category_section ();
1202 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1203 objc_selector_refs_section ();
1204 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1205 objc_selector_fixup_section ();
1206 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1207 objc_symbols_section ();
1208 else if (!strncmp (name, "_OBJC_MODULES", 13))
1209 objc_module_info_section ();
1210 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1211 objc_cat_inst_meth_section ();
1212 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1213 objc_cat_cls_meth_section ();
1214 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1215 objc_cat_cls_meth_section ();
1216 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1217 objc_protocol_section ();
1218 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1219 && !TREE_SIDE_EFFECTS (exp))
1220 {
1221 if (flag_pic && reloc)
1222 const_data_section ();
1223 else
1224 readonly_data_section ();
1225 }
1226 else
1227 data_section ();
1228 }
1229 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1230 {
1231 if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1232 const_data_section ();
1233 else
1234 readonly_data_section ();
1235 }
1236 else
1237 data_section ();
1238 }
1239
1240 /* This can be called with address expressions as "rtx".
1241 They must go in "const". */
1242
1243 void
1244 machopic_select_rtx_section (mode, x, align)
1245 enum machine_mode mode;
1246 rtx x;
1247 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1248 {
1249 if (GET_MODE_SIZE (mode) == 8)
1250 literal8_section ();
1251 else if (GET_MODE_SIZE (mode) == 4
1252 && (GET_CODE (x) == CONST_INT
1253 || GET_CODE (x) == CONST_DOUBLE))
1254 literal4_section ();
1255 else
1256 const_section ();
1257 }
1258
1259 void
1260 machopic_asm_out_constructor (symbol, priority)
1261 rtx symbol;
1262 int priority ATTRIBUTE_UNUSED;
1263 {
1264 if (flag_pic)
1265 mod_init_section ();
1266 else
1267 constructor_section ();
1268 assemble_align (POINTER_SIZE);
1269 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1270
1271 if (!flag_pic)
1272 fprintf (asm_out_file, ".reference .constructors_used\n");
1273 }
1274
1275 void
1276 machopic_asm_out_destructor (symbol, priority)
1277 rtx symbol;
1278 int priority ATTRIBUTE_UNUSED;
1279 {
1280 if (flag_pic)
1281 mod_term_section ();
1282 else
1283 destructor_section ();
1284 assemble_align (POINTER_SIZE);
1285 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1286
1287 if (!flag_pic)
1288 fprintf (asm_out_file, ".reference .destructors_used\n");
1289 }
1290
1291 #include "gt-darwin.h"
1292