]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/darwin.c
builtins.c: Fix formatting.
[thirdparty/gcc.git] / gcc / config / darwin.c
CommitLineData
ee890fe2
SS
1/* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001
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
42#include "darwin-protos.h"
43
44extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
45
46static int machopic_data_defined_p PARAMS ((const char *));
47static int func_name_maybe_scoped PARAMS ((const char *));
df56a27f 48static void update_non_lazy_ptrs PARAMS ((const char *));
4e08ba6c 49static void update_stubs PARAMS ((const char *));
ee890fe2 50
ee890fe2
SS
51int
52name_needs_quotes (name)
53 const char *name;
54{
55 int c;
56 while ((c = *name++) != '\0')
0df6c2c7 57 if (! ISIDNUM (c))
ee890fe2
SS
58 return 1;
59 return 0;
60}
61
62/*
63 * flag_pic = 1 ... generate only indirections
64 * flag_pic = 2 ... generate indirections and pure code
65 */
66
67/* This module assumes that (const (symbol_ref "foo")) is a legal pic
68 reference, which will not be changed. */
69
70static tree machopic_defined_list;
71
72enum machopic_addr_class
73machopic_classify_ident (ident)
74 tree ident;
75{
76 const char *name = IDENTIFIER_POINTER (ident);
77 int lprefix = (((name[0] == '*' || name[0] == '&')
78 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
79 || ( name[0] == '_'
80 && name[1] == 'O'
81 && name[2] == 'B'
82 && name[3] == 'J'
83 && name[4] == 'C'
84 && name[5] == '_'));
df56a27f 85 tree temp;
ee890fe2 86
df56a27f 87 if (name[0] != '!')
ee890fe2 88 {
df56a27f 89 /* Here if no special encoding to be found. */
ee890fe2
SS
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
df56a27f
SS
115 else if (name[1] == 'D')
116 return MACHOPIC_DEFINED_DATA;
ee890fe2 117
df56a27f
SS
118 else if (name[1] == 'T')
119 return MACHOPIC_DEFINED_FUNCTION;
ee890fe2 120
b7fb9feb
TC
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
ee890fe2
SS
137 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
138 {
139 if (ident == TREE_VALUE (temp))
140 {
df56a27f 141 if (name[1] == 'T')
ee890fe2
SS
142 return MACHOPIC_DEFINED_FUNCTION;
143 else
144 return MACHOPIC_DEFINED_DATA;
145 }
146 }
147
df56a27f 148 if (name[1] == 't' || name[1] == 'T')
ee890fe2
SS
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
164
165enum machopic_addr_class
166machopic_classify_name (name)
167 const char *name;
168{
169 return machopic_classify_ident (get_identifier (name));
170}
171
172int
173machopic_ident_defined_p (ident)
174 tree ident;
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
188machopic_data_defined_p (name)
189 const char *name;
190{
191 switch (machopic_classify_ident (get_identifier (name)))
192 {
193 case MACHOPIC_DEFINED_DATA:
194 return 1;
195 default:
196 return 0;
197 }
198}
199
200int
201machopic_name_defined_p (name)
202 const char *name;
203{
204 return machopic_ident_defined_p (get_identifier (name));
205}
206
207void
208machopic_define_ident (ident)
209 tree ident;
210{
211 if (!machopic_ident_defined_p (ident))
212 machopic_defined_list =
213 tree_cons (NULL_TREE, ident, machopic_defined_list);
214}
215
216void
217machopic_define_name (name)
218 const char *name;
219{
220 machopic_define_ident (get_identifier (name));
221}
222
ee890fe2
SS
223/* This is a static to make inline functions work. The rtx
224 representing the PIC base symbol always points to here. */
225
226static char function_base[32];
227
228static int current_pic_label_num;
229
230char *
231machopic_function_base_name ()
232{
c0cbc013 233 static const char *name = NULL;
ee890fe2
SS
234 static const char *current_name;
235
236 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
237
238 if (name != current_name)
239 {
240 current_function_uses_pic_offset_table = 1;
241
242 /* Save mucho space and time. Some of the C++ mangled names are over
243 700 characters long! Note that we produce a label containing a '-'
244 if the function we're compiling is an Objective-C method, as evinced
245 by the incredibly scientific test below. This is because code in
246 rs6000.c makes the same ugly test when loading the PIC reg. */
247
248 ++current_pic_label_num;
249 if (*current_name == '+' || *current_name == '-')
250 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
251 else
252 sprintf (function_base, "*L%d$pb", current_pic_label_num);
253
254 name = current_name;
255 }
256
257 return function_base;
258}
259
260static tree machopic_non_lazy_pointers = NULL;
261
262/* Return a non-lazy pointer name corresponding to the given name,
263 either by finding it in our list of pointer names, or by generating
264 a new one. */
265
266char *
267machopic_non_lazy_ptr_name (name)
268 const char *name;
269{
df56a27f 270 char *temp_name;
ee890fe2
SS
271 tree temp, ident = get_identifier (name);
272
273 for (temp = machopic_non_lazy_pointers;
274 temp != NULL_TREE;
275 temp = TREE_CHAIN (temp))
276 {
277 if (ident == TREE_VALUE (temp))
278 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279 }
280
df56a27f
SS
281 STRIP_NAME_ENCODING (name, name);
282
283 /* Try again, but comparing names this time. */
284 for (temp = machopic_non_lazy_pointers;
285 temp != NULL_TREE;
286 temp = TREE_CHAIN (temp))
287 {
288 if (TREE_VALUE (temp))
289 {
290 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
291 STRIP_NAME_ENCODING (temp_name, temp_name);
292 if (strcmp (name, temp_name) == 0)
293 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
294 }
295 }
296
ee890fe2
SS
297 {
298 char *buffer;
299 tree ptr_name;
300
301 buffer = alloca (strlen (name) + 20);
302
303 strcpy (buffer, "&L");
304 if (name[0] == '*')
305 strcat (buffer, name+1);
306 else
307 {
308 strcat (buffer, "_");
309 strcat (buffer, name);
310 }
311
312 strcat (buffer, "$non_lazy_ptr");
313 ptr_name = get_identifier (buffer);
314
315 machopic_non_lazy_pointers
316 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
317
318 TREE_USED (machopic_non_lazy_pointers) = 0;
319
320 return IDENTIFIER_POINTER (ptr_name);
321 }
322}
323
324static tree machopic_stubs = 0;
325
326/* Make sure the GC knows about our homemade lists. */
327
328void
329machopic_add_gc_roots ()
330{
331 ggc_add_tree_root (&machopic_defined_list, 1);
332 ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
333 ggc_add_tree_root (&machopic_stubs, 1);
334}
335
336/* Return the name of the stub corresponding to the given name,
337 generating a new stub name if necessary. */
338
339char *
340machopic_stub_name (name)
341 const char *name;
342{
343 tree temp, ident = get_identifier (name);
93913281
SS
344 const char *tname;
345
ee890fe2
SS
346 for (temp = machopic_stubs;
347 temp != NULL_TREE;
348 temp = TREE_CHAIN (temp))
349 {
350 if (ident == TREE_VALUE (temp))
351 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
93913281
SS
352 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
353 if (strcmp (name, tname) == 0)
354 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
355 /* A library call name might not be section-encoded yet, so try
356 it against a stripped name. */
357 if (name[0] != '!'
358 && tname[0] == '!'
359 && strcmp (name, tname + 4) == 0)
4e08ba6c 360 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
ee890fe2
SS
361 }
362
df56a27f
SS
363 STRIP_NAME_ENCODING (name, name);
364
ee890fe2
SS
365 {
366 char *buffer;
367 tree ptr_name;
368 int needs_quotes = name_needs_quotes (name);
369
370 buffer = alloca (strlen (name) + 20);
371
372 if (needs_quotes)
373 strcpy (buffer, "&\"L");
374 else
375 strcpy (buffer, "&L");
376 if (name[0] == '*')
377 {
378 strcat (buffer, name+1);
379 }
380 else
381 {
382 strcat (buffer, "_");
383 strcat (buffer, name);
384 }
385
386 if (needs_quotes)
387 strcat (buffer, "$stub\"");
388 else
389 strcat (buffer, "$stub");
390 ptr_name = get_identifier (buffer);
391
392 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
393 TREE_USED (machopic_stubs) = 0;
394
395 return IDENTIFIER_POINTER (ptr_name);
396 }
397}
398
399void
400machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
401 const char *name;
402 int validate_stub;
403{
df56a27f
SS
404 char *real_name;
405 tree temp, ident = get_identifier (name), id2;
ee890fe2
SS
406
407 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
408 temp != NULL_TREE;
409 temp = TREE_CHAIN (temp))
410 if (ident == TREE_PURPOSE (temp))
411 {
412 /* Mark both the stub or non-lazy pointer as well as the
413 original symbol as being referenced. */
414 TREE_USED (temp) = 1;
415 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
416 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
df56a27f
SS
417 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
418 id2 = maybe_get_identifier (real_name);
419 if (id2)
420 TREE_SYMBOL_REFERENCED (id2) = 1;
ee890fe2
SS
421 }
422}
423
424/* Transform ORIG, which may be any data source, to the corresponding
425 source using indirections. */
426
427rtx
428machopic_indirect_data_reference (orig, reg)
429 rtx orig, reg;
430{
431 rtx ptr_ref = orig;
432
433 if (! MACHOPIC_INDIRECT)
434 return orig;
435
436 if (GET_CODE (orig) == SYMBOL_REF)
437 {
438 const char *name = XSTR (orig, 0);
439
440 if (machopic_data_defined_p (name))
441 {
442 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
443 machopic_function_base_name ());
444 rtx offset = gen_rtx (CONST, Pmode,
445 gen_rtx (MINUS, Pmode, orig, pic_base));
446
447#if defined (TARGET_TOC) /* i.e., PowerPC */
448 rtx hi_sum_reg = reg;
449
450 if (reg == NULL)
451 abort ();
452
453 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
454 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
455 gen_rtx (HIGH, Pmode, offset))));
456 emit_insn (gen_rtx (SET, Pmode, reg,
457 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
458
459 orig = reg;
460#else
461#if defined (HAVE_lo_sum)
462 if (reg == 0) abort ();
463
464 emit_insn (gen_rtx (SET, VOIDmode, reg,
465 gen_rtx (HIGH, Pmode, offset)));
466 emit_insn (gen_rtx (SET, VOIDmode, reg,
467 gen_rtx (LO_SUM, Pmode, reg, offset)));
468 emit_insn (gen_rtx (USE, VOIDmode,
469 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
470
471 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
472#endif
473#endif
474 return orig;
475 }
476
477 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
478 machopic_non_lazy_ptr_name (name));
479
480 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
481 RTX_UNCHANGING_P (ptr_ref) = 1;
482
483 return ptr_ref;
484 }
485 else if (GET_CODE (orig) == CONST)
486 {
487 rtx base, result;
488
489 /* legitimize both operands of the PLUS */
490 if (GET_CODE (XEXP (orig, 0)) == PLUS)
491 {
492 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
493 reg);
494 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
495 (base == reg ? 0 : reg));
496 }
497 else
498 return orig;
499
500 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
ed8908e7 501 result = plus_constant (base, INTVAL (orig));
ee890fe2 502 else
ed8908e7 503 result = gen_rtx (PLUS, Pmode, base, orig);
ee890fe2
SS
504
505 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
506 RTX_UNCHANGING_P (result) = 1;
507
508 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
509 {
510 if (reg)
511 {
512 emit_move_insn (reg, result);
513 result = reg;
514 }
515 else
516 {
517 result = force_reg (GET_MODE (result), result);
518 }
519 }
520
521 return result;
522
523 }
524 else if (GET_CODE (orig) == MEM)
525 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
526 /* When the target is i386, this code prevents crashes due to the
527 compiler's ignorance on how to move the PIC base register to
528 other registers. (The reload phase sometimes introduces such
529 insns.) */
530 else if (GET_CODE (orig) == PLUS
531 && GET_CODE (XEXP (orig, 0)) == REG
532 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
533#ifdef I386
534 /* Prevent the same register from being erroneously used
535 as both the base and index registers. */
536 && GET_CODE (XEXP (orig, 1)) == CONST
537#endif
538 && reg)
539 {
540 emit_move_insn (reg, XEXP (orig, 0));
541 XEXP (ptr_ref, 0) = reg;
542 }
543 return ptr_ref;
544}
545
ee890fe2
SS
546/* Transform TARGET (a MEM), which is a function call target, to the
547 corresponding symbol_stub if necessary. Return a new MEM. */
548
549rtx
550machopic_indirect_call_target (target)
551 rtx target;
552{
553 if (GET_CODE (target) != MEM)
554 return target;
555
556 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
557 {
558 enum machine_mode mode = GET_MODE (XEXP (target, 0));
559 const char *name = XSTR (XEXP (target, 0), 0);
560
b7fb9feb
TC
561 /* If the name is already defined, we need do nothing. */
562 if (name[0] == '!' && name[1] == 'T')
563 return target;
564
565 if (!machopic_name_defined_p (name))
ee890fe2
SS
566 {
567 const char *stub_name = machopic_stub_name (name);
568
569 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
570 RTX_UNCHANGING_P (target) = 1;
571 }
572 }
573
574 return target;
575}
576
577rtx
578machopic_legitimize_pic_address (orig, mode, reg)
579 rtx orig, reg;
580 enum machine_mode mode;
581{
582 rtx pic_ref = orig;
583
584 if (! MACHOPIC_PURE)
585 return orig;
586
587 /* First handle a simple SYMBOL_REF or LABEL_REF */
588 if (GET_CODE (orig) == LABEL_REF
589 || (GET_CODE (orig) == SYMBOL_REF
590 ))
591 {
592 /* addr(foo) = &func+(foo-func) */
593 rtx pic_base;
594
595 orig = machopic_indirect_data_reference (orig, reg);
596
597 if (GET_CODE (orig) == PLUS
598 && GET_CODE (XEXP (orig, 0)) == REG)
599 {
600 if (reg == 0)
601 return force_reg (mode, orig);
602
603 emit_move_insn (reg, orig);
604 return reg;
605 }
606
607 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
608
609 if (GET_CODE (orig) == MEM)
610 {
611 if (reg == 0)
612 {
613 if (reload_in_progress)
614 abort ();
615 else
616 reg = gen_reg_rtx (Pmode);
617 }
618
619#ifdef HAVE_lo_sum
620 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
621 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
622 {
623 rtx offset = gen_rtx (CONST, Pmode,
624 gen_rtx (MINUS, Pmode,
625 XEXP (orig, 0), pic_base));
626#if defined (TARGET_TOC) /* i.e., PowerPC */
627 /* Generating a new reg may expose opportunities for
628 common subexpression elimination. */
629 rtx hi_sum_reg =
630 (reload_in_progress ? reg : gen_reg_rtx (SImode));
631
632 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
633 gen_rtx (PLUS, Pmode,
634 pic_offset_table_rtx,
635 gen_rtx (HIGH, Pmode, offset))));
636 emit_insn (gen_rtx (SET, VOIDmode, reg,
637 gen_rtx (MEM, GET_MODE (orig),
638 gen_rtx (LO_SUM, Pmode,
639 hi_sum_reg, offset))));
640 pic_ref = reg;
641
642#else
643 emit_insn (gen_rtx (USE, VOIDmode,
644 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
645
646 emit_insn (gen_rtx (SET, VOIDmode, reg,
647 gen_rtx (HIGH, Pmode,
648 gen_rtx (CONST, Pmode, offset))));
649 emit_insn (gen_rtx (SET, VOIDmode, reg,
650 gen_rtx (LO_SUM, Pmode, reg,
651 gen_rtx (CONST, Pmode, offset))));
652 pic_ref = gen_rtx (PLUS, Pmode,
653 pic_offset_table_rtx, reg);
654#endif
655 }
656 else
657#endif /* HAVE_lo_sum */
658 {
659 rtx pic = pic_offset_table_rtx;
660 if (GET_CODE (pic) != REG)
661 {
662 emit_move_insn (reg, pic);
663 pic = reg;
664 }
665#if 0
666 emit_insn (gen_rtx (USE, VOIDmode,
667 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
668#endif
669
670 pic_ref = gen_rtx (PLUS, Pmode,
671 pic,
672 gen_rtx (CONST, Pmode,
673 gen_rtx (MINUS, Pmode,
674 XEXP (orig, 0),
675 pic_base)));
676 }
677
678#if !defined (TARGET_TOC)
679 RTX_UNCHANGING_P (pic_ref) = 1;
680 emit_move_insn (reg, pic_ref);
681 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
682#endif
683 }
684 else
685 {
686
687#ifdef HAVE_lo_sum
688 if (GET_CODE (orig) == SYMBOL_REF
689 || GET_CODE (orig) == LABEL_REF)
690 {
691 rtx offset = gen_rtx (CONST, Pmode,
692 gen_rtx (MINUS, Pmode, orig, pic_base));
693#if defined (TARGET_TOC) /* i.e., PowerPC */
694 rtx hi_sum_reg;
695
696 if (reg == 0)
697 {
698 if (reload_in_progress)
699 abort ();
700 else
701 reg = gen_reg_rtx (SImode);
702 }
703
704 hi_sum_reg = reg;
705
706 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
707 gen_rtx (PLUS, Pmode,
708 pic_offset_table_rtx,
709 gen_rtx (HIGH, Pmode, offset))));
710 emit_insn (gen_rtx (SET, VOIDmode, reg,
711 gen_rtx (LO_SUM, Pmode,
712 hi_sum_reg, offset)));
713 pic_ref = reg;
714#else
715 emit_insn (gen_rtx (SET, VOIDmode, reg,
716 gen_rtx (HIGH, Pmode, offset)));
717 emit_insn (gen_rtx (SET, VOIDmode, reg,
718 gen_rtx (LO_SUM, Pmode, reg, offset)));
719 pic_ref = gen_rtx (PLUS, Pmode,
720 pic_offset_table_rtx, reg);
721#endif
722 }
723 else
724#endif /* HAVE_lo_sum */
725 {
726 if (GET_CODE (orig) == REG)
727 {
728 return orig;
729 }
730 else
731 {
732 rtx pic = pic_offset_table_rtx;
733 if (GET_CODE (pic) != REG)
734 {
735 emit_move_insn (reg, pic);
736 pic = reg;
737 }
738#if 0
739 emit_insn (gen_rtx (USE, VOIDmode,
740 pic_offset_table_rtx));
741#endif
742 pic_ref = gen_rtx (PLUS, Pmode,
743 pic,
744 gen_rtx (CONST, Pmode,
745 gen_rtx (MINUS, Pmode,
746 orig, pic_base)));
747 }
748 }
749 }
750
751 RTX_UNCHANGING_P (pic_ref) = 1;
752
753 if (GET_CODE (pic_ref) != REG)
754 {
755 if (reg != 0)
756 {
757 emit_move_insn (reg, pic_ref);
758 return reg;
759 }
760 else
761 {
762 return force_reg (mode, pic_ref);
763 }
764 }
765 else
766 {
767 return pic_ref;
768 }
769 }
770
771 else if (GET_CODE (orig) == SYMBOL_REF)
772 return orig;
773
774 else if (GET_CODE (orig) == PLUS
775 && (GET_CODE (XEXP (orig, 0)) == MEM
776 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
777 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
778 && XEXP (orig, 0) != pic_offset_table_rtx
779 && GET_CODE (XEXP (orig, 1)) != REG)
780
781 {
782 rtx base;
783 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
784
785 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
786 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
787 Pmode, (base == reg ? 0 : reg));
788 if (GET_CODE (orig) == CONST_INT)
789 {
ed8908e7 790 pic_ref = plus_constant (base, INTVAL (orig));
ee890fe2
SS
791 is_complex = 1;
792 }
793 else
ed8908e7 794 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
ee890fe2
SS
795
796 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
797 RTX_UNCHANGING_P (pic_ref) = 1;
798
799 if (reg && is_complex)
800 {
801 emit_move_insn (reg, pic_ref);
802 pic_ref = reg;
803 }
804 /* Likewise, should we set special REG_NOTEs here? */
805 }
806
807 else if (GET_CODE (orig) == CONST)
808 {
809 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
810 }
811
812 else if (GET_CODE (orig) == MEM
813 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
814 {
815 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
816
817 addr = gen_rtx (MEM, GET_MODE (orig), addr);
818 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
819 emit_move_insn (reg, addr);
820 pic_ref = reg;
821 }
822
823 return pic_ref;
824}
825
826
827void
828machopic_finish (asm_out_file)
829 FILE *asm_out_file;
830{
831 tree temp;
832
833 for (temp = machopic_stubs;
834 temp != NULL_TREE;
835 temp = TREE_CHAIN (temp))
836 {
91dc3130
KG
837 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
838 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
ee890fe2
SS
839 char *sym;
840 char *stub;
ee890fe2
SS
841
842 if (! TREE_USED (temp))
843 continue;
844
b7fb9feb
TC
845 /* If the symbol is actually defined, we don't need a stub. */
846 if (sym_name[0] == '!' && sym_name[1] == 'T')
847 continue;
848
df56a27f 849 STRIP_NAME_ENCODING (sym_name, sym_name);
ee890fe2
SS
850
851 sym = alloca (strlen (sym_name) + 2);
852 if (sym_name[0] == '*' || sym_name[0] == '&')
853 strcpy (sym, sym_name + 1);
854 else if (sym_name[0] == '-' || sym_name[0] == '+')
855 strcpy (sym, sym_name);
856 else
857 sym[0] = '_', strcpy (sym + 1, sym_name);
858
859 stub = alloca (strlen (stub_name) + 2);
860 if (stub_name[0] == '*' || stub_name[0] == '&')
861 strcpy (stub, stub_name + 1);
862 else
863 stub[0] = '_', strcpy (stub + 1, stub_name);
864
865 machopic_output_stub (asm_out_file, sym, stub);
866 }
867
868 for (temp = machopic_non_lazy_pointers;
869 temp != NULL_TREE;
870 temp = TREE_CHAIN (temp))
871 {
872 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
873 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
874#if 0
875 tree decl = lookup_name_darwin (TREE_VALUE (temp));
876#endif
877
878 if (! TREE_USED (temp))
879 continue;
880
881 if (machopic_ident_defined_p (TREE_VALUE (temp))
882#if 0 /* add back when we have private externs */
883 || (decl && DECL_PRIVATE_EXTERN (decl))
884#endif
885 )
886 {
887 data_section ();
c8af3574 888 assemble_align (GET_MODE_ALIGNMENT (Pmode));
ee890fe2
SS
889 assemble_label (lazy_name);
890 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
c8af3574
RH
891 GET_MODE_SIZE (Pmode),
892 GET_MODE_ALIGNMENT (Pmode), 1);
ee890fe2
SS
893 }
894 else
895 {
896 machopic_nl_symbol_ptr_section ();
897 assemble_name (asm_out_file, lazy_name);
898 fprintf (asm_out_file, ":\n");
899
900 fprintf (asm_out_file, "\t.indirect_symbol ");
901 assemble_name (asm_out_file, sym_name);
902 fprintf (asm_out_file, "\n");
903
c8af3574
RH
904 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
905 GET_MODE_ALIGNMENT (Pmode), 1);
ee890fe2
SS
906 }
907 }
908}
909
910int
911machopic_operand_p (op)
912 rtx op;
913{
914 if (MACHOPIC_JUST_INDIRECT)
915 {
916 while (GET_CODE (op) == CONST)
917 op = XEXP (op, 0);
918
919 if (GET_CODE (op) == SYMBOL_REF)
920 return machopic_name_defined_p (XSTR (op, 0));
921 else
922 return 0;
923 }
924
925 while (GET_CODE (op) == CONST)
926 op = XEXP (op, 0);
927
928 if (GET_CODE (op) == MINUS
929 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
930 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
931 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
932 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
933 return 1;
934
935#if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
936 /* Without this statement, the compiler crashes while compiling enquire.c
937 when targetting PowerPC. It is not known why this code is not needed
938 when targetting other processors. */
939 else if (GET_CODE (op) == SYMBOL_REF
940 && (machopic_classify_name (XSTR (op, 0))
941 == MACHOPIC_DEFINED_FUNCTION))
942 {
943 return 1;
944 }
945#endif
946
947 return 0;
948}
df56a27f
SS
949
950/* This function records whether a given name corresponds to a defined
951 or undefined function or variable, for machopic_classify_ident to
952 use later. */
953
954void
955darwin_encode_section_info (decl)
956 tree decl;
957{
958 char code = '\0';
959 int defined = 0;
353e51f8 960 rtx sym_ref;
c0cbc013
DJ
961 const char *orig_str;
962 char *new_str;
353e51f8 963 size_t len, new_len;
df56a27f
SS
964
965 if ((TREE_CODE (decl) == FUNCTION_DECL
966 || TREE_CODE (decl) == VAR_DECL)
70bdc2ff 967 && !DECL_EXTERNAL (decl)
df56a27f
SS
968 && ((TREE_STATIC (decl)
969 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
abe72dd8
SS
970 || (DECL_INITIAL (decl)
971 && DECL_INITIAL (decl) != error_mark_node)))
df56a27f
SS
972 defined = 1;
973
974 if (TREE_CODE (decl) == FUNCTION_DECL)
975 code = (defined ? 'T' : 't');
976 else if (TREE_CODE (decl) == VAR_DECL)
977 code = (defined ? 'D' : 'd');
978
353e51f8
SS
979 if (code == '\0')
980 return;
df56a27f 981
353e51f8
SS
982 sym_ref = XEXP (DECL_RTL (decl), 0);
983 orig_str = XSTR (sym_ref, 0);
984 len = strlen (orig_str) + 1;
df56a27f 985
353e51f8
SS
986 if (orig_str[0] == '!')
987 {
988 /* Already encoded; see if we need to change it. */
989 if (code == orig_str[1])
990 return;
991 /* Yes, tweak a copy of the name and put it in a new string. */
992 new_str = alloca (len);
993 memcpy (new_str, orig_str, len);
994 new_str[1] = code;
995 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
353e51f8
SS
996 }
997 else
998 {
999 /* Add the encoding. */
1000 new_len = len + 4;
1001 new_str = alloca (new_len);
1002 new_str[0] = '!';
1003 new_str[1] = code;
1004 new_str[2] = '_';
1005 new_str[3] = '_';
1006 memcpy (new_str + 4, orig_str, len);
1007 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
df56a27f 1008 }
4e08ba6c
SS
1009 /* The non-lazy pointer list may have captured references to the
1010 old encoded name, change them. */
b7fb9feb
TC
1011 if (TREE_CODE (decl) == VAR_DECL)
1012 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1013 else
1014 update_stubs (XSTR (sym_ref, 0));
df56a27f
SS
1015}
1016
1017/* Scan the list of non-lazy pointers and update any recorded names whose
1018 stripped name matches the argument. */
1019
1020static void
1021update_non_lazy_ptrs (name)
1022 const char *name;
1023{
91dc3130 1024 const char *name1, *name2;
df56a27f
SS
1025 tree temp;
1026
1027 STRIP_NAME_ENCODING (name1, name);
1028
1029 for (temp = machopic_non_lazy_pointers;
1030 temp != NULL_TREE;
1031 temp = TREE_CHAIN (temp))
1032 {
1033 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1034
1035 if (*sym_name == '!')
1036 {
1037 STRIP_NAME_ENCODING (name2, sym_name);
1038 if (strcmp (name1, name2) == 0)
1039 {
1040 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1041 break;
1042 }
1043 }
1044 }
1045}
4e08ba6c 1046
b7fb9feb
TC
1047/* Function NAME is being defined, and its label has just been output.
1048 If there's already a reference to a stub for this function, we can
1049 just emit the stub label now and we don't bother emitting the stub later. */
1050
1051void
1052machopic_output_possible_stub_label (file, name)
1053 FILE *file;
1054 const char *name;
1055{
1056 tree temp;
1057
1058
1059 /* Ensure we're looking at a section-encoded name. */
1060 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1061 return;
1062
1063 for (temp = machopic_stubs;
1064 temp != NULL_TREE;
1065 temp = TREE_CHAIN (temp))
1066 {
1067 const char *sym_name;
1068
1069 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1070 if (sym_name[0] == '!' && sym_name[1] == 'T'
1071 && ! strcmp (name+2, sym_name+2))
1072 {
1073 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1074 break;
1075 }
1076 }
1077}
4e08ba6c
SS
1078
1079/* Scan the list of stubs and update any recorded names whose
1080 stripped name matches the argument. */
1081
1082static void
1083update_stubs (name)
1084 const char *name;
1085{
91dc3130 1086 const char *name1, *name2;
4e08ba6c
SS
1087 tree temp;
1088
1089 STRIP_NAME_ENCODING (name1, name);
1090
1091 for (temp = machopic_stubs;
1092 temp != NULL_TREE;
1093 temp = TREE_CHAIN (temp))
1094 {
1095 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1096
1097 if (*sym_name == '!')
1098 {
1099 STRIP_NAME_ENCODING (name2, sym_name);
1100 if (strcmp (name1, name2) == 0)
1101 {
1102 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1103 break;
1104 }
1105 }
1106 }
1107}
2cc07db4
RH
1108
1109void
1110machopic_asm_out_constructor (symbol, priority)
1111 rtx symbol;
1112 int priority ATTRIBUTE_UNUSED;
1113{
1114 if (flag_pic)
1115 mod_init_section ();
1116 else
1117 constructor_section ();
c8af3574
RH
1118 assemble_align (POINTER_SIZE);
1119 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2cc07db4
RH
1120
1121 if (!flag_pic)
1122 fprintf (asm_out_file, ".reference .constructors_used\n");
1123}
1124
1125void
1126machopic_asm_out_destructor (symbol, priority)
1127 rtx symbol;
1128 int priority ATTRIBUTE_UNUSED;
1129{
1130 if (flag_pic)
1131 mod_term_section ();
1132 else
1133 destructor_section ();
c8af3574
RH
1134 assemble_align (POINTER_SIZE);
1135 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
2cc07db4
RH
1136
1137 if (!flag_pic)
1138 fprintf (asm_out_file, ".reference .destructors_used\n");
1139}