#include "tm_p.h"
#include "debug.h"
#include "target.h"
+#include "tree-mudflap.h"
#include "cgraph.h"
+#include "cfglayout.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
declarations for e.g. AIX 4.x. */
#endif
-#ifndef TRAMPOLINE_ALIGNMENT
-#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
-#endif
-
#ifndef ASM_STABS_OP
#define ASM_STABS_OP "\t.stabs\t"
#endif
tree last_assemble_variable_decl;
+/* The following global variable indicates if the section label for the
+ "cold" section of code has been output yet to the assembler. The
+ label is useful when running gdb. This is part of the optimization that
+ partitions hot and cold basic blocks into separate sections of the .o
+ file. */
+
+bool unlikely_section_label_printed = false;
+
/* RTX_UNCHANGING_P in a MEM can mean it is stored into, for initialization.
So giving constant the alias set for the type will allow such
initializations to appear to conflict with the load of the constant. We
static void maybe_assemble_visibility (tree);
static int in_named_entry_eq (const void *, const void *);
static hashval_t in_named_entry_hash (const void *);
+#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_BSS
static void asm_output_bss (FILE *, tree, const char *,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
#endif
-#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_ALIGNED_BSS
static void asm_output_aligned_bss (FILE *, tree, const char *,
unsigned HOST_WIDE_INT, int)
unsigned HOST_WIDE_INT);
static void mark_weak (tree);
\f
-enum in_section { no_section, in_text, in_data, in_named
+enum in_section { no_section, in_text, in_unlikely_executed_text, in_data,
+ in_named
#ifdef BSS_SECTION_ASM_OP
, in_bss
#endif
{
in_section = in_text;
fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
+ ASM_OUTPUT_ALIGN (asm_out_file, 2);
+ }
+}
+
+/* Tell assembler to switch to unlikely-to-be-executed text section. */
+
+void
+unlikely_text_section (void)
+{
+ if ((in_section != in_unlikely_executed_text)
+ && (in_section != in_named
+ || strcmp (in_named_name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) != 0))
+ {
+ if (targetm.have_named_sections)
+ named_section (NULL_TREE, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0);
+ else
+ {
+ in_section = in_unlikely_executed_text;
+ fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
+ }
+
+ if (!unlikely_section_label_printed)
+ {
+ fprintf (asm_out_file, "__%s_unlikely_section:\n",
+ current_function_name ());
+ unlikely_section_label_printed = true;
+
+ /* Make sure that we have appropriate alignment for instructions
+ in this section. */
+ assemble_align (FUNCTION_BOUNDARY);
+ }
}
}
if (in_section != in_data)
{
in_section = in_data;
- if (flag_shared_data)
- {
-#ifdef SHARED_SECTION_ASM_OP
- fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);
-#else
- fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
-#endif
- }
- else
- fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
+ fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
}
}
return in_section == in_text;
}
+/* Determine if we're in the unlikely-to-be-executed text section. */
+
+int
+in_unlikely_text_section (void)
+{
+ return in_section == in_unlikely_executed_text;
+}
+
/* Determine if we're in the data section. */
int
if (! set_named_section_flags (name, flags))
abort ();
- (*targetm.asm_out.named_section) (name, flags);
+ targetm.asm_out.named_section (name, flags);
if (flags & SECTION_FORGET)
in_section = no_section;
if (name == NULL)
name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
- flags = (* targetm.section_type_flags) (decl, name, reloc);
+ flags = targetm.section_type_flags (decl, name, reloc);
/* Sanity check user variables for flag changes. Non-user
section flag changes will abort in named_section_flags.
&& targetm.have_named_sections
&& (flag_function_or_data_sections
|| DECL_ONE_ONLY (decl)))
- (*targetm.asm_out.unique_section) (decl, reloc);
+ targetm.asm_out.unique_section (decl, reloc);
}
#ifdef BSS_SECTION_ASM_OP
unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
unsigned HOST_WIDE_INT rounded)
{
- (*targetm.asm_out.globalize_label) (file, name);
+ targetm.asm_out.globalize_label (file, name);
bss_section ();
#ifdef ASM_DECLARE_OBJECT_NAME
last_assemble_variable_decl = decl;
void
function_section (tree decl)
{
- if (decl != NULL_TREE
- && DECL_SECTION_NAME (decl) != NULL_TREE)
- named_section (decl, (char *) 0, 0);
+ if (scan_ahead_for_unlikely_executed_note (get_insns()))
+ unlikely_text_section ();
else
- text_section ();
+ {
+ if (decl != NULL_TREE
+ && DECL_SECTION_NAME (decl) != NULL_TREE)
+ named_section (decl, (char *) 0, 0);
+ else
+ text_section ();
+ }
}
/* Switch to section for variable DECL. RELOC is the same as the
if (IN_NAMED_SECTION (decl))
named_section (decl, NULL, reloc);
else
- (*targetm.asm_out.select_section) (decl, reloc, DECL_ALIGN (decl));
+ targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl));
}
/* Tell assembler to switch to the section for string merging. */
return name;
}
\f
+/* The user has asked for a DECL to have a particular name. Set (or
+ change) it in such a way that we don't prefix an underscore to
+ it. */
+void
+set_user_assembler_name (tree decl, const char *name)
+{
+ char *starred = alloca (strlen (name) + 2);
+ starred[0] = '*';
+ strcpy (starred + 1, name);
+ change_decl_assembler_name (decl, get_identifier (starred));
+ SET_DECL_RTL (decl, NULL_RTX);
+}
+\f
/* Decode an `asm' spec for a declaration as a register name.
Return the register number, or -1 if nothing specified,
or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
There is, however, one exception: this function handles variables
explicitly placed in a particular register by the user.
- ASMSPEC, if not 0, is the string which the user specified as the
- assembler symbol name.
-
This is never called for PARM_DECL nodes. */
void
-make_decl_rtl (tree decl, const char *asmspec)
+make_decl_rtl (tree decl)
{
const char *name = 0;
int reg_number;
SET_DECL_RTL (decl, adjust_address_nv (DECL_RTL (decl),
DECL_MODE (decl), 0));
+ if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
+ return;
+
/* ??? Another way to do this would be to maintain a hashed
table of such critters. Instead of adding stuff to a DECL
to give certain attributes to it, we could use an external
/* Let the target reassign the RTL if it wants.
This is necessary, for example, when one machine specific
decl attribute overrides another. */
- (* targetm.encode_section_info) (decl, DECL_RTL (decl), false);
- return;
- }
+ targetm.encode_section_info (decl, DECL_RTL (decl), false);
- reg_number = decode_reg_name (asmspec);
- if (reg_number == -2)
- {
- /* ASMSPEC is given, and not the name of a register. Mark the
- name with a star so assemble_name won't munge it. */
- char *starred = alloca (strlen (asmspec) + 2);
- starred[0] = '*';
- strcpy (starred + 1, asmspec);
- change_decl_assembler_name (decl, get_identifier (starred));
+ /* Make this function static known to the mudflap runtime. */
+ if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
+ mudflap_enqueue_decl (decl);
+
+ return;
}
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ reg_number = decode_reg_name (name);
+
if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
/* First detect errors in declaring global registers. */
/* Now handle ordinary static variables and functions (in memory).
Also handle vars declared register invalidly. */
- if (reg_number >= 0 || reg_number == -3)
+ if (name[0] == '*' && (reg_number >= 0 || reg_number == -3))
error ("%Jregister name given for non-register variable '%D'", decl, decl);
/* Specifying a section attribute on a variable forces it into a
such as that it is a function name.
If the name is changed, the macro ASM_OUTPUT_LABELREF
will have to know how to strip this information. */
- (* targetm.encode_section_info) (decl, DECL_RTL (decl), true);
+ targetm.encode_section_info (decl, DECL_RTL (decl), true);
+
+ /* Make this function static known to the mudflap runtime. */
+ if (flag_mudflap && TREE_CODE (decl) == VAR_DECL)
+ mudflap_enqueue_decl (decl);
}
/* Make the rtl for variable VAR be volatile.
void
make_var_volatile (tree var)
{
- if (GET_CODE (DECL_RTL (var)) != MEM)
+ if (!MEM_P (DECL_RTL (var)))
abort ();
MEM_VOLATILE_P (DECL_RTL (var)) = 1;
|| (DECL_COMMON (decl)
&& (DECL_INITIAL (decl) == 0
|| DECL_INITIAL (decl) == error_mark_node))))
- || GET_CODE (DECL_RTL (decl)) != MEM)
+ || !MEM_P (DECL_RTL (decl)))
return;
- /* We win when global object is found, but it is usefull to know about weak
+ /* We win when global object is found, but it is useful to know about weak
symbol as well so we can produce nicer unique names. */
if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl))
type = &weak_global_object_name;
char *name;
rtx decl_rtl = DECL_RTL (decl);
- p = (* targetm.strip_name_encoding) (XSTR (XEXP (decl_rtl, 0), 0));
+ p = targetm.strip_name_encoding (XSTR (XEXP (decl_rtl, 0), 0));
name = xstrdup (p);
*type = name;
{
int align;
+ unlikely_section_label_printed = false;
+
/* The following code does not need preprocessing in the assembler. */
app_disable ();
#ifdef ASM_NO_SKIP_IN_TEXT
/* The `space' pseudo in the text section outputs nop insns rather than 0s,
so we must output 0s explicitly in the text section. */
- if (ASM_NO_SKIP_IN_TEXT && in_text_section ())
+ if ((ASM_NO_SKIP_IN_TEXT && in_text_section ())
+ || (ASM_NO_SKIP_IN_TEXT && in_unlikely_text_section ()))
{
unsigned HOST_WIDE_INT i;
for (i = 0; i < size; i++)
rtx decl_rtl;
if (lang_hooks.decls.prepare_assemble_variable)
- (*lang_hooks.decls.prepare_assemble_variable) (decl);
+ lang_hooks.decls.prepare_assemble_variable (decl);
last_assemble_variable_decl = 0;
return;
/* Do nothing for global register variables. */
- if (DECL_RTL_SET_P (decl) && GET_CODE (DECL_RTL (decl)) == REG)
+ if (DECL_RTL_SET_P (decl) && REG_P (DECL_RTL (decl)))
{
TREE_ASM_WRITTEN (decl) = 1;
return;
variable_section (decl, reloc);
/* dbxout.c needs to know this. */
- if (in_text_section ())
+ if (in_text_section () || in_unlikely_text_section ())
DECL_IN_TEXT_SECTION (decl) = 1;
/* Output the alignment of this data. */
if (!dont_output_data)
{
- if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
+ if (DECL_INITIAL (decl)
+ && DECL_INITIAL (decl) != error_mark_node
+ && !initializer_zerop (DECL_INITIAL (decl)))
/* Output the actual data. */
output_constant (DECL_INITIAL (decl),
tree_low_cst (DECL_SIZE_UNIT (decl), 1),
{
rtx rtl = DECL_RTL (decl);
- if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
+ if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
&& !SYMBOL_REF_USED (XEXP (rtl, 0))
&& !incorporeal_function_p (decl))
{
if (! SYMBOL_REF_USED (fun))
{
SYMBOL_REF_USED (fun) = 1;
- (*targetm.asm_out.external_libcall) (fun);
+ targetm.asm_out.external_libcall (fun);
}
}
ASM_OUTPUT_LABEL (asm_out_file, name);
}
-/* Set the symbol_referenced flag for ID and notify callgraph code. */
+/* Set the symbol_referenced flag for ID. */
void
mark_referenced (tree id)
{
- if (!TREE_SYMBOL_REFERENCED (id))
- {
- struct cgraph_node *node;
- struct cgraph_varpool_node *vnode;
-
- if (!cgraph_global_info_ready)
- {
- node = cgraph_node_for_identifier (id);
- if (node)
- cgraph_mark_needed_node (node);
- }
-
- vnode = cgraph_varpool_node_for_identifier (id);
- if (vnode)
- cgraph_varpool_mark_needed_node (vnode);
- }
TREE_SYMBOL_REFERENCED (id) = 1;
}
+/* Set the symbol_referenced flag for DECL and notify callgraph. */
+void
+mark_decl_referenced (tree decl)
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ cgraph_mark_needed_node (cgraph_node (decl));
+ else if (TREE_CODE (decl) == VAR_DECL)
+ cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
+ /* else do nothing - we can get various sorts of CST nodes here,
+ which do not need to be marked. */
+}
+
/* Output to FILE a reference to the assembler name of a C-level name NAME.
If NAME starts with a *, the rest of NAME is output verbatim.
Otherwise NAME is transformed in an implementation-defined way
const char *real_name;
tree id;
- real_name = (* targetm.strip_name_encoding) (name);
+ real_name = targetm.strip_name_encoding (name);
id = maybe_get_identifier (real_name);
if (id)
This is done at most once per compilation.
Returns an RTX for the address of the template. */
+static GTY(()) rtx initial_trampoline;
+
#ifdef TRAMPOLINE_TEMPLATE
rtx
assemble_trampoline_template (void)
int align;
rtx symbol;
+ if (initial_trampoline)
+ return initial_trampoline;
+
/* By default, put trampoline templates in read-only data section. */
#ifdef TRAMPOLINE_SECTION
ASM_OUTPUT_ALIGN (asm_out_file, align);
}
- (*targetm.asm_out.internal_label) (asm_out_file, "LTRAMP", 0);
+ targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
TRAMPOLINE_TEMPLATE (asm_out_file);
/* Record the rtl to refer to it. */
symbol = gen_rtx_SYMBOL_REF (Pmode, name);
SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
- return symbol;
+ initial_trampoline = gen_rtx_MEM (BLKmode, symbol);
+ set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
+
+ return initial_trampoline;
}
#endif
\f
aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT));
/* See if the target hook can handle this kind of object. */
- if ((*targetm.asm_out.integer) (x, size, aligned_p))
+ if (targetm.asm_out.integer (x, size, aligned_p))
return true;
/* If the object is a multi-byte one, try splitting it up. Split
abort ();
}
- if (GET_CODE (x) != MEM)
+ if (!MEM_P (x))
abort ();
x = XEXP (x, 0);
return real_hash (TREE_REAL_CST_PTR (exp));
case STRING_CST:
- if (flag_writable_strings)
- {
- p = (char *) &exp;
- len = sizeof exp;
- }
- else
- {
- p = TREE_STRING_POINTER (exp);
- len = TREE_STRING_LENGTH (exp);
- }
+ p = TREE_STRING_POINTER (exp);
+ len = TREE_STRING_LENGTH (exp);
break;
case COMPLEX_CST:
return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
case STRING_CST:
- if (flag_writable_strings)
- return t1 == t2;
-
if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
return 0;
case NOP_EXPR:
case CONVERT_EXPR:
case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
default:
{
tree nt1, nt2;
- nt1 = (*lang_hooks.expand_constant) (t1);
- nt2 = (*lang_hooks.expand_constant) (t2);
+ nt1 = lang_hooks.expand_constant (t1);
+ nt2 = lang_hooks.expand_constant (t2);
if (nt1 != t1 || nt2 != t2)
return compare_constant (nt1, nt2);
else
case PLUS_EXPR:
case MINUS_EXPR:
- return build (TREE_CODE (exp), TREE_TYPE (exp),
- copy_constant (TREE_OPERAND (exp, 0)),
- copy_constant (TREE_OPERAND (exp, 1)));
+ return build2 (TREE_CODE (exp), TREE_TYPE (exp),
+ copy_constant (TREE_OPERAND (exp, 0)),
+ copy_constant (TREE_OPERAND (exp, 1)));
case NOP_EXPR:
case CONVERT_EXPR:
default:
{
tree t;
- t = (*lang_hooks.expand_constant) (exp);
+ t = lang_hooks.expand_constant (exp);
if (t != exp)
return copy_constant (t);
else
struct constant_descriptor_tree *desc;
desc = ggc_alloc (sizeof (*desc));
- if (flag_writable_strings && TREE_CODE (exp) == STRING_CST)
- desc->value = exp;
- else
- desc->value = copy_constant (exp);
+ desc->value = copy_constant (exp);
+
+ /* Propagate marked-ness to copied constant. */
+ if (flag_mudflap && mf_marked_p (exp))
+ mf_mark (desc->value);
/* Create a string containing the label name, in LABEL. */
labelno = const_labelno++;
information. This call might invalidate our local variable
SYMBOL; we can't use it afterward. */
- (*targetm.encode_section_info) (exp, rtl, true);
+ targetm.encode_section_info (exp, rtl, true);
desc->rtl = rtl;
/* Already output; don't do it again. */
return;
- /* The only constants that cannot safely be deferred, assuming the
- context allows it, are strings under flag_writable_strings. */
- if (defer && (TREE_CODE (exp) != STRING_CST || !flag_writable_strings))
+ /* We can always defer constants as long as the context allows
+ doing so. */
+ if (defer)
{
/* Increment n_deferred_constants if it exists. It needs to be at
least as large as the number of constants actually referred to
if (IN_NAMED_SECTION (exp))
named_section (exp, NULL, reloc);
else
- (*targetm.asm_out.select_section) (exp, reloc, align);
+ targetm.asm_out.select_section (exp, reloc, align);
if (align > BITS_PER_UNIT)
{
/* Output the value of EXP. */
output_constant (exp, size, align);
-}
-
-/* A constant which was deferred in its original location has been
- inserted by the RTL inliner into a different function. The
- current function's deferred constant count must be incremented. */
-void
-notice_rtl_inlining_of_deferred_constant (void)
-{
- n_deferred_constants++;
+ if (flag_mudflap)
+ mudflap_enqueue_constant (exp);
}
/* Look up EXP in the table of constant descriptors. Return the rtl
{
const struct constant_descriptor_rtx *x = a;
const struct constant_descriptor_rtx *y = b;
- return x->sym == y->sym;
+ return XSTR (x->sym, 0) == XSTR (y->sym, 0);
}
/* This is the worker function for const_rtx_hash, called via for_each_rtx. */
void **slot;
/* If we're not allowed to drop X into the constant pool, don't. */
- if ((*targetm.cannot_force_const_mem) (x))
+ if (targetm.cannot_force_const_mem (x))
return NULL_RTX;
/* Lookup the value in the hashtable. */
align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
#ifdef CONSTANT_ALIGNMENT
{
- tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
+ tree type = lang_hooks.types.type_for_mode (mode, 0);
if (type != NULL_TREE)
align = CONSTANT_ALIGNMENT (make_tree (type, x), align);
}
/* Construct the MEM. */
desc->mem = def = gen_rtx_MEM (mode, symbol);
- set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1);
+ set_mem_attributes (def, lang_hooks.types.type_for_mode (mode, 0), 1);
RTX_UNCHANGING_P (def) = 1;
/* If we're dropping a label to the constant pool, make sure we
case LABEL_REF:
tmp = XEXP (x, 0);
if (INSN_DELETED_P (tmp)
- || (GET_CODE (tmp) == NOTE
+ || (NOTE_P (tmp)
&& NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED))
{
abort ();
}
/* First switch to correct section. */
- (*targetm.asm_out.select_rtx_section) (desc->mode, x, desc->align);
+ targetm.asm_out.select_rtx_section (desc->mode, x, desc->align);
#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, desc->mode,
assemble_align (desc->align);
/* Output the label. */
- (*targetm.asm_out.internal_label) (asm_out_file, "LC", desc->labelno);
+ targetm.asm_out.internal_label (asm_out_file, "LC", desc->labelno);
/* Output the data. */
output_constant_pool_2 (desc->mode, x, desc->align);
/* Give the front-end a chance to convert VALUE to something that
looks more like a constant to the back-end. */
- exp = (*lang_hooks.expand_constant) (exp);
+ exp = lang_hooks.expand_constant (exp);
switch (TREE_CODE (exp))
{
/* Give the front-end a chance to convert VALUE to something that
looks more like a constant to the back-end. */
- exp = (*lang_hooks.expand_constant) (exp);
+ exp = lang_hooks.expand_constant (exp);
switch (TREE_CODE (exp))
{
{
/* Give the front-end a chance to convert VALUE to something that
looks more like a constant to the back-end. */
- value = (*lang_hooks.expand_constant) (value);
+ value = lang_hooks.expand_constant (value);
switch (TREE_CODE (value))
{
endtype);
}
- /* Allow conversions to union types if the value inside is okay. */
- if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
+ /* Allow conversions to struct or union types if the value
+ inside is okay. */
+ if (TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
return initializer_constant_valid_p (TREE_OPERAND (value, 0),
endtype);
break;
/* Some front-ends use constants other than the standard language-independent
varieties, but which may still be output directly. Give the front-end a
chance to convert EXP to a language-independent representation. */
- exp = (*lang_hooks.expand_constant) (exp);
+ exp = lang_hooks.expand_constant (exp);
if (size == 0 || flag_syntax_only)
return;
}
/* Now output the underlying data. If we've handling the padding, return.
- Otherwise, break and ensure THISSIZE is the size written. */
+ Otherwise, break and ensure SIZE is the size written. */
switch (code)
{
case CHAR_TYPE:
case OFFSET_TYPE:
if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
EXPAND_INITIALIZER),
- size, align, 0))
+ MIN (size, thissize), align, 0))
error ("initializer for integer value is too complicated");
break;
unsigned int nalign;
enum machine_mode inner;
- inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
+ inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
- elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
+ elt_size = GET_MODE_SIZE (inner);
link = TREE_VECTOR_CST_ELTS (exp);
output_constant (TREE_VALUE (link), elt_size, align);
DECL_WEAK (decl) = 1;
if (DECL_RTL_SET_P (decl)
- && GET_CODE (DECL_RTL (decl)) == MEM
+ && MEM_P (DECL_RTL (decl))
&& XEXP (DECL_RTL (decl), 0)
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
}
return;
}
+#elif defined(ASM_MAKE_LABEL_LINKONCE)
+ if (DECL_ONE_ONLY (decl))
+ ASM_MAKE_LABEL_LINKONCE (asm_out_file, name);
#endif
- (*targetm.asm_out.globalize_label) (asm_out_file, name);
+ targetm.asm_out.globalize_label (asm_out_file, name);
}
/* Emit an assembler directive to make the symbol for DECL an alias to
/* We must force creation of DECL_RTL for debug info generation, even though
we don't use it here. */
- make_decl_rtl (decl, NULL);
+ make_decl_rtl (decl);
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
enum symbol_visibility vis = DECL_VISIBILITY (decl);
if (vis != VISIBILITY_DEFAULT)
- (* targetm.asm_out.visibility) (decl, vis);
+ targetm.asm_out.visibility (decl, vis);
}
/* Returns 1 if the target configuration supports defining public symbols
TREE_PUBLIC (decl) = 1;
- if (TREE_CODE (decl) == VAR_DECL
- && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
- DECL_COMMON (decl) = 1;
- else if (SUPPORTS_ONE_ONLY)
+ if (SUPPORTS_ONE_ONLY)
{
#ifdef MAKE_DECL_ONE_ONLY
MAKE_DECL_ONE_ONLY (decl);
#endif
DECL_ONE_ONLY (decl) = 1;
}
+ else if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+ DECL_COMMON (decl) = 1;
else if (SUPPORTS_WEAK)
DECL_WEAK (decl) = 1;
else
return kind;
}
- is_local = (*targetm.binds_local_p) (decl);
+ is_local = targetm.binds_local_p (decl);
if (!flag_pic)
{
if (is_local)
flags = SECTION_CODE;
else if (decl && decl_readonly_section_1 (decl, reloc, shlib))
flags = 0;
+ else if (strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0)
+ flags = SECTION_CODE;
else
flags = SECTION_WRITE;
readonly = true;
}
else if (TREE_CODE (decl) == STRING_CST)
- readonly = !flag_writable_strings;
+ readonly = true;
else if (! (flag_pic && reloc))
readonly = true;
return SECCAT_TEXT;
else if (TREE_CODE (decl) == STRING_CST)
{
- if (flag_writable_strings)
- return SECCAT_DATA;
+ if (flag_mudflap) /* or !flag_merge_constants */
+ return SECCAT_RODATA;
else
return SECCAT_RODATA_MERGE_STR;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_INITIAL (decl) == NULL
- || DECL_INITIAL (decl) == error_mark_node)
+ || DECL_INITIAL (decl) == error_mark_node
+ || (flag_zero_initialized_in_bss
+ /* Leave constant zeroes in .rodata so they can be shared. */
+ && !TREE_READONLY (decl)
+ && initializer_zerop (DECL_INITIAL (decl))))
ret = SECCAT_BSS;
else if (! TREE_READONLY (decl)
|| TREE_SIDE_EFFECTS (decl)
/* There are no read-only thread-local sections. */
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
{
- if (ret == SECCAT_BSS)
+ /* Note that this would be *just* SECCAT_BSS, except that there's
+ no concept of a read-only thread-local-data section. */
+ if (ret == SECCAT_BSS
+ || (flag_zero_initialized_in_bss
+ && initializer_zerop (DECL_INITIAL (decl))))
ret = SECCAT_TBSS;
else
ret = SECCAT_TDATA;
}
/* If the target uses small data sections, select it. */
- else if ((*targetm.in_small_data_p) (decl))
+ else if (targetm.in_small_data_p (decl))
{
if (ret == SECCAT_BSS)
ret = SECCAT_SBSS;
plen = strlen (prefix);
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = (* targetm.strip_name_encoding) (name);
+ name = targetm.strip_name_encoding (name);
nlen = strlen (name);
string = alloca (nlen + plen + 1);
int flags;
/* Careful not to prod global register variables. */
- if (GET_CODE (rtl) != MEM)
+ if (!MEM_P (rtl))
return;
symbol = XEXP (rtl, 0);
if (GET_CODE (symbol) != SYMBOL_REF)
flags = 0;
if (TREE_CODE (decl) == FUNCTION_DECL)
flags |= SYMBOL_FLAG_FUNCTION;
- if ((*targetm.binds_local_p) (decl))
+ if (targetm.binds_local_p (decl))
flags |= SYMBOL_FLAG_LOCAL;
- if ((*targetm.in_small_data_p) (decl))
+ if (targetm.in_small_data_p (decl))
flags |= SYMBOL_FLAG_SMALL;
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
flags |= decl_tls_model (decl) << SYMBOL_FLAG_TLS_SHIFT;
/* Static variables are always local. */
else if (! TREE_PUBLIC (exp))
local_p = true;
- /* A variable is local if the user tells us so. */
- else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+ /* A variable is local if the user explicitly tells us so. */
+ else if (DECL_VISIBILITY_SPECIFIED (exp) && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
local_p = true;
/* Otherwise, variables defined outside this object may not be local. */
else if (DECL_EXTERNAL (exp))
/* Linkonce and weak data are never local. */
else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
local_p = false;
+ /* If none of the above and visibility is not default, make local. */
+ else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
+ local_p = true;
/* If PIC, then assume that any global name can be overridden by
symbols resolved from other modules. */
else if (shlib)
}
#endif /* GLOBAL_ASM_OP */
+/* Default function to output a label for unwind information. The
+ default is to do nothing. A target that needs nonlocal labels for
+ unwind information must provide its own function to do this. */
+void
+default_emit_unwind_label (FILE * stream ATTRIBUTE_UNUSED,
+ tree decl ATTRIBUTE_UNUSED,
+ int for_eh ATTRIBUTE_UNUSED,
+ int empty ATTRIBUTE_UNUSED)
+{
+}
+
/* This is how to output an internal numbered label where PREFIX is
the class of label and LABELNO is the number within the class. */
which emits a special section directive used to indicate whether or
not this object file needs an executable stack. This is primarily
a GNU extension to ELF but could be used on other targets. */
+
+int trampolines_created;
+
void
file_end_indicate_exec_stack (void)
{