summaryrefslogtreecommitdiff
path: root/gcc/gimple.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/gimple.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/gimple.c')
-rw-r--r--gcc/gimple.c83
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;
}