darwin.md: Delete the altivec patterns which are handled differently now.
[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, 2004
3 Free Software Foundation, Inc.
4 Contributed by Apple Computer Inc.
5
6 This file is part of GCC.
7
8 GCC 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 GCC 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 GCC; 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 #include "errors.h"
45 #include "hashtab.h"
46
47 /* Nonzero if the user passes the -mone-byte-bool switch, which forces
48 sizeof(bool) to be 1. */
49 const char *darwin_one_byte_bool = 0;
50
51 int
52 name_needs_quotes (const char *name)
53 {
54 int c;
55 while ((c = *name++) != '\0')
56 if (! ISIDNUM (c) && c != '.' && c != '$')
57 return 1;
58 return 0;
59 }
60
61 /*
62 * flag_pic = 1 ... generate only indirections
63 * flag_pic = 2 ... generate indirections and pure code
64 */
65
66 static int
67 machopic_symbol_defined_p (rtx sym_ref)
68 {
69 return ((SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
70 /* Local symbols must always be defined. */
71 || SYMBOL_REF_LOCAL_P (sym_ref));
72 }
73
74 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
75 reference, which will not be changed. */
76
77 enum machopic_addr_class
78 machopic_classify_symbol (rtx sym_ref)
79 {
80 int flags;
81 bool function_p;
82
83 flags = SYMBOL_REF_FLAGS (sym_ref);
84 function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
85 if (machopic_symbol_defined_p (sym_ref))
86 return (function_p
87 ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
88 else
89 return (function_p
90 ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
91 }
92
93 static int
94 machopic_data_defined_p (rtx sym_ref)
95 {
96 switch (machopic_classify_symbol (sym_ref))
97 {
98 case MACHOPIC_DEFINED_DATA:
99 return 1;
100 default:
101 return 0;
102 }
103 }
104
105 void
106 machopic_define_symbol (rtx mem)
107 {
108 rtx sym_ref;
109 if (GET_CODE (mem) != MEM)
110 abort ();
111 sym_ref = XEXP (mem, 0);
112 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
113 }
114
115 static GTY(()) char * function_base;
116
117 const char *
118 machopic_function_base_name (void)
119 {
120 /* if dynamic-no-pic is on, we should not get here */
121 if (MACHO_DYNAMIC_NO_PIC_P)
122 abort ();
123
124 if (function_base == NULL)
125 function_base =
126 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
127
128 current_function_uses_pic_offset_table = 1;
129
130 return function_base;
131 }
132
133 /* Return a SYMBOL_REF for the PIC function base. */
134
135 rtx
136 machopic_function_base_sym (void)
137 {
138 rtx sym_ref;
139
140 sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
141 SYMBOL_REF_FLAGS (sym_ref)
142 |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
143 return sym_ref;
144 }
145
146 static GTY(()) const char * function_base_func_name;
147 static GTY(()) int current_pic_label_num;
148
149 void
150 machopic_output_function_base_name (FILE *file)
151 {
152 const char *current_name;
153
154 /* If dynamic-no-pic is on, we should not get here. */
155 if (MACHO_DYNAMIC_NO_PIC_P)
156 abort ();
157 current_name =
158 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
159 if (function_base_func_name != current_name)
160 {
161 ++current_pic_label_num;
162 function_base_func_name = current_name;
163 }
164 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
165 }
166
167 /* The suffix attached to non-lazy pointer symbols. */
168 #define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
169 /* The suffix attached to stub symbols. */
170 #define STUB_SUFFIX "$stub"
171
172 typedef struct machopic_indirection GTY (())
173 {
174 /* The SYMBOL_REF for the entity referenced. */
175 rtx symbol;
176 /* The IDENTIFIER_NODE giving the name of the stub or non-lazy
177 pointer. */
178 tree ptr_name;
179 /* True iff this entry is for a stub (as opposed to a non-lazy
180 pointer). */
181 bool stub_p;
182 /* True iff this stub or pointer pointer has been referenced. */
183 bool used;
184 } machopic_indirection;
185
186 /* A table mapping stub names and non-lazy pointer names to
187 SYMBOL_REFs for the stubbed-to and pointed-to entities. */
188
189 static GTY ((param_is (struct machopic_indirection))) htab_t
190 machopic_indirections;
191
192 /* Return a hash value for a SLOT in the indirections hash table. */
193
194 static hashval_t
195 machopic_indirection_hash (const void *slot)
196 {
197 const machopic_indirection *p = (const machopic_indirection *) slot;
198 return IDENTIFIER_HASH_VALUE (p->ptr_name);
199 }
200
201 /* Returns true if the KEY is the same as that associated with
202 SLOT. */
203
204 static int
205 machopic_indirection_eq (const void *slot, const void *key)
206 {
207 return ((const machopic_indirection *) slot)->ptr_name == (tree) key;
208 }
209
210 /* Return the name of the non-lazy pointer (if STUB_P is false) or
211 stub (if STUB_B is true) corresponding to the given name. */
212
213 const char *
214 machopic_indirection_name (rtx sym_ref, bool stub_p)
215 {
216 char *buffer;
217 const char *name = XSTR (sym_ref, 0);
218 int namelen = strlen (name);
219 tree ptr_name;
220 machopic_indirection *p;
221
222 /* Construct the name of the non-lazy pointer or stub. */
223 if (stub_p)
224 {
225 int needs_quotes = name_needs_quotes (name);
226 buffer = alloca (strlen ("&L")
227 + namelen
228 + strlen (STUB_SUFFIX)
229 + 2 /* possible quotes */
230 + 1 /* '\0' */);
231
232 if (needs_quotes)
233 {
234 if (name[0] == '*')
235 sprintf (buffer, "&\"L%s" STUB_SUFFIX "\"", name + 1);
236 else
237 sprintf (buffer, "&\"L%s%s" STUB_SUFFIX "\"", user_label_prefix,
238 name);
239 }
240 else if (name[0] == '*')
241 sprintf (buffer, "&L%s" STUB_SUFFIX, name + 1);
242 else
243 sprintf (buffer, "&L%s%s" STUB_SUFFIX, user_label_prefix, name);
244 }
245 else
246 {
247 buffer = alloca (strlen ("&L")
248 + strlen (user_label_prefix)
249 + namelen
250 + strlen (NON_LAZY_POINTER_SUFFIX)
251 + 1 /* '\0' */);
252 if (name[0] == '*')
253 sprintf (buffer, "&L%s" NON_LAZY_POINTER_SUFFIX, name + 1);
254 else
255 sprintf (buffer, "&L%s%s" NON_LAZY_POINTER_SUFFIX,
256 user_label_prefix, name);
257 }
258
259 /* See if we already have it. */
260 ptr_name = maybe_get_identifier (buffer);
261 /* If not, create a mapping from the non-lazy pointer to the
262 SYMBOL_REF. */
263 if (!ptr_name)
264 {
265 void **slot;
266 ptr_name = get_identifier (buffer);
267 p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
268 p->symbol = sym_ref;
269 p->ptr_name = ptr_name;
270 p->stub_p = stub_p;
271 p->used = 0;
272 if (!machopic_indirections)
273 machopic_indirections
274 = htab_create_ggc (37,
275 machopic_indirection_hash,
276 machopic_indirection_eq,
277 /*htab_del=*/NULL);
278 slot = htab_find_slot_with_hash (machopic_indirections, ptr_name,
279 IDENTIFIER_HASH_VALUE (ptr_name),
280 INSERT);
281 *((machopic_indirection **) slot) = p;
282 }
283
284 return IDENTIFIER_POINTER (ptr_name);
285 }
286
287 /* Return the name of the stub for the mcount function. */
288
289 const char*
290 machopic_mcount_stub_name (void)
291 {
292 return "&L*mcount$stub";
293 }
294
295 /* If NAME is the name of a stub or a non-lazy pointer , mark the stub
296 or non-lazy pointer as used -- and mark the object to which the
297 pointer/stub refers as used as well, since the pointer/stub will
298 emit a reference to it. */
299
300 void
301 machopic_validate_stub_or_non_lazy_ptr (const char *name)
302 {
303 tree ident = get_identifier (name);
304
305 machopic_indirection *p;
306
307 p = ((machopic_indirection *)
308 (htab_find_with_hash (machopic_indirections, ident,
309 IDENTIFIER_HASH_VALUE (ident))));
310 if (p)
311 {
312 p->used = 1;
313 mark_referenced (ident);
314 mark_referenced (get_identifier (XSTR (p->symbol, 0)));
315 }
316 }
317
318 /* Transform ORIG, which may be any data source, to the corresponding
319 source using indirections. */
320
321 rtx
322 machopic_indirect_data_reference (rtx orig, rtx reg)
323 {
324 rtx ptr_ref = orig;
325
326 if (! MACHOPIC_INDIRECT)
327 return orig;
328
329 if (GET_CODE (orig) == SYMBOL_REF)
330 {
331 int defined = machopic_data_defined_p (orig);
332
333 if (defined && MACHO_DYNAMIC_NO_PIC_P)
334 {
335 #if defined (TARGET_TOC)
336 emit_insn (GET_MODE (orig) == DImode
337 ? gen_macho_high_di (reg, orig)
338 : gen_macho_high (reg, orig));
339 emit_insn (GET_MODE (orig) == DImode
340 ? gen_macho_low_di (reg, reg, orig)
341 : gen_macho_low (reg, reg, orig));
342 #else
343 /* some other cpu -- writeme! */
344 abort ();
345 #endif
346 return reg;
347 }
348 else if (defined)
349 {
350 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
351 rtx pic_base = machopic_function_base_sym ();
352 rtx offset = gen_rtx_CONST (Pmode,
353 gen_rtx_MINUS (Pmode, orig, pic_base));
354 #endif
355
356 #if defined (TARGET_TOC) /* i.e., PowerPC */
357 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
358
359 if (reg == NULL)
360 abort ();
361
362 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
363 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
364 gen_rtx_HIGH (Pmode, offset))));
365 emit_insn (gen_rtx_SET (Pmode, reg,
366 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
367
368 orig = reg;
369 #else
370 #if defined (HAVE_lo_sum)
371 if (reg == 0) abort ();
372
373 emit_insn (gen_rtx_SET (VOIDmode, reg,
374 gen_rtx_HIGH (Pmode, offset)));
375 emit_insn (gen_rtx_SET (VOIDmode, reg,
376 gen_rtx_LO_SUM (Pmode, reg, offset)));
377 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
378
379 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
380 #endif
381 #endif
382 return orig;
383 }
384
385 ptr_ref = (gen_rtx_SYMBOL_REF
386 (Pmode,
387 machopic_indirection_name (orig, /*stub_p=*/false)));
388
389 SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
390
391 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
392 MEM_READONLY_P (ptr_ref) = 1;
393
394 return ptr_ref;
395 }
396 else if (GET_CODE (orig) == CONST)
397 {
398 rtx base, result;
399
400 /* legitimize both operands of the PLUS */
401 if (GET_CODE (XEXP (orig, 0)) == PLUS)
402 {
403 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
404 reg);
405 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
406 (base == reg ? 0 : reg));
407 }
408 else
409 return orig;
410
411 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
412 result = plus_constant (base, INTVAL (orig));
413 else
414 result = gen_rtx_PLUS (Pmode, base, orig);
415
416 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
417 {
418 if (reg)
419 {
420 emit_move_insn (reg, result);
421 result = reg;
422 }
423 else
424 {
425 result = force_reg (GET_MODE (result), result);
426 }
427 }
428
429 return result;
430
431 }
432 else if (GET_CODE (orig) == MEM)
433 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
434 /* When the target is i386, this code prevents crashes due to the
435 compiler's ignorance on how to move the PIC base register to
436 other registers. (The reload phase sometimes introduces such
437 insns.) */
438 else if (GET_CODE (orig) == PLUS
439 && GET_CODE (XEXP (orig, 0)) == REG
440 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
441 #ifdef I386
442 /* Prevent the same register from being erroneously used
443 as both the base and index registers. */
444 && GET_CODE (XEXP (orig, 1)) == CONST
445 #endif
446 && reg)
447 {
448 emit_move_insn (reg, XEXP (orig, 0));
449 XEXP (ptr_ref, 0) = reg;
450 }
451 return ptr_ref;
452 }
453
454 /* Transform TARGET (a MEM), which is a function call target, to the
455 corresponding symbol_stub if necessary. Return a new MEM. */
456
457 rtx
458 machopic_indirect_call_target (rtx target)
459 {
460 if (GET_CODE (target) != MEM)
461 return target;
462
463 if (MACHOPIC_INDIRECT
464 && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
465 && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
466 & MACHO_SYMBOL_FLAG_DEFINED))
467 {
468 rtx sym_ref = XEXP (target, 0);
469 const char *stub_name = machopic_indirection_name (sym_ref,
470 /*stub_p=*/true);
471 enum machine_mode mode = GET_MODE (sym_ref);
472 tree decl = SYMBOL_REF_DECL (sym_ref);
473
474 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
475 SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
476 MEM_READONLY_P (target) = 1;
477 }
478
479 return target;
480 }
481
482 rtx
483 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
484 {
485 rtx pic_ref = orig;
486
487 if (! MACHOPIC_INDIRECT)
488 return orig;
489
490 /* First handle a simple SYMBOL_REF or LABEL_REF */
491 if (GET_CODE (orig) == LABEL_REF
492 || (GET_CODE (orig) == SYMBOL_REF
493 ))
494 {
495 /* addr(foo) = &func+(foo-func) */
496 rtx pic_base;
497
498 orig = machopic_indirect_data_reference (orig, reg);
499
500 if (GET_CODE (orig) == PLUS
501 && GET_CODE (XEXP (orig, 0)) == REG)
502 {
503 if (reg == 0)
504 return force_reg (mode, orig);
505
506 emit_move_insn (reg, orig);
507 return reg;
508 }
509
510 /* if dynamic-no-pic then use 0 as the pic base */
511 if (MACHO_DYNAMIC_NO_PIC_P)
512 pic_base = CONST0_RTX (Pmode);
513 else
514 pic_base = machopic_function_base_sym ();
515
516 if (GET_CODE (orig) == MEM)
517 {
518 if (reg == 0)
519 {
520 if (reload_in_progress)
521 abort ();
522 else
523 reg = gen_reg_rtx (Pmode);
524 }
525
526 #ifdef HAVE_lo_sum
527 if (MACHO_DYNAMIC_NO_PIC_P
528 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
529 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
530 {
531 #if defined (TARGET_TOC) /* ppc */
532 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
533 rtx asym = XEXP (orig, 0);
534 rtx mem;
535
536 emit_insn (mode == DImode
537 ? gen_macho_high_di (temp_reg, asym)
538 : gen_macho_high (temp_reg, asym));
539 mem = gen_rtx_MEM (GET_MODE (orig),
540 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
541 MEM_READONLY_P (mem) = 1;
542 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
543 #else
544 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
545 abort ();
546 #endif
547 pic_ref = reg;
548 }
549 else
550 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
551 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
552 {
553 rtx offset = gen_rtx_CONST (Pmode,
554 gen_rtx_MINUS (Pmode,
555 XEXP (orig, 0),
556 pic_base));
557 #if defined (TARGET_TOC) /* i.e., PowerPC */
558 /* Generating a new reg may expose opportunities for
559 common subexpression elimination. */
560 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
561 rtx mem;
562 rtx insn;
563 rtx sum;
564
565 sum = gen_rtx_HIGH (Pmode, offset);
566 if (! MACHO_DYNAMIC_NO_PIC_P)
567 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
568
569 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
570
571 mem = gen_rtx_MEM (GET_MODE (orig),
572 gen_rtx_LO_SUM (Pmode,
573 hi_sum_reg, offset));
574 MEM_READONLY_P (mem) = 1;
575 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
576 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
577 REG_NOTES (insn));
578
579 pic_ref = reg;
580 #else
581 emit_insn (gen_rtx_USE (VOIDmode,
582 gen_rtx_REG (Pmode,
583 PIC_OFFSET_TABLE_REGNUM)));
584
585 emit_insn (gen_rtx_SET (VOIDmode, reg,
586 gen_rtx_HIGH (Pmode,
587 gen_rtx_CONST (Pmode,
588 offset))));
589 emit_insn (gen_rtx_SET (VOIDmode, reg,
590 gen_rtx_LO_SUM (Pmode, reg,
591 gen_rtx_CONST (Pmode, offset))));
592 pic_ref = gen_rtx_PLUS (Pmode,
593 pic_offset_table_rtx, reg);
594 #endif
595 }
596 else
597 #endif /* HAVE_lo_sum */
598 {
599 rtx pic = pic_offset_table_rtx;
600 if (GET_CODE (pic) != REG)
601 {
602 emit_move_insn (reg, pic);
603 pic = reg;
604 }
605 #if 0
606 emit_insn (gen_rtx_USE (VOIDmode,
607 gen_rtx_REG (Pmode,
608 PIC_OFFSET_TABLE_REGNUM)));
609 #endif
610
611 pic_ref = gen_rtx_PLUS (Pmode,
612 pic,
613 gen_rtx_CONST (Pmode,
614 gen_rtx_MINUS (Pmode,
615 XEXP (orig, 0),
616 pic_base)));
617 }
618
619 #if !defined (TARGET_TOC)
620 emit_move_insn (reg, pic_ref);
621 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
622 MEM_READONLY_P (pic_ref) = 1;
623 #endif
624 }
625 else
626 {
627
628 #ifdef HAVE_lo_sum
629 if (GET_CODE (orig) == SYMBOL_REF
630 || GET_CODE (orig) == LABEL_REF)
631 {
632 rtx offset = gen_rtx_CONST (Pmode,
633 gen_rtx_MINUS (Pmode,
634 orig, pic_base));
635 #if defined (TARGET_TOC) /* i.e., PowerPC */
636 rtx hi_sum_reg;
637
638 if (reg == 0)
639 {
640 if (reload_in_progress)
641 abort ();
642 else
643 reg = gen_reg_rtx (Pmode);
644 }
645
646 hi_sum_reg = reg;
647
648 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
649 (MACHO_DYNAMIC_NO_PIC_P)
650 ? gen_rtx_HIGH (Pmode, offset)
651 : gen_rtx_PLUS (Pmode,
652 pic_offset_table_rtx,
653 gen_rtx_HIGH (Pmode,
654 offset))));
655 emit_insn (gen_rtx_SET (VOIDmode, reg,
656 gen_rtx_LO_SUM (Pmode,
657 hi_sum_reg, offset)));
658 pic_ref = reg;
659 #else
660 emit_insn (gen_rtx_SET (VOIDmode, reg,
661 gen_rtx_HIGH (Pmode, offset)));
662 emit_insn (gen_rtx_SET (VOIDmode, reg,
663 gen_rtx_LO_SUM (Pmode, reg, offset)));
664 pic_ref = gen_rtx_PLUS (Pmode,
665 pic_offset_table_rtx, reg);
666 #endif
667 }
668 else
669 #endif /* HAVE_lo_sum */
670 {
671 if (GET_CODE (orig) == REG)
672 {
673 return orig;
674 }
675 else
676 {
677 rtx pic = pic_offset_table_rtx;
678 if (GET_CODE (pic) != REG)
679 {
680 emit_move_insn (reg, pic);
681 pic = reg;
682 }
683 #if 0
684 emit_insn (gen_rtx_USE (VOIDmode,
685 pic_offset_table_rtx));
686 #endif
687 pic_ref = gen_rtx_PLUS (Pmode,
688 pic,
689 gen_rtx_CONST (Pmode,
690 gen_rtx_MINUS (Pmode,
691 orig, pic_base)));
692 }
693 }
694 }
695
696 if (GET_CODE (pic_ref) != REG)
697 {
698 if (reg != 0)
699 {
700 emit_move_insn (reg, pic_ref);
701 return reg;
702 }
703 else
704 {
705 return force_reg (mode, pic_ref);
706 }
707 }
708 else
709 {
710 return pic_ref;
711 }
712 }
713
714 else if (GET_CODE (orig) == SYMBOL_REF)
715 return orig;
716
717 else if (GET_CODE (orig) == PLUS
718 && (GET_CODE (XEXP (orig, 0)) == MEM
719 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
720 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
721 && XEXP (orig, 0) != pic_offset_table_rtx
722 && GET_CODE (XEXP (orig, 1)) != REG)
723
724 {
725 rtx base;
726 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
727
728 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
729 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
730 Pmode, (base == reg ? 0 : reg));
731 if (GET_CODE (orig) == CONST_INT)
732 {
733 pic_ref = plus_constant (base, INTVAL (orig));
734 is_complex = 1;
735 }
736 else
737 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
738
739 if (reg && is_complex)
740 {
741 emit_move_insn (reg, pic_ref);
742 pic_ref = reg;
743 }
744 /* Likewise, should we set special REG_NOTEs here? */
745 }
746
747 else if (GET_CODE (orig) == CONST)
748 {
749 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
750 }
751
752 else if (GET_CODE (orig) == MEM
753 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
754 {
755 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
756 addr = replace_equiv_address (orig, addr);
757 emit_move_insn (reg, addr);
758 pic_ref = reg;
759 }
760
761 return pic_ref;
762 }
763
764 /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
765 DATA is the FILE* for assembly output. Called from
766 htab_traverse. */
767
768 static int
769 machopic_output_indirection (void **slot, void *data)
770 {
771 machopic_indirection *p = *((machopic_indirection **) slot);
772 FILE *asm_out_file = (FILE *) data;
773 rtx symbol;
774 const char *sym_name;
775 const char *ptr_name;
776
777 if (!p->used)
778 return 1;
779
780 symbol = p->symbol;
781 sym_name = XSTR (symbol, 0);
782 ptr_name = IDENTIFIER_POINTER (p->ptr_name);
783
784 if (p->stub_p)
785 {
786 char *sym;
787 char *stub;
788
789 sym = alloca (strlen (sym_name) + 2);
790 if (sym_name[0] == '*' || sym_name[0] == '&')
791 strcpy (sym, sym_name + 1);
792 else if (sym_name[0] == '-' || sym_name[0] == '+')
793 strcpy (sym, sym_name);
794 else
795 sprintf (sym, "%s%s", user_label_prefix, sym_name);
796
797 stub = alloca (strlen (ptr_name) + 2);
798 if (ptr_name[0] == '*' || ptr_name[0] == '&')
799 strcpy (stub, ptr_name + 1);
800 else
801 sprintf (stub, "%s%s", user_label_prefix, ptr_name);
802
803 machopic_output_stub (asm_out_file, sym, stub);
804 }
805 else if (machopic_symbol_defined_p (symbol))
806 {
807 data_section ();
808 assemble_align (GET_MODE_ALIGNMENT (Pmode));
809 assemble_label (ptr_name);
810 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
811 GET_MODE_SIZE (Pmode),
812 GET_MODE_ALIGNMENT (Pmode), 1);
813 }
814 else
815 {
816 machopic_nl_symbol_ptr_section ();
817 assemble_name (asm_out_file, ptr_name);
818 fprintf (asm_out_file, ":\n");
819
820 fprintf (asm_out_file, "\t.indirect_symbol ");
821 assemble_name (asm_out_file, sym_name);
822 fprintf (asm_out_file, "\n");
823
824 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
825 GET_MODE_ALIGNMENT (Pmode), 1);
826 }
827
828 return 1;
829 }
830
831 void
832 machopic_finish (FILE *asm_out_file)
833 {
834 if (machopic_indirections)
835 htab_traverse_noresize (machopic_indirections,
836 machopic_output_indirection,
837 asm_out_file);
838 }
839
840 int
841 machopic_operand_p (rtx op)
842 {
843 if (MACHOPIC_JUST_INDIRECT)
844 {
845 while (GET_CODE (op) == CONST)
846 op = XEXP (op, 0);
847
848 if (GET_CODE (op) == SYMBOL_REF)
849 return machopic_symbol_defined_p (op);
850 else
851 return 0;
852 }
853
854 while (GET_CODE (op) == CONST)
855 op = XEXP (op, 0);
856
857 if (GET_CODE (op) == MINUS
858 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
859 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
860 && machopic_symbol_defined_p (XEXP (op, 0))
861 && machopic_symbol_defined_p (XEXP (op, 1)))
862 return 1;
863
864 return 0;
865 }
866
867 /* This function records whether a given name corresponds to a defined
868 or undefined function or variable, for machopic_classify_ident to
869 use later. */
870
871 void
872 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
873 {
874 rtx sym_ref;
875
876 /* Do the standard encoding things first. */
877 default_encode_section_info (decl, rtl, first);
878
879 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
880 return;
881
882 sym_ref = XEXP (rtl, 0);
883 if (TREE_CODE (decl) == VAR_DECL)
884 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
885
886 if (!DECL_EXTERNAL (decl)
887 && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
888 && ((TREE_STATIC (decl)
889 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
890 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
891 && DECL_INITIAL (decl) != error_mark_node)))
892 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
893 }
894
895 void
896 darwin_make_decl_one_only (tree decl)
897 {
898 static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
899 static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
900
901 const char *sec = TREE_CODE (decl) == FUNCTION_DECL
902 ? text_section
903 : data_section;
904 TREE_PUBLIC (decl) = 1;
905 DECL_ONE_ONLY (decl) = 1;
906 DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
907 }
908
909 void
910 darwin_mark_decl_preserved (const char *name)
911 {
912 fprintf (asm_out_file, ".no_dead_strip ");
913 assemble_name (asm_out_file, name);
914 fputc ('\n', asm_out_file);
915 }
916
917 void
918 machopic_select_section (tree exp, int reloc,
919 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
920 {
921 void (*base_function)(void);
922
923 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
924 base_function = readonly_data_section;
925 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
926 base_function = const_data_section;
927 else
928 base_function = data_section;
929
930 if (TREE_CODE (exp) == STRING_CST
931 && ((size_t) TREE_STRING_LENGTH (exp)
932 == strlen (TREE_STRING_POINTER (exp)) + 1))
933 cstring_section ();
934 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
935 && flag_merge_constants)
936 {
937 tree size = TYPE_SIZE (TREE_TYPE (exp));
938
939 if (TREE_CODE (size) == INTEGER_CST &&
940 TREE_INT_CST_LOW (size) == 4 &&
941 TREE_INT_CST_HIGH (size) == 0)
942 literal4_section ();
943 else if (TREE_CODE (size) == INTEGER_CST &&
944 TREE_INT_CST_LOW (size) == 8 &&
945 TREE_INT_CST_HIGH (size) == 0)
946 literal8_section ();
947 else
948 base_function ();
949 }
950 else if (TREE_CODE (exp) == CONSTRUCTOR
951 && TREE_TYPE (exp)
952 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
953 && TYPE_NAME (TREE_TYPE (exp)))
954 {
955 tree name = TYPE_NAME (TREE_TYPE (exp));
956 if (TREE_CODE (name) == TYPE_DECL)
957 name = DECL_NAME (name);
958 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
959 objc_constant_string_object_section ();
960 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
961 objc_string_object_section ();
962 else
963 base_function ();
964 }
965 else if (TREE_CODE (exp) == VAR_DECL &&
966 DECL_NAME (exp) &&
967 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
968 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
969 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
970 {
971 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
972
973 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
974 objc_cls_meth_section ();
975 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
976 objc_inst_meth_section ();
977 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
978 objc_cat_cls_meth_section ();
979 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
980 objc_cat_inst_meth_section ();
981 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
982 objc_class_vars_section ();
983 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
984 objc_instance_vars_section ();
985 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
986 objc_cat_cls_meth_section ();
987 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
988 objc_class_names_section ();
989 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
990 objc_meth_var_names_section ();
991 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
992 objc_meth_var_types_section ();
993 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
994 objc_cls_refs_section ();
995 else if (!strncmp (name, "_OBJC_CLASS_", 12))
996 objc_class_section ();
997 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
998 objc_meta_class_section ();
999 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1000 objc_category_section ();
1001 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1002 objc_selector_refs_section ();
1003 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1004 objc_selector_fixup_section ();
1005 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1006 objc_symbols_section ();
1007 else if (!strncmp (name, "_OBJC_MODULES", 13))
1008 objc_module_info_section ();
1009 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1010 objc_image_info_section ();
1011 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1012 objc_cat_inst_meth_section ();
1013 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1014 objc_cat_cls_meth_section ();
1015 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1016 objc_cat_cls_meth_section ();
1017 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1018 objc_protocol_section ();
1019 else
1020 base_function ();
1021 }
1022 else
1023 base_function ();
1024 }
1025
1026 /* This can be called with address expressions as "rtx".
1027 They must go in "const". */
1028
1029 void
1030 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1031 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1032 {
1033 if (GET_MODE_SIZE (mode) == 8)
1034 literal8_section ();
1035 else if (GET_MODE_SIZE (mode) == 4
1036 && (GET_CODE (x) == CONST_INT
1037 || GET_CODE (x) == CONST_DOUBLE))
1038 literal4_section ();
1039 else if (MACHOPIC_INDIRECT
1040 && (GET_CODE (x) == SYMBOL_REF
1041 || GET_CODE (x) == CONST
1042 || GET_CODE (x) == LABEL_REF))
1043 const_data_section ();
1044 else
1045 const_section ();
1046 }
1047
1048 void
1049 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1050 {
1051 if (MACHOPIC_INDIRECT)
1052 mod_init_section ();
1053 else
1054 constructor_section ();
1055 assemble_align (POINTER_SIZE);
1056 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1057
1058 if (! MACHOPIC_INDIRECT)
1059 fprintf (asm_out_file, ".reference .constructors_used\n");
1060 }
1061
1062 void
1063 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1064 {
1065 if (MACHOPIC_INDIRECT)
1066 mod_term_section ();
1067 else
1068 destructor_section ();
1069 assemble_align (POINTER_SIZE);
1070 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1071
1072 if (! MACHOPIC_INDIRECT)
1073 fprintf (asm_out_file, ".reference .destructors_used\n");
1074 }
1075
1076 void
1077 darwin_globalize_label (FILE *stream, const char *name)
1078 {
1079 if (!!strncmp (name, "_OBJC_", 6))
1080 default_globalize_label (stream, name);
1081 }
1082
1083 void
1084 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1085 {
1086 fprintf (asm_out_file, ".section %s\n", name);
1087 }
1088
1089 unsigned int
1090 darwin_section_type_flags (tree decl, const char *name, int reloc)
1091 {
1092 unsigned int flags = default_section_type_flags (decl, name, reloc);
1093
1094 /* Weak or linkonce variables live in a writable section. */
1095 if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1096 && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1097 flags |= SECTION_WRITE;
1098
1099 return flags;
1100 }
1101
1102 void
1103 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1104 {
1105 /* Darwin does not use unique sections. However, the target's
1106 unique_section hook is called for linkonce symbols. We need
1107 to set an appropriate section for such symbols. */
1108 if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1109 darwin_make_decl_one_only (decl);
1110 }
1111
1112 #define HAVE_DEAD_STRIP 0
1113
1114 static void
1115 no_dead_strip (FILE *file, const char *lab)
1116 {
1117 if (HAVE_DEAD_STRIP)
1118 fprintf (file, ".no_dead_strip %s\n", lab);
1119 }
1120
1121 /* Emit a label for an FDE, making it global and/or weak if appropriate.
1122 The third parameter is nonzero if this is for exception handling.
1123 The fourth parameter is nonzero if this is just a placeholder for an
1124 FDE that we are omitting. */
1125
1126 void
1127 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1128 {
1129 tree id = DECL_ASSEMBLER_NAME (decl)
1130 ? DECL_ASSEMBLER_NAME (decl)
1131 : DECL_NAME (decl);
1132
1133 const char *prefix = "_";
1134 const int prefix_len = 1;
1135
1136 const char *base = IDENTIFIER_POINTER (id);
1137 unsigned int base_len = IDENTIFIER_LENGTH (id);
1138
1139 const char *suffix = ".eh";
1140
1141 int need_quotes = name_needs_quotes (base);
1142 int quotes_len = need_quotes ? 2 : 0;
1143 char *lab;
1144
1145 if (! for_eh)
1146 suffix = ".eh1";
1147
1148 lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1149 lab[0] = '\0';
1150
1151 if (need_quotes)
1152 strcat(lab, "\"");
1153 strcat(lab, prefix);
1154 strcat(lab, base);
1155 strcat(lab, suffix);
1156 if (need_quotes)
1157 strcat(lab, "\"");
1158
1159 if (TREE_PUBLIC (decl))
1160 fprintf (file, "%s %s\n",
1161 (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1162 ? ".globl"
1163 : ".private_extern"),
1164 lab);
1165
1166 if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1167 fprintf (file, ".weak_definition %s\n", lab);
1168
1169 if (empty)
1170 {
1171 fprintf (file, "%s = 0\n", lab);
1172
1173 /* Mark the absolute .eh and .eh1 style labels as needed to
1174 ensure that we don't dead code strip them and keep such
1175 labels from another instantiation point until we can fix this
1176 properly with group comdat support. */
1177 no_dead_strip (file, lab);
1178 }
1179 else
1180 fprintf (file, "%s:\n", lab);
1181
1182 free (lab);
1183 }
1184
1185 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
1186
1187 void
1188 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1189 {
1190 const char *nlp_name;
1191
1192 if (GET_CODE (addr) != SYMBOL_REF)
1193 abort ();
1194
1195 nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1196 fputs ("\t.long\t", file);
1197 ASM_OUTPUT_LABELREF (file, nlp_name);
1198 fputs ("-.", file);
1199 }
1200
1201 /* Emit an assembler directive to set visibility for a symbol. The
1202 only supported visibilities are VISIBILITY_DEFAULT and
1203 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1204 extern". There is no MACH-O equivalent of ELF's
1205 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1206
1207 void
1208 darwin_assemble_visibility (tree decl, int vis)
1209 {
1210 if (vis == VISIBILITY_DEFAULT)
1211 ;
1212 else if (vis == VISIBILITY_HIDDEN)
1213 {
1214 fputs ("\t.private_extern ", asm_out_file);
1215 assemble_name (asm_out_file,
1216 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1217 fputs ("\n", asm_out_file);
1218 }
1219 else
1220 warning ("internal and protected visibility attributes not supported"
1221 "in this configuration; ignored");
1222 }
1223
1224 /* Output a difference of two labels that will be an assembly time
1225 constant if the two labels are local. (.long lab1-lab2 will be
1226 very different if lab1 is at the boundary between two sections; it
1227 will be relocated according to the second section, not the first,
1228 so one ends up with a difference between labels in different
1229 sections, which is bad in the dwarf2 eh context for instance.) */
1230
1231 static int darwin_dwarf_label_counter;
1232
1233 void
1234 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1235 const char *lab1, const char *lab2)
1236 {
1237 int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1238 && lab2[0] == '*' && lab2[1] == 'L');
1239
1240 if (islocaldiff)
1241 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1242 else
1243 fprintf (file, "\t%s\t", ".long");
1244 assemble_name (file, lab1);
1245 fprintf (file, "-");
1246 assemble_name (file, lab2);
1247 if (islocaldiff)
1248 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1249 }
1250
1251 void
1252 darwin_file_end (void)
1253 {
1254 machopic_finish (asm_out_file);
1255 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1256 {
1257 constructor_section ();
1258 destructor_section ();
1259 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1260 }
1261 fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1262 }
1263
1264 #include "gt-darwin.h"