aboutsummaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
authorJ"orn Rennecke <joern.rennecke@st.com>2006-02-09 19:17:09 +0000
committerJoern Rennecke <amylaar@gcc.gnu.org>2006-02-09 19:17:09 +0000
commit91b4415af4fafcd53f44b671003e917dd7ec0cfd (patch)
tree7fcf4d414c6e351a2b6ddc6cf557386db43b8be6 /gcc/stmt.c
parent0e692cc0bfb3d8209ee6bfe2e3467f444df860d9 (diff)
downloadgcc-91b4415af4fafcd53f44b671003e917dd7ec0cfd.zip
gcc-91b4415af4fafcd53f44b671003e917dd7ec0cfd.tar.gz
gcc-91b4415af4fafcd53f44b671003e917dd7ec0cfd.tar.bz2
re PR inline-asm/16194 (global register with inline-asm and clobered)
PR inline-asm/16194 gcc: * tree.h (decl_overlaps_hard_reg_set_p) Don't declare. (tree_overlaps_hard_reg_set): Declare. * stmt.c (decl_overlaps_hard_reg_set_p): Now static. Change return type and signature to match function type expected by walk_tree. (tree_overlaps_hard_reg_set): New function. (decl_conflicts_with_clobbers_p): Rename to: (tree_conflicts_with_clobbers_p). Take HARD_REG_SET * argument. Use tree_overlaps_hard_reg_set. Changed caller. * doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Replace decl_overlaps_hard_reg_set_p with tree_overlaps_hard_reg_set. * cris.c (cris_md_asm_clobbers): Likewise. gcc/testsuite: * gcc.dg/pr16194.c: New test. From-SVN: r110810
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c73
1 files changed, 45 insertions, 28 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index da2f750..3bb4f42 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -105,7 +105,7 @@ static int cost_table_initialized;
#define COST_TABLE(I) cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
static int n_occurrences (int, const char *);
-static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET);
+static bool tree_conflicts_with_clobbers_p (tree, HARD_REG_SET *);
static void expand_nl_goto_receiver (void);
static bool check_operand_nalternatives (tree, tree);
static bool check_unique_operand_names (tree, tree);
@@ -558,49 +558,66 @@ parse_input_constraint (const char **constraint_p, int input_num,
return true;
}
-/* Return true iff there's an overlap between REGS and DECL, where DECL
- can be an asm-declared register. */
+/* Return DECL iff there's an overlap between *REGS and DECL, where DECL
+ can be an asm-declared register. Called via walk_tree. */
-bool
-decl_overlaps_hard_reg_set_p (tree decl, const HARD_REG_SET regs)
+static tree
+decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED,
+ void *data)
{
- if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
- && DECL_REGISTER (decl)
- && REG_P (DECL_RTL (decl))
- && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+ tree decl = *declp;
+ const HARD_REG_SET *regs = data;
+
+ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
{
- rtx reg = DECL_RTL (decl);
- unsigned int regno;
-
- for (regno = REGNO (reg);
- regno < (REGNO (reg)
- + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
- regno++)
- if (TEST_HARD_REG_BIT (regs, regno))
- return true;
+ if (DECL_REGISTER (decl)
+ && REG_P (DECL_RTL (decl))
+ && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
+ {
+ rtx reg = DECL_RTL (decl);
+ unsigned int regno;
+
+ for (regno = REGNO (reg);
+ regno < (REGNO (reg)
+ + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
+ regno++)
+ if (TEST_HARD_REG_BIT (*regs, regno))
+ return decl;
+ }
+ walk_subtrees = 0;
}
-
- return false;
+ else if (TYPE_P (decl))
+ walk_subtrees = 0;
+ return NULL_TREE;
}
+/* If there is an overlap between *REGS and DECL, return the first overlap
+ found. */
+tree
+tree_overlaps_hard_reg_set (tree decl, HARD_REG_SET *regs)
+{
+ return walk_tree (&decl, decl_overlaps_hard_reg_set_p, regs, NULL);
+}
/* Check for overlap between registers marked in CLOBBERED_REGS and
- anything inappropriate in DECL. Emit error and return TRUE for error,
- FALSE for ok. */
+ anything inappropriate in T. Emit error and return the register
+ variable definition for error, NULL_TREE for ok. */
static bool
-decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
+tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
{
/* Conflicts between asm-declared register variables and the clobber
list are not allowed. */
- if (decl_overlaps_hard_reg_set_p (decl, clobbered_regs))
+ tree overlap = tree_overlaps_hard_reg_set (t, clobbered_regs);
+
+ if (overlap)
{
error ("asm-specifier for variable %qs conflicts with asm clobber list",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
+ IDENTIFIER_POINTER (DECL_NAME (overlap)));
/* Reset registerness to stop multiple errors emitted for a single
variable. */
- DECL_REGISTER (decl) = 0;
+ DECL_REGISTER (overlap) = 0;
return true;
}
@@ -827,7 +844,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
inout_opnum[ninout++] = i;
}
- if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+ if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
clobber_conflict_found = 1;
}
@@ -923,7 +940,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
= gen_rtx_ASM_INPUT (TYPE_MODE (type),
ggc_strdup (constraints[i + noutputs]));
- if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
+ if (tree_conflicts_with_clobbers_p (val, &clobbered_regs))
clobber_conflict_found = 1;
}