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