imply that this is called once, independent of asms in code.
Adjust to now being pased output and input lists. Mention helper
function decl_overlaps_hard_reg_set_p.
* hooks.c (hook_tree_tree_tree_tree_3rd_identity): Rename from
hook_tree_tree_identity and to take three trees, returning third.
* hooks.h (hook_tree_tree_tree_tree_3rd_identity): Adjust the
prototype.
* stmt.c: include hard-reg-set.h before tree.h.
(decl_overlaps_hard_reg_set_p): New function, broken out from...
(decl_conflicts_with_clobbers_p): Call
decl_overlaps_hard_reg_set_p.
(expand_asm_operands): Pass output and input lists in call to
targetm.md_asm_clobbers.
* target-def.h (TARGET_MD_ASM_CLOBBERS): Define as
hook_tree_tree_tree_tree_3rd_identity.
* target.h (struct gcc_target.md_asm_clobbers): Take three tree
parameters.
* tree.h [HARD_CONST] (decl_overlaps_hard_reg_set_p): Prototype.
* config/i386/i386.c (ix86_md_asm_clobbers): Adjust to three
parameters, first two unused.
* config/cris/cris.c (cris_md_asm_clobbers): Adjust to added
parameters. Only add MOF to clobbers if there's no 'h' mentioned
in constraint letters and MOF is not mentioned as a asm-declared
register in neither of the input and output lists.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96923
138bc75d-0d04-0410-961f-
82ee72b054a4
+2005-03-23 Hans-Peter Nilsson <hp@axis.com>
+
+ * doc/tm.texi (TARGET_MD_ASM_CLOBBERS): Adjust wording to not
+ imply that this is called once, independent of asms in code.
+ Adjust to now being pased output and input lists. Mention helper
+ function decl_overlaps_hard_reg_set_p.
+ * hooks.c (hook_tree_tree_tree_tree_3rd_identity): Rename from
+ hook_tree_tree_identity and to take three trees, returning third.
+ * hooks.h (hook_tree_tree_tree_tree_3rd_identity): Adjust the
+ prototype.
+ * stmt.c: include hard-reg-set.h before tree.h.
+ (decl_overlaps_hard_reg_set_p): New function, broken out from...
+ (decl_conflicts_with_clobbers_p): Call
+ decl_overlaps_hard_reg_set_p.
+ (expand_asm_operands): Pass output and input lists in call to
+ targetm.md_asm_clobbers.
+ * target-def.h (TARGET_MD_ASM_CLOBBERS): Define as
+ hook_tree_tree_tree_tree_3rd_identity.
+ * target.h (struct gcc_target.md_asm_clobbers): Take three tree
+ parameters.
+ * tree.h [HARD_CONST] (decl_overlaps_hard_reg_set_p): Prototype.
+ * config/i386/i386.c (ix86_md_asm_clobbers): Adjust to three
+ parameters, first two unused.
+ * config/cris/cris.c (cris_md_asm_clobbers): Adjust to added
+ parameters. Only add MOF to clobbers if there's no 'h' mentioned
+ in constraint letters and MOF is not mentioned as a asm-declared
+ register in neither of the input and output lists.
+
2005-03-23 DJ Delorie <dj@redhat.com>
* optabs.c (expand_binop): Make sure the first subword's result
tree, bool);
static int cris_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
-static tree cris_md_asm_clobbers (tree);
+static tree cris_md_asm_clobbers (tree, tree, tree);
/* This is the argument from the "-max-stack-stackframe=" option. */
const char *cris_max_stackframe_str;
/* Worker function for TARGET_MD_ASM_CLOBBERS. */
static tree
-cris_md_asm_clobbers (tree clobbers)
+cris_md_asm_clobbers (tree outputs, tree inputs, tree clobbers)
{
+ HARD_REG_SET mof_set;
+ tree t;
+
+ CLEAR_HARD_REG_SET (mof_set);
+ SET_HARD_REG_BIT (mof_set, CRIS_MOF_REGNUM);
+
+ for (t = outputs; t != NULL; t = TREE_CHAIN (t))
+ {
+ tree val = TREE_VALUE (t);
+
+ /* The constraint letter for the singleton register class of MOF
+ is 'h'. If it's mentioned in the constraints, the asm is
+ MOF-aware and adding it to the clobbers would cause it to have
+ impossible constraints. */
+ if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
+ 'h') != NULL
+ || decl_overlaps_hard_reg_set_p (val, mof_set))
+ return clobbers;
+ }
+
+ for (t = inputs; t != NULL; t = TREE_CHAIN (t))
+ {
+ tree val = TREE_VALUE (t);
+
+ if (strchr (TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))),
+ 'h') != NULL
+ || decl_overlaps_hard_reg_set_p (val, mof_set))
+ return clobbers;
+ }
+
return tree_cons (NULL_TREE,
build_string (strlen (reg_names[CRIS_MOF_REGNUM]),
reg_names[CRIS_MOF_REGNUM]),
static int extended_reg_mentioned_1 (rtx *, void *);
static bool ix86_rtx_costs (rtx, int, int, int *);
static int min_insn_size (rtx);
-static tree ix86_md_asm_clobbers (tree clobbers);
+static tree ix86_md_asm_clobbers (tree outputs, tree inputs, tree clobbers);
static bool ix86_must_pass_in_stack (enum machine_mode mode, tree type);
static bool ix86_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
tree, bool);
with the old cc0-based compiler. */
static tree
-ix86_md_asm_clobbers (tree clobbers)
+ix86_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED,
+ tree inputs ATTRIBUTE_UNUSED,
+ tree clobbers)
{
clobbers = tree_cons (NULL_TREE, build_string (5, "flags"),
clobbers);
You need not define this macro if it would always evaluate to zero.
@end defmac
-@deftypefn {Target Hook} tree TARGET_MD_ASM_CLOBBERS (tree @var{clobbers})
+@deftypefn {Target Hook} tree TARGET_MD_ASM_CLOBBERS (tree @var{outputs}, tree @var{inputs}, tree @var{clobbers})
This target hook should add to @var{clobbers} @code{STRING_CST} trees for
-any hard regs the port wishes to automatically clobber for all asms.
+any hard regs the port wishes to automatically clobber for an asm.
It should return the result of the last @code{tree_cons} used to add a
-clobber.
+clobber. The @var{outputs}, @var{inputs} and @var{clobber} lists are the
+corresponding parameters to the asm and may be inspected to avoid
+clobbering a register that is an input or output of the asm. You can use
+@code{decl_overlaps_hard_reg_set_p}, declared in @file{tree.h}, to test
+for overlap with regards to asm-declared registers.
@end deftypefn
@defmac MATH_LIBRARY
return NULL;
}
-/* Generic hook that takes a tree and returns it as is. */
+/* Generic hook that takes three trees and returns the last one as is. */
tree
-hook_tree_tree_identity (tree a)
+hook_tree_tree_tree_tree_3rd_identity (tree a ATTRIBUTE_UNUSED,
+ tree b ATTRIBUTE_UNUSED, tree c)
{
- return a;
+ return c;
}
/* Generic hook that takes a tree and returns a NULL string. */
extern rtx hook_rtx_rtx_identity (rtx);
extern rtx hook_rtx_rtx_null (rtx);
extern rtx hook_rtx_tree_int_null (tree, int);
-extern tree hook_tree_tree_identity (tree a);
+extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree);
extern const char *hook_constcharptr_tree_null (tree);
extern tree hook_tree_tree_tree_bool_null (tree, tree, bool);
#endif
#include "tm.h"
#include "rtl.h"
+#include "hard-reg-set.h"
#include "tree.h"
#include "tm_p.h"
#include "flags.h"
#include "insn-config.h"
#include "expr.h"
#include "libfuncs.h"
-#include "hard-reg-set.h"
#include "recog.h"
#include "machmode.h"
#include "toplev.h"
return true;
}
-/* Check for overlap between registers marked in CLOBBERED_REGS and
- anything inappropriate in DECL. Emit error and return TRUE for error,
- FALSE for ok. */
+/* Return true iff there's an overlap between REGS and DECL, where DECL
+ can be an asm-declared register. */
-static bool
-decl_conflicts_with_clobbers_p (tree decl, const HARD_REG_SET clobbered_regs)
+bool
+decl_overlaps_hard_reg_set_p (tree decl, const HARD_REG_SET regs)
{
- /* Conflicts between asm-declared register variables and the clobber
- list are not allowed. */
if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& DECL_REGISTER (decl)
&& REG_P (DECL_RTL (decl))
regno < (REGNO (reg)
+ hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
regno++)
- if (TEST_HARD_REG_BIT (clobbered_regs, regno))
- {
- error ("asm-specifier for variable %qs conflicts with "
- "asm clobber list",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
-
- /* Reset registerness to stop multiple errors emitted for a
- single variable. */
- DECL_REGISTER (decl) = 0;
- return true;
- }
+ if (TEST_HARD_REG_BIT (regs, regno))
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Check for overlap between registers marked in CLOBBERED_REGS and
+ anything inappropriate in DECL. Emit error and return TRUE for error,
+ FALSE for ok. */
+
+static bool
+decl_conflicts_with_clobbers_p (tree decl, const 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))
+ {
+ error ("asm-specifier for variable %qs conflicts with asm clobber list",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+
+ /* Reset registerness to stop multiple errors emitted for a single
+ variable. */
+ DECL_REGISTER (decl) = 0;
+ return true;
}
+
return false;
}
Case in point is when the i386 backend moved from cc0 to a hard reg --
maintaining source-level compatibility means automatically clobbering
the flags register. */
- clobbers = targetm.md_asm_clobbers (clobbers);
+ clobbers = targetm.md_asm_clobbers (outputs, inputs, clobbers);
/* Count the number of meaningful clobbered registers, ignoring what
we would ignore later. */
#define TARGET_BUILTIN_SETJMP_FRAME_VALUE default_builtin_setjmp_frame_value
-#define TARGET_MD_ASM_CLOBBERS hook_tree_tree_identity
+#define TARGET_MD_ASM_CLOBBERS hook_tree_tree_tree_tree_3rd_identity
#define TARGET_DWARF_CALLING_CONVENTION hook_int_tree_0
rtx (* builtin_setjmp_frame_value) (void);
/* This target hook should add STRING_CST trees for any hard regs
- the port wishes to automatically clobber for all asms. */
- tree (* md_asm_clobbers) (tree);
+ the port wishes to automatically clobber for an asm. */
+ tree (* md_asm_clobbers) (tree, tree, tree);
/* This target hook allows the backend to specify a calling convention
in the debug information. This function actually returns an
extern void expand_case (tree);
extern void expand_decl (tree);
extern void expand_anon_union_decl (tree, tree, tree);
+#ifdef HARD_CONST
+/* Silly ifdef to avoid having all includers depend on hard-reg-set.h. */
+extern bool decl_overlaps_hard_reg_set_p (tree, const HARD_REG_SET);
+#endif
/* In gimplify.c. */
extern tree create_artificial_label (void);