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