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