]> gcc.gnu.org Git - gcc.git/blame - gcc/config/darwin.c
Move constructor/destructor handling into target hooks.
[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')
56 if (!isalnum (c) && c != '_')
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{
216 static char *name = NULL;
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);
327
328 for (temp = machopic_stubs;
329 temp != NULL_TREE;
330 temp = TREE_CHAIN (temp))
331 {
332 if (ident == TREE_VALUE (temp))
333 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
4e08ba6c
SS
334 if (strcmp (name, IDENTIFIER_POINTER (TREE_VALUE (temp))) == 0)
335 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
ee890fe2
SS
336 }
337
df56a27f
SS
338 STRIP_NAME_ENCODING (name, name);
339
ee890fe2
SS
340 {
341 char *buffer;
342 tree ptr_name;
343 int needs_quotes = name_needs_quotes (name);
344
345 buffer = alloca (strlen (name) + 20);
346
347 if (needs_quotes)
348 strcpy (buffer, "&\"L");
349 else
350 strcpy (buffer, "&L");
351 if (name[0] == '*')
352 {
353 strcat (buffer, name+1);
354 }
355 else
356 {
357 strcat (buffer, "_");
358 strcat (buffer, name);
359 }
360
361 if (needs_quotes)
362 strcat (buffer, "$stub\"");
363 else
364 strcat (buffer, "$stub");
365 ptr_name = get_identifier (buffer);
366
367 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
368 TREE_USED (machopic_stubs) = 0;
369
370 return IDENTIFIER_POINTER (ptr_name);
371 }
372}
373
374void
375machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
376 const char *name;
377 int validate_stub;
378{
df56a27f
SS
379 char *real_name;
380 tree temp, ident = get_identifier (name), id2;
ee890fe2
SS
381
382 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
383 temp != NULL_TREE;
384 temp = TREE_CHAIN (temp))
385 if (ident == TREE_PURPOSE (temp))
386 {
387 /* Mark both the stub or non-lazy pointer as well as the
388 original symbol as being referenced. */
389 TREE_USED (temp) = 1;
390 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
391 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
df56a27f
SS
392 STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
393 id2 = maybe_get_identifier (real_name);
394 if (id2)
395 TREE_SYMBOL_REFERENCED (id2) = 1;
ee890fe2
SS
396 }
397}
398
399/* Transform ORIG, which may be any data source, to the corresponding
400 source using indirections. */
401
402rtx
403machopic_indirect_data_reference (orig, reg)
404 rtx orig, reg;
405{
406 rtx ptr_ref = orig;
407
408 if (! MACHOPIC_INDIRECT)
409 return orig;
410
411 if (GET_CODE (orig) == SYMBOL_REF)
412 {
413 const char *name = XSTR (orig, 0);
414
415 if (machopic_data_defined_p (name))
416 {
417 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
418 machopic_function_base_name ());
419 rtx offset = gen_rtx (CONST, Pmode,
420 gen_rtx (MINUS, Pmode, orig, pic_base));
421
422#if defined (TARGET_TOC) /* i.e., PowerPC */
423 rtx hi_sum_reg = reg;
424
425 if (reg == NULL)
426 abort ();
427
428 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
429 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
430 gen_rtx (HIGH, Pmode, offset))));
431 emit_insn (gen_rtx (SET, Pmode, reg,
432 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
433
434 orig = reg;
435#else
436#if defined (HAVE_lo_sum)
437 if (reg == 0) abort ();
438
439 emit_insn (gen_rtx (SET, VOIDmode, reg,
440 gen_rtx (HIGH, Pmode, offset)));
441 emit_insn (gen_rtx (SET, VOIDmode, reg,
442 gen_rtx (LO_SUM, Pmode, reg, offset)));
443 emit_insn (gen_rtx (USE, VOIDmode,
444 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
445
446 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
447#endif
448#endif
449 return orig;
450 }
451
452 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
453 machopic_non_lazy_ptr_name (name));
454
455 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
456 RTX_UNCHANGING_P (ptr_ref) = 1;
457
458 return ptr_ref;
459 }
460 else if (GET_CODE (orig) == CONST)
461 {
462 rtx base, result;
463
464 /* legitimize both operands of the PLUS */
465 if (GET_CODE (XEXP (orig, 0)) == PLUS)
466 {
467 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
468 reg);
469 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
470 (base == reg ? 0 : reg));
471 }
472 else
473 return orig;
474
475 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
ed8908e7 476 result = plus_constant (base, INTVAL (orig));
ee890fe2 477 else
ed8908e7 478 result = gen_rtx (PLUS, Pmode, base, orig);
ee890fe2
SS
479
480 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
481 RTX_UNCHANGING_P (result) = 1;
482
483 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
484 {
485 if (reg)
486 {
487 emit_move_insn (reg, result);
488 result = reg;
489 }
490 else
491 {
492 result = force_reg (GET_MODE (result), result);
493 }
494 }
495
496 return result;
497
498 }
499 else if (GET_CODE (orig) == MEM)
500 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
501 /* When the target is i386, this code prevents crashes due to the
502 compiler's ignorance on how to move the PIC base register to
503 other registers. (The reload phase sometimes introduces such
504 insns.) */
505 else if (GET_CODE (orig) == PLUS
506 && GET_CODE (XEXP (orig, 0)) == REG
507 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
508#ifdef I386
509 /* Prevent the same register from being erroneously used
510 as both the base and index registers. */
511 && GET_CODE (XEXP (orig, 1)) == CONST
512#endif
513 && reg)
514 {
515 emit_move_insn (reg, XEXP (orig, 0));
516 XEXP (ptr_ref, 0) = reg;
517 }
518 return ptr_ref;
519}
520
521/* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
522
523 extern "C" { int f(); }
524 struct X { int f(); int g(); };
525 int X::f() { ::f(); }
526 int X::g() { ::f(); f();}
527
528 This is hairy. Both calls to "::f()" need to be indirect (i.e., to
529 appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
530 GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
531 defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
532 returns TRUE when called with "f", which means that
533 MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
534 indirect one as it should.
535
536 Our quick-n-dirty solution to this is to call the following
537 FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
538 FNAME -- the name of the function which we're calling -- is NOT a
539 mangled C++ name, AND if the current function being compiled is a
540 method, and if so, use an "external" or "indirect" call.
541
542 Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
543 has already indicated that the target is NOT indirect.
544
545 This conservative solution will sometimes make indirect calls where
546 it might have been possible to make direct ones.
547
548 FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
549 which in turns means we should create a stub for an indirect call.
550 */
551
552static int is_cplusplus = -1;
553
554static int
555func_name_maybe_scoped (fname)
556 const char *fname;
557{
558
559 if (is_cplusplus < 0)
560 is_cplusplus = (strcmp (lang_identify (), "cplusplus") == 0);
561
562 if (is_cplusplus)
563 {
564 /* If we have a method, then check whether the function we're trying to
565 call is a "C" function. If so, we should use an indirect call.
566
567 It turns out to be hard to tell whether "we have a method", since
568 static member functions have a TREE_CODE of FUNCTION_TYPE, as do
569 namespace-level non-member functions. So here, we always look for
570 an extern-"C"-like name, and make stubs for them no matter the
571 calling context. This is temporary, and leaves nagging suspicion
572 that improvements should be possible here. (I.e., I suspect that
573 it can still sometimes make stubs where it needn't.) */
574
575 /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
576 {
577 /* If fname is of the form "f__1X" or "f__Fv", it's C++. */
578 while (*fname == '_') ++fname; /* skip leading underscores */
579 while (*fname != 0)
580 {
581 if (fname[0] == '_' && fname[1] == '_'
582 && (fname[2] == 'F' || (fname[2] >= '0' && fname[2] <= '9')))
583 return 0;
584 ++fname;
585 }
586 /* Not a C++ mangled name: must be "C", in which case play safe. */
587 return 1;
588 }
589 }
590 return 0;
591}
592
593/* Transform TARGET (a MEM), which is a function call target, to the
594 corresponding symbol_stub if necessary. Return a new MEM. */
595
596rtx
597machopic_indirect_call_target (target)
598 rtx target;
599{
600 if (GET_CODE (target) != MEM)
601 return target;
602
603 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
604 {
605 enum machine_mode mode = GET_MODE (XEXP (target, 0));
606 const char *name = XSTR (XEXP (target, 0), 0);
607
608 if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name))
609 {
610 const char *stub_name = machopic_stub_name (name);
611
612 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
613 RTX_UNCHANGING_P (target) = 1;
614 }
615 }
616
617 return target;
618}
619
620rtx
621machopic_legitimize_pic_address (orig, mode, reg)
622 rtx orig, reg;
623 enum machine_mode mode;
624{
625 rtx pic_ref = orig;
626
627 if (! MACHOPIC_PURE)
628 return orig;
629
630 /* First handle a simple SYMBOL_REF or LABEL_REF */
631 if (GET_CODE (orig) == LABEL_REF
632 || (GET_CODE (orig) == SYMBOL_REF
633 ))
634 {
635 /* addr(foo) = &func+(foo-func) */
636 rtx pic_base;
637
638 orig = machopic_indirect_data_reference (orig, reg);
639
640 if (GET_CODE (orig) == PLUS
641 && GET_CODE (XEXP (orig, 0)) == REG)
642 {
643 if (reg == 0)
644 return force_reg (mode, orig);
645
646 emit_move_insn (reg, orig);
647 return reg;
648 }
649
650 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
651
652 if (GET_CODE (orig) == MEM)
653 {
654 if (reg == 0)
655 {
656 if (reload_in_progress)
657 abort ();
658 else
659 reg = gen_reg_rtx (Pmode);
660 }
661
662#ifdef HAVE_lo_sum
663 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
664 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
665 {
666 rtx offset = gen_rtx (CONST, Pmode,
667 gen_rtx (MINUS, Pmode,
668 XEXP (orig, 0), pic_base));
669#if defined (TARGET_TOC) /* i.e., PowerPC */
670 /* Generating a new reg may expose opportunities for
671 common subexpression elimination. */
672 rtx hi_sum_reg =
673 (reload_in_progress ? reg : gen_reg_rtx (SImode));
674
675 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
676 gen_rtx (PLUS, Pmode,
677 pic_offset_table_rtx,
678 gen_rtx (HIGH, Pmode, offset))));
679 emit_insn (gen_rtx (SET, VOIDmode, reg,
680 gen_rtx (MEM, GET_MODE (orig),
681 gen_rtx (LO_SUM, Pmode,
682 hi_sum_reg, offset))));
683 pic_ref = reg;
684
685#else
686 emit_insn (gen_rtx (USE, VOIDmode,
687 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
688
689 emit_insn (gen_rtx (SET, VOIDmode, reg,
690 gen_rtx (HIGH, Pmode,
691 gen_rtx (CONST, Pmode, offset))));
692 emit_insn (gen_rtx (SET, VOIDmode, reg,
693 gen_rtx (LO_SUM, Pmode, reg,
694 gen_rtx (CONST, Pmode, offset))));
695 pic_ref = gen_rtx (PLUS, Pmode,
696 pic_offset_table_rtx, reg);
697#endif
698 }
699 else
700#endif /* HAVE_lo_sum */
701 {
702 rtx pic = pic_offset_table_rtx;
703 if (GET_CODE (pic) != REG)
704 {
705 emit_move_insn (reg, pic);
706 pic = reg;
707 }
708#if 0
709 emit_insn (gen_rtx (USE, VOIDmode,
710 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
711#endif
712
713 pic_ref = gen_rtx (PLUS, Pmode,
714 pic,
715 gen_rtx (CONST, Pmode,
716 gen_rtx (MINUS, Pmode,
717 XEXP (orig, 0),
718 pic_base)));
719 }
720
721#if !defined (TARGET_TOC)
722 RTX_UNCHANGING_P (pic_ref) = 1;
723 emit_move_insn (reg, pic_ref);
724 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
725#endif
726 }
727 else
728 {
729
730#ifdef HAVE_lo_sum
731 if (GET_CODE (orig) == SYMBOL_REF
732 || GET_CODE (orig) == LABEL_REF)
733 {
734 rtx offset = gen_rtx (CONST, Pmode,
735 gen_rtx (MINUS, Pmode, orig, pic_base));
736#if defined (TARGET_TOC) /* i.e., PowerPC */
737 rtx hi_sum_reg;
738
739 if (reg == 0)
740 {
741 if (reload_in_progress)
742 abort ();
743 else
744 reg = gen_reg_rtx (SImode);
745 }
746
747 hi_sum_reg = reg;
748
749 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
750 gen_rtx (PLUS, Pmode,
751 pic_offset_table_rtx,
752 gen_rtx (HIGH, Pmode, offset))));
753 emit_insn (gen_rtx (SET, VOIDmode, reg,
754 gen_rtx (LO_SUM, Pmode,
755 hi_sum_reg, offset)));
756 pic_ref = reg;
757#else
758 emit_insn (gen_rtx (SET, VOIDmode, reg,
759 gen_rtx (HIGH, Pmode, offset)));
760 emit_insn (gen_rtx (SET, VOIDmode, reg,
761 gen_rtx (LO_SUM, Pmode, reg, offset)));
762 pic_ref = gen_rtx (PLUS, Pmode,
763 pic_offset_table_rtx, reg);
764#endif
765 }
766 else
767#endif /* HAVE_lo_sum */
768 {
769 if (GET_CODE (orig) == REG)
770 {
771 return orig;
772 }
773 else
774 {
775 rtx pic = pic_offset_table_rtx;
776 if (GET_CODE (pic) != REG)
777 {
778 emit_move_insn (reg, pic);
779 pic = reg;
780 }
781#if 0
782 emit_insn (gen_rtx (USE, VOIDmode,
783 pic_offset_table_rtx));
784#endif
785 pic_ref = gen_rtx (PLUS, Pmode,
786 pic,
787 gen_rtx (CONST, Pmode,
788 gen_rtx (MINUS, Pmode,
789 orig, pic_base)));
790 }
791 }
792 }
793
794 RTX_UNCHANGING_P (pic_ref) = 1;
795
796 if (GET_CODE (pic_ref) != REG)
797 {
798 if (reg != 0)
799 {
800 emit_move_insn (reg, pic_ref);
801 return reg;
802 }
803 else
804 {
805 return force_reg (mode, pic_ref);
806 }
807 }
808 else
809 {
810 return pic_ref;
811 }
812 }
813
814 else if (GET_CODE (orig) == SYMBOL_REF)
815 return orig;
816
817 else if (GET_CODE (orig) == PLUS
818 && (GET_CODE (XEXP (orig, 0)) == MEM
819 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
820 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
821 && XEXP (orig, 0) != pic_offset_table_rtx
822 && GET_CODE (XEXP (orig, 1)) != REG)
823
824 {
825 rtx base;
826 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
827
828 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
829 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
830 Pmode, (base == reg ? 0 : reg));
831 if (GET_CODE (orig) == CONST_INT)
832 {
ed8908e7 833 pic_ref = plus_constant (base, INTVAL (orig));
ee890fe2
SS
834 is_complex = 1;
835 }
836 else
ed8908e7 837 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
ee890fe2
SS
838
839 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
840 RTX_UNCHANGING_P (pic_ref) = 1;
841
842 if (reg && is_complex)
843 {
844 emit_move_insn (reg, pic_ref);
845 pic_ref = reg;
846 }
847 /* Likewise, should we set special REG_NOTEs here? */
848 }
849
850 else if (GET_CODE (orig) == CONST)
851 {
852 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
853 }
854
855 else if (GET_CODE (orig) == MEM
856 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
857 {
858 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
859
860 addr = gen_rtx (MEM, GET_MODE (orig), addr);
861 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
862 emit_move_insn (reg, addr);
863 pic_ref = reg;
864 }
865
866 return pic_ref;
867}
868
869
870void
871machopic_finish (asm_out_file)
872 FILE *asm_out_file;
873{
874 tree temp;
875
876 for (temp = machopic_stubs;
877 temp != NULL_TREE;
878 temp = TREE_CHAIN (temp))
879 {
880 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
881 char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
882 char *sym;
883 char *stub;
ee890fe2
SS
884
885 if (! TREE_USED (temp))
886 continue;
887
df56a27f 888 STRIP_NAME_ENCODING (sym_name, sym_name);
ee890fe2
SS
889
890 sym = alloca (strlen (sym_name) + 2);
891 if (sym_name[0] == '*' || sym_name[0] == '&')
892 strcpy (sym, sym_name + 1);
893 else if (sym_name[0] == '-' || sym_name[0] == '+')
894 strcpy (sym, sym_name);
895 else
896 sym[0] = '_', strcpy (sym + 1, sym_name);
897
898 stub = alloca (strlen (stub_name) + 2);
899 if (stub_name[0] == '*' || stub_name[0] == '&')
900 strcpy (stub, stub_name + 1);
901 else
902 stub[0] = '_', strcpy (stub + 1, stub_name);
903
904 machopic_output_stub (asm_out_file, sym, stub);
905 }
906
907 for (temp = machopic_non_lazy_pointers;
908 temp != NULL_TREE;
909 temp = TREE_CHAIN (temp))
910 {
911 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
912 char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
913#if 0
914 tree decl = lookup_name_darwin (TREE_VALUE (temp));
915#endif
916
917 if (! TREE_USED (temp))
918 continue;
919
920 if (machopic_ident_defined_p (TREE_VALUE (temp))
921#if 0 /* add back when we have private externs */
922 || (decl && DECL_PRIVATE_EXTERN (decl))
923#endif
924 )
925 {
926 data_section ();
927 assemble_align (UNITS_PER_WORD * BITS_PER_UNIT);
928 assemble_label (lazy_name);
929 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
930 GET_MODE_SIZE (Pmode), 1);
931 }
932 else
933 {
934 machopic_nl_symbol_ptr_section ();
935 assemble_name (asm_out_file, lazy_name);
936 fprintf (asm_out_file, ":\n");
937
938 fprintf (asm_out_file, "\t.indirect_symbol ");
939 assemble_name (asm_out_file, sym_name);
940 fprintf (asm_out_file, "\n");
941
942 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode), 1);
943 }
944 }
945}
946
947int
948machopic_operand_p (op)
949 rtx op;
950{
951 if (MACHOPIC_JUST_INDIRECT)
952 {
953 while (GET_CODE (op) == CONST)
954 op = XEXP (op, 0);
955
956 if (GET_CODE (op) == SYMBOL_REF)
957 return machopic_name_defined_p (XSTR (op, 0));
958 else
959 return 0;
960 }
961
962 while (GET_CODE (op) == CONST)
963 op = XEXP (op, 0);
964
965 if (GET_CODE (op) == MINUS
966 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
967 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
968 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
969 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
970 return 1;
971
972#if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
973 /* Without this statement, the compiler crashes while compiling enquire.c
974 when targetting PowerPC. It is not known why this code is not needed
975 when targetting other processors. */
976 else if (GET_CODE (op) == SYMBOL_REF
977 && (machopic_classify_name (XSTR (op, 0))
978 == MACHOPIC_DEFINED_FUNCTION))
979 {
980 return 1;
981 }
982#endif
983
984 return 0;
985}
df56a27f
SS
986
987/* This function records whether a given name corresponds to a defined
988 or undefined function or variable, for machopic_classify_ident to
989 use later. */
990
991void
992darwin_encode_section_info (decl)
993 tree decl;
994{
995 char code = '\0';
996 int defined = 0;
353e51f8
SS
997 rtx sym_ref;
998 char *orig_str, *new_str;
999 size_t len, new_len;
df56a27f
SS
1000
1001 if ((TREE_CODE (decl) == FUNCTION_DECL
1002 || TREE_CODE (decl) == VAR_DECL)
70bdc2ff 1003 && !DECL_EXTERNAL (decl)
df56a27f
SS
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);
353e51f8
SS
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);
df56a27f 1043 }
4e08ba6c
SS
1044 /* The non-lazy pointer list may have captured references to the
1045 old encoded name, change them. */
1046 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1047 update_stubs (XSTR (sym_ref, 0));
df56a27f
SS
1048}
1049
1050/* Scan the list of non-lazy pointers and update any recorded names whose
1051 stripped name matches the argument. */
1052
1053static void
1054update_non_lazy_ptrs (name)
1055 const char *name;
1056{
1057 char *name1, *name2;
1058 tree temp;
1059
1060 STRIP_NAME_ENCODING (name1, name);
1061
1062 for (temp = machopic_non_lazy_pointers;
1063 temp != NULL_TREE;
1064 temp = TREE_CHAIN (temp))
1065 {
1066 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1067
1068 if (*sym_name == '!')
1069 {
1070 STRIP_NAME_ENCODING (name2, sym_name);
1071 if (strcmp (name1, name2) == 0)
1072 {
1073 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1074 break;
1075 }
1076 }
1077 }
1078}
4e08ba6c
SS
1079
1080
1081/* Scan the list of stubs and update any recorded names whose
1082 stripped name matches the argument. */
1083
1084static void
1085update_stubs (name)
1086 const char *name;
1087{
1088 char *name1, *name2;
1089 tree temp;
1090
1091 STRIP_NAME_ENCODING (name1, name);
1092
1093 for (temp = machopic_stubs;
1094 temp != NULL_TREE;
1095 temp = TREE_CHAIN (temp))
1096 {
1097 char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1098
1099 if (*sym_name == '!')
1100 {
1101 STRIP_NAME_ENCODING (name2, sym_name);
1102 if (strcmp (name1, name2) == 0)
1103 {
1104 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1105 break;
1106 }
1107 }
1108 }
1109}
2cc07db4
RH
1110
1111void
1112machopic_asm_out_constructor (symbol, priority)
1113 rtx symbol;
1114 int priority ATTRIBUTE_UNUSED;
1115{
1116 if (flag_pic)
1117 mod_init_section ();
1118 else
1119 constructor_section ();
1120 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, 1);
1121
1122 if (!flag_pic)
1123 fprintf (asm_out_file, ".reference .constructors_used\n");
1124}
1125
1126void
1127machopic_asm_out_destructor (symbol, priority)
1128 rtx symbol;
1129 int priority ATTRIBUTE_UNUSED;
1130{
1131 if (flag_pic)
1132 mod_term_section ();
1133 else
1134 destructor_section ();
1135 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, 1);
1136
1137 if (!flag_pic)
1138 fprintf (asm_out_file, ".reference .destructors_used\n");
1139}
This page took 0.251642 seconds and 5 git commands to generate.