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