Commit 74f0c611 by Richard Henderson Committed by Richard Henderson

re PR inline-asm/15740 (ICE caused by a memory operand in an asm statement)

	PR inline-asm/15740
        * gimplify.c (gimplify_asm_expr): Move resolve asm names ...
        * c-typeck.c (build_asm_expr): ... here.  Validate input
        constraints.  Mark memory inputs addressable.

        * semantics.c (finish_asm_stmt): Resolve asm names.  Validate input
        constraints.  Mark memory inputs addressable.

From-SVN: r92693
parent 85f3cc42
2004-12-28 Richard Henderson <rth@redhat.com>
PR inline-asm/15740
* gimplify.c (gimplify_asm_expr): Move resolve asm names ...
* c-typeck.c (build_asm_expr): ... here. Validate input
constraints. Mark memory inputs addressable.
2004-12-28 Hans-Peter Nilsson <hp@bitrange.com> 2004-12-28 Hans-Peter Nilsson <hp@bitrange.com>
PR target/18321 PR target/18321
......
...@@ -6287,47 +6287,74 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, ...@@ -6287,47 +6287,74 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
tree args; tree args;
int i; int i;
const char *constraint; const char *constraint;
const char **oconstraints;
bool allows_mem, allows_reg, is_inout; bool allows_mem, allows_reg, is_inout;
int ninputs; int ninputs, noutputs;
int noutputs;
ninputs = list_length (inputs); ninputs = list_length (inputs);
noutputs = list_length (outputs); noutputs = list_length (outputs);
oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
string = resolve_asm_operand_names (string, outputs, inputs);
/* Remove output conversions that change the type but not the mode. */ /* Remove output conversions that change the type but not the mode. */
for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail)) for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
{ {
tree output = TREE_VALUE (tail); tree output = TREE_VALUE (tail);
/* ??? Really, this should not be here. Users should be using a
proper lvalue, dammit. But there's a long history of using casts
in the output operands. In cases like longlong.h, this becomes a
primitive form of typechecking -- if the cast can be removed, then
the output operand had a type of the proper width; otherwise we'll
get an error. Gross, but ... */
STRIP_NOPS (output); STRIP_NOPS (output);
TREE_VALUE (tail) = output;
lvalue_or_else (output, lv_asm); if (!lvalue_or_else (output, lv_asm))
output = error_mark_node;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
oconstraints[i] = constraint;
if (!parse_output_constraint (&constraint, i, ninputs, noutputs, if (parse_output_constraint (&constraint, i, ninputs, noutputs,
&allows_mem, &allows_reg, &is_inout)) &allows_mem, &allows_reg, &is_inout))
{ {
/* By marking this operand as erroneous, we will not try /* If the operand is going to end up in memory,
to process this operand again in expand_asm_operands. */ mark it addressable. */
TREE_VALUE (tail) = error_mark_node; if (!allows_reg && !c_mark_addressable (output))
continue; output = error_mark_node;
} }
else
output = error_mark_node;
/* If the operand is a DECL that is going to end up in TREE_VALUE (tail) = output;
memory, assume it is addressable. This is a bit more
conservative than it would ideally be; the exact test is
buried deep in expand_asm_operands and depends on the
DECL_RTL for the OPERAND -- which we don't have at this
point. */
if (!allows_reg && DECL_P (output))
c_mark_addressable (output);
} }
/* Perform default conversions on array and function inputs. /* Perform default conversions on array and function inputs.
Don't do this for other types as it would screw up operands Don't do this for other types as it would screw up operands
expected to be in memory. */ expected to be in memory. */
for (tail = inputs; tail; tail = TREE_CHAIN (tail)) for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail)); {
tree input;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
input = TREE_VALUE (tail);
input = default_function_array_conversion (input);
if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
oconstraints, &allows_mem, &allows_reg))
{
/* If the operand is going to end up in memory,
mark it addressable. */
if (!allows_reg && allows_mem && !c_mark_addressable (input))
input = error_mark_node;
}
else
input = error_mark_node;
TREE_VALUE (tail) = input;
}
args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers); args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
...@@ -6337,6 +6364,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers, ...@@ -6337,6 +6364,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
ASM_VOLATILE_P (args) = 1; ASM_VOLATILE_P (args) = 1;
ASM_INPUT_P (args) = 1; ASM_INPUT_P (args) = 1;
} }
return args; return args;
} }
......
2004-12-28 Richard Henderson <rth@redhat.com>
PR inline-asm/15740
* semantics.c (finish_asm_stmt): Resolve asm names. Validate input
constraints. Mark memory inputs addressable.
2004-12-27 Jason Merrill <jason@redhat.com> 2004-12-27 Jason Merrill <jason@redhat.com>
* decl.c (expand_static_init): Don't use shortcut if * decl.c (expand_static_init): Don't use shortcut if
......
...@@ -1139,62 +1139,80 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, ...@@ -1139,62 +1139,80 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
if (!processing_template_decl) if (!processing_template_decl)
{ {
int ninputs, noutputs;
const char *constraint;
const char **oconstraints;
bool allows_mem, allows_reg, is_inout;
tree operand;
int i; int i;
int ninputs;
int noutputs;
for (t = input_operands; t; t = TREE_CHAIN (t)) ninputs = list_length (input_operands);
noutputs = list_length (output_operands);
oconstraints = (const char **) alloca (noutputs * sizeof (char *));
string = resolve_asm_operand_names (string, output_operands,
input_operands);
for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
{
operand = TREE_VALUE (t);
/* ??? Really, this should not be here. Users should be using a
proper lvalue, dammit. But there's a long history of using
casts in the output operands. In cases like longlong.h, this
becomes a primitive form of typechecking -- if the cast can be
removed, then the output operand had a type of the proper width;
otherwise we'll get an error. Gross, but ... */
STRIP_NOPS (operand);
if (!lvalue_or_else (operand, lv_asm))
operand = error_mark_node;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
oconstraints[i] = constraint;
if (parse_output_constraint (&constraint, i, ninputs, noutputs,
&allows_mem, &allows_reg, &is_inout))
{ {
tree converted_operand /* If the operand is going to end up in memory,
= decay_conversion (TREE_VALUE (t)); mark it addressable. */
if (!allows_reg && !cxx_mark_addressable (operand))
operand = error_mark_node;
}
else
operand = error_mark_node;
TREE_VALUE (t) = operand;
}
for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t))
{
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
operand = decay_conversion (TREE_VALUE (t));
/* If the type of the operand hasn't been determined (e.g., /* If the type of the operand hasn't been determined (e.g.,
because it involves an overloaded function), then issue because it involves an overloaded function), then issue
an error message. There's no context available to an error message. There's no context available to
resolve the overloading. */ resolve the overloading. */
if (TREE_TYPE (converted_operand) == unknown_type_node) if (TREE_TYPE (operand) == unknown_type_node)
{ {
error ("type of asm operand %qE could not be determined", error ("type of asm operand %qE could not be determined",
TREE_VALUE (t)); TREE_VALUE (t));
converted_operand = error_mark_node; operand = error_mark_node;
}
TREE_VALUE (t) = converted_operand;
} }
ninputs = list_length (input_operands); if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
noutputs = list_length (output_operands); oconstraints, &allows_mem, &allows_reg))
for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
{ {
bool allows_mem; /* If the operand is going to end up in memory,
bool allows_reg; mark it addressable. */
bool is_inout; if (!allows_reg && allows_mem && !cxx_mark_addressable (operand))
const char *constraint; operand = error_mark_node;
tree operand;
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
operand = TREE_VALUE (t);
if (!parse_output_constraint (&constraint,
i, ninputs, noutputs,
&allows_mem,
&allows_reg,
&is_inout))
{
/* By marking this operand as erroneous, we will not try
to process this operand again in expand_asm_operands. */
TREE_VALUE (t) = error_mark_node;
continue;
} }
else
operand = error_mark_node;
/* If the operand is a DECL that is going to end up in TREE_VALUE (t) = operand;
memory, assume it is addressable. This is a bit more
conservative than it would ideally be; the exact test is
buried deep in expand_asm_operands and depends on the
DECL_RTL for the OPERAND -- which we don't have at this
point. */
if (!allows_reg && DECL_P (operand))
cxx_mark_addressable (operand);
} }
} }
......
...@@ -3262,10 +3262,6 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p) ...@@ -3262,10 +3262,6 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p)
bool allows_mem, allows_reg, is_inout; bool allows_mem, allows_reg, is_inout;
enum gimplify_status ret, tret; enum gimplify_status ret, tret;
ASM_STRING (expr)
= resolve_asm_operand_names (ASM_STRING (expr), ASM_OUTPUTS (expr),
ASM_INPUTS (expr));
ret = GS_ALL_DONE; ret = GS_ALL_DONE;
for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link)) for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link))
{ {
......
/* PR inline-asm/15740 */
/* { dg-do compile } */
/* { dg-options "-O" } */
void foo(void)
{
int a, b;
a = 1;
b = a + 1;
asm ("" : : "m" (a));
}
/* PR inline-asm/15740 */
/* { dg-do compile } */
/* { dg-options "-O" } */
void foo(void)
{
int a, b;
a = 1;
b = a + 1;
asm ("" : : "m" (a));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment