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
This commit is contained in:
Jakub Jelinek 2006-12-21 14:13:15 +01:00 committed by Jakub Jelinek
parent 4a4cd49c06
commit 5075abae44
5 changed files with 147 additions and 0 deletions

View File

@ -1,5 +1,10 @@
2006-12-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/30262
PR middle-end/30263
* tree-nested.c (walk_asm_expr): New function.
(walk_stmts): Use it for ASM_EXPR.
PR target/30230
* config/ia64/ia64.c (ia64_add_bundle_selector_before): New function.
(bundling): Use it.

View File

@ -1,5 +1,11 @@
2006-12-21 Jakub Jelinek <jakub@redhat.com>
PR middle-end/30262
* gcc.c-torture/execute/20061220-1.c: New test.
PR middle-end/30263
* gcc.dg/gomp/asm-1.c: New test.
PR target/30230
* g++.dg/eh/ia64-2.C: New test.

View File

@ -0,0 +1,72 @@
/* PR middle-end/30262 */
extern void abort (void);
int
foo (void)
{
unsigned int x = 0;
void nested (void)
{
x = 254;
}
nested ();
asm volatile ("" :: "r" (x));
asm volatile ("" :: "m" (x));
asm volatile ("" :: "mr" (x));
asm volatile ("" : "=r" (x) : "0" (x));
asm volatile ("" : "=m" (x) : "m" (x));
return x;
}
int
bar (void)
{
unsigned int x = 0;
void nested (void)
{
asm volatile ("" :: "r" (x));
asm volatile ("" :: "m" (x));
asm volatile ("" :: "mr" (x));
x += 4;
asm volatile ("" : "=r" (x) : "0" (x));
asm volatile ("" : "=m" (x) : "m" (x));
}
nested ();
return x;
}
int
baz (void)
{
unsigned int x = 0;
void nested (void)
{
void nested2 (void)
{
asm volatile ("" :: "r" (x));
asm volatile ("" :: "m" (x));
asm volatile ("" :: "mr" (x));
x += 4;
asm volatile ("" : "=r" (x) : "0" (x));
asm volatile ("" : "=m" (x) : "m" (x));
}
nested2 ();
nested2 ();
}
nested ();
return x;
}
int
main (void)
{
if (foo () != 254 || bar () != 4 || baz () != 8)
abort ();
return 0;
}

View File

@ -0,0 +1,19 @@
/* PR middle-end/30263 */
/* { dg-do compile } */
/* { dg-options "-O2 -fopenmp" } */
void
foo (void)
{
int s0, s1 = 5, s2 = 6;
int p0, p1, p2;
int f0 = 4, f1 = 5, f2 = 6;
#pragma omp parallel shared (s0, s1, s2) private (p0, p1, p2) \
firstprivate (f0, f1, f2)
{
asm ("" : "=m" (p0) : "m" (p1), "mr" (p2));
if (omp_get_thread_num () == 0)
asm ("" : "=m" (s0) : "m" (s1), "mr" (s2));
asm ("" : "=m" (f0) : "m" (f1), "mr" (f2));
}
}

View File

@ -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);