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