aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-12-28 17:22:15 -0800
committerRichard Henderson <rth@gcc.gnu.org>2004-12-28 17:22:15 -0800
commit74f0c611c681e93dfb49bcd0d525f76d8c46af24 (patch)
tree54bc73bf49c5c1cd15ddc720798149307cd44186 /gcc
parent85f3cc42950bc89d6f494397c4ebb39bc830a66e (diff)
downloadgcc-74f0c611c681e93dfb49bcd0d525f76d8c46af24.zip
gcc-74f0c611c681e93dfb49bcd0d525f76d8c46af24.tar.gz
gcc-74f0c611c681e93dfb49bcd0d525f76d8c46af24.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-typeck.c72
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/semantics.c100
-rw-r--r--gcc/gimplify.c4
-rw-r--r--gcc/testsuite/g++.dg/opt/asm2.C11
-rw-r--r--gcc/testsuite/gcc.dg/asm-9.c11
7 files changed, 144 insertions, 67 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7b44126..d89c892 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+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>
PR target/18321
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index d2963b3..5eae3aa 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -6287,47 +6287,74 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
tree args;
int i;
const char *constraint;
+ const char **oconstraints;
bool allows_mem, allows_reg, is_inout;
- int ninputs;
- int noutputs;
+ int ninputs, noutputs;
ninputs = list_length (inputs);
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. */
for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (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);
- 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)));
+ oconstraints[i] = constraint;
- 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 (tail) = error_mark_node;
- continue;
- }
+ if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+ &allows_mem, &allows_reg, &is_inout))
+ {
+ /* If the operand is going to end up in memory,
+ mark it addressable. */
+ if (!allows_reg && !c_mark_addressable (output))
+ output = error_mark_node;
+ }
+ else
+ output = error_mark_node;
- /* If the operand is a DECL that is going to end up in
- 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);
+ TREE_VALUE (tail) = output;
}
/* Perform default conversions on array and function inputs.
Don't do this for other types as it would screw up operands
expected to be in memory. */
- for (tail = inputs; tail; tail = TREE_CHAIN (tail))
- TREE_VALUE (tail) = default_function_array_conversion (TREE_VALUE (tail));
+ for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (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);
@@ -6337,6 +6364,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
ASM_VOLATILE_P (args) = 1;
ASM_INPUT_P (args) = 1;
}
+
return args;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 622a001..9e96120 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+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>
* decl.c (expand_static_init): Don't use shortcut if
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index ab1c028..b34de19 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1139,62 +1139,80 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
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 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)
{
- tree converted_operand
- = decay_conversion (TREE_VALUE (t));
-
+ 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))
+ {
+ /* If the operand is going to end up in memory,
+ 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.,
because it involves an overloaded function), then issue
an error message. There's no context available to
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",
TREE_VALUE (t));
- converted_operand = error_mark_node;
+ operand = error_mark_node;
}
- TREE_VALUE (t) = converted_operand;
- }
-
- ninputs = list_length (input_operands);
- noutputs = list_length (output_operands);
-
- for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i)
- {
- bool allows_mem;
- bool allows_reg;
- bool is_inout;
- const char *constraint;
- 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))
+ if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg))
{
- /* 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;
+ /* If the operand is going to end up in memory,
+ mark it addressable. */
+ if (!allows_reg && allows_mem && !cxx_mark_addressable (operand))
+ operand = error_mark_node;
}
+ else
+ operand = error_mark_node;
- /* If the operand is a DECL that is going to end up in
- 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);
+ TREE_VALUE (t) = operand;
}
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f89b7207..ca37597 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3262,10 +3262,6 @@ gimplify_asm_expr (tree *expr_p, tree *pre_p, tree *post_p)
bool allows_mem, allows_reg, is_inout;
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;
for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = TREE_CHAIN (link))
{
diff --git a/gcc/testsuite/g++.dg/opt/asm2.C b/gcc/testsuite/g++.dg/opt/asm2.C
new file mode 100644
index 0000000..4e32441
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/asm2.C
@@ -0,0 +1,11 @@
+/* PR inline-asm/15740 */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+void foo(void)
+{
+ int a, b;
+ a = 1;
+ b = a + 1;
+ asm ("" : : "m" (a));
+}
diff --git a/gcc/testsuite/gcc.dg/asm-9.c b/gcc/testsuite/gcc.dg/asm-9.c
new file mode 100644
index 0000000..4e32441
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asm-9.c
@@ -0,0 +1,11 @@
+/* PR inline-asm/15740 */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+void foo(void)
+{
+ int a, b;
+ a = 1;
+ b = a + 1;
+ asm ("" : : "m" (a));
+}