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