summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/final.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/final.c')
-rw-r--r--contrib/gcc/final.c544
1 files changed, 345 insertions, 199 deletions
diff --git a/contrib/gcc/final.c b/contrib/gcc/final.c
index d86ed5e..94a0f4c 100644
--- a/contrib/gcc/final.c
+++ b/contrib/gcc/final.c
@@ -68,6 +68,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "debug.h"
#include "expr.h"
+#include "profile.h"
+#include "cfglayout.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -98,6 +100,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
+#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
+#define HAVE_READONLY_DATA_SECTION 1
+#else
+#define HAVE_READONLY_DATA_SECTION 0
+#endif
+
/* Last insn processed by final_scan_insn. */
static rtx debug_insn;
rtx current_output_insn;
@@ -114,15 +122,12 @@ static int high_function_linenum;
/* Filename of last NOTE. */
static const char *last_filename;
-/* Number of instrumented arcs when profile_arc_flag is set. */
-extern int count_instrumented_edges;
-
extern int length_unit_log; /* This is defined in insn-attrtab.c. */
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't abort.
The precise value is the insn being output, to pass to error_for_asm. */
-static rtx this_is_asm_operands;
+rtx this_is_asm_operands;
/* Number of operands of this insn, for an `asm' with operands. */
static unsigned int insn_noperands;
@@ -198,6 +203,17 @@ static char *line_note_exists;
rtx current_insn_predicate;
#endif
+struct function_list
+{
+ struct function_list *next; /* next function */
+ const char *name; /* function name */
+ long cfg_checksum; /* function checksum */
+ long count_edges; /* number of intrumented edges in this function */
+};
+
+static struct function_list *functions_head = 0;
+static struct function_list **functions_tail = &functions_head;
+
#ifdef HAVE_ATTR_length
static int asm_insn_count PARAMS ((rtx));
#endif
@@ -206,6 +222,7 @@ static void profile_after_prologue PARAMS ((FILE *));
static void notice_source_line PARAMS ((rtx));
static rtx walk_alter_subreg PARAMS ((rtx *));
static void output_asm_name PARAMS ((void));
+static void output_alternate_entry_point PARAMS ((FILE *, rtx));
static tree get_mem_expr_from_op PARAMS ((rtx, int *));
static void output_asm_operand_names PARAMS ((rtx *, int *, int));
static void output_operand PARAMS ((rtx, int));
@@ -237,137 +254,268 @@ init_final (filename)
}
/* Called at end of source file,
- to output the block-profiling table for this entire compilation. */
+ to output the arc-profiling table for this entire compilation. */
void
end_final (filename)
const char *filename;
{
- if (profile_arc_flag)
+ if (profile_arc_flag && profile_info.count_instrumented_edges)
{
char name[20];
- int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
- int size, rounded;
- int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
- int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
- int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
- unsigned int align2 = LONG_TYPE_SIZE;
-
- size = gcov_type_bytes * count_instrumented_edges;
- rounded = size;
-
- rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
- rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
- * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-
- /* ??? This _really_ ought to be done with a structure layout
- and with assemble_constructor. If long_bytes != pointer_bytes
- we'll be emitting unaligned data at some point. */
- if (long_bytes != pointer_bytes)
- abort ();
+ tree string_type, string_cst;
+ tree structure_decl, structure_value, structure_pointer_type;
+ tree field_decl, decl_chain, value_chain;
+ tree sizeof_field_value, domain_type;
- data_section ();
+ /* Build types. */
+ string_type = build_pointer_type (char_type_node);
- /* Output the main header, of 11 words:
- 0: 1 if this file is initialized, else 0.
- 1: address of file name (LPBX1).
- 2: address of table of counts (LPBX2).
- 3: number of counts in the table.
- 4: always 0, for compatibility with Sun.
+ /* Libgcc2 bb structure. */
+ structure_decl = make_node (RECORD_TYPE);
+ structure_pointer_type = build_pointer_type (structure_decl);
- The following are GNU extensions:
-
- 5: address of table of start addrs of basic blocks (LPBX3).
- 6: Number of bytes in this header.
- 7: address of table of function names (LPBX4).
- 8: address of table of line numbers (LPBX5) or 0.
- 9: address of table of file names (LPBX6) or 0.
- 10: space reserved for basic block profiling. */
+ /* Output the main header, of 7 words:
+ 0: 1 if this file is initialized, else 0.
+ 1: address of file name (LPBX1).
+ 2: address of table of counts (LPBX2).
+ 3: number of counts in the table.
+ 4: always 0, libgcc2 uses this as a pointer to next ``struct bb''
- ASM_OUTPUT_ALIGN (asm_out_file, align);
+ The following are GNU extensions:
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
+ 5: Number of bytes in this header.
+ 6: address of table of function checksums (LPBX7). */
- /* Zero word. */
- assemble_integer (const0_rtx, long_bytes, align2, 1);
+ /* The zero word. */
+ decl_chain =
+ build_decl (FIELD_DECL, get_identifier ("zero_word"),
+ long_integer_type_node);
+ value_chain = build_tree_list (decl_chain,
+ convert (long_integer_type_node,
+ integer_zero_node));
/* Address of filename. */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- align2, 1);
+ {
+ char *cwd, *da_filename;
+ int da_filename_len;
+
+ field_decl =
+ build_decl (FIELD_DECL, get_identifier ("filename"), string_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ cwd = getpwd ();
+ da_filename_len = strlen (filename) + strlen (cwd) + 4 + 1;
+ da_filename = (char *) alloca (da_filename_len);
+ strcpy (da_filename, cwd);
+ strcat (da_filename, "/");
+ strcat (da_filename, filename);
+ strcat (da_filename, ".da");
+ da_filename_len = strlen (da_filename);
+ string_cst = build_string (da_filename_len + 1, da_filename);
+ domain_type = build_index_type (build_int_2 (da_filename_len, 0));
+ TREE_TYPE (string_cst)
+ = build_array_type (char_type_node, domain_type);
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR, string_type, string_cst),
+ value_chain);
+ }
- /* Address of count table. */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- align2, 1);
+ /* Table of counts. */
+ {
+ tree gcov_type_type = make_unsigned_type (GCOV_TYPE_SIZE);
+ tree gcov_type_pointer_type = build_pointer_type (gcov_type_type);
+ tree domain_tree
+ = build_index_type (build_int_2 (profile_info.
+ count_instrumented_edges - 1, 0));
+ tree gcov_type_array_type
+ = build_array_type (gcov_type_type, domain_tree);
+ tree gcov_type_array_pointer_type
+ = build_pointer_type (gcov_type_array_type);
+ tree counts_table;
+
+ field_decl =
+ build_decl (FIELD_DECL, get_identifier ("counts"),
+ gcov_type_pointer_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ /* No values. */
+ counts_table
+ = build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
+ TREE_STATIC (counts_table) = 1;
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
+ DECL_NAME (counts_table) = get_identifier (name);
+ assemble_variable (counts_table, 0, 0, 0);
+
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR,
+ gcov_type_array_pointer_type,
+ counts_table), value_chain);
+ }
/* Count of the # of instrumented arcs. */
- assemble_integer (GEN_INT (count_instrumented_edges),
- long_bytes, align2, 1);
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("ncounts"),
+ long_integer_type_node);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ value_chain = tree_cons (field_decl,
+ convert (long_integer_type_node,
+ build_int_2 (profile_info.
+ count_instrumented_edges,
+ 0)), value_chain);
+ /* Pointer to the next bb. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("next"),
+ structure_pointer_type);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ value_chain = tree_cons (field_decl, null_pointer_node, value_chain);
+
+ /* sizeof(struct bb). We'll set this after entire structure
+ is laid out. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("sizeof_bb"),
+ long_integer_type_node);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
+
+ sizeof_field_value = tree_cons (field_decl, NULL, value_chain);
+ value_chain = sizeof_field_value;
+
+ /* struct bb_function []. */
+ {
+ struct function_list *item;
+ int num_nodes;
+ tree checksum_field, arc_count_field, name_field;
+ tree domain;
+ tree array_value_chain = NULL_TREE;
+ tree bb_fn_struct_type;
+ tree bb_fn_struct_array_type;
+ tree bb_fn_struct_array_pointer_type;
+ tree bb_fn_struct_pointer_type;
+ tree field_value, field_value_chain;
- /* Zero word (link field). */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ bb_fn_struct_type = make_node (RECORD_TYPE);
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ checksum_field = build_decl (FIELD_DECL, get_identifier ("checksum"),
+ long_integer_type_node);
- /* Byte count for extended structure. */
- assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1);
+ arc_count_field
+ = build_decl (FIELD_DECL, get_identifier ("arc_count"),
+ integer_type_node);
+ TREE_CHAIN (checksum_field) = arc_count_field;
- /* Address of function name table. */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ name_field
+ = build_decl (FIELD_DECL, get_identifier ("name"), string_type);
+ TREE_CHAIN (arc_count_field) = name_field;
- /* Address of line number and filename tables if debugging. */
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
- assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ TYPE_FIELDS (bb_fn_struct_type) = checksum_field;
- /* Space for extension ptr (link field). */
- assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1);
+ num_nodes = 0;
- /* Output the file name changing the suffix to .d for
- Sun tcov compatibility. */
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
- {
- char *cwd = getpwd ();
- int len = strlen (filename) + strlen (cwd) + 1;
- char *data_file = (char *) alloca (len + 4);
-
- strcpy (data_file, cwd);
- strcat (data_file, "/");
- strcat (data_file, filename);
- strip_off_ending (data_file, len);
- strcat (data_file, ".da");
- assemble_string (data_file, strlen (data_file) + 1);
+ for (item = functions_head; item != 0; item = item->next)
+ num_nodes++;
+
+ /* Note that the array contains a terminator, hence no - 1. */
+ domain = build_index_type (build_int_2 (num_nodes, 0));
+
+ bb_fn_struct_pointer_type = build_pointer_type (bb_fn_struct_type);
+ bb_fn_struct_array_type
+ = build_array_type (bb_fn_struct_type, domain);
+ bb_fn_struct_array_pointer_type
+ = build_pointer_type (bb_fn_struct_array_type);
+
+ layout_type (bb_fn_struct_type);
+ layout_type (bb_fn_struct_pointer_type);
+ layout_type (bb_fn_struct_array_type);
+ layout_type (bb_fn_struct_array_pointer_type);
+
+ for (item = functions_head; item != 0; item = item->next)
+ {
+ size_t name_len;
+
+ /* create constructor for structure. */
+ field_value_chain
+ = build_tree_list (checksum_field,
+ convert (long_integer_type_node,
+ build_int_2 (item->cfg_checksum, 0)));
+ field_value_chain
+ = tree_cons (arc_count_field,
+ convert (integer_type_node,
+ build_int_2 (item->count_edges, 0)),
+ field_value_chain);
+
+ name_len = strlen (item->name);
+ string_cst = build_string (name_len + 1, item->name);
+ domain_type = build_index_type (build_int_2 (name_len, 0));
+ TREE_TYPE (string_cst)
+ = build_array_type (char_type_node, domain_type);
+ field_value_chain = tree_cons (name_field,
+ build1 (ADDR_EXPR, string_type,
+ string_cst),
+ field_value_chain);
+
+ /* Add to chain. */
+ array_value_chain
+ = tree_cons (NULL_TREE, build (CONSTRUCTOR,
+ bb_fn_struct_type, NULL_TREE,
+ nreverse (field_value_chain)),
+ array_value_chain);
+ }
+
+ /* Add terminator. */
+ field_value = build_tree_list (arc_count_field,
+ convert (integer_type_node,
+ build_int_2 (-1, 0)));
+
+ array_value_chain = tree_cons (NULL_TREE,
+ build (CONSTRUCTOR, bb_fn_struct_type,
+ NULL_TREE, field_value),
+ array_value_chain);
+
+
+ /* Create constructor for array. */
+ field_decl
+ = build_decl (FIELD_DECL, get_identifier ("function_infos"),
+ bb_fn_struct_pointer_type);
+ value_chain = tree_cons (field_decl,
+ build1 (ADDR_EXPR,
+ bb_fn_struct_array_pointer_type,
+ build (CONSTRUCTOR,
+ bb_fn_struct_array_type,
+ NULL_TREE,
+ nreverse
+ (array_value_chain))),
+ value_chain);
+ TREE_CHAIN (field_decl) = decl_chain;
+ decl_chain = field_decl;
}
- /* Make space for the table of counts. */
- if (size == 0)
- {
- /* Realign data section. */
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
- if (size != 0)
- assemble_zeros (size);
- }
- else
- {
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
-#ifdef ASM_OUTPUT_SHARED_LOCAL
- if (flag_shared_data)
- ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
- else
-#endif
-#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
- ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name,
- size, BIGGEST_ALIGNMENT);
-#else
-#ifdef ASM_OUTPUT_ALIGNED_LOCAL
- ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
- BIGGEST_ALIGNMENT);
-#else
- ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
-#endif
-#endif
- }
+ /* Finish structure. */
+ TYPE_FIELDS (structure_decl) = nreverse (decl_chain);
+ layout_type (structure_decl);
+
+ structure_value
+ = build (VAR_DECL, structure_decl, NULL_TREE, NULL_TREE);
+ DECL_INITIAL (structure_value)
+ = build (CONSTRUCTOR, structure_decl, NULL_TREE,
+ nreverse (value_chain));
+ TREE_STATIC (structure_value) = 1;
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
+ DECL_NAME (structure_value) = get_identifier (name);
+
+ /* Size of this structure. */
+ TREE_VALUE (sizeof_field_value)
+ = convert (long_integer_type_node,
+ build_int_2 (int_size_in_bytes (structure_decl), 0));
+
+ /* Build structure. */
+ assemble_variable (structure_value, 0, 0, 0);
}
}
@@ -438,9 +586,7 @@ dbr_sequence_length ()
static int *insn_lengths;
-#ifdef HAVE_ATTR_length
varray_type insn_addresses_;
-#endif
/* Max uid for which the above arrays are valid. */
static int insn_lengths_max_uid;
@@ -527,7 +673,7 @@ get_attr_length (insn)
case JUMP_INSN:
body = PATTERN (insn);
- if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
+ if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{
/* Alignment is machine-dependent and should be handled by
ADDR_VEC_ALIGN. */
@@ -787,8 +933,8 @@ insn_current_reference_address (branch)
void
compute_alignments ()
{
- int i;
int log, max_skip, max_log;
+ basic_block bb;
if (label_align)
{
@@ -805,9 +951,8 @@ compute_alignments ()
if (! optimize || optimize_size)
return;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
rtx label = bb->head;
int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
edge e;
@@ -837,8 +982,8 @@ compute_alignments ()
if (!has_fallthru
&& (branch_frequency > BB_FREQ_MAX / 10
- || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
- && (BASIC_BLOCK (i - 1)->frequency
+ || (bb->frequency > bb->prev_bb->frequency * 10
+ && (bb->prev_bb->frequency
<= ENTRY_BLOCK_PTR->frequency / 2))))
{
log = JUMP_ALIGN (label);
@@ -849,10 +994,10 @@ compute_alignments ()
}
}
/* In case block is frequent and reached mostly by non-fallthru edge,
- align it. It is most likely an first block of loop. */
+ align it. It is most likely a first block of loop. */
if (has_fallthru
&& branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
- && branch_frequency > fallthru_frequency * 5)
+ && branch_frequency > fallthru_frequency * 2)
{
log = LOOP_ALIGN (label);
if (max_log < log)
@@ -974,11 +1119,7 @@ shorten_branches (first)
next = NEXT_INSN (insn);
/* ADDR_VECs only take room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
if (next && GET_CODE (next) == JUMP_INSN)
{
rtx nextbody = PATTERN (next);
@@ -1128,7 +1269,7 @@ shorten_branches (first)
}
}
- INSN_ADDRESSES (uid) = insn_current_address;
+ INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
|| GET_CODE (insn) == CODE_LABEL)
@@ -1141,11 +1282,7 @@ shorten_branches (first)
{
/* This only takes room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
@@ -1346,11 +1483,7 @@ shorten_branches (first)
PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
max_addr - rel_addr,
body));
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
{
insn_lengths[uid]
= (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@@ -1380,7 +1513,7 @@ shorten_branches (first)
insn_current_address += insn_lengths[inner_uid];
}
- }
+ }
else
insn_current_address += insn_lengths[uid];
@@ -1537,7 +1670,7 @@ final_start_function (first, file, optimize)
if (write_symbols)
{
remove_unnecessary_notes ();
- reorder_blocks ();
+ scope_to_insns_finalize ();
number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
block in the function. But, conceptually, that block is
@@ -1548,12 +1681,6 @@ final_start_function (first, file, optimize)
/* First output the function prologue: code to set up the stack frame. */
(*targetm.asm_out.function_prologue) (file, get_frame_size ());
-#ifdef VMS_DEBUGGING_INFO
- /* Output label after the prologue of the function. */
- if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
- vmsdbgout_after_prologue ();
-#endif
-
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
#ifdef HAVE_prologue
@@ -1591,7 +1718,7 @@ profile_function (file)
#ifndef NO_PROFILE_COUNTERS
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
- ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_profile_label_no);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_funcdef_no);
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
#endif
@@ -1621,7 +1748,7 @@ profile_function (file)
#endif
#endif
- FUNCTION_PROFILER (file, current_function_profile_label_no);
+ FUNCTION_PROFILER (file, current_function_funcdef_no);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
@@ -1664,12 +1791,12 @@ final_end_function ()
(*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
/* And debug output. */
- (*debug_hooks->end_epilogue) ();
+ (*debug_hooks->end_epilogue) (last_linenum, last_filename);
#if defined (DWARF2_UNWIND_INFO)
if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
&& dwarf2out_do_frame ())
- dwarf2out_end_epilogue ();
+ dwarf2out_end_epilogue (last_linenum, last_filename);
#endif
}
@@ -1763,16 +1890,12 @@ final (first, file, optimize, prescan)
#ifdef HAVE_ATTR_length
if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
{
-#ifdef STACK_REGS
- /* Irritatingly, the reg-stack pass is creating new instructions
- and because of REG_DEAD note abuse it has to run after
- shorten_branches. Fake address of -1 then. */
- insn_current_address = -1;
-#else
/* This can be triggered by bugs elsewhere in the compiler if
new insns are created after init_insn_lengths is called. */
- abort ();
-#endif
+ if (GET_CODE (insn) == NOTE)
+ insn_current_address = -1;
+ else
+ abort ();
}
else
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
@@ -1781,6 +1904,23 @@ final (first, file, optimize, prescan)
insn = final_scan_insn (insn, file, optimize, prescan, 0);
}
+ /* Store function names for edge-profiling. */
+ /* ??? Probably should re-use the existing struct function. */
+
+ if (cfun->arc_profile)
+ {
+ struct function_list *new_item = xmalloc (sizeof (struct function_list));
+
+ *functions_tail = new_item;
+ functions_tail = &new_item->next;
+
+ new_item->next = 0;
+ new_item->name = xstrdup (IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (current_function_decl)));
+ new_item->cfg_checksum = profile_info.current_function_cfg_checksum;
+ new_item->count_edges = profile_info.count_edges_instrumented_now;
+ }
+
free (line_note_exists);
line_note_exists = NULL;
}
@@ -1807,6 +1947,39 @@ get_insn_template (code, insn)
}
}
+/* Emit the appropriate declaration for an alternate-entry-point
+ symbol represented by INSN, to FILE. INSN is a CODE_LABEL with
+ LABEL_KIND != LABEL_NORMAL.
+
+ The case fall-through in this function is intentional. */
+static void
+output_alternate_entry_point (file, insn)
+ FILE *file;
+ rtx insn;
+{
+ const char *name = LABEL_NAME (insn);
+
+ switch (LABEL_KIND (insn))
+ {
+ case LABEL_WEAK_ENTRY:
+#ifdef ASM_WEAKEN_LABEL
+ ASM_WEAKEN_LABEL (file, name);
+#endif
+ case LABEL_GLOBAL_ENTRY:
+ (*targetm.asm_out.globalize_label) (file, name);
+ case LABEL_STATIC_ENTRY:
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
+#endif
+ ASM_OUTPUT_LABEL (file, name);
+ break;
+
+ case LABEL_NORMAL:
+ default:
+ abort ();
+ }
+}
+
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
@@ -1850,9 +2023,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
- case NOTE_INSN_RANGE_BEG:
- case NOTE_INSN_RANGE_END:
- case NOTE_INSN_LIVE:
case NOTE_INSN_EXPECTED_VALUE:
break;
@@ -1886,7 +2056,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_FUNCTION_BEG:
app_disable ();
- (*debug_hooks->end_prologue) (last_linenum);
+ (*debug_hooks->end_prologue) (last_linenum, last_filename);
break;
case NOTE_INSN_BLOCK_BEG:
@@ -2016,8 +2186,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
#else
+#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
+ ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
+#else
ASM_OUTPUT_ALIGN (file, align);
#endif
+#endif
}
}
#ifdef HAVE_cc0
@@ -2100,17 +2274,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
NEXT_INSN (insn));
#else
- if (LABEL_ALTERNATE_NAME (insn))
- ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
- else
- ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
break;
}
}
- if (LABEL_ALTERNATE_NAME (insn))
- ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
+ if (LABEL_ALT_ENTRY_P (insn))
+ output_alternate_entry_point (file, insn);
else
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
break;
@@ -2539,13 +2710,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
insn_code_number = recog_memoized (insn);
cleanup_subreg_operands (insn);
- /* Dump the insn in the assembly for debugging. */
- if (flag_dump_rtl_in_asm)
- {
- print_rtx_head = ASM_COMMENT_START;
- print_rtl_single (asm_out_file, insn);
- print_rtx_head = "";
- }
+ /* Dump the insn in the assembly for debugging. */
+ if (flag_dump_rtl_in_asm)
+ {
+ print_rtx_head = ASM_COMMENT_START;
+ print_rtl_single (asm_out_file, insn);
+ print_rtx_head = "";
+ }
if (! constrain_operands_cached (1))
fatal_insn_not_found (insn);
@@ -2755,7 +2926,7 @@ alter_subreg (xp)
ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
/* This field has a different meaning for REGs and SUBREGs. Make
sure to clear it! */
- x->used = 0;
+ RTX_FLAG (x, used) = 0;
}
else
abort ();
@@ -2970,7 +3141,7 @@ output_operand_lossage VPARAMS ((const char *msgid, ...))
pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
vasprintf (&new_message, fmt_string, ap);
-
+
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "%s", new_message);
else
@@ -3768,7 +3939,6 @@ split_double (value, first, second)
}
else
{
-#ifdef REAL_ARITHMETIC
REAL_VALUE_TYPE r;
long l[2];
REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@@ -3797,30 +3967,6 @@ split_double (value, first, second)
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
*second = GEN_INT ((HOST_WIDE_INT) l[1]);
-#else
- if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
- || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
- && ! flag_pretend_float)
- abort ();
-
- if (
-#ifdef HOST_WORDS_BIG_ENDIAN
- WORDS_BIG_ENDIAN
-#else
- ! WORDS_BIG_ENDIAN
-#endif
- )
- {
- /* Host and target agree => no need to swap. */
- *first = GEN_INT (CONST_DOUBLE_LOW (value));
- *second = GEN_INT (CONST_DOUBLE_HIGH (value));
- }
- else
- {
- *second = GEN_INT (CONST_DOUBLE_LOW (value));
- *first = GEN_INT (CONST_DOUBLE_HIGH (value));
- }
-#endif /* no REAL_ARITHMETIC */
}
}
@@ -3865,7 +4011,7 @@ leaf_function_p ()
return 1;
}
-/* Return 1 if branch is an forward branch.
+/* Return 1 if branch is a forward branch.
Uses insn_shuid array, so it works only in the final pass. May be used by
output templates to customary add branch prediction hints.
*/
OpenPOWER on IntegriCloud