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