aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-nested.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-12-21 14:13:15 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2006-12-21 14:13:15 +0100
commit5075abae44d4c23e075a7210635306ea21e55305 (patch)
tree69466bf4e0591fc2f8589b38412c0b9a5d416980 /gcc/tree-nested.c
parent4a4cd49c06a5bc003ce6282c4c613575185ac118 (diff)
downloadgcc-5075abae44d4c23e075a7210635306ea21e55305.zip
gcc-5075abae44d4c23e075a7210635306ea21e55305.tar.gz
gcc-5075abae44d4c23e075a7210635306ea21e55305.tar.bz2
re PR middle-end/30262 (ICE with nested fn accessed var in asm "m" constraint)
PR middle-end/30262 PR middle-end/30263 * tree-nested.c (walk_asm_expr): New function. (walk_stmts): Use it for ASM_EXPR. * gcc.c-torture/execute/20061220-1.c: New test. * gcc.dg/gomp/asm-1.c: New test. From-SVN: r120106
Diffstat (limited to 'gcc/tree-nested.c')
-rw-r--r--gcc/tree-nested.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 42aef32..166debb 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -546,6 +546,47 @@ get_nl_goto_field (struct nesting_info *info)
return field;
}
+/* Helper function for walk_stmts. Walk output operands of an ASM_EXPR. */
+
+static void
+walk_asm_expr (struct walk_stmt_info *wi, tree stmt)
+{
+ int noutputs = list_length (ASM_OUTPUTS (stmt));
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ int i;
+ tree link;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+
+ wi->is_lhs = true;
+ for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ oconstraints[i] = constraint;
+ parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+ &allows_reg, &is_inout);
+
+ wi->val_only = (allows_reg || !allows_mem);
+ walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+ }
+
+ for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+
+ 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;
+ walk_tree (&TREE_VALUE (link), wi->callback, wi, NULL);
+ }
+
+ wi->is_lhs = false;
+ wi->val_only = true;
+}
+
/* Iterate over all sub-statements of *TP calling walk_tree with
WI->CALLBACK for every sub-expression in each statement found. */
@@ -628,6 +669,10 @@ walk_stmts (struct walk_stmt_info *wi, tree *tp)
wi->is_lhs = false;
break;
+ case ASM_EXPR:
+ walk_asm_expr (wi, *tp);
+ break;
+
default:
wi->val_only = true;
walk_tree (tp, wi->callback, wi, NULL);