diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-14 20:17:24 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-14 20:17:24 +0000 |
commit | 78f55ca8366d5fc6a1547b4ab5998397e7618216 (patch) | |
tree | d43d66a4da24c2d77ee8f88fc747f6a2f149435f /gcc/recog.c | |
parent | cf07a5908aeeb95b9662cb7b523d30a61cc15cce (diff) | |
download | gcc-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.c | 252 |
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; |