/* Register to Stack convert for GNU compiler.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 1992-2013 Free Software Foundation, Inc.
This file is part of GCC.
#include "hard-reg-set.h"
#include "flags.h"
#include "recog.h"
-#include "output.h"
#include "basic-block.h"
-#include "cfglayout.h"
#include "reload.h"
#include "ggc.h"
-#include "timevar.h"
#include "tree-pass.h"
#include "target.h"
#include "df.h"
-#include "vecprim.h"
#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
#ifdef STACK_REGS
Indexed by insn UIDs. A value of zero is uninitialized, one indicates
the insn uses stack registers, two indicates the insn does not use
stack registers. */
-static VEC(char,heap) *stack_regs_mentioned_data;
+static vec<char> stack_regs_mentioned_data;
#define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1)
int top; /* index to top stack element */
HARD_REG_SET reg_set; /* set of live registers */
unsigned char reg[REG_STACK_SIZE];/* register - stack mapping */
-} *stack;
+} *stack_ptr;
/* This is used to carry information about basic blocks. It is
attached to the AUX field of the standard CFG block. */
/* Forward declarations */
static int stack_regs_mentioned_p (const_rtx pat);
-static void pop_stack (stack, int);
+static void pop_stack (stack_ptr, int);
static rtx *get_true_reg (rtx *);
static int check_asm_stack_operands (rtx);
static rtx stack_result (tree);
static void replace_reg (rtx *, int);
static void remove_regno_note (rtx, enum reg_note, unsigned int);
-static int get_hard_regnum (stack, rtx);
-static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
-static void swap_to_top(rtx, stack, rtx, rtx);
-static bool move_for_stack_reg (rtx, stack, rtx);
-static bool move_nan_for_stack_reg (rtx, stack, rtx);
+static int get_hard_regnum (stack_ptr, rtx);
+static rtx emit_pop_insn (rtx, stack_ptr, rtx, enum emit_where);
+static void swap_to_top(rtx, stack_ptr, rtx, rtx);
+static bool move_for_stack_reg (rtx, stack_ptr, rtx);
+static bool move_nan_for_stack_reg (rtx, stack_ptr, rtx);
static int swap_rtx_condition_1 (rtx);
static int swap_rtx_condition (rtx);
-static void compare_for_stack_reg (rtx, stack, rtx);
-static bool subst_stack_regs_pat (rtx, stack, rtx);
-static void subst_asm_stack_regs (rtx, stack);
-static bool subst_stack_regs (rtx, stack);
-static void change_stack (rtx, stack, stack, enum emit_where);
-static void print_stack (FILE *, stack);
+static void compare_for_stack_reg (rtx, stack_ptr, rtx);
+static bool subst_stack_regs_pat (rtx, stack_ptr, rtx);
+static void subst_asm_stack_regs (rtx, stack_ptr);
+static bool subst_stack_regs (rtx, stack_ptr);
+static void change_stack (rtx, stack_ptr, stack_ptr, enum emit_where);
+static void print_stack (FILE *, stack_ptr);
static rtx next_flags_user (rtx);
\f
/* Return nonzero if any stack register is mentioned somewhere within PAT. */
unsigned int uid, max;
int test;
- if (! INSN_P (insn) || !stack_regs_mentioned_data)
+ if (! INSN_P (insn) || !stack_regs_mentioned_data.exists ())
return 0;
uid = INSN_UID (insn);
- max = VEC_length (char, stack_regs_mentioned_data);
+ max = stack_regs_mentioned_data.length ();
if (uid >= max)
{
/* Allocate some extra size to avoid too many reallocs, but
do not grow too quickly. */
max = uid + uid / 20 + 1;
- VEC_safe_grow_cleared (char, heap, stack_regs_mentioned_data, max);
+ stack_regs_mentioned_data.safe_grow_cleared (max);
}
- test = VEC_index (char, stack_regs_mentioned_data, uid);
+ test = stack_regs_mentioned_data[uid];
if (test == 0)
{
/* This insn has yet to be examined. Do so now. */
test = stack_regs_mentioned_p (PATTERN (insn)) ? 1 : 2;
- VEC_replace (char, stack_regs_mentioned_data, uid, test);
+ stack_regs_mentioned_data[uid] = test;
}
return test == 1;
/* Reorganize the stack into ascending numbers, before this insn. */
static void
-straighten_stack (rtx insn, stack regstack)
+straighten_stack (rtx insn, stack_ptr regstack)
{
struct stack_def temp_stack;
int top;
/* Pop a register from the stack. */
static void
-pop_stack (stack regstack, int regno)
+pop_stack (stack_ptr regstack, int regno)
{
int top = regstack->top;
actual FP register in use. */
{
rtx subreg;
- if (FP_REG_P (subreg = SUBREG_REG (*pat)))
+ if (STACK_REG_P (subreg = SUBREG_REG (*pat)))
{
int regno_off = subreg_regno_offset (REGNO (subreg),
GET_MODE (subreg),
returned if the register is not found. */
static int
-get_hard_regnum (stack regstack, rtx reg)
+get_hard_regnum (stack_ptr regstack, rtx reg)
{
int i;
cases the movdf pattern to pop. */
static rtx
-emit_pop_insn (rtx insn, stack regstack, rtx reg, enum emit_where where)
+emit_pop_insn (rtx insn, stack_ptr regstack, rtx reg, enum emit_where where)
{
rtx pop_insn, pop_rtx;
int hard_regno;
If REG is already at the top of the stack, no insn is emitted. */
static void
-emit_swap_insn (rtx insn, stack regstack, rtx reg)
+emit_swap_insn (rtx insn, stack_ptr regstack, rtx reg)
{
int hard_regno;
rtx swap_rtx;
is emitted. */
static void
-swap_to_top (rtx insn, stack regstack, rtx src1, rtx src2)
+swap_to_top (rtx insn, stack_ptr regstack, rtx src1, rtx src2)
{
struct stack_def temp_stack;
int regno, j, k, temp;
was deleted in the process. */
static bool
-move_for_stack_reg (rtx insn, stack regstack, rtx pat)
+move_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat)
{
rtx *psrc = get_true_reg (&SET_SRC (pat));
rtx *pdest = get_true_reg (&SET_DEST (pat));
a NaN into DEST, then invokes move_for_stack_reg. */
static bool
-move_nan_for_stack_reg (rtx insn, stack regstack, rtx dest)
+move_nan_for_stack_reg (rtx insn, stack_ptr regstack, rtx dest)
{
rtx pat;
set up. */
static void
-compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src)
+compare_for_stack_reg (rtx insn, stack_ptr regstack, rtx pat_src)
{
rtx *src1, *src2;
rtx src1_note, src2_note;
static int
subst_stack_regs_in_debug_insn (rtx *loc, void *data)
{
- stack regstack = (stack)data;
+ stack_ptr regstack = (stack_ptr)data;
int hard_regno;
if (!STACK_REG_P (*loc))
was deleted in the process. */
static bool
-subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
+subst_stack_regs_pat (rtx insn, stack_ptr regstack, rtx pat)
{
rtx *dest, *src;
bool control_flow_insn_deleted = false;
if (STACK_REG_P (*src)
|| (STACK_REG_P (*dest)
&& (REG_P (*src) || MEM_P (*src)
- || GET_CODE (*src) == CONST_DOUBLE)))
+ || CONST_DOUBLE_P (*src))))
{
control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
break;
requirements, since record_asm_stack_regs removes any problem asm. */
static void
-subst_asm_stack_regs (rtx insn, stack regstack)
+subst_asm_stack_regs (rtx insn, stack_ptr regstack)
{
rtx body = PATTERN (insn);
int alt;
a control flow insn was deleted in the process. */
static bool
-subst_stack_regs (rtx insn, stack regstack)
+subst_stack_regs (rtx insn, stack_ptr regstack)
{
rtx *note_link, note;
bool control_flow_insn_deleted = false;
is no longer needed once this has executed. */
static void
-change_stack (rtx insn, stack old, stack new_stack, enum emit_where where)
+change_stack (rtx insn, stack_ptr old, stack_ptr new_stack, enum emit_where where)
{
int reg;
int update_end = 0;
/* Print stack configuration. */
static void
-print_stack (FILE *file, stack s)
+print_stack (FILE *file, stack_ptr s)
{
if (! file)
return;
convert_regs_exit (void)
{
int value_reg_low, value_reg_high;
- stack output_stack;
+ stack_ptr output_stack;
rtx retvalue;
retvalue = stack_result (current_function_decl);
static void
propagate_stack (edge e)
{
- stack src_stack = &BLOCK_INFO (e->src)->stack_out;
- stack dest_stack = &BLOCK_INFO (e->dest)->stack_in;
+ stack_ptr src_stack = &BLOCK_INFO (e->src)->stack_out;
+ stack_ptr dest_stack = &BLOCK_INFO (e->dest)->stack_in;
int reg;
/* Preserve the order of the original stack, but check whether
compensate_edge (edge e)
{
basic_block source = e->src, target = e->dest;
- stack target_stack = &BLOCK_INFO (target)->stack_in;
- stack source_stack = &BLOCK_INFO (source)->stack_out;
+ stack_ptr target_stack = &BLOCK_INFO (target)->stack_in;
+ stack_ptr source_stack = &BLOCK_INFO (source)->stack_out;
struct stack_def regstack;
int reg;
int max_uid;
/* Clean up previous run. */
- if (stack_regs_mentioned_data != NULL)
- VEC_free (char, heap, stack_regs_mentioned_data);
+ stack_regs_mentioned_data.release ();
/* See if there is something to do. Flow analysis is quite
expensive so we might save some compilation time. */
/* Allocate a cache for stack_regs_mentioned. */
max_uid = get_max_uid ();
- stack_regs_mentioned_data = VEC_alloc (char, heap, max_uid + 1);
- memset (VEC_address (char, stack_regs_mentioned_data),
+ stack_regs_mentioned_data.create (max_uid + 1);
+ memset (stack_regs_mentioned_data.address (),
0, sizeof (char) * (max_uid + 1));
convert_regs ();
{
RTL_PASS,
"*stack_regs", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
gate_handle_stack_regs, /* gate */
NULL, /* execute */
NULL, /* sub */
{
RTL_PASS,
"stack", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
NULL, /* gate */
rest_of_handle_stack_regs, /* execute */
NULL, /* sub */