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