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