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/gimple.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/gimple.c')
-rw-r--r-- | gcc/gimple.c | 83 |
1 files changed, 35 insertions, 48 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index 33daafc6ad0..425463c31ca 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -507,17 +507,22 @@ gimple_build_bind (tree vars, gimple_seq body, tree block) static inline gimple gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, - unsigned nclobbers) + unsigned nclobbers, unsigned nlabels) { gimple p; int size = strlen (string); + /* ASMs with labels cannot have outputs. This should have been + enforced by the front end. */ + gcc_assert (nlabels == 0 || noutputs == 0); + p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK, - ninputs + noutputs + nclobbers); + ninputs + noutputs + nclobbers + nlabels); p->gimple_asm.ni = ninputs; p->gimple_asm.no = noutputs; p->gimple_asm.nc = nclobbers; + p->gimple_asm.nl = nlabels; p->gimple_asm.string = ggc_alloc_string (string, size); #ifdef GATHER_STATISTICS @@ -535,11 +540,13 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs, NCLOBBERS is the number of clobbered registers. INPUTS is a vector of the input register parameters. OUTPUTS is a vector of the output register parameters. - CLOBBERS is a vector of the clobbered register parameters. */ + CLOBBERS is a vector of the clobbered register parameters. + LABELS is a vector of destination labels. */ gimple gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, - VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers) + VEC(tree,gc)* outputs, VEC(tree,gc)* clobbers, + VEC(tree,gc)* labels) { gimple p; unsigned i; @@ -547,7 +554,8 @@ gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, p = gimple_build_asm_1 (string, VEC_length (tree, inputs), VEC_length (tree, outputs), - VEC_length (tree, clobbers)); + VEC_length (tree, clobbers), + VEC_length (tree, labels)); for (i = 0; i < VEC_length (tree, inputs); i++) gimple_asm_set_input_op (p, i, VEC_index (tree, inputs, i)); @@ -558,39 +566,8 @@ gimple_build_asm_vec (const char *string, VEC(tree,gc)* inputs, for (i = 0; i < VEC_length (tree, clobbers); i++) gimple_asm_set_clobber_op (p, i, VEC_index (tree, clobbers, i)); - return p; -} - -/* Build a GIMPLE_ASM statement. - - STRING is the assembly code. - NINPUT is the number of register inputs. - NOUTPUT is the number of register outputs. - NCLOBBERS is the number of clobbered registers. - ... are trees for each input, output and clobbered register. */ - -gimple -gimple_build_asm (const char *string, unsigned ninputs, unsigned noutputs, - unsigned nclobbers, ...) -{ - gimple p; - unsigned i; - va_list ap; - - p = gimple_build_asm_1 (string, ninputs, noutputs, nclobbers); - - va_start (ap, nclobbers); - - for (i = 0; i < ninputs; i++) - gimple_asm_set_input_op (p, i, va_arg (ap, tree)); - - for (i = 0; i < noutputs; i++) - gimple_asm_set_output_op (p, i, va_arg (ap, tree)); - - for (i = 0; i < nclobbers; i++) - gimple_asm_set_clobber_op (p, i, va_arg (ap, tree)); - - va_end (ap); + for (i = 0; i < VEC_length (tree, labels); i++) + gimple_asm_set_label_op (p, i, VEC_index (tree, labels, i)); return p; } @@ -1230,10 +1207,10 @@ static tree walk_gimple_asm (gimple stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) { - tree ret; + tree ret, op; unsigned noutputs; const char **oconstraints; - unsigned i; + unsigned i, n; const char *constraint; bool allows_mem, allows_reg, is_inout; @@ -1245,7 +1222,7 @@ walk_gimple_asm (gimple stmt, walk_tree_fn callback_op, for (i = 0; i < noutputs; i++) { - tree op = gimple_asm_output_op (stmt, i); + op = gimple_asm_output_op (stmt, i); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); oconstraints[i] = constraint; parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg, @@ -1257,18 +1234,19 @@ walk_gimple_asm (gimple stmt, walk_tree_fn callback_op, return ret; } - for (i = 0; i < gimple_asm_ninputs (stmt); i++) + n = gimple_asm_ninputs (stmt); + for (i = 0; i < n; i++) { - tree op = gimple_asm_input_op (stmt, i); + op = gimple_asm_input_op (stmt, i); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints, &allows_mem, &allows_reg); if (wi) - wi->val_only = (allows_reg || !allows_mem); - - /* Although input "m" is not really a LHS, we need a lvalue. */ - if (wi) - wi->is_lhs = !wi->val_only; + { + wi->val_only = (allows_reg || !allows_mem); + /* Although input "m" is not really a LHS, we need a lvalue. */ + wi->is_lhs = !wi->val_only; + } ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL); if (ret) return ret; @@ -1280,6 +1258,15 @@ walk_gimple_asm (gimple stmt, walk_tree_fn callback_op, wi->val_only = true; } + n = gimple_asm_nlabels (stmt); + for (i = 0; i < n; i++) + { + op = gimple_asm_label_op (stmt, i); + ret = walk_tree (&TREE_VALUE (op), callback_op, wi, NULL); + if (ret) + return ret; + } + return NULL_TREE; } |