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