summaryrefslogtreecommitdiff
path: root/gcc/recog.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-14 20:17:24 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-14 20:17:24 +0000
commit78f55ca8366d5fc6a1547b4ab5998397e7618216 (patch)
treed43d66a4da24c2d77ee8f88fc747f6a2f149435f /gcc/recog.c
parentcf07a5908aeeb95b9662cb7b523d30a61cc15cce (diff)
downloadgcc-78f55ca8366d5fc6a1547b4ab5998397e7618216.tar.gz
* builtins.c (expand_builtin_synchronize): Use gimple_build_asm_vec.
* cfgbuild.c (make_edges): Handle asm goto. * cfglayout.c (fixup_reorder_chain): Likewise. * cfgrtl.c (patch_jump_insn): Likewise. * gimple-pretty-print.c (dump_gimple_asm): Likewise. * gimple.c (gimple_build_asm_1): Add and use nlabels parameter. (gimple_build_asm_vec): Add and use labels parameter. (gimple_build_asm): Remove. (walk_gimple_asm): Walk labels too. * gimple.def (GIMPLE_ASM): Update docs. * gimple.h: Update decls. (struct gimple_statement_asm): Change nc to use unsigned char; add nl member. (gimple_asm_nlabels): New. (gimple_asm_label_op, gimple_asm_set_label_op): New. * gimplify.c (gimplify_asm_expr): Copy labels from ASM_EXPR into gimple_build_asm_vec. * jump.c (mark_jump_label_asm): New. (mark_jump_label): Use it. (redirect_jump_1): Handle asm goto. (invert_jump_1): Soft fail if X is null. * recog.c (extract_asm_operands): New. (asm_noperands): Use it; handle asm labels. (decode_asm_operands): Use extract_asm_operands. (asm_operand_ok): Properly handle empty string. * reg-stack.c (get_asm_operands_in_out): Rename from get_asm_operand_n_inputs; use extract_asm_operands; return both inputs and outputs by reference; update all callers. * rtl.def (ASM_OPERANDS): Add label vector as operand 6. * rtl.h (ASM_OPERANDS_LABEL_VEC): New. (ASM_OPERANDS_LABEL_LENGTH, ASM_OPERANDS_LABEL): New. (ASM_OPERANDS_SOURCE_LOCATION): Renumber. (extract_asm_operands): Declare. * stmt.c (expand_asm_operands): Add and use labels parameter. (check_unique_operand_names): Likewise. (resolve_asm_operand_names, resolve_operand_name_1): Likewise. (expand_asm_stmt): Handle asm labels. * tree-cfg.c (make_gimple_asm_edges): New. (make_edges): Use it. (cleanup_dead_labels): Handle asm labels. (is_ctrl_altering_stmt): Likewise. (gimple_redirect_edge_and_branch): Likewise. * tree.def (ASM_EXPR): Add 5th operand. * tree.h (ASM_LABELS): New. (resolve_asm_operand_names): Update decl. * c-parser.c (c_parser_asm_statement): Parse asm goto. (c_parser_asm_goto_operands): New. * c-tree.h (build_asm_expr): Update decl. * c-typeck.c (build_asm_expr): Add and use labels parameter. * doc/extend.texi: Document asm goto. gcc/ada/ * gcc-interface/trans.c (Pragma_to_gnu): Use build5 for ASM_EXPR. gcc/cp/ * cp-tree.h (finish_asm_stmt): Update decl. * parser.c (cp_parser_asm_definition): Parse asm goto. (cp_parser_asm_label_list): New. * pt.c (tsubst_copy_asm_operands): Don't recurse on labels. (tsubst_expr): Handle asm labels. * semantics.c (finish_asm_stmt): Add and use labels parameter. gcc/testsuite/ * c-c++-common/asmgoto-1.c, c-c++-common/asmgoto-2.c, c-c++-common/asmgoto-3.c, gcc.c-torture/compile/asmgoto-1.c, gcc.dg/tree-ssa/asmgoto-1.c: New files. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151701 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/recog.c')
-rw-r--r--gcc/recog.c252
1 files changed, 125 insertions, 127 deletions
diff --git a/gcc/recog.c b/gcc/recog.c
index bfca43b4552..6874d6c5c60 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1373,6 +1373,42 @@ comparison_operator (rtx op, enum machine_mode mode)
&& COMPARISON_P (op));
}
+/* If BODY is an insn body that uses ASM_OPERANDS, return it. */
+
+rtx
+extract_asm_operands (rtx body)
+{
+ rtx tmp;
+ switch (GET_CODE (body))
+ {
+ case ASM_OPERANDS:
+ return body;
+
+ case SET:
+ /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */
+ tmp = SET_SRC (body);
+ if (GET_CODE (tmp) == ASM_OPERANDS)
+ return tmp;
+ break;
+
+ case PARALLEL:
+ tmp = XVECEXP (body, 0, 0);
+ if (GET_CODE (tmp) == ASM_OPERANDS)
+ return tmp;
+ if (GET_CODE (tmp) == SET)
+ {
+ tmp = SET_SRC (tmp);
+ if (GET_CODE (tmp) == ASM_OPERANDS)
+ return tmp;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
/* If BODY is an insn body that uses ASM_OPERANDS,
return the number of operands (both input and output) in the insn.
Otherwise return -1. */
@@ -1380,26 +1416,22 @@ comparison_operator (rtx op, enum machine_mode mode)
int
asm_noperands (const_rtx body)
{
- switch (GET_CODE (body))
+ rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body));
+ int n_sets = 0;
+
+ if (asm_op == NULL)
+ return -1;
+
+ if (GET_CODE (body) == SET)
+ n_sets = 1;
+ else if (GET_CODE (body) == PARALLEL)
{
- case ASM_OPERANDS:
- /* No output operands: return number of input operands. */
- return ASM_OPERANDS_INPUT_LENGTH (body);
- case SET:
- if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
- /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */
- return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1;
- else
- return -1;
- case PARALLEL:
- if (GET_CODE (XVECEXP (body, 0, 0)) == SET
- && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
+ int i;
+ if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
{
/* Multiple output operands, or 1 output plus some clobbers:
- body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */
- int i;
- int n_sets;
-
+ body is
+ [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */
/* Count backwards through CLOBBERs to determine number of SETs. */
for (i = XVECLEN (body, 0); i > 0; i--)
{
@@ -1425,30 +1457,23 @@ asm_noperands (const_rtx body)
/* If these ASM_OPERANDS rtx's came from different original insns
then they aren't allowed together. */
if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
- != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0))))
+ != ASM_OPERANDS_INPUT_VEC (asm_op))
return -1;
}
- return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)))
- + n_sets);
}
- else if (GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
+ else
{
/* 0 outputs, but some clobbers:
body is [(asm_operands ...) (clobber (reg ...))...]. */
- int i;
-
/* Make sure all the other parallel things really are clobbers. */
for (i = XVECLEN (body, 0) - 1; i > 0; i--)
if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
return -1;
-
- return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
}
- else
- return -1;
- default:
- return -1;
}
+
+ return (ASM_OPERANDS_INPUT_LENGTH (asm_op)
+ + ASM_OPERANDS_LABEL_LENGTH (asm_op) + n_sets);
}
/* Assuming BODY is an insn body that uses ASM_OPERANDS,
@@ -1466,28 +1491,19 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
const char **constraints, enum machine_mode *modes,
location_t *loc)
{
- int i;
- int noperands;
- rtx asmop = 0;
+ int noperands, nbase = 0, n, i;
+ rtx asmop;
- if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
+ switch (GET_CODE (body))
{
- asmop = SET_SRC (body);
- /* Single output operand: BODY is (set OUTPUT (asm_operands ....)). */
-
- noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1;
+ case ASM_OPERANDS:
+ /* Zero output asm: BODY is (asm_operands ...). */
+ asmop = body;
+ break;
- for (i = 1; i < noperands; i++)
- {
- if (operand_locs)
- operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1);
- if (operands)
- operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
- if (constraints)
- constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
- if (modes)
- modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
- }
+ case SET:
+ /* Single output asm: BODY is (set OUTPUT (asm_operands ...)). */
+ asmop = SET_SRC (body);
/* The output is in the SET.
Its constraint is in the ASM_OPERANDS itself. */
@@ -1499,93 +1515,70 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
if (modes)
modes[0] = GET_MODE (SET_DEST (body));
- }
- else if (GET_CODE (body) == ASM_OPERANDS)
- {
- asmop = body;
- /* No output operands: BODY is (asm_operands ....). */
-
- noperands = ASM_OPERANDS_INPUT_LENGTH (asmop);
-
- /* The input operands are found in the 1st element vector. */
- /* Constraints for inputs are in the 2nd element vector. */
- for (i = 0; i < noperands; i++)
- {
- if (operand_locs)
- operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
- if (operands)
- operands[i] = ASM_OPERANDS_INPUT (asmop, i);
- if (constraints)
- constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
- if (modes)
- modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
- }
- }
- else if (GET_CODE (body) == PARALLEL
- && GET_CODE (XVECEXP (body, 0, 0)) == SET
- && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
- {
- int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */
- int nin;
- int nout = 0; /* Does not include CLOBBERs. */
-
- asmop = SET_SRC (XVECEXP (body, 0, 0));
- nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
+ nbase = 1;
+ break;
- /* At least one output, plus some CLOBBERs. */
+ case PARALLEL:
+ {
+ int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */
- /* The outputs are in the SETs.
- Their constraints are in the ASM_OPERANDS itself. */
- for (i = 0; i < nparallel; i++)
- {
- if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
- break; /* Past last SET */
+ asmop = XVECEXP (body, 0, 0);
+ if (GET_CODE (asmop) == SET)
+ {
+ asmop = SET_SRC (asmop);
- if (operands)
- operands[i] = SET_DEST (XVECEXP (body, 0, i));
- if (operand_locs)
- operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
- if (constraints)
- constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
- if (modes)
- modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
- nout++;
- }
+ /* At least one output, plus some CLOBBERs. The outputs are in
+ the SETs. Their constraints are in the ASM_OPERANDS itself. */
+ for (i = 0; i < nparallel; i++)
+ {
+ if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
+ break; /* Past last SET */
+ if (operands)
+ operands[i] = SET_DEST (XVECEXP (body, 0, i));
+ if (operand_locs)
+ operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
+ if (constraints)
+ constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
+ if (modes)
+ modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
+ }
+ nbase = i;
+ }
+ break;
+ }
- for (i = 0; i < nin; i++)
- {
- if (operand_locs)
- operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i);
- if (operands)
- operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
- if (constraints)
- constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
- if (modes)
- modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
- }
+ default:
+ gcc_unreachable ();
}
- else if (GET_CODE (body) == PARALLEL
- && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
- {
- /* No outputs, but some CLOBBERs. */
-
- int nin;
- asmop = XVECEXP (body, 0, 0);
- nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
+ noperands = (ASM_OPERANDS_INPUT_LENGTH (asmop)
+ + ASM_OPERANDS_LABEL_LENGTH (asmop) + nbase);
- for (i = 0; i < nin; i++)
- {
- if (operand_locs)
- operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
- if (operands)
- operands[i] = ASM_OPERANDS_INPUT (asmop, i);
- if (constraints)
- constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
- if (modes)
- modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
- }
+ n = ASM_OPERANDS_INPUT_LENGTH (asmop);
+ for (i = 0; i < n; i++)
+ {
+ if (operand_locs)
+ operand_locs[nbase + i] = &ASM_OPERANDS_INPUT (asmop, i);
+ if (operands)
+ operands[nbase + i] = ASM_OPERANDS_INPUT (asmop, i);
+ if (constraints)
+ constraints[nbase + i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
+ if (modes)
+ modes[nbase + i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
+ }
+ nbase += n;
+ n = ASM_OPERANDS_LABEL_LENGTH (asmop);
+ for (i = 0; i < n; i++)
+ {
+ if (operand_locs)
+ operand_locs[nbase + i] = &ASM_OPERANDS_LABEL (asmop, i);
+ if (operands)
+ operands[nbase + i] = ASM_OPERANDS_LABEL (asmop, i);
+ if (constraints)
+ constraints[nbase + i] = "";
+ if (modes)
+ modes[nbase + i] = Pmode;
}
if (loc)
@@ -1605,6 +1598,11 @@ asm_operand_ok (rtx op, const char *constraint, const char **constraints)
/* Use constrain_operands after reload. */
gcc_assert (!reload_completed);
+ /* Empty constraint string is the same as "X,...,X", i.e. X for as
+ many alternatives as required to match the other operands. */
+ if (*constraint == '\0')
+ return 1;
+
while (*constraint)
{
char c = *constraint;