aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c266
1 files changed, 170 insertions, 96 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9210c41..d2aeac6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -52,6 +52,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tree-mudflap.h"
#include "cgraph.h"
#include "cfglayout.h"
+#include "basic-block.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -95,25 +96,44 @@ int size_directive_output;
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. */
+/* The following global variable indicates if the first basic block
+ in a function belongs to the cold partition or not. */
-static bool unlikely_section_label_printed = false;
+bool first_function_block_is_cold;
/* The following global variable indicates the label name to be put at
the start of the first cold section within each function, when
- partitioning basic blocks into hot and cold sections. */
+ partitioning basic blocks into hot and cold sections. Used for
+ debug info. */
-static char *unlikely_section_label = NULL;
+char *unlikely_section_label;
+
+/* The following global variable indicates the label name to be put at
+ the start of the first hot section within each function, when
+ partitioning basic blocks into hot and cold sections. Used for
+ debug info. */
+
+char *hot_section_label;
+
+/* The following global variable indicates the label name to be put at
+ the end of the last hot section within each function, when
+ partitioning basic blocks into hot and cold sections. Used for
+ debug info. */
+
+char *hot_section_end_label;
+
+/* The following global variable indicates the label name to be put at
+ the end of the last cold section within each function, when
+ partitioning basic blocks into hot and cold sections. Used for
+ debug info.*/
+
+char *cold_section_end_label;
-/* The following global variable indicates the section name to be used
- for the current cold section, when partitioning hot and cold basic
+/* The following global variable indicates the seciton name to be used
+ for the current cold section, when partitiong hot and cold basic
blocks into separate sections. */
-static char *unlikely_text_section_name = NULL;
+char *unlikely_text_section_name;
/* We give all constants their own alias set. Perhaps redundant with
MEM_READONLY_P, but pre-dates it. */
@@ -140,6 +160,7 @@ static void globalize_decl (tree);
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 *);
+static void initialize_cold_section_name (void);
#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_BSS
static void asm_output_bss (FILE *, tree, const char *,
@@ -156,25 +177,8 @@ static bool asm_emit_uninitialised (tree, const char*,
unsigned HOST_WIDE_INT);
static void mark_weak (tree);
-enum in_section { no_section, in_text, in_unlikely_executed_text, in_data,
- in_named
-#ifdef BSS_SECTION_ASM_OP
- , in_bss
-#endif
-#ifdef CTORS_SECTION_ASM_OP
- , in_ctors
-#endif
-#ifdef DTORS_SECTION_ASM_OP
- , in_dtors
-#endif
-#ifdef READONLY_DATA_SECTION_ASM_OP
- , in_readonly_data
-#endif
-#ifdef EXTRA_SECTIONS
- , EXTRA_SECTIONS
-#endif
-};
static GTY(()) enum in_section in_section = no_section;
+enum in_section last_text_section;
/* Return a nonzero value if DECL has a section attribute. */
#ifndef IN_NAMED_SECTION
@@ -185,6 +189,7 @@ static GTY(()) enum in_section in_section = no_section;
/* Text of section name when in_section == in_named. */
static GTY(()) const char *in_named_name;
+const char *last_text_section_name;
/* Hash table of flags that have been used for a particular named section. */
@@ -202,24 +207,10 @@ static GTY((param_is (struct in_named_entry))) htab_t in_named_htab;
EXTRA_SECTION_FUNCTIONS
#endif
-/* Tell assembler to switch to text section. */
-
-void
-text_section (void)
-{
- if (in_section != in_text)
- {
- in_section = in_text;
- fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
- }
-}
-
-/* Tell assembler to switch to unlikely-to-be-executed text section. */
-
-void
-unlikely_text_section (void)
+static void
+initialize_cold_section_name (void)
{
- const char *name;
+ const char* name;
int len;
if (! unlikely_text_section_name)
@@ -235,18 +226,35 @@ unlikely_text_section (void)
name = TREE_STRING_POINTER (DECL_SECTION_NAME
(current_function_decl));
len = strlen (name);
- unlikely_text_section_name = xmalloc ((len + 10) * sizeof (char));
- strcpy (unlikely_text_section_name, name);
- strcat (unlikely_text_section_name, "_unlikely");
+ unlikely_text_section_name = xmalloc (len + 10);
+ sprintf (unlikely_text_section_name, "%s%s", name, "_unlikely");
}
else
- {
- len = strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
- unlikely_text_section_name = xmalloc (len+1 * sizeof (char));
- strcpy (unlikely_text_section_name,
- UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
- }
+ unlikely_text_section_name =
+ xstrdup (UNLIKELY_EXECUTED_TEXT_SECTION_NAME);
+ }
+}
+
+/* Tell assembler to switch to text section. */
+
+void
+text_section (void)
+{
+ if (in_section != in_text)
+ {
+ in_section = in_text;
+ last_text_section = in_text;
+ fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
}
+}
+
+/* Tell assembler to switch to unlikely-to-be-executed text section. */
+
+void
+unlikely_text_section (void)
+{
+ if (! unlikely_text_section_name)
+ initialize_cold_section_name ();
if ((in_section != in_unlikely_executed_text)
&& (in_section != in_named
@@ -254,12 +262,7 @@ unlikely_text_section (void)
{
named_section (NULL_TREE, unlikely_text_section_name, 0);
in_section = in_unlikely_executed_text;
-
- if (!unlikely_section_label_printed)
- {
- ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label);
- unlikely_section_label_printed = true;
- }
+ last_text_section = in_unlikely_executed_text;
}
}
@@ -437,6 +440,12 @@ named_section_real (const char *name, unsigned int flags, tree decl)
in_section = in_named;
}
}
+
+ if (in_text_section () || in_unlikely_text_section ())
+ {
+ last_text_section = in_section;
+ last_text_section_name = name;
+ }
}
/* Tell assembler to change to section NAME for DECL.
@@ -565,28 +574,40 @@ asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
void
function_section (tree decl)
{
- if (decl == NULL_TREE)
- text_section ();
+ bool unlikely = false;
+
+ if (first_function_block_is_cold)
+ unlikely = true;
+
+#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
+ targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
+#else
+ if (decl != NULL_TREE
+ && DECL_SECTION_NAME (decl) != NULL_TREE)
+ named_section (decl, (char *) 0, 0);
else
- {
- /* ??? Typical use of this function maybe shouldn't be looking
- for unlikely blocks at all - in the event that an entire
- function is going into the unlikely-execute section, that
- should be reflected in its DECL_SECTION_NAME. */
- rtx insns = cfun && cfun->emit ? get_insns () : 0;
- bool unlikely = insns && scan_ahead_for_unlikely_executed_note (insns);
+ text_section ();
+#endif
+}
+void
+current_function_section (tree decl)
+{
#ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
- targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
+ bool unlikely = (in_unlikely_text_section ()
+ || (last_text_section == in_unlikely_executed_text));
+
+ targetm.asm_out.select_section (decl, unlikely, DECL_ALIGN (decl));
#else
- if (unlikely)
- unlikely_text_section ();
- else if (DECL_SECTION_NAME (decl))
- named_section (decl, 0, 0);
- else
- text_section ();
+ if (last_text_section == in_unlikely_executed_text)
+ unlikely_text_section ();
+ else if (last_text_section == in_text)
+ text_section ();
+ else if (last_text_section == in_named)
+ named_section (NULL_TREE, last_text_section_name, 0);
+ else
+ function_section (decl);
#endif
- }
}
/* Switch to read-only data section associated with function DECL. */
@@ -1203,16 +1224,19 @@ void
assemble_start_function (tree decl, const char *fnname)
{
int align;
+ bool hot_label_written = false;
- if (unlikely_text_section_name)
- free (unlikely_text_section_name);
-
- unlikely_section_label_printed = false;
unlikely_text_section_name = NULL;
+ first_function_block_is_cold = false;
+ hot_section_label = reconcat (hot_section_label, fnname, ".hot_section", NULL);
unlikely_section_label = reconcat (unlikely_section_label,
fnname, ".unlikely_section", NULL);
-
+ hot_section_end_label = reconcat (hot_section_end_label,
+ fnname, ".end", NULL);
+ cold_section_end_label = reconcat (cold_section_end_label,
+ fnname, ".end.cold", NULL);
+
/* The following code does not need preprocessing in the assembler. */
app_disable ();
@@ -1220,22 +1244,67 @@ assemble_start_function (tree decl, const char *fnname)
if (CONSTANT_POOL_BEFORE_FUNCTION)
output_constant_pool (fnname, decl);
- /* Make sure the cold text (code) section is properly aligned. This
- is necessary here in the case where the function has both hot and
- cold sections, because we don't want to re-set the alignment when the
- section switch happens mid-function. We don't need to set the hot
- section alignment here, because code further down in this function
- sets the alignment for whichever section comes first, and if there
- is a hot section it is guaranteed to be first. */
+ /* Make sure the not and cold text (code) sections are properly
+ aligned. This is necessary here in the case where the function
+ has both hot and cold sections, because we don't want to re-set
+ the alignment when the section switch happens mid-function. */
if (flag_reorder_blocks_and_partition)
{
unlikely_text_section ();
assemble_align (FUNCTION_BOUNDARY);
+ ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label);
+ if (BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
+ {
+ /* Since the function starts with a cold section, we need to
+ explicitly align the hot section and write out the hot
+ section label. */
+ text_section ();
+ assemble_align (FUNCTION_BOUNDARY);
+ ASM_OUTPUT_LABEL (asm_out_file, hot_section_label);
+ hot_label_written = true;
+ first_function_block_is_cold = true;
+ }
}
+ else if (DECL_SECTION_NAME (decl))
+ {
+ /* Calls to function_section rely on first_function_block_is_cold
+ being accurate. The first block may be cold even if we aren't
+ doing partitioning, if the entire function was decided by
+ choose_function_section (predict.c) to be cold. */
+
+ int i;
+ int len;
+ char *s;
+ initialize_cold_section_name ();
+
+ /* The following is necessary, because 'strcmp
+ (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), blah)' always
+ fails, presumably because TREE_STRING_POINTER is declared to
+ be an array of size 1 of char. */
+
+ len = TREE_STRING_LENGTH (DECL_SECTION_NAME (decl));
+ s = (char *) xmalloc (len + 1);
+
+ for (i = 0; i < len; i ++)
+ s[i] = (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)))[i];
+ s[len] = '\0';
+
+ if (unlikely_text_section_name
+ && (strcmp (s, unlikely_text_section_name) == 0))
+ first_function_block_is_cold = true;
+ }
+
+ last_text_section = no_section;
+ in_section = no_section;
resolve_unique_section (decl, 0, flag_function_sections);
+
+ /* Switch to the correct text section for the start of the function. */
+
function_section (decl);
+ if (!hot_label_written)
+ ASM_OUTPUT_LABEL (asm_out_file, hot_section_label);
/* Tell assembler to move to target machine's alignment for functions. */
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
@@ -1288,12 +1357,7 @@ assemble_start_function (tree decl, const char *fnname)
ASM_OUTPUT_LABEL (asm_out_file, fnname);
#endif /* ASM_DECLARE_FUNCTION_NAME */
- if (in_unlikely_text_section ()
- && !unlikely_section_label_printed)
- {
- ASM_OUTPUT_LABEL (asm_out_file, unlikely_section_label);
- unlikely_section_label_printed = true;
- }
+ insert_section_boundary_note ();
}
/* Output assembler code associated with defining the size of the
@@ -1302,6 +1366,7 @@ assemble_start_function (tree decl, const char *fnname)
void
assemble_end_function (tree decl, const char *fnname)
{
+ enum in_section save_text_section;
#ifdef ASM_DECLARE_FUNCTION_SIZE
ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
#endif
@@ -1310,6 +1375,15 @@ assemble_end_function (tree decl, const char *fnname)
output_constant_pool (fnname, decl);
function_section (decl); /* need to switch back */
}
+ /* Output labels for end of hot/cold text sections (to be used by
+ debug info.) */
+ save_text_section = in_section;
+ unlikely_text_section ();
+ ASM_OUTPUT_LABEL (asm_out_file, cold_section_end_label);
+ text_section ();
+ ASM_OUTPUT_LABEL (asm_out_file, hot_section_end_label);
+ if (save_text_section == in_unlikely_executed_text)
+ unlikely_text_section ();
}
/* Assemble code to leave SIZE bytes of zeros. */