xref: /openbsd/gnu/usr.bin/gcc/gcc/config/darwin.c (revision c87b03e5)
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