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