]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/darwin.c
Merge basic-improvements-branch to trunk
[thirdparty/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 "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "reload.h"
40 #include "function.h"
41 #include "ggc.h"
42 #include "langhooks.h"
43 #include "tm_p.h"
44
45 static int machopic_data_defined_p PARAMS ((const char *));
46 static void update_non_lazy_ptrs PARAMS ((const char *));
47 static void update_stubs PARAMS ((const char *));
48
49 int
50 name_needs_quotes (name)
51 const char *name;
52 {
53 int c;
54 while ((c = *name++) != '\0')
55 if (! ISIDNUM (c))
56 return 1;
57 return 0;
58 }
59
60 /*
61 * flag_pic = 1 ... generate only indirections
62 * flag_pic = 2 ... generate indirections and pure code
63 */
64
65 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
66 reference, which will not be changed. */
67
68 static GTY(()) tree machopic_defined_list;
69
70 enum machopic_addr_class
71 machopic_classify_ident (ident)
72 tree ident;
73 {
74 const char *name = IDENTIFIER_POINTER (ident);
75 int lprefix = (((name[0] == '*' || name[0] == '&')
76 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
77 || ( name[0] == '_'
78 && name[1] == 'O'
79 && name[2] == 'B'
80 && name[3] == 'J'
81 && name[4] == 'C'
82 && name[5] == '_'));
83 tree temp;
84
85 if (name[0] != '!')
86 {
87 /* Here if no special encoding to be found. */
88 if (lprefix)
89 {
90 const char *name = IDENTIFIER_POINTER (ident);
91 int len = strlen (name);
92
93 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
94 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
95 return MACHOPIC_DEFINED_FUNCTION;
96 return MACHOPIC_DEFINED_DATA;
97 }
98
99 for (temp = machopic_defined_list;
100 temp != NULL_TREE;
101 temp = TREE_CHAIN (temp))
102 {
103 if (ident == TREE_VALUE (temp))
104 return MACHOPIC_DEFINED_DATA;
105 }
106
107 if (TREE_ASM_WRITTEN (ident))
108 return MACHOPIC_DEFINED_DATA;
109
110 return MACHOPIC_UNDEFINED;
111 }
112
113 else if (name[1] == 'D')
114 return MACHOPIC_DEFINED_DATA;
115
116 else if (name[1] == 'T')
117 return MACHOPIC_DEFINED_FUNCTION;
118
119 /* It is possible that someone is holding a "stale" name, which has
120 since been defined. See if there is a "defined" name (i.e,
121 different from NAME only in having a '!D_' or a '!T_' instead of
122 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
123 that this identifier is defined. */
124 else if (name[1] == 'd' || name[1] == 't')
125 {
126 char *new_name;
127 new_name = (char *)alloca (strlen (name) + 1);
128 strcpy (new_name, name);
129 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
130 if (maybe_get_identifier (new_name) != NULL)
131 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
132 : MACHOPIC_DEFINED_FUNCTION;
133 }
134
135 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
136 {
137 if (ident == TREE_VALUE (temp))
138 {
139 if (name[1] == 'T')
140 return MACHOPIC_DEFINED_FUNCTION;
141 else
142 return MACHOPIC_DEFINED_DATA;
143 }
144 }
145
146 if (name[1] == 't' || name[1] == 'T')
147 {
148 if (lprefix)
149 return MACHOPIC_DEFINED_FUNCTION;
150 else
151 return MACHOPIC_UNDEFINED_FUNCTION;
152 }
153 else
154 {
155 if (lprefix)
156 return MACHOPIC_DEFINED_DATA;
157 else
158 return MACHOPIC_UNDEFINED_DATA;
159 }
160 }
161
162
163 enum machopic_addr_class
164 machopic_classify_name (name)
165 const char *name;
166 {
167 return machopic_classify_ident (get_identifier (name));
168 }
169
170 int
171 machopic_ident_defined_p (ident)
172 tree ident;
173 {
174 switch (machopic_classify_ident (ident))
175 {
176 case MACHOPIC_UNDEFINED:
177 case MACHOPIC_UNDEFINED_DATA:
178 case MACHOPIC_UNDEFINED_FUNCTION:
179 return 0;
180 default:
181 return 1;
182 }
183 }
184
185 static int
186 machopic_data_defined_p (name)
187 const char *name;
188 {
189 switch (machopic_classify_ident (get_identifier (name)))
190 {
191 case MACHOPIC_DEFINED_DATA:
192 return 1;
193 default:
194 return 0;
195 }
196 }
197
198 int
199 machopic_name_defined_p (name)
200 const char *name;
201 {
202 return machopic_ident_defined_p (get_identifier (name));
203 }
204
205 void
206 machopic_define_ident (ident)
207 tree ident;
208 {
209 if (!machopic_ident_defined_p (ident))
210 machopic_defined_list =
211 tree_cons (NULL_TREE, ident, machopic_defined_list);
212 }
213
214 void
215 machopic_define_name (name)
216 const char *name;
217 {
218 machopic_define_ident (get_identifier (name));
219 }
220
221 /* This is a static to make inline functions work. The rtx
222 representing the PIC base symbol always points to here. */
223
224 static char function_base[32];
225
226 static int current_pic_label_num;
227
228 const char *
229 machopic_function_base_name ()
230 {
231 static const char *name = NULL;
232 static const char *current_name;
233
234 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
235
236 if (name != current_name)
237 {
238 current_function_uses_pic_offset_table = 1;
239
240 /* Save mucho space and time. Some of the C++ mangled names are over
241 700 characters long! Note that we produce a label containing a '-'
242 if the function we're compiling is an Objective-C method, as evinced
243 by the incredibly scientific test below. This is because code in
244 rs6000.c makes the same ugly test when loading the PIC reg. */
245
246 ++current_pic_label_num;
247 if (*current_name == '+' || *current_name == '-')
248 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
249 else
250 sprintf (function_base, "*L%d$pb", current_pic_label_num);
251
252 name = current_name;
253 }
254
255 return function_base;
256 }
257
258 static GTY(()) tree machopic_non_lazy_pointers;
259
260 /* Return a non-lazy pointer name corresponding to the given name,
261 either by finding it in our list of pointer names, or by generating
262 a new one. */
263
264 const char *
265 machopic_non_lazy_ptr_name (name)
266 const char *name;
267 {
268 const char *temp_name;
269 tree temp, ident = get_identifier (name);
270
271 for (temp = machopic_non_lazy_pointers;
272 temp != NULL_TREE;
273 temp = TREE_CHAIN (temp))
274 {
275 if (ident == TREE_VALUE (temp))
276 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
277 }
278
279 name = darwin_strip_name_encoding (name);
280
281 /* Try again, but comparing names this time. */
282 for (temp = machopic_non_lazy_pointers;
283 temp != NULL_TREE;
284 temp = TREE_CHAIN (temp))
285 {
286 if (TREE_VALUE (temp))
287 {
288 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
289 temp_name = darwin_strip_name_encoding (temp_name);
290 if (strcmp (name, temp_name) == 0)
291 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
292 }
293 }
294
295 {
296 char *buffer;
297 tree ptr_name;
298
299 buffer = alloca (strlen (name) + 20);
300
301 strcpy (buffer, "&L");
302 if (name[0] == '*')
303 strcat (buffer, name+1);
304 else
305 {
306 strcat (buffer, "_");
307 strcat (buffer, name);
308 }
309
310 strcat (buffer, "$non_lazy_ptr");
311 ptr_name = get_identifier (buffer);
312
313 machopic_non_lazy_pointers
314 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
315
316 TREE_USED (machopic_non_lazy_pointers) = 0;
317
318 return IDENTIFIER_POINTER (ptr_name);
319 }
320 }
321
322 static GTY(()) tree machopic_stubs;
323
324 /* Return the name of the stub corresponding to the given name,
325 generating a new stub name if necessary. */
326
327 const char *
328 machopic_stub_name (name)
329 const char *name;
330 {
331 tree temp, ident = get_identifier (name);
332 const char *tname;
333
334 for (temp = machopic_stubs;
335 temp != NULL_TREE;
336 temp = TREE_CHAIN (temp))
337 {
338 if (ident == TREE_VALUE (temp))
339 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
340 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
341 if (strcmp (name, tname) == 0)
342 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
343 /* A library call name might not be section-encoded yet, so try
344 it against a stripped name. */
345 if (name[0] != '!'
346 && tname[0] == '!'
347 && strcmp (name, tname + 4) == 0)
348 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349 }
350
351 name = darwin_strip_name_encoding (name);
352
353 {
354 char *buffer;
355 tree ptr_name;
356 int needs_quotes = name_needs_quotes (name);
357
358 buffer = alloca (strlen (name) + 20);
359
360 if (needs_quotes)
361 strcpy (buffer, "&\"L");
362 else
363 strcpy (buffer, "&L");
364 if (name[0] == '*')
365 {
366 strcat (buffer, name+1);
367 }
368 else
369 {
370 strcat (buffer, "_");
371 strcat (buffer, name);
372 }
373
374 if (needs_quotes)
375 strcat (buffer, "$stub\"");
376 else
377 strcat (buffer, "$stub");
378 ptr_name = get_identifier (buffer);
379
380 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
381 TREE_USED (machopic_stubs) = 0;
382
383 return IDENTIFIER_POINTER (ptr_name);
384 }
385 }
386
387 void
388 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
389 const char *name;
390 int validate_stub;
391 {
392 const char *real_name;
393 tree temp, ident = get_identifier (name), id2;
394
395 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
396 temp != NULL_TREE;
397 temp = TREE_CHAIN (temp))
398 if (ident == TREE_PURPOSE (temp))
399 {
400 /* Mark both the stub or non-lazy pointer as well as the
401 original symbol as being referenced. */
402 TREE_USED (temp) = 1;
403 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
404 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
405 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
406 real_name = darwin_strip_name_encoding (real_name);
407 id2 = maybe_get_identifier (real_name);
408 if (id2)
409 TREE_SYMBOL_REFERENCED (id2) = 1;
410 }
411 }
412
413 /* Transform ORIG, which may be any data source, to the corresponding
414 source using indirections. */
415
416 rtx
417 machopic_indirect_data_reference (orig, reg)
418 rtx orig, reg;
419 {
420 rtx ptr_ref = orig;
421
422 if (! MACHOPIC_INDIRECT)
423 return orig;
424
425 if (GET_CODE (orig) == SYMBOL_REF)
426 {
427 const char *name = XSTR (orig, 0);
428
429 if (machopic_data_defined_p (name))
430 {
431 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
432 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
433 machopic_function_base_name ());
434 rtx offset = gen_rtx (CONST, Pmode,
435 gen_rtx (MINUS, Pmode, orig, pic_base));
436 #endif
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 (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
497 {
498 if (reg)
499 {
500 emit_move_insn (reg, result);
501 result = reg;
502 }
503 else
504 {
505 result = force_reg (GET_MODE (result), result);
506 }
507 }
508
509 return result;
510
511 }
512 else if (GET_CODE (orig) == MEM)
513 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
514 /* When the target is i386, this code prevents crashes due to the
515 compiler's ignorance on how to move the PIC base register to
516 other registers. (The reload phase sometimes introduces such
517 insns.) */
518 else if (GET_CODE (orig) == PLUS
519 && GET_CODE (XEXP (orig, 0)) == REG
520 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
521 #ifdef I386
522 /* Prevent the same register from being erroneously used
523 as both the base and index registers. */
524 && GET_CODE (XEXP (orig, 1)) == CONST
525 #endif
526 && reg)
527 {
528 emit_move_insn (reg, XEXP (orig, 0));
529 XEXP (ptr_ref, 0) = reg;
530 }
531 return ptr_ref;
532 }
533
534 /* Transform TARGET (a MEM), which is a function call target, to the
535 corresponding symbol_stub if necessary. Return a new MEM. */
536
537 rtx
538 machopic_indirect_call_target (target)
539 rtx target;
540 {
541 if (GET_CODE (target) != MEM)
542 return target;
543
544 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
545 {
546 enum machine_mode mode = GET_MODE (XEXP (target, 0));
547 const char *name = XSTR (XEXP (target, 0), 0);
548
549 /* If the name is already defined, we need do nothing. */
550 if (name[0] == '!' && name[1] == 'T')
551 return target;
552
553 if (!machopic_name_defined_p (name))
554 {
555 const char *stub_name = machopic_stub_name (name);
556
557 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
558 RTX_UNCHANGING_P (target) = 1;
559 }
560 }
561
562 return target;
563 }
564
565 rtx
566 machopic_legitimize_pic_address (orig, mode, reg)
567 rtx orig, reg;
568 enum machine_mode mode;
569 {
570 rtx pic_ref = orig;
571
572 if (! MACHOPIC_PURE)
573 return orig;
574
575 /* First handle a simple SYMBOL_REF or LABEL_REF */
576 if (GET_CODE (orig) == LABEL_REF
577 || (GET_CODE (orig) == SYMBOL_REF
578 ))
579 {
580 /* addr(foo) = &func+(foo-func) */
581 rtx pic_base;
582
583 orig = machopic_indirect_data_reference (orig, reg);
584
585 if (GET_CODE (orig) == PLUS
586 && GET_CODE (XEXP (orig, 0)) == REG)
587 {
588 if (reg == 0)
589 return force_reg (mode, orig);
590
591 emit_move_insn (reg, orig);
592 return reg;
593 }
594
595 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
596
597 if (GET_CODE (orig) == MEM)
598 {
599 if (reg == 0)
600 {
601 if (reload_in_progress)
602 abort ();
603 else
604 reg = gen_reg_rtx (Pmode);
605 }
606
607 #ifdef HAVE_lo_sum
608 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
609 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
610 {
611 rtx offset = gen_rtx (CONST, Pmode,
612 gen_rtx (MINUS, Pmode,
613 XEXP (orig, 0), pic_base));
614 #if defined (TARGET_TOC) /* i.e., PowerPC */
615 /* Generating a new reg may expose opportunities for
616 common subexpression elimination. */
617 rtx hi_sum_reg =
618 (reload_in_progress ? reg : gen_reg_rtx (SImode));
619
620 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
621 gen_rtx (PLUS, Pmode,
622 pic_offset_table_rtx,
623 gen_rtx (HIGH, Pmode, offset))));
624 emit_insn (gen_rtx (SET, VOIDmode, reg,
625 gen_rtx (MEM, GET_MODE (orig),
626 gen_rtx (LO_SUM, Pmode,
627 hi_sum_reg, offset))));
628 pic_ref = reg;
629
630 #else
631 emit_insn (gen_rtx (USE, VOIDmode,
632 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
633
634 emit_insn (gen_rtx (SET, VOIDmode, reg,
635 gen_rtx (HIGH, Pmode,
636 gen_rtx (CONST, Pmode, offset))));
637 emit_insn (gen_rtx (SET, VOIDmode, reg,
638 gen_rtx (LO_SUM, Pmode, reg,
639 gen_rtx (CONST, Pmode, offset))));
640 pic_ref = gen_rtx (PLUS, Pmode,
641 pic_offset_table_rtx, reg);
642 #endif
643 }
644 else
645 #endif /* HAVE_lo_sum */
646 {
647 rtx pic = pic_offset_table_rtx;
648 if (GET_CODE (pic) != REG)
649 {
650 emit_move_insn (reg, pic);
651 pic = reg;
652 }
653 #if 0
654 emit_insn (gen_rtx (USE, VOIDmode,
655 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
656 #endif
657
658 pic_ref = gen_rtx (PLUS, Pmode,
659 pic,
660 gen_rtx (CONST, Pmode,
661 gen_rtx (MINUS, Pmode,
662 XEXP (orig, 0),
663 pic_base)));
664 }
665
666 #if !defined (TARGET_TOC)
667 emit_move_insn (reg, pic_ref);
668 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
669 #endif
670 RTX_UNCHANGING_P (pic_ref) = 1;
671 }
672 else
673 {
674
675 #ifdef HAVE_lo_sum
676 if (GET_CODE (orig) == SYMBOL_REF
677 || GET_CODE (orig) == LABEL_REF)
678 {
679 rtx offset = gen_rtx (CONST, Pmode,
680 gen_rtx (MINUS, Pmode, orig, pic_base));
681 #if defined (TARGET_TOC) /* i.e., PowerPC */
682 rtx hi_sum_reg;
683
684 if (reg == 0)
685 {
686 if (reload_in_progress)
687 abort ();
688 else
689 reg = gen_reg_rtx (SImode);
690 }
691
692 hi_sum_reg = reg;
693
694 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
695 gen_rtx (PLUS, Pmode,
696 pic_offset_table_rtx,
697 gen_rtx (HIGH, Pmode, offset))));
698 emit_insn (gen_rtx (SET, VOIDmode, reg,
699 gen_rtx (LO_SUM, Pmode,
700 hi_sum_reg, offset)));
701 pic_ref = reg;
702 RTX_UNCHANGING_P (pic_ref) = 1;
703 #else
704 emit_insn (gen_rtx (SET, VOIDmode, reg,
705 gen_rtx (HIGH, Pmode, offset)));
706 emit_insn (gen_rtx (SET, VOIDmode, reg,
707 gen_rtx (LO_SUM, Pmode, reg, offset)));
708 pic_ref = gen_rtx (PLUS, Pmode,
709 pic_offset_table_rtx, reg);
710 RTX_UNCHANGING_P (pic_ref) = 1;
711 #endif
712 }
713 else
714 #endif /* HAVE_lo_sum */
715 {
716 if (GET_CODE (orig) == REG)
717 {
718 return orig;
719 }
720 else
721 {
722 rtx pic = pic_offset_table_rtx;
723 if (GET_CODE (pic) != REG)
724 {
725 emit_move_insn (reg, pic);
726 pic = reg;
727 }
728 #if 0
729 emit_insn (gen_rtx (USE, VOIDmode,
730 pic_offset_table_rtx));
731 #endif
732 pic_ref = gen_rtx (PLUS, Pmode,
733 pic,
734 gen_rtx (CONST, Pmode,
735 gen_rtx (MINUS, Pmode,
736 orig, pic_base)));
737 }
738 }
739 }
740
741 if (GET_CODE (pic_ref) != REG)
742 {
743 if (reg != 0)
744 {
745 emit_move_insn (reg, pic_ref);
746 return reg;
747 }
748 else
749 {
750 return force_reg (mode, pic_ref);
751 }
752 }
753 else
754 {
755 return pic_ref;
756 }
757 }
758
759 else if (GET_CODE (orig) == SYMBOL_REF)
760 return orig;
761
762 else if (GET_CODE (orig) == PLUS
763 && (GET_CODE (XEXP (orig, 0)) == MEM
764 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
765 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
766 && XEXP (orig, 0) != pic_offset_table_rtx
767 && GET_CODE (XEXP (orig, 1)) != REG)
768
769 {
770 rtx base;
771 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
772
773 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
774 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
775 Pmode, (base == reg ? 0 : reg));
776 if (GET_CODE (orig) == CONST_INT)
777 {
778 pic_ref = plus_constant (base, INTVAL (orig));
779 is_complex = 1;
780 }
781 else
782 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
783
784 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
785 RTX_UNCHANGING_P (pic_ref) = 1;
786
787 if (reg && is_complex)
788 {
789 emit_move_insn (reg, pic_ref);
790 pic_ref = reg;
791 }
792 /* Likewise, should we set special REG_NOTEs here? */
793 }
794
795 else if (GET_CODE (orig) == CONST)
796 {
797 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
798 }
799
800 else if (GET_CODE (orig) == MEM
801 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
802 {
803 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
804
805 addr = gen_rtx (MEM, GET_MODE (orig), addr);
806 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
807 emit_move_insn (reg, addr);
808 pic_ref = reg;
809 }
810
811 return pic_ref;
812 }
813
814
815 void
816 machopic_finish (asm_out_file)
817 FILE *asm_out_file;
818 {
819 tree temp;
820
821 for (temp = machopic_stubs;
822 temp != NULL_TREE;
823 temp = TREE_CHAIN (temp))
824 {
825 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
826 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
827 char *sym;
828 char *stub;
829
830 if (! TREE_USED (temp))
831 continue;
832
833 /* If the symbol is actually defined, we don't need a stub. */
834 if (sym_name[0] == '!' && sym_name[1] == 'T')
835 continue;
836
837 sym_name = darwin_strip_name_encoding (sym_name);
838
839 sym = alloca (strlen (sym_name) + 2);
840 if (sym_name[0] == '*' || sym_name[0] == '&')
841 strcpy (sym, sym_name + 1);
842 else if (sym_name[0] == '-' || sym_name[0] == '+')
843 strcpy (sym, sym_name);
844 else
845 sym[0] = '_', strcpy (sym + 1, sym_name);
846
847 stub = alloca (strlen (stub_name) + 2);
848 if (stub_name[0] == '*' || stub_name[0] == '&')
849 strcpy (stub, stub_name + 1);
850 else
851 stub[0] = '_', strcpy (stub + 1, stub_name);
852
853 machopic_output_stub (asm_out_file, sym, stub);
854 }
855
856 for (temp = machopic_non_lazy_pointers;
857 temp != NULL_TREE;
858 temp = TREE_CHAIN (temp))
859 {
860 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
861 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
862
863 if (! TREE_USED (temp))
864 continue;
865
866 if (machopic_ident_defined_p (TREE_VALUE (temp)))
867 {
868 data_section ();
869 assemble_align (GET_MODE_ALIGNMENT (Pmode));
870 assemble_label (lazy_name);
871 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
872 GET_MODE_SIZE (Pmode),
873 GET_MODE_ALIGNMENT (Pmode), 1);
874 }
875 else
876 {
877 machopic_nl_symbol_ptr_section ();
878 assemble_name (asm_out_file, lazy_name);
879 fprintf (asm_out_file, ":\n");
880
881 fprintf (asm_out_file, "\t.indirect_symbol ");
882 assemble_name (asm_out_file, sym_name);
883 fprintf (asm_out_file, "\n");
884
885 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
886 GET_MODE_ALIGNMENT (Pmode), 1);
887 }
888 }
889 }
890
891 int
892 machopic_operand_p (op)
893 rtx op;
894 {
895 if (MACHOPIC_JUST_INDIRECT)
896 {
897 while (GET_CODE (op) == CONST)
898 op = XEXP (op, 0);
899
900 if (GET_CODE (op) == SYMBOL_REF)
901 return machopic_name_defined_p (XSTR (op, 0));
902 else
903 return 0;
904 }
905
906 while (GET_CODE (op) == CONST)
907 op = XEXP (op, 0);
908
909 if (GET_CODE (op) == MINUS
910 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
911 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
912 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
913 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
914 return 1;
915
916 return 0;
917 }
918
919 /* This function records whether a given name corresponds to a defined
920 or undefined function or variable, for machopic_classify_ident to
921 use later. */
922
923 void
924 darwin_encode_section_info (decl, first)
925 tree decl;
926 int first ATTRIBUTE_UNUSED;
927 {
928 char code = '\0';
929 int defined = 0;
930 rtx sym_ref;
931 const char *orig_str;
932 char *new_str;
933 size_t len, new_len;
934
935 if ((TREE_CODE (decl) == FUNCTION_DECL
936 || TREE_CODE (decl) == VAR_DECL)
937 && !DECL_EXTERNAL (decl)
938 && ((TREE_STATIC (decl)
939 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
940 || (DECL_INITIAL (decl)
941 && DECL_INITIAL (decl) != error_mark_node)))
942 defined = 1;
943
944 if (TREE_CODE (decl) == FUNCTION_DECL)
945 code = (defined ? 'T' : 't');
946 else if (TREE_CODE (decl) == VAR_DECL)
947 code = (defined ? 'D' : 'd');
948
949 if (code == '\0')
950 return;
951
952 sym_ref = XEXP (DECL_RTL (decl), 0);
953 orig_str = XSTR (sym_ref, 0);
954 len = strlen (orig_str) + 1;
955
956 if (orig_str[0] == '!')
957 {
958 /* Already encoded; see if we need to change it. */
959 if (code == orig_str[1])
960 return;
961 /* Yes, tweak a copy of the name and put it in a new string. */
962 new_str = alloca (len);
963 memcpy (new_str, orig_str, len);
964 new_str[1] = code;
965 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
966 }
967 else
968 {
969 /* Add the encoding. */
970 new_len = len + 4;
971 new_str = alloca (new_len);
972 new_str[0] = '!';
973 new_str[1] = code;
974 new_str[2] = '_';
975 new_str[3] = '_';
976 memcpy (new_str + 4, orig_str, len);
977 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
978 }
979 /* The non-lazy pointer list may have captured references to the
980 old encoded name, change them. */
981 if (TREE_CODE (decl) == VAR_DECL)
982 update_non_lazy_ptrs (XSTR (sym_ref, 0));
983 else
984 update_stubs (XSTR (sym_ref, 0));
985 }
986
987 /* Undo the effects of the above. */
988
989 const char *
990 darwin_strip_name_encoding (str)
991 const char *str;
992 {
993 return str[0] == '!' ? str + 4 : str;
994 }
995
996 /* Scan the list of non-lazy pointers and update any recorded names whose
997 stripped name matches the argument. */
998
999 static void
1000 update_non_lazy_ptrs (name)
1001 const char *name;
1002 {
1003 const char *name1, *name2;
1004 tree temp;
1005
1006 name1 = darwin_strip_name_encoding (name);
1007
1008 for (temp = machopic_non_lazy_pointers;
1009 temp != NULL_TREE;
1010 temp = TREE_CHAIN (temp))
1011 {
1012 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1013
1014 if (*sym_name == '!')
1015 {
1016 name2 = darwin_strip_name_encoding (sym_name);
1017 if (strcmp (name1, name2) == 0)
1018 {
1019 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1020 break;
1021 }
1022 }
1023 }
1024 }
1025
1026 /* Function NAME is being defined, and its label has just been output.
1027 If there's already a reference to a stub for this function, we can
1028 just emit the stub label now and we don't bother emitting the stub later. */
1029
1030 void
1031 machopic_output_possible_stub_label (file, name)
1032 FILE *file;
1033 const char *name;
1034 {
1035 tree temp;
1036
1037
1038 /* Ensure we're looking at a section-encoded name. */
1039 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1040 return;
1041
1042 for (temp = machopic_stubs;
1043 temp != NULL_TREE;
1044 temp = TREE_CHAIN (temp))
1045 {
1046 const char *sym_name;
1047
1048 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1049 if (sym_name[0] == '!' && sym_name[1] == 'T'
1050 && ! strcmp (name+2, sym_name+2))
1051 {
1052 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1053 /* Avoid generating a stub for this. */
1054 TREE_USED (temp) = 0;
1055 break;
1056 }
1057 }
1058 }
1059
1060 /* Scan the list of stubs and update any recorded names whose
1061 stripped name matches the argument. */
1062
1063 static void
1064 update_stubs (name)
1065 const char *name;
1066 {
1067 const char *name1, *name2;
1068 tree temp;
1069
1070 name1 = darwin_strip_name_encoding (name);
1071
1072 for (temp = machopic_stubs;
1073 temp != NULL_TREE;
1074 temp = TREE_CHAIN (temp))
1075 {
1076 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1077
1078 if (*sym_name == '!')
1079 {
1080 name2 = darwin_strip_name_encoding (sym_name);
1081 if (strcmp (name1, name2) == 0)
1082 {
1083 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1084 break;
1085 }
1086 }
1087 }
1088 }
1089
1090 void
1091 machopic_select_section (exp, reloc, align)
1092 tree exp;
1093 int reloc;
1094 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1095 {
1096 if (TREE_CODE (exp) == STRING_CST)
1097 {
1098 if (flag_writable_strings)
1099 data_section ();
1100 else if (TREE_STRING_LENGTH (exp) !=
1101 strlen (TREE_STRING_POINTER (exp)) + 1)
1102 readonly_data_section ();
1103 else
1104 cstring_section ();
1105 }
1106 else if (TREE_CODE (exp) == INTEGER_CST
1107 || TREE_CODE (exp) == REAL_CST)
1108 {
1109 tree size = TYPE_SIZE (TREE_TYPE (exp));
1110
1111 if (TREE_CODE (size) == INTEGER_CST &&
1112 TREE_INT_CST_LOW (size) == 4 &&
1113 TREE_INT_CST_HIGH (size) == 0)
1114 literal4_section ();
1115 else if (TREE_CODE (size) == INTEGER_CST &&
1116 TREE_INT_CST_LOW (size) == 8 &&
1117 TREE_INT_CST_HIGH (size) == 0)
1118 literal8_section ();
1119 else
1120 readonly_data_section ();
1121 }
1122 else if (TREE_CODE (exp) == CONSTRUCTOR
1123 && TREE_TYPE (exp)
1124 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1125 && TYPE_NAME (TREE_TYPE (exp)))
1126 {
1127 tree name = TYPE_NAME (TREE_TYPE (exp));
1128 if (TREE_CODE (name) == TYPE_DECL)
1129 name = DECL_NAME (name);
1130 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1131 objc_constant_string_object_section ();
1132 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1133 objc_string_object_section ();
1134 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1135 {
1136 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1137 const_data_section ();
1138 else
1139 readonly_data_section ();
1140 }
1141 else
1142 data_section ();
1143 }
1144 else if (TREE_CODE (exp) == VAR_DECL &&
1145 DECL_NAME (exp) &&
1146 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1147 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1148 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1149 {
1150 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1151
1152 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1153 objc_cls_meth_section ();
1154 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1155 objc_inst_meth_section ();
1156 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1157 objc_cat_cls_meth_section ();
1158 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1159 objc_cat_inst_meth_section ();
1160 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1161 objc_class_vars_section ();
1162 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1163 objc_instance_vars_section ();
1164 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1165 objc_cat_cls_meth_section ();
1166 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1167 objc_class_names_section ();
1168 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1169 objc_meth_var_names_section ();
1170 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1171 objc_meth_var_types_section ();
1172 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1173 objc_cls_refs_section ();
1174 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1175 objc_class_section ();
1176 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1177 objc_meta_class_section ();
1178 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1179 objc_category_section ();
1180 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1181 objc_selector_refs_section ();
1182 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1183 objc_selector_fixup_section ();
1184 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1185 objc_symbols_section ();
1186 else if (!strncmp (name, "_OBJC_MODULES", 13))
1187 objc_module_info_section ();
1188 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1189 objc_cat_inst_meth_section ();
1190 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1191 objc_cat_cls_meth_section ();
1192 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1193 objc_cat_cls_meth_section ();
1194 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1195 objc_protocol_section ();
1196 else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1197 && !TREE_SIDE_EFFECTS (exp))
1198 {
1199 if (flag_pic && reloc)
1200 const_data_section ();
1201 else
1202 readonly_data_section ();
1203 }
1204 else
1205 data_section ();
1206 }
1207 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1208 {
1209 if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1210 const_data_section ();
1211 else
1212 readonly_data_section ();
1213 }
1214 else
1215 data_section ();
1216 }
1217
1218 /* This can be called with address expressions as "rtx".
1219 They must go in "const". */
1220
1221 void
1222 machopic_select_rtx_section (mode, x, align)
1223 enum machine_mode mode;
1224 rtx x;
1225 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1226 {
1227 if (GET_MODE_SIZE (mode) == 8)
1228 literal8_section ();
1229 else if (GET_MODE_SIZE (mode) == 4
1230 && (GET_CODE (x) == CONST_INT
1231 || GET_CODE (x) == CONST_DOUBLE))
1232 literal4_section ();
1233 else
1234 const_section ();
1235 }
1236
1237 void
1238 machopic_asm_out_constructor (symbol, priority)
1239 rtx symbol;
1240 int priority ATTRIBUTE_UNUSED;
1241 {
1242 if (flag_pic)
1243 mod_init_section ();
1244 else
1245 constructor_section ();
1246 assemble_align (POINTER_SIZE);
1247 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1248
1249 if (!flag_pic)
1250 fprintf (asm_out_file, ".reference .constructors_used\n");
1251 }
1252
1253 void
1254 machopic_asm_out_destructor (symbol, priority)
1255 rtx symbol;
1256 int priority ATTRIBUTE_UNUSED;
1257 {
1258 if (flag_pic)
1259 mod_term_section ();
1260 else
1261 destructor_section ();
1262 assemble_align (POINTER_SIZE);
1263 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1264
1265 if (!flag_pic)
1266 fprintf (asm_out_file, ".reference .destructors_used\n");
1267 }
1268
1269 void
1270 darwin_globalize_label (stream, name)
1271 FILE *stream;
1272 const char *name;
1273 {
1274 if (!!strncmp (name, "_OBJC_", 6))
1275 default_globalize_label (stream, name);
1276 }
1277
1278 /* Output a difference of two labels that will be an assembly time
1279 constant if the two labels are local. (.long lab1-lab2 will be
1280 very different if lab1 is at the boundary between two sections; it
1281 will be relocated according to the second section, not the first,
1282 so one ends up with a difference between labels in different
1283 sections, which is bad in the dwarf2 eh context for instance.) */
1284
1285 static int darwin_dwarf_label_counter;
1286
1287 void
1288 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1289 FILE *file;
1290 int size ATTRIBUTE_UNUSED;
1291 const char *lab1, *lab2;
1292 {
1293 const char *p = lab1 + (lab1[0] == '*');
1294 int islocaldiff = (p[0] == 'L');
1295
1296 if (islocaldiff)
1297 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1298 else
1299 fprintf (file, "\t%s\t", ".long");
1300 assemble_name (file, lab1);
1301 fprintf (file, "-");
1302 assemble_name (file, lab2);
1303 if (islocaldiff)
1304 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1305 }
1306
1307 #include "gt-darwin.h"
1308