/* Convert RTL to assembler code and output it, for GNU compiler.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
This file is part of GCC.
function_epilogue. Those instructions never exist as rtl. */
#include "config.h"
+#define INCLUDE_ALGORITHM /* reverse */
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-
-#include "tree.h"
-#include "varasm.h"
-#include "hard-reg-set.h"
+#include "backend.h"
+#include "target.h"
#include "rtl.h"
+#include "tree.h"
+#include "cfghooks.h"
+#include "df.h"
+#include "memmodel.h"
#include "tm_p.h"
-#include "regs.h"
#include "insn-config.h"
-#include "insn-attr.h"
+#include "regs.h"
+#include "emit-rtl.h"
#include "recog.h"
+#include "cgraph.h"
+#include "tree-pretty-print.h" /* for dump_function_header */
+#include "varasm.h"
+#include "insn-attr.h"
#include "conditions.h"
#include "flags.h"
#include "output.h"
#include "except.h"
-#include "function.h"
#include "rtl-error.h"
#include "toplev.h" /* exact_log2, floor_log2 */
#include "reload.h"
#include "intl.h"
-#include "basic-block.h"
-#include "target.h"
-#include "targhooks.h"
+#include "cfgrtl.h"
#include "debug.h"
-#include "expr.h"
#include "tree-pass.h"
-#include "cgraph.h"
#include "tree-ssa.h"
-#include "coverage.h"
-#include "df.h"
-#include "ggc.h"
#include "cfgloop.h"
#include "params.h"
-#include "tree-pretty-print.h" /* for dump_function_header */
+#include "stringpool.h"
+#include "attribs.h"
#include "asan.h"
-#include "wide-int-print.h"
#include "rtl-iter.h"
+#include "print-rtl.h"
#ifdef XCOFF_DEBUGGING_INFO
-#include "xcoffout.h" /* Needed for external data
- declarations for e.g. AIX 4.x. */
+#include "xcoffout.h" /* Needed for external data declarations. */
#endif
#include "dwarf2out.h"
#include "dbxout.h"
#endif
-#ifdef SDB_DEBUGGING_INFO
-#include "sdbout.h"
-#endif
-
/* Most ports that aren't using cc0 don't need to define CC_STATUS_INIT.
So define a null default for it to save conditionalization later. */
#ifndef CC_STATUS_INIT
/* Line number of last NOTE. */
static int last_linenum;
+/* Column number of last NOTE. */
+static int last_columnnum;
+
/* Last discriminator written to assembly. */
static int last_discriminator;
/* Filename of last NOTE. */
static const char *last_filename;
-/* Override filename and line number. */
+/* Override filename, line and column number. */
static const char *override_filename;
static int override_linenum;
+static int override_columnnum;
/* Whether to force emission of a line note before the next insn. */
static bool force_source_line = false;
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't die.
The precise value is the insn being output, to pass to error_for_asm. */
-rtx this_is_asm_operands;
+const rtx_insn *this_is_asm_operands;
/* Number of operands of this insn, for an `asm' with operands. */
static unsigned int insn_noperands;
static int insn_counter = 0;
-#ifdef HAVE_cc0
/* This variable contains machine-dependent flags (defined in tm.h)
set and examined by output routines
that describe how to interpret the condition codes properly. */
from before the insn. */
CC_STATUS cc_prev_status;
-#endif
/* Number of unmatched NOTE_INSN_BLOCK_BEG notes we have seen. */
#ifdef LEAF_REGISTERS
static void leaf_renumber_regs (rtx_insn *);
#endif
-#ifdef HAVE_cc0
+#if HAVE_cc0
static int alter_cond (rtx);
#endif
-#ifndef ADDR_VEC_ALIGN
-static int final_addr_vec_align (rtx);
-#endif
static int align_fuzz (rtx, rtx, int, unsigned);
static void collect_fn_hard_reg_usage (void);
static tree get_call_fndecl (rtx_insn *);
If not overridden for epilogue code, then the function body itself
contains return instructions wherever needed. */
void
-default_function_pro_epilogue (FILE *file ATTRIBUTE_UNUSED,
- HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+default_function_pro_epilogue (FILE *)
{
}
delayed branch sequence (we don't count the insn needing the
delay slot). Zero if not in a delayed branch sequence. */
-#ifdef DELAY_SLOTS
int
dbr_sequence_length (void)
{
else
return 0;
}
-#endif
\f
/* The next two pages contain routines used to compute the length of an insn
and to shorten branches. */
get its actual length. Otherwise, use FALLBACK_FN to calculate the
length. */
static int
-get_attr_length_1 (rtx uncast_insn, int (*fallback_fn) (rtx))
+get_attr_length_1 (rtx_insn *insn, int (*fallback_fn) (rtx_insn *))
{
- rtx_insn *insn = as_a <rtx_insn *> (uncast_insn);
rtx body;
int i;
int length = 0;
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, get its maximum length. */
int
-get_attr_length (rtx insn)
+get_attr_length (rtx_insn *insn)
{
return get_attr_length_1 (insn, insn_default_length);
}
/* Obtain the current length of an insn. If branch shortening has been done,
get its actual length. Otherwise, get its minimum length. */
int
-get_attr_min_length (rtx insn)
+get_attr_min_length (rtx_insn *insn)
{
return get_attr_length_1 (insn, insn_min_length);
}
#endif
int
-default_label_align_after_barrier_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_label_align_after_barrier_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return 0;
}
int
-default_loop_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_loop_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_loops_max_skip;
}
int
-default_label_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_label_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_labels_max_skip;
}
int
-default_jump_align_max_skip (rtx insn ATTRIBUTE_UNUSED)
+default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
{
return align_jumps_max_skip;
}
#ifndef ADDR_VEC_ALIGN
static int
-final_addr_vec_align (rtx addr_vec)
+final_addr_vec_align (rtx_jump_table_data *addr_vec)
{
- int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
+ int align = GET_MODE_SIZE (addr_vec->get_data_mode ());
if (align > BIGGEST_ALIGNMENT / BITS_PER_UNIT)
align = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
int
insn_current_reference_address (rtx_insn *branch)
{
- rtx dest, seq;
+ rtx dest;
int seq_uid;
if (! INSN_ADDRESSES_SET_P ())
return 0;
- seq = NEXT_INSN (PREV_INSN (branch));
+ rtx_insn *seq = NEXT_INSN (PREV_INSN (branch));
seq_uid = INSN_UID (seq);
if (!JUMP_P (branch))
/* This can happen for example on the PA; the objective is to know the
if (INSN_P (insn))
continue;
- if (LABEL_P (insn))
+ if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
{
- rtx_insn *next;
- bool next_is_jumptable;
-
/* Merge in alignments computed by compute_alignments. */
- log = LABEL_TO_ALIGNMENT (insn);
+ log = LABEL_TO_ALIGNMENT (label);
if (max_log < log)
{
max_log = log;
- max_skip = LABEL_TO_MAX_SKIP (insn);
+ max_skip = LABEL_TO_MAX_SKIP (label);
}
- next = next_nonnote_insn (insn);
- next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
- if (!next_is_jumptable)
+ rtx_jump_table_data *table = jump_table_for_label (label);
+ if (!table)
{
- log = LABEL_ALIGN (insn);
+ log = LABEL_ALIGN (label);
if (max_log < log)
{
max_log = log;
- max_skip = targetm.asm_out.label_align_max_skip (insn);
+ max_skip = targetm.asm_out.label_align_max_skip (label);
}
}
/* ADDR_VECs only take room if read-only data goes into the text
section. */
if ((JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == text_section)
- && next_is_jumptable)
+ && table)
{
- log = ADDR_VEC_ALIGN (next);
+ log = ADDR_VEC_ALIGN (table);
if (max_log < log)
{
max_log = log;
- max_skip = targetm.asm_out.label_align_max_skip (insn);
+ max_skip = targetm.asm_out.label_align_max_skip (label);
}
}
- LABEL_TO_ALIGNMENT (insn) = max_log;
- LABEL_TO_MAX_SKIP (insn) = max_skip;
+ LABEL_TO_ALIGNMENT (label) = max_log;
+ LABEL_TO_MAX_SKIP (label) = max_skip;
max_log = 0;
max_skip = 0;
}
#endif /* CASE_VECTOR_SHORTEN_MODE */
/* Compute initial lengths, addresses, and varying flags for each insn. */
- int (*length_fun) (rtx) = increasing ? insn_min_length : insn_default_length;
+ int (*length_fun) (rtx_insn *) = increasing ? insn_min_length : insn_default_length;
for (insn_current_address = 0, insn = first;
insn != 0;
if (NOTE_P (insn) || BARRIER_P (insn)
|| LABEL_P (insn) || DEBUG_INSN_P (insn))
continue;
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
continue;
body = PATTERN (insn);
- if (JUMP_TABLE_DATA_P (insn))
+ if (rtx_jump_table_data *table = dyn_cast <rtx_jump_table_data *> (insn))
{
/* This only takes room if read-only data goes into the text
section. */
|| readonly_data_section == text_section)
insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC)
- * GET_MODE_SIZE (GET_MODE (body)));
+ * GET_MODE_SIZE (table->get_data_mode ()));
/* Alignment is handled by ADDR_VEC_ALIGN. */
}
else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
{
int i;
int const_delay_slots;
-#ifdef DELAY_SLOTS
- const_delay_slots = const_num_delay_slots (body_seq->insn (0));
-#else
- const_delay_slots = 0;
-#endif
- int (*inner_length_fun) (rtx)
+ if (DELAY_SLOTS)
+ const_delay_slots = const_num_delay_slots (body_seq->insn (0));
+ else
+ const_delay_slots = 0;
+
+ int (*inner_length_fun) (rtx_insn *)
= const_delay_slots ? length_fun : insn_default_length;
/* Inside a delay slot sequence, we do not do any branch shortening
if the shortening could change the number of delay slots
int inner_uid = INSN_UID (inner_insn);
int inner_length;
- if (GET_CODE (body) == ASM_INPUT
+ if (GET_CODE (PATTERN (inner_insn)) == ASM_INPUT
|| asm_noperands (PATTERN (inner_insn)) >= 0)
inner_length = (asm_insn_count (PATTERN (inner_insn))
* insn_default_length (inner_insn));
uid = INSN_UID (insn);
- if (LABEL_P (insn))
+ if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
{
- int log = LABEL_TO_ALIGNMENT (insn);
+ int log = LABEL_TO_ALIGNMENT (label);
#ifdef CASE_VECTOR_SHORTEN_MODE
/* If the mode of a following jump table was changed, we
may need to update the alignment of this label. */
- rtx_insn *next;
- bool next_is_jumptable;
-
- next = next_nonnote_insn (insn);
- next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
- if ((JUMP_TABLES_IN_TEXT_SECTION
- || readonly_data_section == text_section)
- && next_is_jumptable)
+
+ if (JUMP_TABLES_IN_TEXT_SECTION
+ || readonly_data_section == text_section)
{
- int newlog = ADDR_VEC_ALIGN (next);
- if (newlog != log)
+ rtx_jump_table_data *table = jump_table_for_label (label);
+ if (table)
{
- log = newlog;
- LABEL_TO_ALIGNMENT (insn) = log;
- something_changed = 1;
+ int newlog = ADDR_VEC_ALIGN (table);
+ if (newlog != log)
+ {
+ log = newlog;
+ LABEL_TO_ALIGNMENT (insn) = log;
+ something_changed = 1;
+ }
}
}
#endif
&& JUMP_TABLE_DATA_P (insn)
&& GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
{
+ rtx_jump_table_data *table = as_a <rtx_jump_table_data *> (insn);
rtx body = PATTERN (insn);
int old_length = insn_lengths[uid];
rtx_insn *rel_lab =
rtx_insn *prev;
int rel_align = 0;
addr_diff_vec_flags flags;
- enum machine_mode vec_mode;
+ scalar_int_mode vec_mode;
/* Avoid automatic aggregate initialization. */
flags = ADDR_DIFF_VEC_FLAGS (body);
max_addr - rel_addr, body);
if (!increasing
|| (GET_MODE_SIZE (vec_mode)
- >= GET_MODE_SIZE (GET_MODE (body))))
+ >= GET_MODE_SIZE (table->get_data_mode ())))
PUT_MODE (body, vec_mode);
if (JUMP_TABLES_IN_TEXT_SECTION
|| readonly_data_section == text_section)
{
insn_lengths[uid]
- = (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
+ = (XVECLEN (body, 1)
+ * GET_MODE_SIZE (table->get_data_mode ()));
insn_current_address += insn_lengths[uid];
if (insn_lengths[uid] != old_length)
something_changed = 1;
if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
+ rtx_sequence *seqn = as_a <rtx_sequence *> (PATTERN (insn));
int i;
body = PATTERN (insn);
new_length = 0;
- for (i = 0; i < XVECLEN (body, 0); i++)
+ for (i = 0; i < seqn->len (); i++)
{
- rtx inner_insn = XVECEXP (body, 0, i);
+ rtx_insn *inner_insn = seqn->insn (i);
int inner_uid = INSN_UID (inner_insn);
int inner_length;
if (!increasing)
break;
}
-
+ crtl->max_insn_address = insn_current_address;
free (varying_length);
}
/* Structure recording the mapping from source file and directory
names at compile time to those to be embedded in debug
information. */
-typedef struct debug_prefix_map
+struct debug_prefix_map
{
const char *old_prefix;
const char *new_prefix;
size_t old_len;
size_t new_len;
struct debug_prefix_map *next;
-} debug_prefix_map;
+};
/* Linked list of such structures. */
static debug_prefix_map *debug_prefix_maps;
last_filename = LOCATION_FILE (prologue_location);
last_linenum = LOCATION_LINE (prologue_location);
+ last_columnnum = LOCATION_COLUMN (prologue_location);
last_discriminator = discriminator = 0;
high_block_linenum = high_function_linenum = last_linenum;
asan_function_start ();
if (!DECL_IGNORED_P (current_function_decl))
- debug_hooks->begin_prologue (last_linenum, last_filename);
+ debug_hooks->begin_prologue (last_linenum, last_columnnum, last_filename);
if (!dwarf2_debug_info_emitted_p (current_function_decl))
- dwarf2out_begin_prologue (0, NULL);
+ dwarf2out_begin_prologue (0, 0, NULL);
#ifdef LEAF_REG_REMAP
if (crtl->uses_only_leaf_regs)
if the profiling code comes after the prologue. */
if (targetm.profile_before_prologue () && crtl->profile)
{
- if (targetm.asm_out.function_prologue
- == default_function_pro_epilogue
-#ifdef HAVE_prologue
- && HAVE_prologue
-#endif
- )
+ if (targetm.asm_out.function_prologue == default_function_pro_epilogue
+ && targetm.have_prologue ())
{
rtx_insn *insn;
for (insn = first; insn; insn = NEXT_INSN (insn))
}
/* First output the function prologue: code to set up the stack frame. */
- targetm.asm_out.function_prologue (file, get_frame_size ());
+ targetm.asm_out.function_prologue (file);
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
-#ifdef HAVE_prologue
- if (! HAVE_prologue)
-#endif
+ if (! targetm.have_prologue ())
profile_after_prologue (file);
}
/* Finally, output the function epilogue:
code to restore the stack frame and return to the caller. */
- targetm.asm_out.function_epilogue (asm_out_file, get_frame_size ());
+ targetm.asm_out.function_epilogue (asm_out_file);
/* And debug output. */
if (!DECL_IGNORED_P (current_function_decl))
fprintf (file, "%s BLOCK %d", ASM_COMMENT_START, bb->index);
if (bb->frequency)
fprintf (file, " freq:%d", bb->frequency);
- if (bb->count)
- fprintf (file, " count:%"PRId64,
- bb->count);
+ if (bb->count.initialized_p ())
+ {
+ fprintf (file, ", count:");
+ bb->count.dump (file);
+ }
fprintf (file, " seq:%d", (*bb_seqn)++);
fprintf (file, "\n%s PRED:", ASM_COMMENT_START);
FOR_EACH_EDGE (e, ei, bb->preds)
last_ignored_compare = 0;
-#ifdef HAVE_cc0
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- /* If CC tracking across branches is enabled, record the insn which
- jumps to each branch only reached from one place. */
- if (optimize_p && JUMP_P (insn))
- {
- rtx lab = JUMP_LABEL (insn);
- if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
- {
- LABEL_REFS (lab) = insn;
- }
- }
- }
-#endif
+ if (HAVE_cc0)
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ /* If CC tracking across branches is enabled, record the insn which
+ jumps to each branch only reached from one place. */
+ if (optimize_p && JUMP_P (insn))
+ {
+ rtx lab = JUMP_LABEL (insn);
+ if (lab && LABEL_P (lab) && LABEL_NUSES (lab) == 1)
+ {
+ LABEL_REFS (lab) = insn;
+ }
+ }
+ }
init_recog ();
case LABEL_WEAK_ENTRY:
#ifdef ASM_WEAKEN_LABEL
ASM_WEAKEN_LABEL (file, name);
+ gcc_fallthrough ();
#endif
case LABEL_GLOBAL_ENTRY:
targetm.asm_out.globalize_label (file, name);
+ gcc_fallthrough ();
case LABEL_STATIC_ENTRY:
#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
return x;
}
+/* Print a comment into the asm showing FILENAME, LINENUM, and the
+ corresponding source line, if available. */
+
+static void
+asm_show_source (const char *filename, int linenum)
+{
+ if (!filename)
+ return;
+
+ int line_size;
+ const char *line = location_get_source_line (filename, linenum, &line_size);
+ if (!line)
+ return;
+
+ fprintf (asm_out_file, "%s %s:%i: ", ASM_COMMENT_START, filename, linenum);
+ /* "line" is not 0-terminated, so we must use line_size. */
+ fwrite (line, 1, line_size, asm_out_file);
+ fputc ('\n', asm_out_file);
+}
+
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
int nopeepholes ATTRIBUTE_UNUSED, int *seen)
{
-#ifdef HAVE_cc0
+#if HAVE_cc0
rtx set;
#endif
rtx_insn *next;
+ rtx_jump_table_data *table;
insn_counter++;
/* Ignore deleted insns. These can occur when we split insns (due to a
template of "#") while not optimizing. */
- if (INSN_DELETED_P (insn))
+ if (insn->deleted ())
return NEXT_INSN (insn);
switch (GET_CODE (insn))
switch (NOTE_KIND (insn))
{
case NOTE_INSN_DELETED:
+ case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
suffixing "cold" to the original function's name. */
if (in_cold_section_p)
{
- tree cold_function_name
+ cold_function_name
= clone_function_name (current_function_decl, "cold");
+#ifdef ASM_DECLARE_COLD_FUNCTION_NAME
+ ASM_DECLARE_COLD_FUNCTION_NAME (asm_out_file,
+ IDENTIFIER_POINTER
+ (cold_function_name),
+ current_function_decl);
+#else
ASM_OUTPUT_LABEL (asm_out_file,
IDENTIFIER_POINTER (cold_function_name));
+#endif
}
break;
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
+ BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
}
- if (write_symbols == DBX_DEBUG
- || write_symbols == SDB_DEBUG)
+ if (write_symbols == DBX_DEBUG)
{
location_t *locus_ptr
= block_nonartificial_location (NOTE_BLOCK (insn));
{
override_filename = LOCATION_FILE (*locus_ptr);
override_linenum = LOCATION_LINE (*locus_ptr);
+ override_columnnum = LOCATION_COLUMN (*locus_ptr);
}
}
break;
if (!DECL_IGNORED_P (current_function_decl))
debug_hooks->end_block (high_block_linenum, n);
+ gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
+ == in_cold_section_p);
}
- if (write_symbols == DBX_DEBUG
- || write_symbols == SDB_DEBUG)
+ if (write_symbols == DBX_DEBUG)
{
tree outer_block = BLOCK_SUPERCONTEXT (NOTE_BLOCK (insn));
location_t *locus_ptr
{
override_filename = LOCATION_FILE (*locus_ptr);
override_linenum = LOCATION_LINE (*locus_ptr);
+ override_columnnum = LOCATION_COLUMN (*locus_ptr);
}
else
{
override_filename = NULL;
override_linenum = 0;
+ override_columnnum = 0;
}
}
break;
app_disable ();
- next = next_nonnote_insn (insn);
/* If this label is followed by a jump-table, make sure we put
the label in the read-only section. Also possibly write the
label and jump table together. */
- if (next != 0 && JUMP_TABLE_DATA_P (next))
+ table = jump_table_for_label (as_a <rtx_code_label *> (insn));
+ if (table)
{
#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
/* In this case, the case vector is being moved by the
(current_function_decl));
#ifdef ADDR_VEC_ALIGN
- log_align = ADDR_VEC_ALIGN (next);
+ log_align = ADDR_VEC_ALIGN (table);
#else
log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
#endif
switch_to_section (current_function_section ());
#ifdef ASM_OUTPUT_CASE_LABEL
- ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
- next);
+ ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
#else
targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
#endif
|| GET_CODE (body) == CLOBBER)
break;
-#ifdef HAVE_cc0
+#if HAVE_cc0
{
/* If there is a REG_CC_SETTER note on this insn, it means that
the setting of the condition code was done in the delay slot
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
if (note)
{
- NOTICE_UPDATE_CC (PATTERN (XEXP (note, 0)), XEXP (note, 0));
+ rtx_insn *other = as_a <rtx_insn *> (XEXP (note, 0));
+ NOTICE_UPDATE_CC (PATTERN (other), other);
cc_prev_status = cc_status;
}
}
note in a row. */
if (!DECL_IGNORED_P (current_function_decl)
&& notice_source_line (insn, &is_stmt))
- (*debug_hooks->source_line) (last_linenum, last_filename,
- last_discriminator, is_stmt);
+ {
+ if (flag_verbose_asm)
+ asm_show_source (last_filename, last_linenum);
+ (*debug_hooks->source_line) (last_linenum, last_columnnum,
+ last_filename, last_discriminator,
+ is_stmt);
+ }
+
+ if (GET_CODE (body) == PARALLEL
+ && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
+ body = XVECEXP (body, 0, 0);
if (GET_CODE (body) == ASM_INPUT)
{
body = PATTERN (insn);
-#ifdef HAVE_cc0
+#if HAVE_cc0
set = single_set (insn);
/* Check for redundant test and compare instructions
#endif
-#ifdef HAVE_peephole
/* Do machine-specific peephole optimizations if desired. */
- if (optimize_p && !flag_no_peephole && !nopeepholes)
+ if (HAVE_peephole && optimize_p && !flag_no_peephole && !nopeepholes)
{
rtx_insn *next = peephole (insn);
/* When peepholing, if there were notes within the peephole,
/* PEEPHOLE might have changed this. */
body = PATTERN (insn);
}
-#endif
/* Try to recognize the instruction.
If successful, verify that the operands satisfy the
print_rtx_head = "";
}
- if (! constrain_operands_cached (1))
+ if (! constrain_operands_cached (insn, 1))
fatal_insn_not_found (insn);
/* Some target machines need to prescan each insn before
&& GET_CODE (PATTERN (insn)) == COND_EXEC)
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
-#ifdef HAVE_cc0
+#if HAVE_cc0
cc_prev_status = cc_status;
/* Update `cc_status' for this instruction.
&& targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
- if (rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn))
+ rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn);
+ if (call_insn != NULL)
{
rtx x = call_from_call_insn (call_insn);
x = XEXP (x, 0);
if (t)
assemble_external (t);
}
- if (!DECL_IGNORED_P (current_function_decl))
- debug_hooks->var_location (insn);
}
/* Output assembler code from the template. */
&& targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
+ /* Let the debug info back-end know about this call. We do this only
+ after the instruction has been emitted because labels that may be
+ created to reference the call instruction must appear after it. */
+ if (call_insn != NULL && !DECL_IGNORED_P (current_function_decl))
+ debug_hooks->var_location (insn);
+
current_output_insn = debug_insn = 0;
}
}
notice_source_line (rtx_insn *insn, bool *is_stmt)
{
const char *filename;
- int linenum;
+ int linenum, columnnum;
if (override_filename)
{
filename = override_filename;
linenum = override_linenum;
+ columnnum = override_columnnum;
}
else if (INSN_HAS_LOCATION (insn))
{
expanded_location xloc = insn_location (insn);
filename = xloc.file;
linenum = xloc.line;
+ columnnum = xloc.column;
}
else
{
filename = NULL;
linenum = 0;
+ columnnum = 0;
}
if (filename == NULL)
if (force_source_line
|| filename != last_filename
- || last_linenum != linenum)
+ || last_linenum != linenum
+ || (debug_column_info && last_columnnum != columnnum))
{
force_source_line = false;
last_filename = filename;
last_linenum = linenum;
+ last_columnnum = columnnum;
last_discriminator = discriminator;
*is_stmt = true;
high_block_linenum = MAX (last_linenum, high_block_linenum);
directly to the desired hard register. */
void
-cleanup_subreg_operands (rtx insn)
+cleanup_subreg_operands (rtx_insn *insn)
{
int i;
bool changed = false;
*recog_data.dup_loc[i] = walk_alter_subreg (recog_data.dup_loc[i], &changed);
}
if (changed)
- df_insn_rescan (as_a <rtx_insn *> (insn));
+ df_insn_rescan (insn);
}
/* If X is a SUBREG, try to replace it with a REG or a MEM, based on
/* For paradoxical subregs on big-endian machines, SUBREG_BYTE
contains 0 instead of the proper offset. See simplify_subreg. */
- if (offset == 0
- && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
- {
- int difference = GET_MODE_SIZE (GET_MODE (y))
- - GET_MODE_SIZE (GET_MODE (x));
- if (WORDS_BIG_ENDIAN)
- offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
- if (BYTES_BIG_ENDIAN)
- offset += difference % UNITS_PER_WORD;
- }
+ if (paradoxical_subreg_p (x))
+ offset = byte_lowpart_offset (GET_MODE (x), GET_MODE (y));
if (final_p)
*xp = adjust_address (y, GET_MODE (x), offset);
else
*xp = adjust_address_nv (y, GET_MODE (x), offset);
}
- else
+ else if (REG_P (y) && HARD_REGISTER_P (y))
{
rtx new_rtx = simplify_subreg (GET_MODE (x), y, GET_MODE (y),
SUBREG_BYTE (x));
return *xp;
}
\f
-#ifdef HAVE_cc0
+#if HAVE_cc0
/* Given BODY, the body of a jump instruction, alter the jump condition
as required by the bits that are set in cc_status.flags.
va_start (ap, cmsgid);
pfx_str = this_is_asm_operands ? _("invalid 'asm': ") : "output_operand: ";
- asprintf (&fmt_string, "%s%s", pfx_str, _(cmsgid));
- vasprintf (&new_message, fmt_string, ap);
+ fmt_string = xasprintf ("%s%s", pfx_str, _(cmsgid));
+ new_message = xvasprintf (fmt_string, ap);
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "%s", new_message);
else if (letter == 'l')
output_asm_label (operands[opnum]);
else if (letter == 'a')
- output_address (operands[opnum]);
+ output_address (VOIDmode, operands[opnum]);
else if (letter == 'c')
{
if (CONSTANT_ADDRESS_P (operands[opnum]))
char buf[256];
if (GET_CODE (x) == LABEL_REF)
- x = XEXP (x, 0);
+ x = label_ref_label (x);
if (LABEL_P (x)
|| (NOTE_P (x)
&& NOTE_KIND (x) == NOTE_INSN_DELETED_LABEL))
x = alter_subreg (&x, true);
/* X must not be a pseudo reg. */
- gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
+ if (!targetm.no_register_allocation)
+ gcc_assert (!x || !REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER);
targetm.asm_out.print_operand (asm_out_file, x, code);
machine-dependent assembler syntax. */
void
-output_address (rtx x)
+output_address (machine_mode mode, rtx x)
{
bool changed = false;
walk_alter_subreg (&x, &changed);
- targetm.asm_out.print_operand_address (asm_out_file, x);
+ targetm.asm_out.print_operand_address (asm_out_file, mode, x);
}
\f
/* Print an integer constant expression in assembler syntax.
break;
case LABEL_REF:
- x = XEXP (x, 0);
+ x = label_ref_label (x);
/* Fall through. */
case CODE_LABEL:
ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
int
sprint_ul (char *s, unsigned long value)
{
- int len;
- char tmp_c;
- int i;
- int j;
-
- len = sprint_ul_rev (s, value);
+ int len = sprint_ul_rev (s, value);
s[len] = '\0';
- /* Reverse the string. */
- i = 0;
- j = len - 1;
- while (i < j)
- {
- tmp_c = s[i];
- s[i] = s[j];
- s[j] = tmp_c;
- i++; j--;
- }
-
+ std::reverse (s, s + len);
return len;
}
{
rtx_insn *insn;
+ /* Ensure we walk the entire function body. */
+ gcc_assert (!in_sequence_p ());
+
/* Some back-ends (e.g. s390) want leaf functions to stay leaf
functions even if they call mcount. */
if (crtl->profile && !targetm.keep_leaf_when_profiled ())
df_set_regs_ever_live (newreg, true);
SET_REGNO (in_rtx, newreg);
in_rtx->used = 1;
+ return;
}
if (INSN_P (in_rtx))
static unsigned int
rest_of_handle_final (void)
{
- rtx x;
- const char *fnname;
-
- /* Get the function's name, as described by its RTL. This may be
- different from the DECL_NAME name used in the source file. */
-
- x = DECL_RTL (current_function_decl);
- gcc_assert (MEM_P (x));
- x = XEXP (x, 0);
- gcc_assert (GET_CODE (x) == SYMBOL_REF);
- fnname = XSTR (x, 0);
+ const char *fnname = get_fnname_from_decl (current_function_decl);
assemble_start_function (current_function_decl, fnname);
final_start_function (get_insns (), asm_out_file, optimize);
final (get_insns (), asm_out_file, optimize);
- if (flag_use_caller_save)
+ if (flag_ipa_ra
+ && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl)))
collect_fn_hard_reg_usage ();
final_end_function ();
assemble_end_function (current_function_decl, fnname);
- user_defined_section_attribute = false;
-
/* Free up reg info memory. */
free_reg_info ();
}
}
- /* In case the function was not output,
- don't leave any temporary anonymous types
- queued up for sdb output. */
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_types (NULL_TREE);
-#endif
-
flag_rerun_cse_after_global_opts = 0;
reload_completed = 0;
epilogue_completed = 0;
free_bb_for_insn ();
- delete_tree_ssa ();
+ if (cfun->gimple_df)
+ delete_tree_ssa (cfun);
/* We can reduce stack alignment on call site only when we are sure that
the function body just produced will be actually used in the final
return new pass_clean_state (ctxt);
}
-/* Return true if INSN is a call to the the current function. */
+/* Return true if INSN is a call to the current function. */
static bool
self_recursive_call_p (rtx_insn *insn)
in REG_SET. Return DEFAULT_SET in REG_SET if not found. */
bool
-get_call_reg_set_usage (rtx uncast_insn, HARD_REG_SET *reg_set,
+get_call_reg_set_usage (rtx_insn *insn, HARD_REG_SET *reg_set,
HARD_REG_SET default_set)
{
- rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
- if (flag_use_caller_save)
+ if (flag_ipa_ra)
{
struct cgraph_rtl_info *node = get_call_cgraph_rtl_info (insn);
if (node != NULL