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