1 /* Functions for generic Darwin as target machine for GNU C compiler.
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002
3 Free Software Foundation, Inc.
4 Contributed by Apple Computer Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, 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"
38 #include "function.h"
39 #include "ggc.h"
40 #include "langhooks.h"
41 #include "tm_p.h"
42
43 static int machopic_data_defined_p PARAMS ((const char *));
44 static void update_non_lazy_ptrs PARAMS ((const char *));
45 static void update_stubs PARAMS ((const char *));
46
47 int
name_needs_quotes(name)48 name_needs_quotes (name)
49 const char *name;
50 {
51 int c;
52 while ((c = *name++) != '\0')
53 if (! ISIDNUM (c))
54 return 1;
55 return 0;
56 }
57
58 /*
59 * flag_pic = 1 ... generate only indirections
60 * flag_pic = 2 ... generate indirections and pure code
61 */
62
63 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
64 reference, which will not be changed. */
65
66 static GTY(()) tree machopic_defined_list;
67
68 enum machopic_addr_class
machopic_classify_ident(ident)69 machopic_classify_ident (ident)
70 tree ident;
71 {
72 const char *name = IDENTIFIER_POINTER (ident);
73 int lprefix = (((name[0] == '*' || name[0] == '&')
74 && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
75 || ( name[0] == '_'
76 && name[1] == 'O'
77 && name[2] == 'B'
78 && name[3] == 'J'
79 && name[4] == 'C'
80 && name[5] == '_'));
81 tree temp;
82
83 if (name[0] != '!')
84 {
85 /* Here if no special encoding to be found. */
86 if (lprefix)
87 {
88 const char *name = IDENTIFIER_POINTER (ident);
89 int len = strlen (name);
90
91 if ((len > 5 && !strcmp (name + len - 5, "$stub"))
92 || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
93 return MACHOPIC_DEFINED_FUNCTION;
94 return MACHOPIC_DEFINED_DATA;
95 }
96
97 for (temp = machopic_defined_list;
98 temp != NULL_TREE;
99 temp = TREE_CHAIN (temp))
100 {
101 if (ident == TREE_VALUE (temp))
102 return MACHOPIC_DEFINED_DATA;
103 }
104
105 if (TREE_ASM_WRITTEN (ident))
106 return MACHOPIC_DEFINED_DATA;
107
108 return MACHOPIC_UNDEFINED;
109 }
110
111 else if (name[1] == 'D')
112 return MACHOPIC_DEFINED_DATA;
113
114 else if (name[1] == 'T')
115 return MACHOPIC_DEFINED_FUNCTION;
116
117 /* It is possible that someone is holding a "stale" name, which has
118 since been defined. See if there is a "defined" name (i.e,
119 different from NAME only in having a '!D_' or a '!T_' instead of
120 a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
121 that this identifier is defined. */
122 else if (name[1] == 'd' || name[1] == 't')
123 {
124 char *new_name;
125 new_name = (char *)alloca (strlen (name) + 1);
126 strcpy (new_name, name);
127 new_name[1] = (name[1] == 'd') ? 'D' : 'T';
128 if (maybe_get_identifier (new_name) != NULL)
129 return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
130 : MACHOPIC_DEFINED_FUNCTION;
131 }
132
133 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
134 {
135 if (ident == TREE_VALUE (temp))
136 {
137 if (name[1] == 'T')
138 return MACHOPIC_DEFINED_FUNCTION;
139 else
140 return MACHOPIC_DEFINED_DATA;
141 }
142 }
143
144 if (name[1] == 't' || name[1] == 'T')
145 {
146 if (lprefix)
147 return MACHOPIC_DEFINED_FUNCTION;
148 else
149 return MACHOPIC_UNDEFINED_FUNCTION;
150 }
151 else
152 {
153 if (lprefix)
154 return MACHOPIC_DEFINED_DATA;
155 else
156 return MACHOPIC_UNDEFINED_DATA;
157 }
158 }
159
160
161 enum machopic_addr_class
machopic_classify_name(name)162 machopic_classify_name (name)
163 const char *name;
164 {
165 return machopic_classify_ident (get_identifier (name));
166 }
167
168 int
machopic_ident_defined_p(ident)169 machopic_ident_defined_p (ident)
170 tree ident;
171 {
172 switch (machopic_classify_ident (ident))
173 {
174 case MACHOPIC_UNDEFINED:
175 case MACHOPIC_UNDEFINED_DATA:
176 case MACHOPIC_UNDEFINED_FUNCTION:
177 return 0;
178 default:
179 return 1;
180 }
181 }
182
183 static int
machopic_data_defined_p(name)184 machopic_data_defined_p (name)
185 const char *name;
186 {
187 switch (machopic_classify_ident (get_identifier (name)))
188 {
189 case MACHOPIC_DEFINED_DATA:
190 return 1;
191 default:
192 return 0;
193 }
194 }
195
196 int
machopic_name_defined_p(name)197 machopic_name_defined_p (name)
198 const char *name;
199 {
200 return machopic_ident_defined_p (get_identifier (name));
201 }
202
203 void
machopic_define_ident(ident)204 machopic_define_ident (ident)
205 tree ident;
206 {
207 if (!machopic_ident_defined_p (ident))
208 machopic_defined_list =
209 tree_cons (NULL_TREE, ident, machopic_defined_list);
210 }
211
212 void
machopic_define_name(name)213 machopic_define_name (name)
214 const char *name;
215 {
216 machopic_define_ident (get_identifier (name));
217 }
218
219 /* This is a static to make inline functions work. The rtx
220 representing the PIC base symbol always points to here. */
221
222 static char function_base[32];
223
224 static int current_pic_label_num;
225
226 const char *
machopic_function_base_name()227 machopic_function_base_name ()
228 {
229 static const char *name = NULL;
230 static const char *current_name;
231
232 current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
233
234 if (name != current_name)
235 {
236 current_function_uses_pic_offset_table = 1;
237
238 /* Save mucho space and time. Some of the C++ mangled names are over
239 700 characters long! Note that we produce a label containing a '-'
240 if the function we're compiling is an Objective-C method, as evinced
241 by the incredibly scientific test below. This is because code in
242 rs6000.c makes the same ugly test when loading the PIC reg. */
243
244 ++current_pic_label_num;
245 if (*current_name == '+' || *current_name == '-')
246 sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
247 else
248 sprintf (function_base, "*L%d$pb", current_pic_label_num);
249
250 name = current_name;
251 }
252
253 return function_base;
254 }
255
256 static GTY(()) tree machopic_non_lazy_pointers;
257
258 /* Return a non-lazy pointer name corresponding to the given name,
259 either by finding it in our list of pointer names, or by generating
260 a new one. */
261
262 const char *
machopic_non_lazy_ptr_name(name)263 machopic_non_lazy_ptr_name (name)
264 const char *name;
265 {
266 const char *temp_name;
267 tree temp, ident = get_identifier (name);
268
269 for (temp = machopic_non_lazy_pointers;
270 temp != NULL_TREE;
271 temp = TREE_CHAIN (temp))
272 {
273 if (ident == TREE_VALUE (temp))
274 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
275 }
276
277 name = darwin_strip_name_encoding (name);
278
279 /* Try again, but comparing names this time. */
280 for (temp = machopic_non_lazy_pointers;
281 temp != NULL_TREE;
282 temp = TREE_CHAIN (temp))
283 {
284 if (TREE_VALUE (temp))
285 {
286 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
287 temp_name = darwin_strip_name_encoding (temp_name);
288 if (strcmp (name, temp_name) == 0)
289 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
290 }
291 }
292
293 {
294 char *buffer;
295 tree ptr_name;
296
297 buffer = alloca (strlen (name) + 20);
298
299 strcpy (buffer, "&L");
300 if (name[0] == '*')
301 strcat (buffer, name+1);
302 else
303 {
304 strcat (buffer, "_");
305 strcat (buffer, name);
306 }
307
308 strcat (buffer, "$non_lazy_ptr");
309 ptr_name = get_identifier (buffer);
310
311 machopic_non_lazy_pointers
312 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
313
314 TREE_USED (machopic_non_lazy_pointers) = 0;
315
316 return IDENTIFIER_POINTER (ptr_name);
317 }
318 }
319
320 static GTY(()) tree machopic_stubs;
321
322 /* Return the name of the stub corresponding to the given name,
323 generating a new stub name if necessary. */
324
325 const char *
machopic_stub_name(name)326 machopic_stub_name (name)
327 const char *name;
328 {
329 tree temp, ident = get_identifier (name);
330 const char *tname;
331
332 for (temp = machopic_stubs;
333 temp != NULL_TREE;
334 temp = TREE_CHAIN (temp))
335 {
336 if (ident == TREE_VALUE (temp))
337 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
338 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
339 if (strcmp (name, tname) == 0)
340 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
341 /* A library call name might not be section-encoded yet, so try
342 it against a stripped name. */
343 if (name[0] != '!'
344 && tname[0] == '!'
345 && strcmp (name, tname + 4) == 0)
346 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
347 }
348
349 name = darwin_strip_name_encoding (name);
350
351 {
352 char *buffer;
353 tree ptr_name;
354 int needs_quotes = name_needs_quotes (name);
355
356 buffer = alloca (strlen (name) + 20);
357
358 if (needs_quotes)
359 strcpy (buffer, "&\"L");
360 else
361 strcpy (buffer, "&L");
362 if (name[0] == '*')
363 {
364 strcat (buffer, name+1);
365 }
366 else
367 {
368 strcat (buffer, "_");
369 strcat (buffer, name);
370 }
371
372 if (needs_quotes)
373 strcat (buffer, "$stub\"");
374 else
375 strcat (buffer, "$stub");
376 ptr_name = get_identifier (buffer);
377
378 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
379 TREE_USED (machopic_stubs) = 0;
380
381 return IDENTIFIER_POINTER (ptr_name);
382 }
383 }
384
385 void
machopic_validate_stub_or_non_lazy_ptr(name,validate_stub)386 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
387 const char *name;
388 int validate_stub;
389 {
390 const char *real_name;
391 tree temp, ident = get_identifier (name), id2;
392
393 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
394 temp != NULL_TREE;
395 temp = TREE_CHAIN (temp))
396 if (ident == TREE_PURPOSE (temp))
397 {
398 /* Mark both the stub or non-lazy pointer as well as the
399 original symbol as being referenced. */
400 TREE_USED (temp) = 1;
401 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
402 TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
403 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
404 real_name = darwin_strip_name_encoding (real_name);
405 id2 = maybe_get_identifier (real_name);
406 if (id2)
407 TREE_SYMBOL_REFERENCED (id2) = 1;
408 }
409 }
410
411 /* Transform ORIG, which may be any data source, to the corresponding
412 source using indirections. */
413
414 rtx
machopic_indirect_data_reference(orig,reg)415 machopic_indirect_data_reference (orig, reg)
416 rtx orig, reg;
417 {
418 rtx ptr_ref = orig;
419
420 if (! MACHOPIC_INDIRECT)
421 return orig;
422
423 if (GET_CODE (orig) == SYMBOL_REF)
424 {
425 const char *name = XSTR (orig, 0);
426
427 if (machopic_data_defined_p (name))
428 {
429 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
430 rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
431 machopic_function_base_name ());
432 rtx offset = gen_rtx (CONST, Pmode,
433 gen_rtx (MINUS, Pmode, orig, pic_base));
434 #endif
435
436 #if defined (TARGET_TOC) /* i.e., PowerPC */
437 rtx hi_sum_reg = reg;
438
439 if (reg == NULL)
440 abort ();
441
442 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
443 gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
444 gen_rtx (HIGH, Pmode, offset))));
445 emit_insn (gen_rtx (SET, Pmode, reg,
446 gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
447
448 orig = reg;
449 #else
450 #if defined (HAVE_lo_sum)
451 if (reg == 0) abort ();
452
453 emit_insn (gen_rtx (SET, VOIDmode, reg,
454 gen_rtx (HIGH, Pmode, offset)));
455 emit_insn (gen_rtx (SET, VOIDmode, reg,
456 gen_rtx (LO_SUM, Pmode, reg, offset)));
457 emit_insn (gen_rtx (USE, VOIDmode,
458 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
459
460 orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
461 #endif
462 #endif
463 return orig;
464 }
465
466 ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
467 machopic_non_lazy_ptr_name (name));
468
469 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
470 RTX_UNCHANGING_P (ptr_ref) = 1;
471
472 return ptr_ref;
473 }
474 else if (GET_CODE (orig) == CONST)
475 {
476 rtx base, result;
477
478 /* legitimize both operands of the PLUS */
479 if (GET_CODE (XEXP (orig, 0)) == PLUS)
480 {
481 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
482 reg);
483 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
484 (base == reg ? 0 : reg));
485 }
486 else
487 return orig;
488
489 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
490 result = plus_constant (base, INTVAL (orig));
491 else
492 result = gen_rtx (PLUS, Pmode, base, orig);
493
494 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
495 {
496 if (reg)
497 {
498 emit_move_insn (reg, result);
499 result = reg;
500 }
501 else
502 {
503 result = force_reg (GET_MODE (result), result);
504 }
505 }
506
507 return result;
508
509 }
510 else if (GET_CODE (orig) == MEM)
511 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
512 /* When the target is i386, this code prevents crashes due to the
513 compiler's ignorance on how to move the PIC base register to
514 other registers. (The reload phase sometimes introduces such
515 insns.) */
516 else if (GET_CODE (orig) == PLUS
517 && GET_CODE (XEXP (orig, 0)) == REG
518 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
519 #ifdef I386
520 /* Prevent the same register from being erroneously used
521 as both the base and index registers. */
522 && GET_CODE (XEXP (orig, 1)) == CONST
523 #endif
524 && reg)
525 {
526 emit_move_insn (reg, XEXP (orig, 0));
527 XEXP (ptr_ref, 0) = reg;
528 }
529 return ptr_ref;
530 }
531
532 /* Transform TARGET (a MEM), which is a function call target, to the
533 corresponding symbol_stub if necessary. Return a new MEM. */
534
535 rtx
machopic_indirect_call_target(target)536 machopic_indirect_call_target (target)
537 rtx target;
538 {
539 if (GET_CODE (target) != MEM)
540 return target;
541
542 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
543 {
544 enum machine_mode mode = GET_MODE (XEXP (target, 0));
545 const char *name = XSTR (XEXP (target, 0), 0);
546
547 /* If the name is already defined, we need do nothing. */
548 if (name[0] == '!' && name[1] == 'T')
549 return target;
550
551 if (!machopic_name_defined_p (name))
552 {
553 const char *stub_name = machopic_stub_name (name);
554
555 XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
556 RTX_UNCHANGING_P (target) = 1;
557 }
558 }
559
560 return target;
561 }
562
563 rtx
machopic_legitimize_pic_address(orig,mode,reg)564 machopic_legitimize_pic_address (orig, mode, reg)
565 rtx orig, reg;
566 enum machine_mode mode;
567 {
568 rtx pic_ref = orig;
569
570 if (! MACHOPIC_PURE)
571 return orig;
572
573 /* First handle a simple SYMBOL_REF or LABEL_REF */
574 if (GET_CODE (orig) == LABEL_REF
575 || (GET_CODE (orig) == SYMBOL_REF
576 ))
577 {
578 /* addr(foo) = &func+(foo-func) */
579 rtx pic_base;
580
581 orig = machopic_indirect_data_reference (orig, reg);
582
583 if (GET_CODE (orig) == PLUS
584 && GET_CODE (XEXP (orig, 0)) == REG)
585 {
586 if (reg == 0)
587 return force_reg (mode, orig);
588
589 emit_move_insn (reg, orig);
590 return reg;
591 }
592
593 pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
594
595 if (GET_CODE (orig) == MEM)
596 {
597 if (reg == 0)
598 {
599 if (reload_in_progress)
600 abort ();
601 else
602 reg = gen_reg_rtx (Pmode);
603 }
604
605 #ifdef HAVE_lo_sum
606 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
607 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
608 {
609 rtx offset = gen_rtx (CONST, Pmode,
610 gen_rtx (MINUS, Pmode,
611 XEXP (orig, 0), pic_base));
612 #if defined (TARGET_TOC) /* i.e., PowerPC */
613 /* Generating a new reg may expose opportunities for
614 common subexpression elimination. */
615 rtx hi_sum_reg =
616 (reload_in_progress ? reg : gen_reg_rtx (SImode));
617
618 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
619 gen_rtx (PLUS, Pmode,
620 pic_offset_table_rtx,
621 gen_rtx (HIGH, Pmode, offset))));
622 emit_insn (gen_rtx (SET, VOIDmode, reg,
623 gen_rtx (MEM, GET_MODE (orig),
624 gen_rtx (LO_SUM, Pmode,
625 hi_sum_reg, offset))));
626 pic_ref = reg;
627
628 #else
629 emit_insn (gen_rtx (USE, VOIDmode,
630 gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
631
632 emit_insn (gen_rtx (SET, VOIDmode, reg,
633 gen_rtx (HIGH, Pmode,
634 gen_rtx (CONST, Pmode, offset))));
635 emit_insn (gen_rtx (SET, VOIDmode, reg,
636 gen_rtx (LO_SUM, Pmode, reg,
637 gen_rtx (CONST, Pmode, offset))));
638 pic_ref = gen_rtx (PLUS, Pmode,
639 pic_offset_table_rtx, reg);
640 #endif
641 }
642 else
643 #endif /* HAVE_lo_sum */
644 {
645 rtx pic = pic_offset_table_rtx;
646 if (GET_CODE (pic) != REG)
647 {
648 emit_move_insn (reg, pic);
649 pic = reg;
650 }
651 #if 0
652 emit_insn (gen_rtx (USE, VOIDmode,
653 gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
654 #endif
655
656 pic_ref = gen_rtx (PLUS, Pmode,
657 pic,
658 gen_rtx (CONST, Pmode,
659 gen_rtx (MINUS, Pmode,
660 XEXP (orig, 0),
661 pic_base)));
662 }
663
664 #if !defined (TARGET_TOC)
665 emit_move_insn (reg, pic_ref);
666 pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
667 #endif
668 RTX_UNCHANGING_P (pic_ref) = 1;
669 }
670 else
671 {
672
673 #ifdef HAVE_lo_sum
674 if (GET_CODE (orig) == SYMBOL_REF
675 || GET_CODE (orig) == LABEL_REF)
676 {
677 rtx offset = gen_rtx (CONST, Pmode,
678 gen_rtx (MINUS, Pmode, orig, pic_base));
679 #if defined (TARGET_TOC) /* i.e., PowerPC */
680 rtx hi_sum_reg;
681
682 if (reg == 0)
683 {
684 if (reload_in_progress)
685 abort ();
686 else
687 reg = gen_reg_rtx (SImode);
688 }
689
690 hi_sum_reg = reg;
691
692 emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
693 gen_rtx (PLUS, Pmode,
694 pic_offset_table_rtx,
695 gen_rtx (HIGH, Pmode, offset))));
696 emit_insn (gen_rtx (SET, VOIDmode, reg,
697 gen_rtx (LO_SUM, Pmode,
698 hi_sum_reg, offset)));
699 pic_ref = reg;
700 RTX_UNCHANGING_P (pic_ref) = 1;
701 #else
702 emit_insn (gen_rtx (SET, VOIDmode, reg,
703 gen_rtx (HIGH, Pmode, offset)));
704 emit_insn (gen_rtx (SET, VOIDmode, reg,
705 gen_rtx (LO_SUM, Pmode, reg, offset)));
706 pic_ref = gen_rtx (PLUS, Pmode,
707 pic_offset_table_rtx, reg);
708 RTX_UNCHANGING_P (pic_ref) = 1;
709 #endif
710 }
711 else
712 #endif /* HAVE_lo_sum */
713 {
714 if (GET_CODE (orig) == REG)
715 {
716 return orig;
717 }
718 else
719 {
720 rtx pic = pic_offset_table_rtx;
721 if (GET_CODE (pic) != REG)
722 {
723 emit_move_insn (reg, pic);
724 pic = reg;
725 }
726 #if 0
727 emit_insn (gen_rtx (USE, VOIDmode,
728 pic_offset_table_rtx));
729 #endif
730 pic_ref = gen_rtx (PLUS, Pmode,
731 pic,
732 gen_rtx (CONST, Pmode,
733 gen_rtx (MINUS, Pmode,
734 orig, pic_base)));
735 }
736 }
737 }
738
739 if (GET_CODE (pic_ref) != REG)
740 {
741 if (reg != 0)
742 {
743 emit_move_insn (reg, pic_ref);
744 return reg;
745 }
746 else
747 {
748 return force_reg (mode, pic_ref);
749 }
750 }
751 else
752 {
753 return pic_ref;
754 }
755 }
756
757 else if (GET_CODE (orig) == SYMBOL_REF)
758 return orig;
759
760 else if (GET_CODE (orig) == PLUS
761 && (GET_CODE (XEXP (orig, 0)) == MEM
762 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
763 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
764 && XEXP (orig, 0) != pic_offset_table_rtx
765 && GET_CODE (XEXP (orig, 1)) != REG)
766
767 {
768 rtx base;
769 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
770
771 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
772 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
773 Pmode, (base == reg ? 0 : reg));
774 if (GET_CODE (orig) == CONST_INT)
775 {
776 pic_ref = plus_constant (base, INTVAL (orig));
777 is_complex = 1;
778 }
779 else
780 pic_ref = gen_rtx (PLUS, Pmode, base, orig);
781
782 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
783 RTX_UNCHANGING_P (pic_ref) = 1;
784
785 if (reg && is_complex)
786 {
787 emit_move_insn (reg, pic_ref);
788 pic_ref = reg;
789 }
790 /* Likewise, should we set special REG_NOTEs here? */
791 }
792
793 else if (GET_CODE (orig) == CONST)
794 {
795 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
796 }
797
798 else if (GET_CODE (orig) == MEM
799 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
800 {
801 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
802
803 addr = gen_rtx (MEM, GET_MODE (orig), addr);
804 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
805 emit_move_insn (reg, addr);
806 pic_ref = reg;
807 }
808
809 return pic_ref;
810 }
811
812
813 void
machopic_finish(asm_out_file)814 machopic_finish (asm_out_file)
815 FILE *asm_out_file;
816 {
817 tree temp;
818
819 for (temp = machopic_stubs;
820 temp != NULL_TREE;
821 temp = TREE_CHAIN (temp))
822 {
823 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
824 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
825 char *sym;
826 char *stub;
827
828 if (! TREE_USED (temp))
829 continue;
830
831 /* If the symbol is actually defined, we don't need a stub. */
832 if (sym_name[0] == '!' && sym_name[1] == 'T')
833 continue;
834
835 sym_name = darwin_strip_name_encoding (sym_name);
836
837 sym = alloca (strlen (sym_name) + 2);
838 if (sym_name[0] == '*' || sym_name[0] == '&')
839 strcpy (sym, sym_name + 1);
840 else if (sym_name[0] == '-' || sym_name[0] == '+')
841 strcpy (sym, sym_name);
842 else
843 sym[0] = '_', strcpy (sym + 1, sym_name);
844
845 stub = alloca (strlen (stub_name) + 2);
846 if (stub_name[0] == '*' || stub_name[0] == '&')
847 strcpy (stub, stub_name + 1);
848 else
849 stub[0] = '_', strcpy (stub + 1, stub_name);
850
851 machopic_output_stub (asm_out_file, sym, stub);
852 }
853
854 for (temp = machopic_non_lazy_pointers;
855 temp != NULL_TREE;
856 temp = TREE_CHAIN (temp))
857 {
858 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
859 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
860
861 if (! TREE_USED (temp))
862 continue;
863
864 if (machopic_ident_defined_p (TREE_VALUE (temp)))
865 {
866 data_section ();
867 assemble_align (GET_MODE_ALIGNMENT (Pmode));
868 assemble_label (lazy_name);
869 assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
870 GET_MODE_SIZE (Pmode),
871 GET_MODE_ALIGNMENT (Pmode), 1);
872 }
873 else
874 {
875 machopic_nl_symbol_ptr_section ();
876 assemble_name (asm_out_file, lazy_name);
877 fprintf (asm_out_file, ":\n");
878
879 fprintf (asm_out_file, "\t.indirect_symbol ");
880 assemble_name (asm_out_file, sym_name);
881 fprintf (asm_out_file, "\n");
882
883 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
884 GET_MODE_ALIGNMENT (Pmode), 1);
885 }
886 }
887 }
888
889 int
machopic_operand_p(op)890 machopic_operand_p (op)
891 rtx op;
892 {
893 if (MACHOPIC_JUST_INDIRECT)
894 {
895 while (GET_CODE (op) == CONST)
896 op = XEXP (op, 0);
897
898 if (GET_CODE (op) == SYMBOL_REF)
899 return machopic_name_defined_p (XSTR (op, 0));
900 else
901 return 0;
902 }
903
904 while (GET_CODE (op) == CONST)
905 op = XEXP (op, 0);
906
907 if (GET_CODE (op) == MINUS
908 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
909 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
910 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
911 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
912 return 1;
913
914 return 0;
915 }
916
917 /* This function records whether a given name corresponds to a defined
918 or undefined function or variable, for machopic_classify_ident to
919 use later. */
920
921 void
darwin_encode_section_info(decl,first)922 darwin_encode_section_info (decl, first)
923 tree decl;
924 int first ATTRIBUTE_UNUSED;
925 {
926 char code = '\0';
927 int defined = 0;
928 rtx sym_ref;
929 const char *orig_str;
930 char *new_str;
931 size_t len, new_len;
932
933 if ((TREE_CODE (decl) == FUNCTION_DECL
934 || TREE_CODE (decl) == VAR_DECL)
935 && !DECL_EXTERNAL (decl)
936 && ((TREE_STATIC (decl)
937 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
938 || (DECL_INITIAL (decl)
939 && DECL_INITIAL (decl) != error_mark_node)))
940 defined = 1;
941
942 if (TREE_CODE (decl) == FUNCTION_DECL)
943 code = (defined ? 'T' : 't');
944 else if (TREE_CODE (decl) == VAR_DECL)
945 code = (defined ? 'D' : 'd');
946
947 if (code == '\0')
948 return;
949
950 sym_ref = XEXP (DECL_RTL (decl), 0);
951 orig_str = XSTR (sym_ref, 0);
952 len = strlen (orig_str) + 1;
953
954 if (orig_str[0] == '!')
955 {
956 /* Already encoded; see if we need to change it. */
957 if (code == orig_str[1])
958 return;
959 /* Yes, tweak a copy of the name and put it in a new string. */
960 new_str = alloca (len);
961 memcpy (new_str, orig_str, len);
962 new_str[1] = code;
963 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
964 }
965 else
966 {
967 /* Add the encoding. */
968 new_len = len + 4;
969 new_str = alloca (new_len);
970 new_str[0] = '!';
971 new_str[1] = code;
972 new_str[2] = '_';
973 new_str[3] = '_';
974 memcpy (new_str + 4, orig_str, len);
975 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
976 }
977 /* The non-lazy pointer list may have captured references to the
978 old encoded name, change them. */
979 if (TREE_CODE (decl) == VAR_DECL)
980 update_non_lazy_ptrs (XSTR (sym_ref, 0));
981 else
982 update_stubs (XSTR (sym_ref, 0));
983 }
984
985 /* Undo the effects of the above. */
986
987 const char *
darwin_strip_name_encoding(str)988 darwin_strip_name_encoding (str)
989 const char *str;
990 {
991 return str[0] == '!' ? str + 4 : str;
992 }
993
994 /* Scan the list of non-lazy pointers and update any recorded names whose
995 stripped name matches the argument. */
996
997 static void
update_non_lazy_ptrs(name)998 update_non_lazy_ptrs (name)
999 const char *name;
1000 {
1001 const char *name1, *name2;
1002 tree temp;
1003
1004 name1 = darwin_strip_name_encoding (name);
1005
1006 for (temp = machopic_non_lazy_pointers;
1007 temp != NULL_TREE;
1008 temp = TREE_CHAIN (temp))
1009 {
1010 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1011
1012 if (*sym_name == '!')
1013 {
1014 name2 = darwin_strip_name_encoding (sym_name);
1015 if (strcmp (name1, name2) == 0)
1016 {
1017 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1018 break;
1019 }
1020 }
1021 }
1022 }
1023
1024 /* Function NAME is being defined, and its label has just been output.
1025 If there's already a reference to a stub for this function, we can
1026 just emit the stub label now and we don't bother emitting the stub later. */
1027
1028 void
machopic_output_possible_stub_label(file,name)1029 machopic_output_possible_stub_label (file, name)
1030 FILE *file;
1031 const char *name;
1032 {
1033 tree temp;
1034
1035
1036 /* Ensure we're looking at a section-encoded name. */
1037 if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1038 return;
1039
1040 for (temp = machopic_stubs;
1041 temp != NULL_TREE;
1042 temp = TREE_CHAIN (temp))
1043 {
1044 const char *sym_name;
1045
1046 sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1047 if (sym_name[0] == '!' && sym_name[1] == 'T'
1048 && ! strcmp (name+2, sym_name+2))
1049 {
1050 ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1051 /* Avoid generating a stub for this. */
1052 TREE_USED (temp) = 0;
1053 break;
1054 }
1055 }
1056 }
1057
1058 /* Scan the list of stubs and update any recorded names whose
1059 stripped name matches the argument. */
1060
1061 static void
update_stubs(name)1062 update_stubs (name)
1063 const char *name;
1064 {
1065 const char *name1, *name2;
1066 tree temp;
1067
1068 name1 = darwin_strip_name_encoding (name);
1069
1070 for (temp = machopic_stubs;
1071 temp != NULL_TREE;
1072 temp = TREE_CHAIN (temp))
1073 {
1074 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1075
1076 if (*sym_name == '!')
1077 {
1078 name2 = darwin_strip_name_encoding (sym_name);
1079 if (strcmp (name1, name2) == 0)
1080 {
1081 IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1082 break;
1083 }
1084 }
1085 }
1086 }
1087
1088 void
machopic_select_section(exp,reloc,align)1089 machopic_select_section (exp, reloc, align)
1090 tree exp;
1091 int reloc;
1092 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1093 {
1094 void (*base_function)(void);
1095
1096 if (decl_readonly_section (exp, reloc))
1097 base_function = readonly_data_section;
1098 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1099 base_function = const_data_section;
1100 else
1101 base_function = data_section;
1102
1103 if (TREE_CODE (exp) == STRING_CST
1104 && TREE_STRING_LENGTH (exp) == strlen (TREE_STRING_POINTER (exp)) + 1
1105 && ! flag_writable_strings)
1106 cstring_section ();
1107 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1108 && flag_merge_constants)
1109 {
1110 tree size = TYPE_SIZE (TREE_TYPE (exp));
1111
1112 if (TREE_CODE (size) == INTEGER_CST &&
1113 TREE_INT_CST_LOW (size) == 4 &&
1114 TREE_INT_CST_HIGH (size) == 0)
1115 literal4_section ();
1116 else if (TREE_CODE (size) == INTEGER_CST &&
1117 TREE_INT_CST_LOW (size) == 8 &&
1118 TREE_INT_CST_HIGH (size) == 0)
1119 literal8_section ();
1120 else
1121 base_function ();
1122 }
1123 else if (TREE_CODE (exp) == CONSTRUCTOR
1124 && TREE_TYPE (exp)
1125 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1126 && TYPE_NAME (TREE_TYPE (exp)))
1127 {
1128 tree name = TYPE_NAME (TREE_TYPE (exp));
1129 if (TREE_CODE (name) == TYPE_DECL)
1130 name = DECL_NAME (name);
1131 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1132 objc_constant_string_object_section ();
1133 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1134 objc_string_object_section ();
1135 else
1136 base_function ();
1137 }
1138 else if (TREE_CODE (exp) == VAR_DECL &&
1139 DECL_NAME (exp) &&
1140 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1141 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1142 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1143 {
1144 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1145
1146 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1147 objc_cls_meth_section ();
1148 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1149 objc_inst_meth_section ();
1150 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1151 objc_cat_cls_meth_section ();
1152 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1153 objc_cat_inst_meth_section ();
1154 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1155 objc_class_vars_section ();
1156 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1157 objc_instance_vars_section ();
1158 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1159 objc_cat_cls_meth_section ();
1160 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1161 objc_class_names_section ();
1162 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1163 objc_meth_var_names_section ();
1164 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1165 objc_meth_var_types_section ();
1166 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1167 objc_cls_refs_section ();
1168 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1169 objc_class_section ();
1170 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1171 objc_meta_class_section ();
1172 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1173 objc_category_section ();
1174 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1175 objc_selector_refs_section ();
1176 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1177 objc_selector_fixup_section ();
1178 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1179 objc_symbols_section ();
1180 else if (!strncmp (name, "_OBJC_MODULES", 13))
1181 objc_module_info_section ();
1182 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1183 objc_cat_inst_meth_section ();
1184 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1185 objc_cat_cls_meth_section ();
1186 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1187 objc_cat_cls_meth_section ();
1188 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1189 objc_protocol_section ();
1190 else
1191 base_function ();
1192 }
1193 else
1194 base_function ();
1195 }
1196
1197 /* This can be called with address expressions as "rtx".
1198 They must go in "const". */
1199
1200 void
machopic_select_rtx_section(mode,x,align)1201 machopic_select_rtx_section (mode, x, align)
1202 enum machine_mode mode;
1203 rtx x;
1204 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1205 {
1206 if (GET_MODE_SIZE (mode) == 8)
1207 literal8_section ();
1208 else if (GET_MODE_SIZE (mode) == 4
1209 && (GET_CODE (x) == CONST_INT
1210 || GET_CODE (x) == CONST_DOUBLE))
1211 literal4_section ();
1212 else
1213 const_section ();
1214 }
1215
1216 void
machopic_asm_out_constructor(symbol,priority)1217 machopic_asm_out_constructor (symbol, priority)
1218 rtx symbol;
1219 int priority ATTRIBUTE_UNUSED;
1220 {
1221 if (flag_pic)
1222 mod_init_section ();
1223 else
1224 constructor_section ();
1225 assemble_align (POINTER_SIZE);
1226 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1227
1228 if (!flag_pic)
1229 fprintf (asm_out_file, ".reference .constructors_used\n");
1230 }
1231
1232 void
machopic_asm_out_destructor(symbol,priority)1233 machopic_asm_out_destructor (symbol, priority)
1234 rtx symbol;
1235 int priority ATTRIBUTE_UNUSED;
1236 {
1237 if (flag_pic)
1238 mod_term_section ();
1239 else
1240 destructor_section ();
1241 assemble_align (POINTER_SIZE);
1242 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1243
1244 if (!flag_pic)
1245 fprintf (asm_out_file, ".reference .destructors_used\n");
1246 }
1247
1248 void
darwin_globalize_label(stream,name)1249 darwin_globalize_label (stream, name)
1250 FILE *stream;
1251 const char *name;
1252 {
1253 if (!!strncmp (name, "_OBJC_", 6))
1254 default_globalize_label (stream, name);
1255 }
1256
1257 /* Output a difference of two labels that will be an assembly time
1258 constant if the two labels are local. (.long lab1-lab2 will be
1259 very different if lab1 is at the boundary between two sections; it
1260 will be relocated according to the second section, not the first,
1261 so one ends up with a difference between labels in different
1262 sections, which is bad in the dwarf2 eh context for instance.) */
1263
1264 static int darwin_dwarf_label_counter;
1265
1266 void
darwin_asm_output_dwarf_delta(file,size,lab1,lab2)1267 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1268 FILE *file;
1269 int size ATTRIBUTE_UNUSED;
1270 const char *lab1, *lab2;
1271 {
1272 const char *p = lab1 + (lab1[0] == '*');
1273 int islocaldiff = (p[0] == 'L');
1274
1275 if (islocaldiff)
1276 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1277 else
1278 fprintf (file, "\t%s\t", ".long");
1279 assemble_name (file, lab1);
1280 fprintf (file, "-");
1281 assemble_name (file, lab2);
1282 if (islocaldiff)
1283 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1284 }
1285
1286 #include "gt-darwin.h"
1287
1288