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