darwin.c revision 117395
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
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"
38#include "function.h"
39#include "ggc.h"
40#include "langhooks.h"
41#include "tm_p.h"
42
43static int machopic_data_defined_p PARAMS ((const char *));
44static void update_non_lazy_ptrs PARAMS ((const char *));
45static void update_stubs PARAMS ((const char *));
46
47int
48name_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
66static GTY(()) tree machopic_defined_list;
67
68enum machopic_addr_class
69machopic_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
161enum machopic_addr_class
162machopic_classify_name (name)
163     const char *name;
164{
165  return machopic_classify_ident (get_identifier (name));
166}
167
168int
169machopic_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
183static int
184machopic_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
196int
197machopic_name_defined_p (name)
198     const char *name;
199{
200  return machopic_ident_defined_p (get_identifier (name));
201}
202
203void
204machopic_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
212void
213machopic_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
222static char function_base[32];
223
224static int current_pic_label_num;
225
226const char *
227machopic_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
256static 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
262const char *
263machopic_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
320static 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
325const char *
326machopic_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
385void
386machopic_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
414rtx
415machopic_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
535rtx
536machopic_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
563rtx
564machopic_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
813void
814machopic_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
889int
890machopic_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
921void
922darwin_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
987const char *
988darwin_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
997static void
998update_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
1028void
1029machopic_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
1061static void
1062update_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
1088void
1089machopic_select_section (exp, reloc, align)
1090     tree exp;
1091     int reloc;
1092     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1093{
1094  if (TREE_CODE (exp) == STRING_CST)
1095    {
1096      if (flag_writable_strings)
1097	data_section ();
1098      else if (TREE_STRING_LENGTH (exp) !=
1099	       strlen (TREE_STRING_POINTER (exp)) + 1)
1100	readonly_data_section ();
1101      else
1102	cstring_section ();
1103    }
1104  else if (TREE_CODE (exp) == INTEGER_CST
1105	   || TREE_CODE (exp) == REAL_CST)
1106    {
1107      tree size = TYPE_SIZE (TREE_TYPE (exp));
1108
1109      if (TREE_CODE (size) == INTEGER_CST &&
1110	  TREE_INT_CST_LOW (size) == 4 &&
1111	  TREE_INT_CST_HIGH (size) == 0)
1112	literal4_section ();
1113      else if (TREE_CODE (size) == INTEGER_CST &&
1114	       TREE_INT_CST_LOW (size) == 8 &&
1115	       TREE_INT_CST_HIGH (size) == 0)
1116	literal8_section ();
1117      else
1118	readonly_data_section ();
1119    }
1120  else if (TREE_CODE (exp) == CONSTRUCTOR
1121	   && TREE_TYPE (exp)
1122	   && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1123	   && TYPE_NAME (TREE_TYPE (exp)))
1124    {
1125      tree name = TYPE_NAME (TREE_TYPE (exp));
1126      if (TREE_CODE (name) == TYPE_DECL)
1127	name = DECL_NAME (name);
1128      if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1129	objc_constant_string_object_section ();
1130      else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1131	objc_string_object_section ();
1132      else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1133	{
1134	  if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1135	    const_data_section ();
1136	  else
1137	    readonly_data_section ();
1138	}
1139      else
1140	data_section ();
1141    }
1142  else if (TREE_CODE (exp) == VAR_DECL &&
1143	   DECL_NAME (exp) &&
1144	   TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1145	   IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1146	   !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1147    {
1148      const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1149
1150      if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1151	objc_cls_meth_section ();
1152      else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1153	objc_inst_meth_section ();
1154      else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1155	objc_cat_cls_meth_section ();
1156      else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1157	objc_cat_inst_meth_section ();
1158      else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1159	objc_class_vars_section ();
1160      else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1161	objc_instance_vars_section ();
1162      else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1163	objc_cat_cls_meth_section ();
1164      else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1165	objc_class_names_section ();
1166      else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1167	objc_meth_var_names_section ();
1168      else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1169	objc_meth_var_types_section ();
1170      else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1171	objc_cls_refs_section ();
1172      else if (!strncmp (name, "_OBJC_CLASS_", 12))
1173	objc_class_section ();
1174      else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1175	objc_meta_class_section ();
1176      else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1177	objc_category_section ();
1178      else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1179	objc_selector_refs_section ();
1180      else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1181	objc_selector_fixup_section ();
1182      else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1183	objc_symbols_section ();
1184      else if (!strncmp (name, "_OBJC_MODULES", 13))
1185	objc_module_info_section ();
1186      else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1187	objc_cat_inst_meth_section ();
1188      else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1189	objc_cat_cls_meth_section ();
1190      else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1191	objc_cat_cls_meth_section ();
1192      else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1193	objc_protocol_section ();
1194      else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1195	       && !TREE_SIDE_EFFECTS (exp))
1196	{
1197	  if (flag_pic && reloc)
1198	    const_data_section ();
1199	  else
1200	    readonly_data_section ();
1201	}
1202      else
1203	data_section ();
1204    }
1205  else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1206    {
1207      if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1208	const_data_section ();
1209      else
1210	readonly_data_section ();
1211    }
1212  else
1213    data_section ();
1214}
1215
1216/* This can be called with address expressions as "rtx".
1217   They must go in "const".  */
1218
1219void
1220machopic_select_rtx_section (mode, x, align)
1221     enum machine_mode mode;
1222     rtx x;
1223     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1224{
1225  if (GET_MODE_SIZE (mode) == 8)
1226    literal8_section ();
1227  else if (GET_MODE_SIZE (mode) == 4
1228	   && (GET_CODE (x) == CONST_INT
1229	       || GET_CODE (x) == CONST_DOUBLE))
1230    literal4_section ();
1231  else
1232    const_section ();
1233}
1234
1235void
1236machopic_asm_out_constructor (symbol, priority)
1237     rtx symbol;
1238     int priority ATTRIBUTE_UNUSED;
1239{
1240  if (flag_pic)
1241    mod_init_section ();
1242  else
1243    constructor_section ();
1244  assemble_align (POINTER_SIZE);
1245  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1246
1247  if (!flag_pic)
1248    fprintf (asm_out_file, ".reference .constructors_used\n");
1249}
1250
1251void
1252machopic_asm_out_destructor (symbol, priority)
1253     rtx symbol;
1254     int priority ATTRIBUTE_UNUSED;
1255{
1256  if (flag_pic)
1257    mod_term_section ();
1258  else
1259    destructor_section ();
1260  assemble_align (POINTER_SIZE);
1261  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1262
1263  if (!flag_pic)
1264    fprintf (asm_out_file, ".reference .destructors_used\n");
1265}
1266
1267void
1268darwin_globalize_label (stream, name)
1269     FILE *stream;
1270     const char *name;
1271{
1272  if (!!strncmp (name, "_OBJC_", 6))
1273    default_globalize_label (stream, name);
1274}
1275
1276/* Output a difference of two labels that will be an assembly time
1277   constant if the two labels are local.  (.long lab1-lab2 will be
1278   very different if lab1 is at the boundary between two sections; it
1279   will be relocated according to the second section, not the first,
1280   so one ends up with a difference between labels in different
1281   sections, which is bad in the dwarf2 eh context for instance.)  */
1282
1283static int darwin_dwarf_label_counter;
1284
1285void
1286darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1287     FILE *file;
1288     int size ATTRIBUTE_UNUSED;
1289     const char *lab1, *lab2;
1290{
1291  const char *p = lab1 + (lab1[0] == '*');
1292  int islocaldiff = (p[0] == 'L');
1293
1294  if (islocaldiff)
1295    fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1296  else
1297    fprintf (file, "\t%s\t", ".long");
1298  assemble_name (file, lab1);
1299  fprintf (file, "-");
1300  assemble_name (file, lab2);
1301  if (islocaldiff)
1302    fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1303}
1304
1305#include "gt-darwin.h"
1306
1307