/* Functions for generic Darwin as target machine for GNU C compiler.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
+ 2005
Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
#include "function.h"
#include "ggc.h"
#include "langhooks.h"
+#include "target.h"
#include "tm_p.h"
#include "errors.h"
#include "hashtab.h"
are required by consumers of the generated code. Currently, gdb
uses this to patch in a jump to the overriding function, this
allows all uses of the old name to forward to the replacement,
- including existing function poiinters and virtual methods. See
+ including existing function pointers and virtual methods. See
rs6000_emit_prologue for the code that handles the nop insertions.
The added indirection allows gdb to redirect accesses to static
return 0;
}
-/*
- * flag_pic = 1 ... generate only indirections
- * flag_pic = 2 ... generate indirections and pure code
- */
-
+/* Return true if SYM_REF can be used without an indirection. */
static int
machopic_symbol_defined_p (rtx sym_ref)
{
- return (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
- || (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref));
+ if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
+ return true;
+
+ /* If a symbol references local and is not an extern to this
+ file, then the symbol might be able to declared as defined. */
+ if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
+ {
+ /* If the symbol references a variable and the variable is a
+ common symbol, then this symbol is not defined. */
+ if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
+ {
+ tree decl = SYMBOL_REF_DECL (sym_ref);
+ if (!decl)
+ return true;
+ if (DECL_COMMON (decl))
+ return false;
+ }
+ return true;
+ }
+ return false;
}
/* This module assumes that (const (symbol_ref "foo")) is a legal pic
/* Indicate when fix-and-continue style code generation is being used
and when a reference to data should be indirected so that it can be
- rebound in a new translation unit to refernce the original instance
+ rebound in a new translation unit to reference the original instance
of that data. Symbol names that are for code generation local to
the translation unit are bound to the new translation unit;
currently this means symbols that begin with L or _OBJC_;
switch (machopic_classify_symbol (sym_ref))
{
case MACHOPIC_DEFINED_DATA:
+ case MACHOPIC_DEFINED_FUNCTION:
return 1;
default:
return 0;
{
/* The SYMBOL_REF for the entity referenced. */
rtx symbol;
- /* The IDENTIFIER_NODE giving the name of the stub or non-lazy
- pointer. */
- tree ptr_name;
+ /* The name of the stub or non-lazy pointer. */
+ const char * ptr_name;
/* True iff this entry is for a stub (as opposed to a non-lazy
pointer). */
bool stub_p;
machopic_indirection_hash (const void *slot)
{
const machopic_indirection *p = (const machopic_indirection *) slot;
- return IDENTIFIER_HASH_VALUE (p->ptr_name);
+ return htab_hash_string (p->ptr_name);
}
/* Returns true if the KEY is the same as that associated with
static int
machopic_indirection_eq (const void *slot, const void *key)
{
- return ((const machopic_indirection *) slot)->ptr_name == (tree) key;
+ return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
}
/* Return the name of the non-lazy pointer (if STUB_P is false) or
{
char *buffer;
const char *name = XSTR (sym_ref, 0);
- int namelen = strlen (name);
- tree ptr_name;
+ size_t namelen = strlen (name);
machopic_indirection *p;
+ void ** slot;
/* Construct the name of the non-lazy pointer or stub. */
if (stub_p)
user_label_prefix, name);
}
- /* See if we already have it. */
- ptr_name = maybe_get_identifier (buffer);
- /* If not, create a mapping from the non-lazy pointer to the
- SYMBOL_REF. */
- if (!ptr_name)
+ if (!machopic_indirections)
+ machopic_indirections = htab_create_ggc (37,
+ machopic_indirection_hash,
+ machopic_indirection_eq,
+ /*htab_del=*/NULL);
+
+ slot = htab_find_slot_with_hash (machopic_indirections, buffer,
+ htab_hash_string (buffer), INSERT);
+ if (*slot)
+ {
+ p = (machopic_indirection *) *slot;
+ }
+ else
{
- void **slot;
- ptr_name = get_identifier (buffer);
p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
p->symbol = sym_ref;
- p->ptr_name = ptr_name;
+ p->ptr_name = xstrdup (buffer);
p->stub_p = stub_p;
- p->used = 0;
- if (!machopic_indirections)
- machopic_indirections
- = htab_create_ggc (37,
- machopic_indirection_hash,
- machopic_indirection_eq,
- /*htab_del=*/NULL);
- slot = htab_find_slot_with_hash (machopic_indirections, ptr_name,
- IDENTIFIER_HASH_VALUE (ptr_name),
- INSERT);
- *((machopic_indirection **) slot) = p;
+ p->used = false;
+ *slot = p;
}
- return IDENTIFIER_POINTER (ptr_name);
+ return p->ptr_name;
}
/* Return the name of the stub for the mcount function. */
const char*
machopic_mcount_stub_name (void)
{
- return "&L*mcount$stub";
+ rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
+ return machopic_indirection_name (symbol, /*stub_p=*/true);
}
/* If NAME is the name of a stub or a non-lazy pointer , mark the stub
void
machopic_validate_stub_or_non_lazy_ptr (const char *name)
{
- tree ident = get_identifier (name);
-
machopic_indirection *p;
p = ((machopic_indirection *)
- (htab_find_with_hash (machopic_indirections, ident,
- IDENTIFIER_HASH_VALUE (ident))));
- if (p)
+ (htab_find_with_hash (machopic_indirections, name,
+ htab_hash_string (name))));
+ if (p && ! p->used)
{
- p->used = 1;
- mark_referenced (ident);
- mark_referenced (get_identifier (XSTR (p->symbol, 0)));
+ const char *real_name;
+ tree id;
+
+ p->used = true;
+
+ /* Do what output_addr_const will do when we actually call it. */
+ if (SYMBOL_REF_DECL (p->symbol))
+ mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
+
+ real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
+
+ id = maybe_get_identifier (real_name);
+ if (id)
+ mark_referenced (id);
}
}
if (defined && MACHO_DYNAMIC_NO_PIC_P)
{
#if defined (TARGET_TOC)
- emit_insn (GET_MODE (orig) == DImode
- ? gen_macho_high_di (reg, orig)
- : gen_macho_high (reg, orig));
- emit_insn (GET_MODE (orig) == DImode
- ? gen_macho_low_di (reg, reg, orig)
- : gen_macho_low (reg, reg, orig));
+ emit_insn (gen_macho_high (reg, orig));
+ emit_insn (gen_macho_low (reg, reg, orig));
#else
/* some other cpu -- writeme! */
abort ();
rtx asym = XEXP (orig, 0);
rtx mem;
- emit_insn (mode == DImode
- ? gen_macho_high_di (temp_reg, asym)
- : gen_macho_high (temp_reg, asym));
+ emit_insn (gen_macho_high (temp_reg, asym));
mem = gen_const_mem (GET_MODE (orig),
gen_rtx_LO_SUM (Pmode, temp_reg, asym));
emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
else
#endif /* HAVE_lo_sum */
{
- if (GET_CODE (orig) == REG)
+ if (REG_P (orig)
+ || GET_CODE (orig) == SUBREG)
{
return orig;
}
symbol = p->symbol;
sym_name = XSTR (symbol, 0);
- ptr_name = IDENTIFIER_POINTER (p->ptr_name);
+ ptr_name = p->ptr_name;
if (p->stub_p)
{
else
sprintf (stub, "%s%s", user_label_prefix, ptr_name);
- machopic_output_stub (asm_out_file, sym, stub);
+ machopic_output_stub (asm_out_file, sym, stub);
}
else if (! indirect_data (symbol)
&& (machopic_symbol_defined_p (symbol)
SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
if (!DECL_EXTERNAL (decl)
- && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
+ && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
&& ((TREE_STATIC (decl)
&& (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
|| (!DECL_COMMON (decl) && DECL_INITIAL (decl)
SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
}
-static GTY(()) tree textcoal_section = 0;
-static GTY(()) tree datacoal_section = 0;
-
-void
-darwin_make_decl_one_only (tree decl)
-{
- tree sec = 0;
- if (textcoal_section == 0)
- {
- static const char *ts = "__TEXT,__textcoal_nt,coalesced,no_toc";
- static const char *ds = "__DATA,__datacoal_nt,coalesced,no_toc";
- textcoal_section = build_string (strlen (ts), ts);
- datacoal_section = build_string (strlen (ds), ds);
- }
-
- sec = TREE_CODE (decl) == FUNCTION_DECL
- ? textcoal_section
- : datacoal_section;
- TREE_PUBLIC (decl) = 1;
- DECL_ONE_ONLY (decl) = 1;
- DECL_SECTION_NAME (decl) = sec;
-}
-
void
darwin_mark_decl_preserved (const char *name)
{
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
void (*base_function)(void);
-
- if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
- base_function = readonly_data_section;
+ bool weak_p = DECL_P (exp) && DECL_WEAK (exp);
+ static void (* const base_funs[][2])(void) = {
+ { text_section, text_coal_section },
+ { text_unlikely_section, text_unlikely_coal_section },
+ { readonly_data_section, const_coal_section },
+ { const_data_section, const_data_coal_section },
+ { data_section, data_coal_section }
+ };
+
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ base_function = base_funs[reloc][weak_p];
+ else if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
+ base_function = base_funs[2][weak_p];
else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
- base_function = const_data_section;
+ base_function = base_funs[3][weak_p];
else
- base_function = data_section;
+ base_function = base_funs[4][weak_p];
if (TREE_CODE (exp) == STRING_CST
&& ((size_t) TREE_STRING_LENGTH (exp)
else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
&& flag_merge_constants)
{
- tree size = TYPE_SIZE (TREE_TYPE (exp));
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
if (TREE_CODE (size) == INTEGER_CST &&
TREE_INT_CST_LOW (size) == 4 &&
else
base_function ();
}
+ /* ::operator new and ::operator delete must be coalesced, even
+ if not weak. There are 8 variants that we look for. */
+ else if (TREE_CODE (exp) == FUNCTION_DECL
+ && ! DECL_ONE_ONLY (exp))
+ {
+ const char * name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (exp));
+ if (name[0] == '_' && name[1] == 'Z'
+ && ((name[2] == 'n' && (name[3] == 'a' || name[3] == 'w')
+ && name[4] == 'm')
+ || (name[2] == 'd' && (name[3] == 'a' || name[3] == 'l')
+ && name[4] == 'P' && name[5] == 'v')))
+ {
+ bool delete_p = name[2] == 'd';
+ if (name[5 + delete_p] == 0
+ || strcmp (name + 5 + delete_p, "KSt9nothrow_t") == 0)
+ base_funs[reloc][1] ();
+ else
+ base_function ();
+ }
+ else
+ base_function ();
+ }
else
base_function ();
}
}
void
-darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
+darwin_asm_named_section (const char *name,
+ unsigned int flags ATTRIBUTE_UNUSED,
+ tree decl ATTRIBUTE_UNUSED)
{
- fprintf (asm_out_file, ".section %s\n", name);
+ fprintf (asm_out_file, "\t.section %s\n", name);
}
-unsigned int
-darwin_section_type_flags (tree decl, const char *name, int reloc)
-{
- unsigned int flags = default_section_type_flags (decl, name, reloc);
-
- /* Weak or linkonce variables live in a writable section. */
- if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
- && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
- flags |= SECTION_WRITE;
-
- return flags;
-}
-
void
-darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
+darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
{
- /* Darwin does not use unique sections. However, the target's
- unique_section hook is called for linkonce symbols. We need
- to set an appropriate section for such symbols. */
- if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
- darwin_make_decl_one_only (decl);
+ /* Darwin does not use unique sections. */
}
-#define HAVE_DEAD_STRIP 0
+/* Handle a "weak_import" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+tree
+darwin_handle_weak_import_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool * no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
+ {
+ warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ declare_weak (*node);
+
+ return NULL_TREE;
+}
static void
no_dead_strip (FILE *file, const char *lab)
{
- if (HAVE_DEAD_STRIP)
- fprintf (file, ".no_dead_strip %s\n", lab);
+ fprintf (file, ".no_dead_strip %s\n", lab);
}
/* Emit a label for an FDE, making it global and/or weak if appropriate.
strcat(lab, "\"");
if (TREE_PUBLIC (decl))
- fprintf (file, "%s %s\n",
+ fprintf (file, "\t%s %s\n",
(DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
? ".globl"
: ".private_extern"),
lab);
- if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
- fprintf (file, ".weak_definition %s\n", lab);
+ if (DECL_WEAK (decl))
+ fprintf (file, "\t.weak_definition %s\n", lab);
if (empty)
{
fputs ("\n", asm_out_file);
}
else
- warning ("internal and protected visibility attributes not supported"
+ warning ("internal and protected visibility attributes not supported "
"in this configuration; ignored");
}
static int darwin_dwarf_label_counter;
void
-darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
+darwin_asm_output_dwarf_delta (FILE *file, int size,
const char *lab1, const char *lab2)
{
int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
&& lab2[0] == '*' && lab2[1] == 'L');
+ const char *directive = (size == 8 ? ".quad" : ".long");
if (islocaldiff)
fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
else
- fprintf (file, "\t%s\t", ".long");
- assemble_name (file, lab1);
+ fprintf (file, "\t%s\t", directive);
+ assemble_name_raw (file, lab1);
fprintf (file, "-");
- assemble_name (file, lab2);
+ assemble_name_raw (file, lab2);
if (islocaldiff)
- fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
+ fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
}
void