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