190075Sobrien/* Functions for generic Darwin as target machine for GNU C compiler.
2169689Skan   Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
3169689Skan   2005
490075Sobrien   Free Software Foundation, Inc.
590075Sobrien   Contributed by Apple Computer Inc.
690075Sobrien
7132718SkanThis file is part of GCC.
890075Sobrien
9132718SkanGCC is free software; you can redistribute it and/or modify
1090075Sobrienit under the terms of the GNU General Public License as published by
1190075Sobrienthe Free Software Foundation; either version 2, or (at your option)
1290075Sobrienany later version.
1390075Sobrien
14132718SkanGCC is distributed in the hope that it will be useful,
1590075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1690075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1790075SobrienGNU General Public License for more details.
1890075Sobrien
1990075SobrienYou should have received a copy of the GNU General Public License
20132718Skanalong with GCC; see the file COPYING.  If not, write to
21169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
22169689SkanBoston, MA 02110-1301, USA.  */
2390075Sobrien
2490075Sobrien#include "config.h"
2590075Sobrien#include "system.h"
26132718Skan#include "coretypes.h"
27132718Skan#include "tm.h"
2890075Sobrien#include "rtl.h"
2990075Sobrien#include "regs.h"
3090075Sobrien#include "hard-reg-set.h"
3190075Sobrien#include "real.h"
3290075Sobrien#include "insn-config.h"
3390075Sobrien#include "conditions.h"
3490075Sobrien#include "insn-flags.h"
3590075Sobrien#include "output.h"
3690075Sobrien#include "insn-attr.h"
3790075Sobrien#include "flags.h"
3890075Sobrien#include "tree.h"
3990075Sobrien#include "expr.h"
4090075Sobrien#include "reload.h"
4190075Sobrien#include "function.h"
4290075Sobrien#include "ggc.h"
4390075Sobrien#include "langhooks.h"
44169689Skan#include "target.h"
45117395Skan#include "tm_p.h"
46169689Skan#include "toplev.h"
47169689Skan#include "hashtab.h"
4890075Sobrien
49169689Skan/* Darwin supports a feature called fix-and-continue, which is used
50169689Skan   for rapid turn around debugging.  When code is compiled with the
51169689Skan   -mfix-and-continue flag, two changes are made to the generated code
52169689Skan   that allow the system to do things that it would normally not be
53169689Skan   able to do easily.  These changes allow gdb to load in
54169689Skan   recompilation of a translation unit that has been changed into a
55169689Skan   running program and replace existing functions and methods of that
56169689Skan   translation unit with versions of those functions and methods
57169689Skan   from the newly compiled translation unit.  The new functions access
58169689Skan   the existing static symbols from the old translation unit, if the
59169689Skan   symbol existed in the unit to be replaced, and from the new
60169689Skan   translation unit, otherwise.
6190075Sobrien
62169689Skan   The changes are to insert 5 nops at the beginning of all functions
63169689Skan   and to use indirection to get at static symbols.  The 5 nops
64169689Skan   are required by consumers of the generated code.  Currently, gdb
65169689Skan   uses this to patch in a jump to the overriding function, this
66169689Skan   allows all uses of the old name to forward to the replacement,
67169689Skan   including existing function pointers and virtual methods.  See
68169689Skan   rs6000_emit_prologue for the code that handles the nop insertions.
6990075Sobrien
70169689Skan   The added indirection allows gdb to redirect accesses to static
71169689Skan   symbols from the newly loaded translation unit to the existing
72169689Skan   symbol, if any.  @code{static} symbols are special and are handled by
73169689Skan   setting the second word in the .non_lazy_symbol_pointer data
74169689Skan   structure to symbol.  See indirect_data for the code that handles
75169689Skan   the extra indirection, and machopic_output_indirection and its use
76169689Skan   of MACHO_SYMBOL_STATIC for the code that handles @code{static}
77169689Skan   symbol indirection.  */
7890075Sobrien
79169689Skan/* Section names.  */
80169689Skansection * darwin_sections[NUM_DARWIN_SECTIONS];
8190075Sobrien
82169689Skan/* True if we're setting __attribute__ ((ms_struct)).  */
83169689Skanint darwin_ms_struct = false;
8490075Sobrien
85169689Skan/* A get_unnamed_section callback used to switch to an ObjC section.
86169689Skan   DIRECTIVE is as for output_section_asm_op.  */
87169689Skan
88169689Skanstatic void
89169689Skanoutput_objc_section_asm_op (const void *directive)
9090075Sobrien{
91169689Skan  static bool been_here = false;
9290075Sobrien
93169689Skan  if (! been_here)
9490075Sobrien    {
95169689Skan      static const enum darwin_section_enum tomark[] =
9690075Sobrien	{
97169689Skan	  /* written, cold -> hot */
98169689Skan	  objc_cat_cls_meth_section,
99169689Skan	  objc_cat_inst_meth_section,
100169689Skan	  objc_string_object_section,
101169689Skan	  objc_constant_string_object_section,
102169689Skan	  objc_selector_refs_section,
103169689Skan	  objc_selector_fixup_section,
104169689Skan	  objc_cls_refs_section,
105169689Skan	  objc_class_section,
106169689Skan	  objc_meta_class_section,
107169689Skan	  /* shared, hot -> cold */
108169689Skan	  objc_cls_meth_section,
109169689Skan	  objc_inst_meth_section,
110169689Skan	  objc_protocol_section,
111169689Skan	  objc_class_names_section,
112169689Skan	  objc_meth_var_types_section,
113169689Skan	  objc_meth_var_names_section,
114169689Skan	  objc_category_section,
115169689Skan	  objc_class_vars_section,
116169689Skan	  objc_instance_vars_section,
117169689Skan	  objc_module_info_section,
118169689Skan	  objc_symbols_section
119169689Skan	};
120169689Skan      size_t i;
12190075Sobrien
122169689Skan      been_here = true;
123169689Skan      for (i = 0; i < ARRAY_SIZE (tomark); i++)
124169689Skan	switch_to_section (darwin_sections[tomark[i]]);
125169689Skan    }
126169689Skan  output_section_asm_op (directive);
127169689Skan}
12890075Sobrien
129169689Skan/* Implement TARGET_ASM_INIT_SECTIONS.  */
13090075Sobrien
131169689Skanvoid
132169689Skandarwin_init_sections (void)
133169689Skan{
134169689Skan#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC)		\
135169689Skan  darwin_sections[NAME] =					\
136169689Skan    get_unnamed_section (FLAGS, (OBJC				\
137169689Skan				 ? output_objc_section_asm_op	\
138169689Skan				 : output_section_asm_op),	\
139169689Skan			 "\t" DIRECTIVE);
140169689Skan#include "config/darwin-sections.def"
141169689Skan#undef DEF_SECTION
14290075Sobrien
143169689Skan  readonly_data_section = darwin_sections[const_section];
144169689Skan  exception_section = darwin_sections[darwin_exception_section];
145169689Skan  eh_frame_section = darwin_sections[darwin_eh_frame_section];
146169689Skan}
14790075Sobrien
148169689Skanint
149169689Skanname_needs_quotes (const char *name)
150169689Skan{
151169689Skan  int c;
152169689Skan  while ((c = *name++) != '\0')
153169689Skan    if (! ISIDNUM (c) && c != '.' && c != '$')
154169689Skan      return 1;
155169689Skan  return 0;
156169689Skan}
15790075Sobrien
158169689Skan/* Return true if SYM_REF can be used without an indirection.  */
159169689Skanstatic int
160169689Skanmachopic_symbol_defined_p (rtx sym_ref)
161169689Skan{
162169689Skan  if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
163169689Skan    return true;
16490075Sobrien
165169689Skan  /* If a symbol references local and is not an extern to this
166169689Skan     file, then the symbol might be able to declared as defined.  */
167169689Skan  if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
16890075Sobrien    {
169169689Skan      /* If the symbol references a variable and the variable is a
170169689Skan	 common symbol, then this symbol is not defined.  */
171169689Skan      if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
17290075Sobrien	{
173169689Skan	  tree decl = SYMBOL_REF_DECL (sym_ref);
174169689Skan	  if (!decl)
175169689Skan	    return true;
176169689Skan	  if (DECL_COMMON (decl))
177169689Skan	    return false;
17890075Sobrien	}
179169689Skan      return true;
18090075Sobrien    }
181169689Skan  return false;
18290075Sobrien}
18390075Sobrien
184169689Skan/* This module assumes that (const (symbol_ref "foo")) is a legal pic
185169689Skan   reference, which will not be changed.  */
186132718Skan
18790075Sobrienenum machopic_addr_class
188169689Skanmachopic_classify_symbol (rtx sym_ref)
18990075Sobrien{
190169689Skan  int flags;
191169689Skan  bool function_p;
192169689Skan
193169689Skan  flags = SYMBOL_REF_FLAGS (sym_ref);
194169689Skan  function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
195169689Skan  if (machopic_symbol_defined_p (sym_ref))
196169689Skan    return (function_p
197169689Skan	    ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
198169689Skan  else
199169689Skan    return (function_p
200169689Skan	    ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
20190075Sobrien}
20290075Sobrien
203169689Skan#ifndef TARGET_FIX_AND_CONTINUE
204169689Skan#define TARGET_FIX_AND_CONTINUE 0
205169689Skan#endif
206169689Skan
207169689Skan/* Indicate when fix-and-continue style code generation is being used
208169689Skan   and when a reference to data should be indirected so that it can be
209169689Skan   rebound in a new translation unit to reference the original instance
210169689Skan   of that data.  Symbol names that are for code generation local to
211169689Skan   the translation unit are bound to the new translation unit;
212169689Skan   currently this means symbols that begin with L or _OBJC_;
213169689Skan   otherwise, we indicate that an indirect reference should be made to
214169689Skan   permit the runtime to rebind new instances of the translation unit
215169689Skan   to the original instance of the data.  */
216169689Skan
217169689Skanstatic int
218169689Skanindirect_data (rtx sym_ref)
21990075Sobrien{
220169689Skan  int lprefix;
221169689Skan  const char *name;
222169689Skan
223169689Skan  /* If we aren't generating fix-and-continue code, don't do anything special.  */
224169689Skan  if (TARGET_FIX_AND_CONTINUE == 0)
225169689Skan    return 0;
226169689Skan
227169689Skan  /* Otherwise, all symbol except symbols that begin with L or _OBJC_
228169689Skan     are indirected.  Symbols that begin with L and _OBJC_ are always
229169689Skan     bound to the current translation unit as they are used for
230169689Skan     generated local data of the translation unit.  */
231169689Skan
232169689Skan  name = XSTR (sym_ref, 0);
233169689Skan
234169689Skan  lprefix = (((name[0] == '*' || name[0] == '&')
235169689Skan              && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
236169689Skan             || (strncmp (name, "_OBJC_", 6) == 0));
237169689Skan
238169689Skan  return ! lprefix;
23990075Sobrien}
24090075Sobrien
241169689Skan
24290075Sobrienstatic int
243169689Skanmachopic_data_defined_p (rtx sym_ref)
24490075Sobrien{
245169689Skan  if (indirect_data (sym_ref))
246169689Skan    return 0;
247169689Skan
248169689Skan  switch (machopic_classify_symbol (sym_ref))
24990075Sobrien    {
25090075Sobrien    case MACHOPIC_DEFINED_DATA:
251169689Skan    case MACHOPIC_DEFINED_FUNCTION:
25290075Sobrien      return 1;
25390075Sobrien    default:
25490075Sobrien      return 0;
25590075Sobrien    }
25690075Sobrien}
25790075Sobrien
25890075Sobrienvoid
259169689Skanmachopic_define_symbol (rtx mem)
26090075Sobrien{
261169689Skan  rtx sym_ref;
26290075Sobrien
263169689Skan  gcc_assert (GET_CODE (mem) == MEM);
264169689Skan  sym_ref = XEXP (mem, 0);
265169689Skan  SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
26690075Sobrien}
26790075Sobrien
268132718Skanstatic GTY(()) char * function_base;
26990075Sobrien
270132718Skanconst char *
271132718Skanmachopic_function_base_name (void)
272132718Skan{
273132718Skan  /* if dynamic-no-pic is on, we should not get here */
274169689Skan  gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
27590075Sobrien
276132718Skan  if (function_base == NULL)
277132718Skan    function_base =
278132718Skan      (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
27990075Sobrien
280132718Skan  current_function_uses_pic_offset_table = 1;
281132718Skan
282132718Skan  return function_base;
283132718Skan}
284132718Skan
285169689Skan/* Return a SYMBOL_REF for the PIC function base.  */
286169689Skan
287169689Skanrtx
288169689Skanmachopic_function_base_sym (void)
289169689Skan{
290169689Skan  rtx sym_ref;
291169689Skan
292169689Skan  sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
293169689Skan  SYMBOL_REF_FLAGS (sym_ref)
294169689Skan    |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
295169689Skan  return sym_ref;
296169689Skan}
297169689Skan
298169689Skan/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending
299169689Skan   on whether pic_base is NULL or not.  */
300169689Skanstatic inline rtx
301169689Skangen_pic_offset (rtx orig, rtx pic_base)
302169689Skan{
303169689Skan  if (!pic_base)
304169689Skan    return orig;
305169689Skan  else
306169689Skan    return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base));
307169689Skan}
308169689Skan
309132718Skanstatic GTY(()) const char * function_base_func_name;
310132718Skanstatic GTY(()) int current_pic_label_num;
311132718Skan
312132718Skanvoid
313132718Skanmachopic_output_function_base_name (FILE *file)
31490075Sobrien{
315132718Skan  const char *current_name;
31690075Sobrien
317169689Skan  /* If dynamic-no-pic is on, we should not get here.  */
318169689Skan  gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
319132718Skan  current_name =
320132718Skan    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
321132718Skan  if (function_base_func_name != current_name)
32290075Sobrien    {
32390075Sobrien      ++current_pic_label_num;
324132718Skan      function_base_func_name = current_name;
32590075Sobrien    }
326132718Skan  fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
32790075Sobrien}
32890075Sobrien
329169689Skan/* The suffix attached to non-lazy pointer symbols.  */
330169689Skan#define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
331169689Skan/* The suffix attached to stub symbols.  */
332169689Skan#define STUB_SUFFIX "$stub"
33390075Sobrien
334169689Skantypedef struct machopic_indirection GTY (())
335169689Skan{
336169689Skan  /* The SYMBOL_REF for the entity referenced.  */
337169689Skan  rtx symbol;
338169689Skan  /* The name of the stub or non-lazy pointer.  */
339169689Skan  const char * ptr_name;
340169689Skan  /* True iff this entry is for a stub (as opposed to a non-lazy
341169689Skan     pointer).  */
342169689Skan  bool stub_p;
343169689Skan  /* True iff this stub or pointer pointer has been referenced.  */
344169689Skan  bool used;
345169689Skan} machopic_indirection;
34690075Sobrien
347169689Skan/* A table mapping stub names and non-lazy pointer names to
348169689Skan   SYMBOL_REFs for the stubbed-to and pointed-to entities.  */
349169689Skan
350169689Skanstatic GTY ((param_is (struct machopic_indirection))) htab_t
351169689Skan  machopic_indirections;
352169689Skan
353169689Skan/* Return a hash value for a SLOT in the indirections hash table.  */
354169689Skan
355169689Skanstatic hashval_t
356169689Skanmachopic_indirection_hash (const void *slot)
35790075Sobrien{
358169689Skan  const machopic_indirection *p = (const machopic_indirection *) slot;
359169689Skan  return htab_hash_string (p->ptr_name);
360169689Skan}
361132718Skan
362169689Skan/* Returns true if the KEY is the same as that associated with
363169689Skan   SLOT.  */
36490075Sobrien
365169689Skanstatic int
366169689Skanmachopic_indirection_eq (const void *slot, const void *key)
367169689Skan{
368169689Skan  return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
369169689Skan}
37090075Sobrien
371169689Skan/* Return the name of the non-lazy pointer (if STUB_P is false) or
372169689Skan   stub (if STUB_B is true) corresponding to the given name.  */
373169689Skan
374169689Skanconst char *
375169689Skanmachopic_indirection_name (rtx sym_ref, bool stub_p)
376169689Skan{
377169689Skan  char *buffer;
378169689Skan  const char *name = XSTR (sym_ref, 0);
379169689Skan  size_t namelen = strlen (name);
380169689Skan  machopic_indirection *p;
381169689Skan  void ** slot;
382169689Skan  bool saw_star = false;
383169689Skan  bool needs_quotes;
384169689Skan  const char *suffix;
385169689Skan  const char *prefix = user_label_prefix;
386169689Skan  const char *quote = "";
387169689Skan  tree id;
388169689Skan
389169689Skan  id = maybe_get_identifier (name);
390169689Skan  if (id)
39190075Sobrien    {
392169689Skan      tree id_orig = id;
393169689Skan
394169689Skan      while (IDENTIFIER_TRANSPARENT_ALIAS (id))
395169689Skan	id = TREE_CHAIN (id);
396169689Skan      if (id != id_orig)
39790075Sobrien	{
398169689Skan	  name = IDENTIFIER_POINTER (id);
399169689Skan	  namelen = strlen (name);
40090075Sobrien	}
40190075Sobrien    }
40290075Sobrien
403169689Skan  if (name[0] == '*')
404169689Skan    {
405169689Skan      saw_star = true;
406169689Skan      prefix = "";
407169689Skan      ++name;
408169689Skan      --namelen;
409169689Skan    }
41090075Sobrien
411169689Skan  needs_quotes = name_needs_quotes (name);
412169689Skan  if (needs_quotes)
413169689Skan    {
414169689Skan      quote = "\"";
415169689Skan    }
41690075Sobrien
417169689Skan  if (stub_p)
418169689Skan    suffix = STUB_SUFFIX;
419169689Skan  else
420169689Skan    suffix = NON_LAZY_POINTER_SUFFIX;
421132718Skan
422169689Skan  buffer = alloca (strlen ("&L")
423169689Skan		   + strlen (prefix)
424169689Skan		   + namelen
425169689Skan		   + strlen (suffix)
426169689Skan		   + 2 * strlen (quote)
427169689Skan		   + 1 /* '\0' */);
42890075Sobrien
429169689Skan  /* Construct the name of the non-lazy pointer or stub.  */
430169689Skan  sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote);
43190075Sobrien
432169689Skan  if (!machopic_indirections)
433169689Skan    machopic_indirections = htab_create_ggc (37,
434169689Skan					     machopic_indirection_hash,
435169689Skan					     machopic_indirection_eq,
436169689Skan					     /*htab_del=*/NULL);
43790075Sobrien
438169689Skan  slot = htab_find_slot_with_hash (machopic_indirections, buffer,
439169689Skan				   htab_hash_string (buffer), INSERT);
440169689Skan  if (*slot)
441169689Skan    {
442169689Skan      p = (machopic_indirection *) *slot;
443169689Skan    }
444169689Skan  else
445169689Skan    {
446169689Skan      p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
447169689Skan      p->symbol = sym_ref;
448169689Skan      p->ptr_name = xstrdup (buffer);
449169689Skan      p->stub_p = stub_p;
450169689Skan      p->used = false;
451169689Skan      *slot = p;
452169689Skan    }
453169689Skan
454169689Skan  return p->ptr_name;
45590075Sobrien}
45690075Sobrien
457169689Skan/* Return the name of the stub for the mcount function.  */
45890075Sobrien
459169689Skanconst char*
460169689Skanmachopic_mcount_stub_name (void)
461169689Skan{
462169689Skan  rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
463169689Skan  return machopic_indirection_name (symbol, /*stub_p=*/true);
464169689Skan}
46590075Sobrien
466169689Skan/* If NAME is the name of a stub or a non-lazy pointer , mark the stub
467169689Skan   or non-lazy pointer as used -- and mark the object to which the
468169689Skan   pointer/stub refers as used as well, since the pointer/stub will
469169689Skan   emit a reference to it.  */
470169689Skan
471169689Skanvoid
472169689Skanmachopic_validate_stub_or_non_lazy_ptr (const char *name)
47390075Sobrien{
474169689Skan  machopic_indirection *p;
47590075Sobrien
476169689Skan  p = ((machopic_indirection *)
477169689Skan       (htab_find_with_hash (machopic_indirections, name,
478169689Skan			     htab_hash_string (name))));
479169689Skan  if (p && ! p->used)
48090075Sobrien    {
481169689Skan      const char *real_name;
482169689Skan      tree id;
48390075Sobrien
484169689Skan      p->used = true;
48590075Sobrien
486169689Skan      /* Do what output_addr_const will do when we actually call it.  */
487169689Skan      if (SYMBOL_REF_DECL (p->symbol))
488169689Skan	mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
48990075Sobrien
490169689Skan      real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
49190075Sobrien
492169689Skan      id = maybe_get_identifier (real_name);
493169689Skan      if (id)
494169689Skan	mark_referenced (id);
495169689Skan    }
49690075Sobrien}
49790075Sobrien
49890075Sobrien/* Transform ORIG, which may be any data source, to the corresponding
49990075Sobrien   source using indirections.  */
50090075Sobrien
50190075Sobrienrtx
502132718Skanmachopic_indirect_data_reference (rtx orig, rtx reg)
50390075Sobrien{
50490075Sobrien  rtx ptr_ref = orig;
505132718Skan
50690075Sobrien  if (! MACHOPIC_INDIRECT)
50790075Sobrien    return orig;
50890075Sobrien
50990075Sobrien  if (GET_CODE (orig) == SYMBOL_REF)
51090075Sobrien    {
511169689Skan      int defined = machopic_data_defined_p (orig);
51290075Sobrien
513132718Skan      if (defined && MACHO_DYNAMIC_NO_PIC_P)
51490075Sobrien	{
515132718Skan#if defined (TARGET_TOC)
516169689Skan	  /* Create a new register for CSE opportunities.  */
517169689Skan	  rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
518169689Skan 	  emit_insn (gen_macho_high (hi_reg, orig));
519169689Skan 	  emit_insn (gen_macho_low (reg, hi_reg, orig));
520132718Skan#else
521132718Skan	   /* some other cpu -- writeme!  */
522169689Skan	   gcc_unreachable ();
523132718Skan#endif
524132718Skan	   return reg;
525132718Skan	}
526132718Skan      else if (defined)
527132718Skan	{
528117395Skan#if defined (TARGET_TOC) || defined (HAVE_lo_sum)
529169689Skan	  rtx pic_base = machopic_function_base_sym ();
530169689Skan	  rtx offset = gen_pic_offset (orig, pic_base);
531117395Skan#endif
53290075Sobrien
53390075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */
534132718Skan	  rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
53590075Sobrien
536169689Skan	  gcc_assert (reg);
53790075Sobrien
538132718Skan	  emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
539132718Skan			      gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
540132718Skan				       gen_rtx_HIGH (Pmode, offset))));
541132718Skan	  emit_insn (gen_rtx_SET (Pmode, reg,
542132718Skan				  gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
54390075Sobrien
54490075Sobrien	  orig = reg;
54590075Sobrien#else
54690075Sobrien#if defined (HAVE_lo_sum)
547169689Skan	  gcc_assert (reg);
54890075Sobrien
549132718Skan	  emit_insn (gen_rtx_SET (VOIDmode, reg,
550132718Skan				  gen_rtx_HIGH (Pmode, offset)));
551132718Skan	  emit_insn (gen_rtx_SET (VOIDmode, reg,
552132718Skan				  gen_rtx_LO_SUM (Pmode, reg, offset)));
553132718Skan	  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
55490075Sobrien
555132718Skan	  orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
55690075Sobrien#endif
55790075Sobrien#endif
55890075Sobrien	  return orig;
55990075Sobrien	}
56090075Sobrien
561169689Skan      ptr_ref = (gen_rtx_SYMBOL_REF
562169689Skan		 (Pmode,
563169689Skan		  machopic_indirection_name (orig, /*stub_p=*/false)));
56490075Sobrien
565169689Skan      SYMBOL_REF_DATA (ptr_ref) = SYMBOL_REF_DATA (orig);
56690075Sobrien
567169689Skan      ptr_ref = gen_const_mem (Pmode, ptr_ref);
568169689Skan      machopic_define_symbol (ptr_ref);
569169689Skan
57090075Sobrien      return ptr_ref;
57190075Sobrien    }
57290075Sobrien  else if (GET_CODE (orig) == CONST)
57390075Sobrien    {
57490075Sobrien      rtx base, result;
57590075Sobrien
57690075Sobrien      /* legitimize both operands of the PLUS */
57790075Sobrien      if (GET_CODE (XEXP (orig, 0)) == PLUS)
57890075Sobrien	{
57990075Sobrien	  base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
58090075Sobrien						   reg);
58190075Sobrien	  orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
58290075Sobrien						   (base == reg ? 0 : reg));
58390075Sobrien	}
584132718Skan      else
58590075Sobrien	return orig;
58690075Sobrien
58790075Sobrien      if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
58890075Sobrien	result = plus_constant (base, INTVAL (orig));
58990075Sobrien      else
590132718Skan	result = gen_rtx_PLUS (Pmode, base, orig);
59190075Sobrien
59290075Sobrien      if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
59390075Sobrien	{
59490075Sobrien	  if (reg)
59590075Sobrien	    {
59690075Sobrien	      emit_move_insn (reg, result);
59790075Sobrien	      result = reg;
59890075Sobrien	    }
59990075Sobrien	  else
60090075Sobrien	    {
60190075Sobrien	      result = force_reg (GET_MODE (result), result);
60290075Sobrien	    }
60390075Sobrien	}
60490075Sobrien
60590075Sobrien      return result;
60690075Sobrien
60790075Sobrien    }
60890075Sobrien  else if (GET_CODE (orig) == MEM)
60990075Sobrien    XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
61090075Sobrien  /* When the target is i386, this code prevents crashes due to the
61190075Sobrien     compiler's ignorance on how to move the PIC base register to
61290075Sobrien     other registers.  (The reload phase sometimes introduces such
61390075Sobrien     insns.)  */
61490075Sobrien  else if (GET_CODE (orig) == PLUS
61590075Sobrien	   && GET_CODE (XEXP (orig, 0)) == REG
61690075Sobrien	   && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
61790075Sobrien#ifdef I386
61890075Sobrien	   /* Prevent the same register from being erroneously used
61990075Sobrien	      as both the base and index registers.  */
62090075Sobrien	   && GET_CODE (XEXP (orig, 1)) == CONST
62190075Sobrien#endif
62290075Sobrien	   && reg)
62390075Sobrien    {
62490075Sobrien      emit_move_insn (reg, XEXP (orig, 0));
62590075Sobrien      XEXP (ptr_ref, 0) = reg;
62690075Sobrien    }
62790075Sobrien  return ptr_ref;
62890075Sobrien}
62990075Sobrien
63090075Sobrien/* Transform TARGET (a MEM), which is a function call target, to the
63190075Sobrien   corresponding symbol_stub if necessary.  Return a new MEM.  */
63290075Sobrien
63390075Sobrienrtx
634132718Skanmachopic_indirect_call_target (rtx target)
63590075Sobrien{
63690075Sobrien  if (GET_CODE (target) != MEM)
63790075Sobrien    return target;
63890075Sobrien
639169689Skan  if (MACHOPIC_INDIRECT
640169689Skan      && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
641169689Skan      && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
642169689Skan	   & MACHO_SYMBOL_FLAG_DEFINED))
643132718Skan    {
644169689Skan      rtx sym_ref = XEXP (target, 0);
645169689Skan      const char *stub_name = machopic_indirection_name (sym_ref,
646169689Skan							 /*stub_p=*/true);
647169689Skan      enum machine_mode mode = GET_MODE (sym_ref);
64890075Sobrien
649169689Skan      XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
650169689Skan      SYMBOL_REF_DATA (XEXP (target, 0)) = SYMBOL_REF_DATA (sym_ref);
651169689Skan      MEM_READONLY_P (target) = 1;
652169689Skan      MEM_NOTRAP_P (target) = 1;
65390075Sobrien    }
65490075Sobrien
65590075Sobrien  return target;
65690075Sobrien}
65790075Sobrien
65890075Sobrienrtx
659132718Skanmachopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
66090075Sobrien{
66190075Sobrien  rtx pic_ref = orig;
66290075Sobrien
663132718Skan  if (! MACHOPIC_INDIRECT)
66490075Sobrien    return orig;
66590075Sobrien
66690075Sobrien  /* First handle a simple SYMBOL_REF or LABEL_REF */
66790075Sobrien  if (GET_CODE (orig) == LABEL_REF
66890075Sobrien      || (GET_CODE (orig) == SYMBOL_REF
66990075Sobrien	  ))
67090075Sobrien    {
67190075Sobrien      /* addr(foo) = &func+(foo-func) */
67290075Sobrien      rtx pic_base;
67390075Sobrien
67490075Sobrien      orig = machopic_indirect_data_reference (orig, reg);
67590075Sobrien
676132718Skan      if (GET_CODE (orig) == PLUS
67790075Sobrien	  && GET_CODE (XEXP (orig, 0)) == REG)
67890075Sobrien	{
67990075Sobrien	  if (reg == 0)
68090075Sobrien	    return force_reg (mode, orig);
68190075Sobrien
68290075Sobrien	  emit_move_insn (reg, orig);
68390075Sobrien	  return reg;
684132718Skan	}
68590075Sobrien
686169689Skan      /* if dynamic-no-pic we don't have a pic base  */
687132718Skan      if (MACHO_DYNAMIC_NO_PIC_P)
688169689Skan	pic_base = NULL;
689132718Skan      else
690169689Skan	pic_base = machopic_function_base_sym ();
69190075Sobrien
69290075Sobrien      if (GET_CODE (orig) == MEM)
69390075Sobrien	{
69490075Sobrien	  if (reg == 0)
69590075Sobrien	    {
696169689Skan	      gcc_assert (!reload_in_progress);
697169689Skan	      reg = gen_reg_rtx (Pmode);
69890075Sobrien	    }
699132718Skan
70090075Sobrien#ifdef HAVE_lo_sum
701132718Skan	  if (MACHO_DYNAMIC_NO_PIC_P
702132718Skan	      && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
703132718Skan		  || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
704132718Skan	    {
705132718Skan#if defined (TARGET_TOC)	/* ppc  */
706132718Skan	      rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
707132718Skan	      rtx asym = XEXP (orig, 0);
708132718Skan	      rtx mem;
709132718Skan
710132718Skan	      emit_insn (gen_macho_high (temp_reg, asym));
711169689Skan	      mem = gen_const_mem (GET_MODE (orig),
712169689Skan				   gen_rtx_LO_SUM (Pmode, temp_reg, asym));
713132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
714132718Skan#else
715132718Skan	      /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
716169689Skan	      gcc_unreachable ();
717132718Skan#endif
718132718Skan	      pic_ref = reg;
719132718Skan	    }
720132718Skan	  else
721132718Skan	  if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
72290075Sobrien	      || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
72390075Sobrien	    {
724169689Skan	      rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base);
72590075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */
72690075Sobrien	      /* Generating a new reg may expose opportunities for
72790075Sobrien		 common subexpression elimination.  */
728169689Skan              rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
729132718Skan	      rtx mem;
730132718Skan	      rtx insn;
731132718Skan	      rtx sum;
732169689Skan
733132718Skan	      sum = gen_rtx_HIGH (Pmode, offset);
734132718Skan	      if (! MACHO_DYNAMIC_NO_PIC_P)
735132718Skan		sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
73690075Sobrien
737132718Skan	      emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
738132718Skan
739169689Skan	      mem = gen_const_mem (GET_MODE (orig),
740169689Skan				  gen_rtx_LO_SUM (Pmode,
741169689Skan						  hi_sum_reg, offset));
742132718Skan	      insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
743169689Skan	      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
744132718Skan						    REG_NOTES (insn));
745132718Skan
74690075Sobrien	      pic_ref = reg;
74790075Sobrien#else
748132718Skan	      emit_insn (gen_rtx_USE (VOIDmode,
749169689Skan				      gen_rtx_REG (Pmode,
750132718Skan						   PIC_OFFSET_TABLE_REGNUM)));
75190075Sobrien
752132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg,
753132718Skan				      gen_rtx_HIGH (Pmode,
754169689Skan						    gen_rtx_CONST (Pmode,
755132718Skan								   offset))));
756132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg,
757132718Skan				  gen_rtx_LO_SUM (Pmode, reg,
758132718Skan					   gen_rtx_CONST (Pmode, offset))));
759132718Skan	      pic_ref = gen_rtx_PLUS (Pmode,
760132718Skan				      pic_offset_table_rtx, reg);
76190075Sobrien#endif
76290075Sobrien	    }
76390075Sobrien	  else
76490075Sobrien#endif  /* HAVE_lo_sum */
76590075Sobrien	    {
76690075Sobrien	      rtx pic = pic_offset_table_rtx;
76790075Sobrien	      if (GET_CODE (pic) != REG)
76890075Sobrien		{
76990075Sobrien		  emit_move_insn (reg, pic);
77090075Sobrien		  pic = reg;
77190075Sobrien		}
77290075Sobrien#if 0
773132718Skan	      emit_insn (gen_rtx_USE (VOIDmode,
774169689Skan				      gen_rtx_REG (Pmode,
775132718Skan						   PIC_OFFSET_TABLE_REGNUM)));
77690075Sobrien#endif
77790075Sobrien
778169689Skan	      if (reload_in_progress)
779169689Skan		regs_ever_live[REGNO (pic)] = 1;
780169689Skan	      pic_ref = gen_rtx_PLUS (Pmode, pic,
781169689Skan				      gen_pic_offset (XEXP (orig, 0),
782169689Skan						      pic_base));
78390075Sobrien	    }
784132718Skan
78590075Sobrien#if !defined (TARGET_TOC)
78690075Sobrien	  emit_move_insn (reg, pic_ref);
787169689Skan	  pic_ref = gen_const_mem (GET_MODE (orig), reg);
78890075Sobrien#endif
78990075Sobrien	}
79090075Sobrien      else
79190075Sobrien	{
79290075Sobrien
79390075Sobrien#ifdef HAVE_lo_sum
794132718Skan	  if (GET_CODE (orig) == SYMBOL_REF
79590075Sobrien	      || GET_CODE (orig) == LABEL_REF)
79690075Sobrien	    {
797169689Skan	      rtx offset = gen_pic_offset (orig, pic_base);
79890075Sobrien#if defined (TARGET_TOC) /* i.e., PowerPC */
79990075Sobrien              rtx hi_sum_reg;
80090075Sobrien
80190075Sobrien	      if (reg == 0)
80290075Sobrien		{
803169689Skan		  gcc_assert (!reload_in_progress);
804169689Skan		  reg = gen_reg_rtx (Pmode);
80590075Sobrien		}
806132718Skan
80790075Sobrien	      hi_sum_reg = reg;
80890075Sobrien
809132718Skan	      emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
810132718Skan				      (MACHO_DYNAMIC_NO_PIC_P)
811132718Skan				      ? gen_rtx_HIGH (Pmode, offset)
812132718Skan				      : gen_rtx_PLUS (Pmode,
813132718Skan						      pic_offset_table_rtx,
814169689Skan						      gen_rtx_HIGH (Pmode,
815132718Skan								    offset))));
816132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg,
817132718Skan				      gen_rtx_LO_SUM (Pmode,
818132718Skan						      hi_sum_reg, offset)));
81990075Sobrien	      pic_ref = reg;
82090075Sobrien#else
821132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg,
822132718Skan				      gen_rtx_HIGH (Pmode, offset)));
823132718Skan	      emit_insn (gen_rtx_SET (VOIDmode, reg,
824132718Skan				      gen_rtx_LO_SUM (Pmode, reg, offset)));
825132718Skan	      pic_ref = gen_rtx_PLUS (Pmode,
826132718Skan				      pic_offset_table_rtx, reg);
82790075Sobrien#endif
82890075Sobrien	    }
82990075Sobrien	  else
83090075Sobrien#endif  /*  HAVE_lo_sum  */
83190075Sobrien	    {
832169689Skan	      if (REG_P (orig)
833169689Skan	          || GET_CODE (orig) == SUBREG)
83490075Sobrien		{
83590075Sobrien		  return orig;
83690075Sobrien		}
83790075Sobrien	      else
83890075Sobrien		{
83990075Sobrien		  rtx pic = pic_offset_table_rtx;
84090075Sobrien		  if (GET_CODE (pic) != REG)
84190075Sobrien		    {
84290075Sobrien		      emit_move_insn (reg, pic);
84390075Sobrien		      pic = reg;
84490075Sobrien		    }
84590075Sobrien#if 0
846132718Skan		  emit_insn (gen_rtx_USE (VOIDmode,
847132718Skan					  pic_offset_table_rtx));
84890075Sobrien#endif
849169689Skan		  if (reload_in_progress)
850169689Skan		    regs_ever_live[REGNO (pic)] = 1;
851132718Skan		  pic_ref = gen_rtx_PLUS (Pmode,
852132718Skan					  pic,
853169689Skan					  gen_pic_offset (orig, pic_base));
85490075Sobrien		}
85590075Sobrien	    }
85690075Sobrien	}
85790075Sobrien
85890075Sobrien      if (GET_CODE (pic_ref) != REG)
85990075Sobrien        {
86090075Sobrien          if (reg != 0)
86190075Sobrien            {
86290075Sobrien              emit_move_insn (reg, pic_ref);
86390075Sobrien              return reg;
86490075Sobrien            }
86590075Sobrien          else
86690075Sobrien            {
86790075Sobrien              return force_reg (mode, pic_ref);
86890075Sobrien            }
86990075Sobrien        }
87090075Sobrien      else
87190075Sobrien        {
87290075Sobrien          return pic_ref;
87390075Sobrien        }
87490075Sobrien    }
87590075Sobrien
87690075Sobrien  else if (GET_CODE (orig) == SYMBOL_REF)
87790075Sobrien    return orig;
87890075Sobrien
87990075Sobrien  else if (GET_CODE (orig) == PLUS
88090075Sobrien	   && (GET_CODE (XEXP (orig, 0)) == MEM
88190075Sobrien	       || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
88290075Sobrien	       || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
88390075Sobrien	   && XEXP (orig, 0) != pic_offset_table_rtx
88490075Sobrien	   && GET_CODE (XEXP (orig, 1)) != REG)
885132718Skan
88690075Sobrien    {
88790075Sobrien      rtx base;
88890075Sobrien      int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
88990075Sobrien
89090075Sobrien      base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
89190075Sobrien      orig = machopic_legitimize_pic_address (XEXP (orig, 1),
89290075Sobrien					      Pmode, (base == reg ? 0 : reg));
89390075Sobrien      if (GET_CODE (orig) == CONST_INT)
89490075Sobrien	{
89590075Sobrien	  pic_ref = plus_constant (base, INTVAL (orig));
89690075Sobrien	  is_complex = 1;
89790075Sobrien	}
89890075Sobrien      else
899132718Skan	pic_ref = gen_rtx_PLUS (Pmode, base, orig);
90090075Sobrien
90190075Sobrien      if (reg && is_complex)
90290075Sobrien	{
90390075Sobrien	  emit_move_insn (reg, pic_ref);
90490075Sobrien	  pic_ref = reg;
90590075Sobrien	}
90690075Sobrien      /* Likewise, should we set special REG_NOTEs here?  */
90790075Sobrien    }
90890075Sobrien
90990075Sobrien  else if (GET_CODE (orig) == CONST)
91090075Sobrien    {
91190075Sobrien      return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
91290075Sobrien    }
91390075Sobrien
91490075Sobrien  else if (GET_CODE (orig) == MEM
91590075Sobrien	   && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
91690075Sobrien    {
91790075Sobrien      rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
918169689Skan      addr = replace_equiv_address (orig, addr);
91990075Sobrien      emit_move_insn (reg, addr);
92090075Sobrien      pic_ref = reg;
92190075Sobrien    }
92290075Sobrien
92390075Sobrien  return pic_ref;
92490075Sobrien}
92590075Sobrien
926169689Skan/* Output the stub or non-lazy pointer in *SLOT, if it has been used.
927169689Skan   DATA is the FILE* for assembly output.  Called from
928169689Skan   htab_traverse.  */
92990075Sobrien
930169689Skanstatic int
931169689Skanmachopic_output_indirection (void **slot, void *data)
93290075Sobrien{
933169689Skan  machopic_indirection *p = *((machopic_indirection **) slot);
934169689Skan  FILE *asm_out_file = (FILE *) data;
935169689Skan  rtx symbol;
936169689Skan  const char *sym_name;
937169689Skan  const char *ptr_name;
93890075Sobrien
939169689Skan  if (!p->used)
940169689Skan    return 1;
941169689Skan
942169689Skan  symbol = p->symbol;
943169689Skan  sym_name = XSTR (symbol, 0);
944169689Skan  ptr_name = p->ptr_name;
945169689Skan
946169689Skan  if (p->stub_p)
94790075Sobrien    {
94890075Sobrien      char *sym;
94990075Sobrien      char *stub;
950169689Skan      tree id;
95190075Sobrien
952169689Skan      id = maybe_get_identifier (sym_name);
953169689Skan      if (id)
954169689Skan	{
955169689Skan	  tree id_orig = id;
95690075Sobrien
957169689Skan	  while (IDENTIFIER_TRANSPARENT_ALIAS (id))
958169689Skan	    id = TREE_CHAIN (id);
959169689Skan	  if (id != id_orig)
960169689Skan	    sym_name = IDENTIFIER_POINTER (id);
961169689Skan	}
96290075Sobrien
96390075Sobrien      sym = alloca (strlen (sym_name) + 2);
96490075Sobrien      if (sym_name[0] == '*' || sym_name[0] == '&')
96590075Sobrien	strcpy (sym, sym_name + 1);
96690075Sobrien      else if (sym_name[0] == '-' || sym_name[0] == '+')
967132718Skan	strcpy (sym, sym_name);
96890075Sobrien      else
969169689Skan	sprintf (sym, "%s%s", user_label_prefix, sym_name);
97090075Sobrien
971169689Skan      stub = alloca (strlen (ptr_name) + 2);
972169689Skan      if (ptr_name[0] == '*' || ptr_name[0] == '&')
973169689Skan	strcpy (stub, ptr_name + 1);
97490075Sobrien      else
975169689Skan	sprintf (stub, "%s%s", user_label_prefix, ptr_name);
97690075Sobrien
97790075Sobrien      machopic_output_stub (asm_out_file, sym, stub);
97890075Sobrien    }
979169689Skan  else if (! indirect_data (symbol)
980169689Skan	   && (machopic_symbol_defined_p (symbol)
981169689Skan	       || SYMBOL_REF_LOCAL_P (symbol)))
98290075Sobrien    {
983169689Skan      switch_to_section (data_section);
984169689Skan      assemble_align (GET_MODE_ALIGNMENT (Pmode));
985169689Skan      assemble_label (ptr_name);
986169689Skan      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
987169689Skan			GET_MODE_SIZE (Pmode),
988169689Skan			GET_MODE_ALIGNMENT (Pmode), 1);
989169689Skan    }
990169689Skan  else
991169689Skan    {
992169689Skan      rtx init = const0_rtx;
99390075Sobrien
994169689Skan      switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
995169689Skan      assemble_name (asm_out_file, ptr_name);
996169689Skan      fprintf (asm_out_file, ":\n");
99790075Sobrien
998169689Skan      fprintf (asm_out_file, "\t.indirect_symbol ");
999169689Skan      assemble_name (asm_out_file, sym_name);
1000169689Skan      fprintf (asm_out_file, "\n");
100190075Sobrien
1002169689Skan      /* Variables that are marked with MACHO_SYMBOL_STATIC need to
1003169689Skan	 have their symbol name instead of 0 in the second entry of
1004169689Skan	 the non-lazy symbol pointer data structure when they are
1005169689Skan	 defined.  This allows the runtime to rebind newer instances
1006169689Skan	 of the translation unit with the original instance of the
1007169689Skan	 symbol.  */
100890075Sobrien
1009169689Skan      if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
1010169689Skan	  && machopic_symbol_defined_p (symbol))
1011169689Skan	init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
1012169689Skan
1013169689Skan      assemble_integer (init, GET_MODE_SIZE (Pmode),
1014169689Skan			GET_MODE_ALIGNMENT (Pmode), 1);
101590075Sobrien    }
1016169689Skan
1017169689Skan  return 1;
101890075Sobrien}
101990075Sobrien
1020169689Skanvoid
1021169689Skanmachopic_finish (FILE *asm_out_file)
1022169689Skan{
1023169689Skan  if (machopic_indirections)
1024169689Skan    htab_traverse_noresize (machopic_indirections,
1025169689Skan			    machopic_output_indirection,
1026169689Skan			    asm_out_file);
1027169689Skan}
1028169689Skan
1029132718Skanint
1030132718Skanmachopic_operand_p (rtx op)
103190075Sobrien{
103290075Sobrien  if (MACHOPIC_JUST_INDIRECT)
103390075Sobrien    {
103490075Sobrien      while (GET_CODE (op) == CONST)
103590075Sobrien	op = XEXP (op, 0);
103690075Sobrien
103790075Sobrien      if (GET_CODE (op) == SYMBOL_REF)
1038169689Skan	return machopic_symbol_defined_p (op);
103990075Sobrien      else
104090075Sobrien	return 0;
104190075Sobrien    }
104290075Sobrien
104390075Sobrien  while (GET_CODE (op) == CONST)
104490075Sobrien    op = XEXP (op, 0);
104590075Sobrien
104690075Sobrien  if (GET_CODE (op) == MINUS
104790075Sobrien      && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
104890075Sobrien      && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1049169689Skan      && machopic_symbol_defined_p (XEXP (op, 0))
1050169689Skan      && machopic_symbol_defined_p (XEXP (op, 1)))
105190075Sobrien      return 1;
105290075Sobrien
105390075Sobrien  return 0;
105490075Sobrien}
105590075Sobrien
105690075Sobrien/* This function records whether a given name corresponds to a defined
105790075Sobrien   or undefined function or variable, for machopic_classify_ident to
105890075Sobrien   use later.  */
105990075Sobrien
106090075Sobrienvoid
1061132718Skandarwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
106290075Sobrien{
106390075Sobrien  rtx sym_ref;
106490075Sobrien
1065132718Skan  /* Do the standard encoding things first.  */
1066132718Skan  default_encode_section_info (decl, rtl, first);
1067132718Skan
1068169689Skan  if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
1069169689Skan    return;
1070132718Skan
1071169689Skan  sym_ref = XEXP (rtl, 0);
1072169689Skan  if (TREE_CODE (decl) == VAR_DECL)
1073169689Skan    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
1074169689Skan
1075169689Skan  if (!DECL_EXTERNAL (decl)
1076169689Skan      && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
1077169689Skan      && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
107890075Sobrien      && ((TREE_STATIC (decl)
107990075Sobrien	   && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1080132718Skan	  || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
108190075Sobrien	      && DECL_INITIAL (decl) != error_mark_node)))
1082169689Skan    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
108390075Sobrien
1084169689Skan  if (! TREE_PUBLIC (decl))
1085169689Skan    SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
108690075Sobrien}
108790075Sobrien
1088169689Skanvoid
1089169689Skandarwin_mark_decl_preserved (const char *name)
1090117395Skan{
1091169689Skan  fprintf (asm_out_file, ".no_dead_strip ");
1092169689Skan  assemble_name (asm_out_file, name);
1093169689Skan  fputc ('\n', asm_out_file);
1094117395Skan}
1095117395Skan
1096169689Skanint
1097169689Skanmachopic_reloc_rw_mask (void)
109890075Sobrien{
1099169689Skan  return MACHOPIC_INDIRECT ? 3 : 0;
110090075Sobrien}
110190075Sobrien
1102169689Skansection *
1103169689Skanmachopic_select_section (tree exp, int reloc,
1104169689Skan			 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
110590075Sobrien{
1106169689Skan  section *base_section;
1107169689Skan  bool weak_p = (DECL_P (exp) && DECL_WEAK (exp)
1108169689Skan		 && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp))
1109169689Skan		     || ! lookup_attribute ("weak_import",
1110169689Skan					    DECL_ATTRIBUTES (exp))));
111190075Sobrien
1112169689Skan  if (TREE_CODE (exp) == FUNCTION_DECL)
111390075Sobrien    {
1114169689Skan      if (reloc == 1)
1115169689Skan	base_section = (weak_p
1116169689Skan			? darwin_sections[text_unlikely_coal_section]
1117169689Skan			: unlikely_text_section ());
1118169689Skan      else
1119169689Skan	base_section = weak_p ? darwin_sections[text_coal_section] : text_section;
112090075Sobrien    }
1121169689Skan  else if (decl_readonly_section (exp, reloc))
1122169689Skan    base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section];
1123119256Skan  else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1124169689Skan    base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section];
1125119256Skan  else
1126169689Skan    base_section = weak_p ? darwin_sections[data_coal_section] : data_section;
1127119256Skan
1128119256Skan  if (TREE_CODE (exp) == STRING_CST
1129132718Skan      && ((size_t) TREE_STRING_LENGTH (exp)
1130169689Skan	  == strlen (TREE_STRING_POINTER (exp)) + 1))
1131169689Skan    return darwin_sections[cstring_section];
1132119256Skan  else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1133119256Skan	   && flag_merge_constants)
1134117395Skan    {
1135169689Skan      tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
1136117395Skan
1137117395Skan      if (TREE_CODE (size) == INTEGER_CST &&
1138117395Skan	  TREE_INT_CST_LOW (size) == 4 &&
1139117395Skan	  TREE_INT_CST_HIGH (size) == 0)
1140169689Skan	return darwin_sections[literal4_section];
1141117395Skan      else if (TREE_CODE (size) == INTEGER_CST &&
1142117395Skan	       TREE_INT_CST_LOW (size) == 8 &&
1143117395Skan	       TREE_INT_CST_HIGH (size) == 0)
1144169689Skan	return darwin_sections[literal8_section];
1145169689Skan      else if (TARGET_64BIT
1146169689Skan	       && TREE_CODE (size) == INTEGER_CST
1147169689Skan	       && TREE_INT_CST_LOW (size) == 16
1148169689Skan	       && TREE_INT_CST_HIGH (size) == 0)
1149169689Skan	return darwin_sections[literal16_section];
1150117395Skan      else
1151169689Skan	return base_section;
1152117395Skan    }
1153117395Skan  else if (TREE_CODE (exp) == CONSTRUCTOR
1154117395Skan	   && TREE_TYPE (exp)
1155117395Skan	   && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1156117395Skan	   && TYPE_NAME (TREE_TYPE (exp)))
1157117395Skan    {
1158117395Skan      tree name = TYPE_NAME (TREE_TYPE (exp));
1159117395Skan      if (TREE_CODE (name) == TYPE_DECL)
1160117395Skan	name = DECL_NAME (name);
1161169689Skan
1162169689Skan      if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
1163169689Skan	{
1164169689Skan	  if (flag_next_runtime)
1165169689Skan	    return darwin_sections[objc_constant_string_object_section];
1166169689Skan	  else
1167169689Skan	    return darwin_sections[objc_string_object_section];
1168169689Skan	}
1169132718Skan      else
1170169689Skan	return base_section;
1171117395Skan    }
1172117395Skan  else if (TREE_CODE (exp) == VAR_DECL &&
1173117395Skan	   DECL_NAME (exp) &&
1174117395Skan	   TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1175117395Skan	   IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1176117395Skan	   !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1177117395Skan    {
1178117395Skan      const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1179117395Skan
1180117395Skan      if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1181169689Skan	return darwin_sections[objc_cls_meth_section];
1182117395Skan      else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1183169689Skan	return darwin_sections[objc_inst_meth_section];
1184117395Skan      else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1185169689Skan	return darwin_sections[objc_cat_cls_meth_section];
1186117395Skan      else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1187169689Skan	return darwin_sections[objc_cat_inst_meth_section];
1188117395Skan      else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1189169689Skan	return darwin_sections[objc_class_vars_section];
1190117395Skan      else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1191169689Skan	return darwin_sections[objc_instance_vars_section];
1192117395Skan      else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1193169689Skan	return darwin_sections[objc_cat_cls_meth_section];
1194117395Skan      else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1195169689Skan	return darwin_sections[objc_class_names_section];
1196117395Skan      else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1197169689Skan	return darwin_sections[objc_meth_var_names_section];
1198117395Skan      else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1199169689Skan	return darwin_sections[objc_meth_var_types_section];
1200117395Skan      else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1201169689Skan	return darwin_sections[objc_cls_refs_section];
1202117395Skan      else if (!strncmp (name, "_OBJC_CLASS_", 12))
1203169689Skan	return darwin_sections[objc_class_section];
1204117395Skan      else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1205169689Skan	return darwin_sections[objc_meta_class_section];
1206117395Skan      else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1207169689Skan	return darwin_sections[objc_category_section];
1208117395Skan      else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1209169689Skan	return darwin_sections[objc_selector_refs_section];
1210117395Skan      else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1211169689Skan	return darwin_sections[objc_selector_fixup_section];
1212117395Skan      else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1213169689Skan	return darwin_sections[objc_symbols_section];
1214117395Skan      else if (!strncmp (name, "_OBJC_MODULES", 13))
1215169689Skan	return darwin_sections[objc_module_info_section];
1216132718Skan      else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1217169689Skan	return darwin_sections[objc_image_info_section];
1218117395Skan      else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1219169689Skan	return darwin_sections[objc_cat_inst_meth_section];
1220117395Skan      else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1221169689Skan	return darwin_sections[objc_cat_cls_meth_section];
1222117395Skan      else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1223169689Skan	return darwin_sections[objc_cat_cls_meth_section];
1224117395Skan      else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1225169689Skan	return darwin_sections[objc_protocol_section];
1226132718Skan      else
1227169689Skan	return base_section;
1228117395Skan    }
1229132718Skan  else
1230169689Skan    return base_section;
1231117395Skan}
1232117395Skan
1233117395Skan/* This can be called with address expressions as "rtx".
1234117395Skan   They must go in "const".  */
1235117395Skan
1236169689Skansection *
1237132718Skanmachopic_select_rtx_section (enum machine_mode mode, rtx x,
1238132718Skan			     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1239117395Skan{
1240169689Skan  if (GET_MODE_SIZE (mode) == 8
1241169689Skan      && (GET_CODE (x) == CONST_INT
1242169689Skan	  || GET_CODE (x) == CONST_DOUBLE))
1243169689Skan    return darwin_sections[literal8_section];
1244117395Skan  else if (GET_MODE_SIZE (mode) == 4
1245117395Skan	   && (GET_CODE (x) == CONST_INT
1246117395Skan	       || GET_CODE (x) == CONST_DOUBLE))
1247169689Skan    return darwin_sections[literal4_section];
1248169689Skan  else if (TARGET_64BIT
1249169689Skan	   && GET_MODE_SIZE (mode) == 16
1250169689Skan	   && (GET_CODE (x) == CONST_INT
1251169689Skan	       || GET_CODE (x) == CONST_DOUBLE
1252169689Skan	       || GET_CODE (x) == CONST_VECTOR))
1253169689Skan    return darwin_sections[literal16_section];
1254132718Skan  else if (MACHOPIC_INDIRECT
1255132718Skan	   && (GET_CODE (x) == SYMBOL_REF
1256132718Skan	       || GET_CODE (x) == CONST
1257132718Skan	       || GET_CODE (x) == LABEL_REF))
1258169689Skan    return darwin_sections[const_data_section];
1259117395Skan  else
1260169689Skan    return darwin_sections[const_section];
1261117395Skan}
1262117395Skan
1263117395Skanvoid
1264132718Skanmachopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
126590075Sobrien{
1266132718Skan  if (MACHOPIC_INDIRECT)
1267169689Skan    switch_to_section (darwin_sections[mod_init_section]);
126890075Sobrien  else
1269169689Skan    switch_to_section (darwin_sections[constructor_section]);
127090075Sobrien  assemble_align (POINTER_SIZE);
127190075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
127290075Sobrien
1273132718Skan  if (! MACHOPIC_INDIRECT)
127490075Sobrien    fprintf (asm_out_file, ".reference .constructors_used\n");
127590075Sobrien}
127690075Sobrien
127790075Sobrienvoid
1278132718Skanmachopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
127990075Sobrien{
1280132718Skan  if (MACHOPIC_INDIRECT)
1281169689Skan    switch_to_section (darwin_sections[mod_term_section]);
128290075Sobrien  else
1283169689Skan    switch_to_section (darwin_sections[destructor_section]);
128490075Sobrien  assemble_align (POINTER_SIZE);
128590075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
128690075Sobrien
1287132718Skan  if (! MACHOPIC_INDIRECT)
128890075Sobrien    fprintf (asm_out_file, ".reference .destructors_used\n");
128990075Sobrien}
1290117395Skan
1291117395Skanvoid
1292132718Skandarwin_globalize_label (FILE *stream, const char *name)
1293117395Skan{
1294117395Skan  if (!!strncmp (name, "_OBJC_", 6))
1295117395Skan    default_globalize_label (stream, name);
1296117395Skan}
1297117395Skan
1298169689Skanvoid
1299169689Skandarwin_asm_named_section (const char *name,
1300169689Skan			  unsigned int flags ATTRIBUTE_UNUSED,
1301169689Skan			  tree decl ATTRIBUTE_UNUSED)
1302169689Skan{
1303169689Skan  fprintf (asm_out_file, "\t.section %s\n", name);
1304169689Skan}
1305169689Skan
1306169689Skanvoid
1307169689Skandarwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
1308169689Skan{
1309169689Skan  /* Darwin does not use unique sections.  */
1310169689Skan}
1311169689Skan
1312169689Skan/* Handle __attribute__ ((apple_kext_compatibility)).
1313169689Skan   This only applies to darwin kexts for 2.95 compatibility -- it shrinks the
1314169689Skan   vtable for classes with this attribute (and their descendants) by not
1315169689Skan   outputting the new 3.0 nondeleting destructor.  This means that such
1316169689Skan   objects CANNOT be allocated on the stack or as globals UNLESS they have
1317169689Skan   a completely empty `operator delete'.
1318169689Skan   Luckily, this fits in with the Darwin kext model.
1319169689Skan
1320169689Skan   This attribute also disables gcc3's potential overlaying of derived
1321169689Skan   class data members on the padding at the end of the base class.  */
1322169689Skan
1323169689Skantree
1324169689Skandarwin_handle_kext_attribute (tree *node, tree name,
1325169689Skan			      tree args ATTRIBUTE_UNUSED,
1326169689Skan			      int flags ATTRIBUTE_UNUSED,
1327169689Skan			      bool *no_add_attrs)
1328169689Skan{
1329169689Skan  /* APPLE KEXT stuff -- only applies with pure static C++ code.  */
1330169689Skan  if (! TARGET_KEXTABI)
1331169689Skan    {
1332169689Skan      warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1333169689Skan	       "only when compiling a kext", IDENTIFIER_POINTER (name));
1334169689Skan
1335169689Skan      *no_add_attrs = true;
1336169689Skan    }
1337169689Skan  else if (TREE_CODE (*node) != RECORD_TYPE)
1338169689Skan    {
1339169689Skan      warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1340169689Skan	       "only to C++ classes", IDENTIFIER_POINTER (name));
1341169689Skan
1342169689Skan      *no_add_attrs = true;
1343169689Skan    }
1344169689Skan
1345169689Skan  return NULL_TREE;
1346169689Skan}
1347169689Skan
1348169689Skan/* Handle a "weak_import" attribute; arguments as in
1349169689Skan   struct attribute_spec.handler.  */
1350169689Skan
1351169689Skantree
1352169689Skandarwin_handle_weak_import_attribute (tree *node, tree name,
1353169689Skan				     tree ARG_UNUSED (args),
1354169689Skan				     int ARG_UNUSED (flags),
1355169689Skan				     bool * no_add_attrs)
1356169689Skan{
1357169689Skan  if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
1358169689Skan    {
1359169689Skan      warning (OPT_Wattributes, "%qs attribute ignored",
1360169689Skan	       IDENTIFIER_POINTER (name));
1361169689Skan      *no_add_attrs = true;
1362169689Skan    }
1363169689Skan  else
1364169689Skan    declare_weak (*node);
1365169689Skan
1366169689Skan  return NULL_TREE;
1367169689Skan}
1368169689Skan
1369169689Skanstatic void
1370169689Skanno_dead_strip (FILE *file, const char *lab)
1371169689Skan{
1372169689Skan  fprintf (file, ".no_dead_strip %s\n", lab);
1373169689Skan}
1374169689Skan
1375169689Skan/* Emit a label for an FDE, making it global and/or weak if appropriate.
1376169689Skan   The third parameter is nonzero if this is for exception handling.
1377169689Skan   The fourth parameter is nonzero if this is just a placeholder for an
1378169689Skan   FDE that we are omitting. */
1379169689Skan
1380169689Skanvoid
1381169689Skandarwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1382169689Skan{
1383169689Skan  const char *base;
1384169689Skan  char *lab;
1385169689Skan  bool need_quotes;
1386169689Skan
1387169689Skan  if (DECL_ASSEMBLER_NAME_SET_P (decl))
1388169689Skan    base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1389169689Skan  else
1390169689Skan    base = IDENTIFIER_POINTER (DECL_NAME (decl));
1391169689Skan
1392169689Skan  base = targetm.strip_name_encoding (base);
1393169689Skan  need_quotes = name_needs_quotes (base);
1394169689Skan
1395169689Skan  if (! for_eh)
1396169689Skan    return;
1397169689Skan
1398169689Skan  lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
1399169689Skan		need_quotes ? "\"" : "", NULL);
1400169689Skan
1401169689Skan  if (TREE_PUBLIC (decl))
1402169689Skan    fprintf (file, "\t%s %s\n",
1403169689Skan	     (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1404169689Skan	      ? ".globl"
1405169689Skan	      : ".private_extern"),
1406169689Skan	     lab);
1407169689Skan
1408169689Skan  if (DECL_WEAK (decl))
1409169689Skan    fprintf (file, "\t.weak_definition %s\n", lab);
1410169689Skan
1411169689Skan  if (empty)
1412169689Skan    {
1413169689Skan      fprintf (file, "%s = 0\n", lab);
1414169689Skan
1415169689Skan      /* Mark the absolute .eh and .eh1 style labels as needed to
1416169689Skan	 ensure that we don't dead code strip them and keep such
1417169689Skan	 labels from another instantiation point until we can fix this
1418169689Skan	 properly with group comdat support.  */
1419169689Skan      no_dead_strip (file, lab);
1420169689Skan    }
1421169689Skan  else
1422169689Skan    fprintf (file, "%s:\n", lab);
1423169689Skan
1424169689Skan  free (lab);
1425169689Skan}
1426169689Skan
1427169689Skanstatic GTY(()) unsigned long except_table_label_num;
1428169689Skan
1429169689Skanvoid
1430169689Skandarwin_emit_except_table_label (FILE *file)
1431169689Skan{
1432169689Skan  char section_start_label[30];
1433169689Skan
1434169689Skan  ASM_GENERATE_INTERNAL_LABEL (section_start_label, "GCC_except_table",
1435169689Skan			       except_table_label_num++);
1436169689Skan  ASM_OUTPUT_LABEL (file, section_start_label);
1437169689Skan}
1438169689Skan/* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */
1439169689Skan
1440169689Skanvoid
1441169689Skandarwin_non_lazy_pcrel (FILE *file, rtx addr)
1442169689Skan{
1443169689Skan  const char *nlp_name;
1444169689Skan
1445169689Skan  gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1446169689Skan
1447169689Skan  nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1448169689Skan  fputs ("\t.long\t", file);
1449169689Skan  ASM_OUTPUT_LABELREF (file, nlp_name);
1450169689Skan  fputs ("-.", file);
1451169689Skan}
1452169689Skan
1453132718Skan/* Emit an assembler directive to set visibility for a symbol.  The
1454132718Skan   only supported visibilities are VISIBILITY_DEFAULT and
1455132718Skan   VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1456132718Skan   extern".  There is no MACH-O equivalent of ELF's
1457132718Skan   VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1458132718Skan
1459169689Skanvoid
1460132718Skandarwin_assemble_visibility (tree decl, int vis)
1461132718Skan{
1462132718Skan  if (vis == VISIBILITY_DEFAULT)
1463132718Skan    ;
1464132718Skan  else if (vis == VISIBILITY_HIDDEN)
1465132718Skan    {
1466132718Skan      fputs ("\t.private_extern ", asm_out_file);
1467132718Skan      assemble_name (asm_out_file,
1468132718Skan		     (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1469132718Skan      fputs ("\n", asm_out_file);
1470132718Skan    }
1471132718Skan  else
1472169689Skan    warning (OPT_Wattributes, "internal and protected visibility attributes "
1473169689Skan	     "not supported in this configuration; ignored");
1474132718Skan}
1475132718Skan
1476117395Skan/* Output a difference of two labels that will be an assembly time
1477117395Skan   constant if the two labels are local.  (.long lab1-lab2 will be
1478117395Skan   very different if lab1 is at the boundary between two sections; it
1479117395Skan   will be relocated according to the second section, not the first,
1480117395Skan   so one ends up with a difference between labels in different
1481117395Skan   sections, which is bad in the dwarf2 eh context for instance.)  */
1482117395Skan
1483117395Skanstatic int darwin_dwarf_label_counter;
1484117395Skan
1485117395Skanvoid
1486169689Skandarwin_asm_output_dwarf_delta (FILE *file, int size,
1487132718Skan			       const char *lab1, const char *lab2)
1488117395Skan{
1489169689Skan  int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1490169689Skan		     && lab2[0] == '*' && lab2[1] == 'L');
1491169689Skan  const char *directive = (size == 8 ? ".quad" : ".long");
1492117395Skan
1493117395Skan  if (islocaldiff)
1494117395Skan    fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1495117395Skan  else
1496169689Skan    fprintf (file, "\t%s\t", directive);
1497169689Skan  assemble_name_raw (file, lab1);
1498117395Skan  fprintf (file, "-");
1499169689Skan  assemble_name_raw (file, lab2);
1500117395Skan  if (islocaldiff)
1501169689Skan    fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
1502117395Skan}
1503117395Skan
1504169689Skan/* Output labels for the start of the DWARF sections if necessary.  */
1505132718Skanvoid
1506169689Skandarwin_file_start (void)
1507169689Skan{
1508169689Skan  if (write_symbols == DWARF2_DEBUG)
1509169689Skan    {
1510169689Skan      static const char * const debugnames[] =
1511169689Skan	{
1512169689Skan	  DEBUG_FRAME_SECTION,
1513169689Skan	  DEBUG_INFO_SECTION,
1514169689Skan	  DEBUG_ABBREV_SECTION,
1515169689Skan	  DEBUG_ARANGES_SECTION,
1516169689Skan	  DEBUG_MACINFO_SECTION,
1517169689Skan	  DEBUG_LINE_SECTION,
1518169689Skan	  DEBUG_LOC_SECTION,
1519169689Skan	  DEBUG_PUBNAMES_SECTION,
1520260395Spfg	  DEBUG_PUBTYPES_SECTION,
1521169689Skan	  DEBUG_STR_SECTION,
1522169689Skan	  DEBUG_RANGES_SECTION
1523169689Skan	};
1524169689Skan      size_t i;
1525169689Skan
1526169689Skan      for (i = 0; i < ARRAY_SIZE (debugnames); i++)
1527169689Skan	{
1528169689Skan	  int namelen;
1529169689Skan
1530169689Skan	  switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL));
1531169689Skan
1532169689Skan	  gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0);
1533169689Skan	  gcc_assert (strchr (debugnames[i] + 8, ','));
1534169689Skan
1535169689Skan	  namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8);
1536169689Skan	  fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
1537169689Skan	}
1538169689Skan    }
1539169689Skan}
1540169689Skan
1541169689Skan/* Output an offset in a DWARF section on Darwin.  On Darwin, DWARF section
1542169689Skan   offsets are not represented using relocs in .o files; either the
1543169689Skan   section never leaves the .o file, or the linker or other tool is
1544169689Skan   responsible for parsing the DWARF and updating the offsets.  */
1545169689Skan
1546169689Skanvoid
1547169689Skandarwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
1548169689Skan				section *base)
1549169689Skan{
1550169689Skan  char sname[64];
1551169689Skan  int namelen;
1552169689Skan
1553169689Skan  gcc_assert (base->common.flags & SECTION_NAMED);
1554169689Skan  gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
1555169689Skan  gcc_assert (strchr (base->named.name + 8, ','));
1556169689Skan
1557169689Skan  namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
1558169689Skan  sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
1559169689Skan  darwin_asm_output_dwarf_delta (file, size, lab, sname);
1560169689Skan}
1561169689Skan
1562169689Skanvoid
1563132718Skandarwin_file_end (void)
1564132718Skan{
1565132718Skan  machopic_finish (asm_out_file);
1566132718Skan  if (strcmp (lang_hooks.name, "GNU C++") == 0)
1567132718Skan    {
1568169689Skan      switch_to_section (darwin_sections[constructor_section]);
1569169689Skan      switch_to_section (darwin_sections[destructor_section]);
1570132718Skan      ASM_OUTPUT_ALIGN (asm_out_file, 1);
1571132718Skan    }
1572169689Skan  fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1573132718Skan}
1574132718Skan
1575169689Skan/* TODO: Add a language hook for identifying if a decl is a vtable.  */
1576169689Skan#define DARWIN_VTABLE_P(DECL) 0
1577169689Skan
1578169689Skan/* Cross-module name binding.  Darwin does not support overriding
1579169689Skan   functions at dynamic-link time, except for vtables in kexts.  */
1580169689Skan
1581169689Skanbool
1582169689Skandarwin_binds_local_p (tree decl)
1583169689Skan{
1584169689Skan  return default_binds_local_p_1 (decl,
1585169689Skan				  TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
1586169689Skan}
1587169689Skan
1588169689Skan#if 0
1589169689Skan/* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet.  */
1590169689Skan/* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR.  Define the
1591169689Skan   anchor relative to ".", the current section position.  We cannot use
1592169689Skan   the default one because ASM_OUTPUT_DEF is wrong for Darwin.  */
1593169689Skan
1594169689Skanvoid
1595169689Skandarwin_asm_output_anchor (rtx symbol)
1596169689Skan{
1597169689Skan  fprintf (asm_out_file, "\t.set\t");
1598169689Skan  assemble_name (asm_out_file, XSTR (symbol, 0));
1599169689Skan  fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n",
1600169689Skan	   SYMBOL_REF_BLOCK_OFFSET (symbol));
1601169689Skan}
1602169689Skan#endif
1603169689Skan
1604169689Skan/* Set the darwin specific attributes on TYPE.  */
1605169689Skanvoid
1606169689Skandarwin_set_default_type_attributes (tree type)
1607169689Skan{
1608169689Skan  if (darwin_ms_struct
1609169689Skan      && TREE_CODE (type) == RECORD_TYPE)
1610169689Skan    TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
1611169689Skan                                        NULL_TREE,
1612169689Skan                                        TYPE_ATTRIBUTES (type));
1613169689Skan}
1614169689Skan
1615169689Skan/* True, iff we're generating code for loadable kernel extentions.  */
1616169689Skan
1617169689Skanbool
1618169689Skandarwin_kextabi_p (void) {
1619169689Skan  return flag_apple_kext;
1620169689Skan}
1621169689Skan
1622169689Skanvoid
1623169689Skandarwin_override_options (void)
1624169689Skan{
1625169689Skan  if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0)
1626169689Skan    {
1627169689Skan      warning (0, "command line option %<-fapple-kext%> is only valid for C++");
1628169689Skan      flag_apple_kext = 0;
1629169689Skan    }
1630169689Skan  if (flag_mkernel || flag_apple_kext)
1631169689Skan    {
1632169689Skan      /* -mkernel implies -fapple-kext for C++ */
1633169689Skan      if (strcmp (lang_hooks.name, "GNU C++") == 0)
1634169689Skan	flag_apple_kext = 1;
1635169689Skan
1636169689Skan      flag_no_common = 1;
1637169689Skan
1638169689Skan      /* No EH in kexts.  */
1639169689Skan      flag_exceptions = 0;
1640169689Skan      /* No -fnon-call-exceptions data in kexts.  */
1641169689Skan      flag_non_call_exceptions = 0;
1642169689Skan    }
1643169689Skan}
1644169689Skan
1645117395Skan#include "gt-darwin.h"
1646