static int iris6_section_align_1 PARAMS ((void **, void *));
static void iris6_file_start PARAMS ((void));
static void iris6_file_end PARAMS ((void));
+static unsigned int iris6_section_type_flags PARAMS ((tree, const char *,
+ int));
#endif
static int mips_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int mips_issue_rate PARAMS ((void));
static struct machine_function * mips_init_machine_status PARAMS ((void));
static void mips_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT))
ATTRIBUTE_UNUSED;
-static void mips_unique_section PARAMS ((tree, int))
- ATTRIBUTE_UNUSED;
static void mips_select_rtx_section PARAMS ((enum machine_mode, rtx,
unsigned HOST_WIDE_INT));
static int mips_use_dfa_pipeline_interface PARAMS ((void));
static bool mips_rtx_costs PARAMS ((rtx, int, int, int *));
static int mips_address_cost PARAMS ((rtx));
+static bool mips_in_small_data_p PARAMS ((tree));
static void mips_encode_section_info PARAMS ((tree, rtx, int));
static void mips_file_start PARAMS ((void));
static void mips_file_end PARAMS ((void));
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO mips_encode_section_info
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P mips_in_small_data_p
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG mips_reorg
#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+#ifdef TARGET_IRIX6
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS iris6_section_type_flags
+#endif
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f
/* If X is one of the constants described by mips_constant_type,
return SYMBOL_GOT_LOCAL;
}
+ if (SYMBOL_REF_SMALL_P (x))
+ return SYMBOL_SMALL_DATA;
+
if (TARGET_ABICALLS)
return (SYMBOL_REF_FLAG (x) ? SYMBOL_GOT_LOCAL : SYMBOL_GOT_GLOBAL);
- return (SYMBOL_REF_FLAG (x) ? SYMBOL_SMALL_DATA : SYMBOL_GENERAL);
+ return SYMBOL_GENERAL;
}
mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
- if (mips_section_threshold <= 0)
- target_flags &= ~MASK_GPOPT;
- else if (optimize)
- target_flags |= MASK_GPOPT;
-
/* Interpret -mabi. */
mips_abi = MIPS_ABI_DEFAULT;
if (mips_abi_string != 0)
do this, it was very invasive and fragile. It no longer seems
worth the effort. */
if (!TARGET_EXPLICIT_RELOCS && !TARGET_GAS)
- {
- mips_section_threshold = 0;
- target_flags &= ~MASK_GPOPT;
- }
+ mips_section_threshold = 0;
/* -membedded-pic is a form of PIC code suitable for embedded
systems. All calls are made using PC relative addressing, and
return default_assemble_integer (x, size, aligned_p);
}
\f
-/* If optimizing for the global pointer, keep track of all of the externs, so
- that at the end of the file, we can emit the appropriate .extern
- declaration for them, before writing out the text section. We assume all
- names passed to us are in the permanent obstack, so they will be valid at
- the end of the compilation.
+/* When using assembler macros, keep track of all of small-data externs
+ so that mips_file_end can emit the appropriate declarations for them.
- If we have -G 0, or the extern size is unknown, or the object is in a user
- specified section that is not .sbss/.sdata, don't bother emitting the
- .externs. In the case of user specified sections this behavior is
- required as otherwise GAS will think the object lives in .sbss/.sdata. */
+ In most cases it would be safe (though pointless) to emit .externs
+ for other symbols too. One exception is when an object is within
+ the -G limit but declared by the user to be in a section other
+ than .sbss or .sdata. */
int
mips_output_external (file, decl, name)
const char *name;
{
register struct extern_list *p;
- int len;
- tree section_name;
- if (TARGET_GP_OPT
- && TREE_CODE (decl) != FUNCTION_DECL
- && !DECL_COMDAT (decl)
- && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
- && ((section_name = DECL_SECTION_NAME (decl)) == NULL
- || strcmp (TREE_STRING_POINTER (section_name), ".sbss") == 0
- || strcmp (TREE_STRING_POINTER (section_name), ".sdata") == 0))
+ if (!TARGET_EXPLICIT_RELOCS && mips_in_small_data_p (decl))
{
p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
p->next = extern_head;
p->name = name;
- p->size = len;
+ p->size = int_size_in_bytes (TREE_TYPE (decl));
extern_head = p;
}
}
}
-/* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
- is used, so that we don't emit an .extern for it in mips_file_end. */
+/* Emit either a label, .comm, or .lcomm directive. When using assembler
+ macros, mark the symbol as written so that mips_file_end won't emit an
+ .extern for it. */
void
mips_declare_object (stream, name, init_string, final_string, size)
assemble_name (stream, name);
fprintf (stream, final_string, size); /* ":\n", ",%u\n", ",%u\n" */
- if (TARGET_GP_OPT)
+ if (!TARGET_EXPLICIT_RELOCS)
{
tree name_tree = get_identifier (name);
TREE_ASM_WRITTEN (name_tree) = 1;
if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold
&& mips_section_threshold > 0)
- SMALL_DATA_SECTION ();
+ named_section (0, ".sdata", 0);
else if (flag_pic && symbolic_expression_p (x))
{
if (targetm.have_named_sections)
- named_section (NULL_TREE, ".data.rel.ro", 3);
+ named_section (0, ".data.rel.ro", 3);
else
data_section ();
}
}
/* Choose the section to use for DECL. RELOC is true if its value contains
- any relocatable expression.
-
- ??? This would be fixed by implementing targetm.is_small_data_p. */
+ any relocatable expression. */
static void
mips_select_section (decl, reloc, align)
int reloc;
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
{
- int size = int_size_in_bytes (TREE_TYPE (decl));
-
if ((TARGET_EMBEDDED_PIC || TARGET_MIPS16)
&& TREE_CODE (decl) == STRING_CST
&& !flag_writable_strings)
For mips16 code, put strings in the text section so that a PC
relative load instruction can be used to get their address. */
text_section ();
- else if (TARGET_EMBEDDED_DATA)
+ else
+ default_elf_select_section (decl, reloc, align);
+}
+
+
+/* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
+ access DECL using %gp_rel(...)($gp). */
+
+static bool
+mips_in_small_data_p (decl)
+ tree decl;
+{
+ HOST_WIDE_INT size;
+
+ if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
{
- /* For embedded applications, always put an object in read-only data
- if possible, in order to reduce RAM usage. */
-
- if (((TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl))))
- /* Deal with calls from output_constant_def_contents. */
- || (TREE_CODE (decl) != VAR_DECL
- && (TREE_CODE (decl) != STRING_CST
- || !flag_writable_strings)))
- && ! (flag_pic && reloc))
- readonly_data_section ();
- else if (size > 0 && size <= mips_section_threshold)
- SMALL_DATA_SECTION ();
- else
- data_section ();
+ const char *name;
+
+ /* Reject anything that isn't in a known small-data section. */
+ name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
+ return false;
+
+ /* If a symbol is defined externally, the assembler will use the
+ usual -G rules when deciding how to implement macros. */
+ if (TARGET_EXPLICIT_RELOCS || !DECL_EXTERNAL (decl))
+ return true;
}
- else
+ else if (TARGET_EMBEDDED_DATA)
{
- /* For hosted applications, always put an object in small data if
- possible, as this gives the best performance. */
+ /* Don't put constants into the small data section: we want them
+ to be in ROM rather than RAM. */
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
- if (size > 0 && size <= mips_section_threshold)
- SMALL_DATA_SECTION ();
- else if (((TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl))))
- /* Deal with calls from output_constant_def_contents. */
- || (TREE_CODE (decl) != VAR_DECL
- && (TREE_CODE (decl) != STRING_CST
- || !flag_writable_strings)))
- && ! (flag_pic && reloc))
- readonly_data_section ();
- else
- data_section ();
+ if (TREE_READONLY (decl)
+ && !TREE_SIDE_EFFECTS (decl)
+ && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
+ return false;
}
+ else if (TARGET_MIPS16)
+ {
+ /* Alhough it seems strange to have separate rules for -mips16,
+ this behaviour is long-standing. */
+ if (TREE_PUBLIC (decl)
+ && (DECL_COMMON (decl)
+ || DECL_ONE_ONLY (decl)
+ || DECL_WEAK (decl)))
+ return false;
+ }
+
+ size = int_size_in_bytes (TREE_TYPE (decl));
+ return (size > 0 && size <= mips_section_threshold);
}
-/* When optimizing for the $gp pointer, SYMBOL_REF_FLAG is set for all
- small objects.
- When generating embedded PIC code, SYMBOL_REF_FLAG is set for
+/* When generating embedded PIC code, SYMBOL_REF_FLAG is set for
symbols which are not in the .text section.
When generating mips16 code, SYMBOL_REF_FLAG is set for string
whether we need to split the constant table, and need not be
precisely correct.
- When not mips16 code nor embedded PIC, if a symbol is in a
- gp addressable section, SYMBOL_REF_FLAG is set prevent gcc from
- splitting the reference so that gas can generate a gp relative
- reference.
-
- When TARGET_EMBEDDED_DATA is set, we assume that all const
- variables will be stored in ROM, which is too far from %gp to use
- %gprel addressing. Note that (1) we include "extern const"
- variables in this, which mips_select_section doesn't, and (2) we
- can't always tell if they're really const (they might be const C++
- objects with non-const constructors), so we err on the side of
- caution and won't use %gprel anyway (otherwise we'd have to defer
- this decision to the linker/loader). The handling of extern consts
- is why the DECL_INITIAL macros differ from mips_select_section. */
+ When generating -mabicalls code, SYMBOL_REF_FLAG is set if we
+ should treat the symbol as SYMBOL_GOT_LOCAL. */
static void
mips_encode_section_info (decl, rtl, first)
}
}
- if (TARGET_EMBEDDED_DATA
- && (TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl))
- && (!DECL_INITIAL (decl)
- || TREE_CONSTANT (DECL_INITIAL (decl))))
- {
- SYMBOL_REF_FLAG (symbol) = 0;
- }
-
- else if (TARGET_EMBEDDED_PIC)
+ if (TARGET_EMBEDDED_PIC)
{
if (TREE_CODE (decl) == VAR_DECL)
SYMBOL_REF_FLAG (symbol) = 1;
SYMBOL_REF_FLAG (symbol) = 1;
}
- else if (TREE_CODE (decl) == VAR_DECL
- && DECL_SECTION_NAME (decl) != NULL_TREE
- && (0 == strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sdata")
- || 0 == strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
- ".sbss")))
- {
- SYMBOL_REF_FLAG (symbol) = 1;
- }
-
- /* We can not perform GP optimizations on variables which are in
- specific sections, except for .sdata and .sbss which are
- handled above. */
- else if (TARGET_GP_OPT && TREE_CODE (decl) == VAR_DECL
- && DECL_SECTION_NAME (decl) == NULL_TREE
- && ! (TARGET_MIPS16 && TREE_PUBLIC (decl)
- && (DECL_COMMON (decl)
- || DECL_ONE_ONLY (decl)
- || DECL_WEAK (decl))))
- {
- int size = int_size_in_bytes (TREE_TYPE (decl));
-
- if (size > 0 && size <= mips_section_threshold)
- SYMBOL_REF_FLAG (symbol) = 1;
- }
-
+ default_encode_section_info (decl, rtl, first);
}
return cost;
}
-/* ??? This could be replaced with the default elf version if
- TARGET_IS_SMALL_DATA_P is set properly. */
-
-static void
-mips_unique_section (decl, reloc)
- tree decl;
- int reloc;
-{
- int len, size, sec;
- const char *name, *prefix;
- char *string;
- static const char *const prefixes[4][2] = {
- { ".text.", ".gnu.linkonce.t." },
- { ".rodata.", ".gnu.linkonce.r." },
- { ".data.", ".gnu.linkonce.d." },
- { ".sdata.", ".gnu.linkonce.s." }
- };
-
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = (* targetm.strip_name_encoding) (name);
- size = int_size_in_bytes (TREE_TYPE (decl));
-
- /* Determine the base section we are interested in:
- 0=text, 1=rodata, 2=data, 3=sdata, [4=bss]. */
- if (TREE_CODE (decl) == FUNCTION_DECL)
- sec = 0;
- else if (DECL_INITIAL (decl) == 0
- || DECL_INITIAL (decl) == error_mark_node)
- sec = 2;
- else if ((TARGET_EMBEDDED_PIC || TARGET_MIPS16)
- && TREE_CODE (decl) == STRING_CST
- && !flag_writable_strings)
- {
- /* For embedded position independent code, put constant
- strings in the text section, because the data section
- is limited to 64K in size. For mips16 code, put
- strings in the text section so that a PC relative load
- instruction can be used to get their address. */
- sec = 0;
- }
- else if (TARGET_EMBEDDED_DATA)
- {
- /* For embedded applications, always put an object in
- read-only data if possible, in order to reduce RAM
- usage. */
-
- if (decl_readonly_section (decl, reloc))
- sec = 1;
- else if (size > 0 && size <= mips_section_threshold)
- sec = 3;
- else
- sec = 2;
- }
- else
- {
- /* For hosted applications, always put an object in
- small data if possible, as this gives the best
- performance. */
-
- if (size > 0 && size <= mips_section_threshold)
- sec = 3;
- else if (decl_readonly_section (decl, reloc))
- sec = 1;
- else
- sec = 2;
- }
-
- prefix = prefixes[sec][DECL_ONE_ONLY (decl)];
- len = strlen (name) + strlen (prefix);
- string = alloca (len + 1);
- sprintf (string, "%s%s", prefix, name);
-
- DECL_SECTION_NAME (decl) = build_string (len, string);
-}
-
unsigned int
mips_hard_regno_nregs (regno, mode)
int regno;
mips_file_end ();
}
+
+
+/* Implement TARGET_SECTION_TYPE_FLAGS. Make sure that .sdata and
+ .sbss sections get the SECTION_SMALL flag: this isn't set by the
+ default code. */
+
+static unsigned int
+iris6_section_type_flags (decl, section, relocs_p)
+ tree decl;
+ const char *section;
+ int relocs_p;
+{
+ unsigned int flags;
+
+ flags = default_section_type_flags (decl, section, relocs_p);
+
+ if (strcmp (section, ".sdata") == 0
+ || strcmp (section, ".sbss") == 0
+ || strncmp (section, ".gnu.linkonce.s.", 16) == 0
+ || strncmp (section, ".gnu.linkonce.sb.", 17) == 0)
+ flags |= SECTION_SMALL;
+
+ return flags;
+}
+
+
#endif /* TARGET_IRIX6 */
#include "gt-mips.h"
extern const struct mips_cpu_info *mips_arch_info;
extern const struct mips_cpu_info *mips_tune_info;
-/* Functions to change what output section we are using. */
-extern void sdata_section PARAMS ((void));
-extern void sbss_section PARAMS ((void));
-
/* Macros to silence warnings about numbers being signed in traditional
C and unsigned in ISO C when compiled on 32-bit hosts. */
#define MASK_INT64 0x00000001 /* ints are 64 bits */
#define MASK_LONG64 0x00000002 /* longs are 64 bits */
#define MASK_SPLIT_ADDR 0x00000004 /* Address splitting is enabled. */
-#define MASK_GPOPT 0x00000008 /* Optimize for global pointer */
+#define MASK_NO_FUSED_MADD 0x00000008 /* Don't generate floating point
+ multiply-add operations. */
#define MASK_GAS 0x00000010 /* Gas used instead of MIPS as */
#define MASK_NAME_REGS 0x00000020 /* Use MIPS s/w reg name convention */
#define MASK_EXPLICIT_RELOCS 0x00000040 /* Use relocation operators. */
#define MASK_UNINIT_CONST_IN_RODATA \
0x00800000 /* Store uninitialized
consts in rodata */
-#define MASK_NO_FUSED_MADD 0x01000000 /* Don't generate floating point
- multiply-add operations. */
/* Debug switches, not documented */
#define MASK_DEBUG 0 /* unused */
/* Reg. Naming in .s ($21 vs. $a0) */
#define TARGET_NAME_REGS (target_flags & MASK_NAME_REGS)
- /* Optimize for Sdata/Sbss */
-#define TARGET_GP_OPT (target_flags & MASK_GPOPT)
-
/* call memcpy instead of inline code */
#define TARGET_MEMCPY (target_flags & MASK_MEMCPY)
N_("Use symbolic register names")}, \
{"no-rnames", -MASK_NAME_REGS, \
N_("Don't use symbolic register names")}, \
- {"gpOPT", MASK_GPOPT, \
- N_("Use GP relative sdata/sbss sections")}, \
- {"gpopt", MASK_GPOPT, \
- N_("Use GP relative sdata/sbss sections")}, \
- {"no-gpOPT", -MASK_GPOPT, \
- N_("Don't use GP relative sdata/sbss sections")}, \
- {"no-gpopt", -MASK_GPOPT, \
- N_("Don't use GP relative sdata/sbss sections")}, \
+ {"gpOPT", 0, \
+ N_("Use GP relative sdata/sbss sections (now ignored)")}, \
+ {"gpopt", 0, \
+ N_("Use GP relative sdata/sbss sections (now ignored)")}, \
+ {"no-gpOPT", 0, \
+ N_("Don't use GP relative sdata/sbss sections (now ignored)")}, \
+ {"no-gpopt", 0, \
+ N_("Don't use GP relative sdata/sbss sections (now ignored)")}, \
{"stats", 0, \
N_("Output compiler statistics (now ignored)")}, \
{"no-stats", 0, \
#undef READONLY_DATA_SECTION_ASM_OP
#define READONLY_DATA_SECTION_ASM_OP "\t.rdata" /* read-only data */
-#define SMALL_DATA_SECTION sdata_section
-
-/* What other sections we support other than the normal .data/.text. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_sdata
-
-/* Define the additional functions to select our additional sections. */
-
-/* on the MIPS it is not a good idea to put constants in the text
- section, since this defeats the sdata/data mechanism. This is
- especially true when -O is used. In this case an effort is made to
- address with faster (gp) register relative addressing, which can
- only get at sdata and sbss items (there is no stext !!) However,
- if the constant is too large for sdata, and it's readonly, it
- will go into the .rdata section. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
-void \
-sdata_section () \
-{ \
- if (in_section != in_sdata) \
- { \
- fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
- in_section = in_sdata; \
- } \
-}
-
/* Given a decl node or constant node, choose the section to output it in
and select that section. */