inline-asm: Fix ICE with bitfields in "m" operands [PR100785]
Bitfields, while they live in memory, aren't something inline-asm can easily
operate on.
For C and "=m" or "+m", we were diagnosing bitfields in the past in the
FE, where c_mark_addressable had:
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
{
error
("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
return false;
}
but that check got moved in GCC 6 to build_unary_op instead and now we
emit an error during expansion and ICE afterwards (i.e. error-recovery).
For "m" it used to be diagnosed in c_mark_addressable too, but since
GCC 6 it is ice-on-invalid.
For C++, this was never diagnosed in the FE, but used to be diagnosed
in the gimplifier and/or during expansion before 4.8.
The following patch does multiple things:
1) diagnoses it in the FEs
2) simplifies during expansion the inline asm if any errors have been
reported (similarly how e.g. vregs pass if it detects errors on
inline-asm either deletes them or simplifies to bare minimum -
just labels), so that we don't have error-recovery ICEs there
2021-06-11 Jakub Jelinek <jakub@redhat.com>
PR inline-asm/100785
gcc/
* cfgexpand.c (expand_asm_stmt): If errors are emitted,
remove all inputs, outputs and clobbers from the asm and
set template to "".
gcc/c/
* c-typeck.c (c_mark_addressable): Diagnose trying to make
bit-fields addressable.
gcc/cp/
* typeck.c (cxx_mark_addressable): Diagnose trying to make
bit-fields addressable.
gcc/testsuite/
* c-c++-common/pr100785.c: New test.
(cherry picked from commit 644c2cc5f2
)
This commit is contained in:
parent
914540797a
commit
b6e4453172
@ -5033,8 +5033,17 @@ c_mark_addressable (tree exp, bool array_ref_p)
|
||||
&& TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
|
||||
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
|
||||
return true;
|
||||
/* FALLTHRU */
|
||||
x = TREE_OPERAND (x, 0);
|
||||
break;
|
||||
|
||||
case COMPONENT_REF:
|
||||
if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
|
||||
{
|
||||
error ("cannot take address of bit-field %qD",
|
||||
TREE_OPERAND (x, 1));
|
||||
return false;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case ADDR_EXPR:
|
||||
case ARRAY_REF:
|
||||
case REALPART_EXPR:
|
||||
|
@ -3076,6 +3076,7 @@ expand_asm_stmt (gasm *stmt)
|
||||
unsigned ninputs = gimple_asm_ninputs (stmt);
|
||||
unsigned nlabels = gimple_asm_nlabels (stmt);
|
||||
unsigned i;
|
||||
bool error_seen = false;
|
||||
|
||||
/* ??? Diagnose during gimplification? */
|
||||
if (ninputs + noutputs + nlabels > MAX_RECOG_OPERANDS)
|
||||
@ -3134,6 +3135,7 @@ expand_asm_stmt (gasm *stmt)
|
||||
{
|
||||
/* ??? Diagnose during gimplification? */
|
||||
error ("unknown register name %qs in %<asm%>", regname);
|
||||
error_seen = true;
|
||||
}
|
||||
else if (j == -4)
|
||||
{
|
||||
@ -3196,7 +3198,10 @@ expand_asm_stmt (gasm *stmt)
|
||||
&& REG_P (DECL_RTL (output_tvec[j]))
|
||||
&& HARD_REGISTER_P (DECL_RTL (output_tvec[j]))
|
||||
&& output_hregno == REGNO (DECL_RTL (output_tvec[j])))
|
||||
error ("invalid hard register usage between output operands");
|
||||
{
|
||||
error ("invalid hard register usage between output operands");
|
||||
error_seen = true;
|
||||
}
|
||||
|
||||
/* Verify matching constraint operands use the same hard register
|
||||
and that the non-matching constraint operands do not use the same
|
||||
@ -3219,13 +3224,19 @@ expand_asm_stmt (gasm *stmt)
|
||||
}
|
||||
if (i == match
|
||||
&& output_hregno != input_hregno)
|
||||
error ("invalid hard register usage between output operand "
|
||||
"and matching constraint operand");
|
||||
{
|
||||
error ("invalid hard register usage between output "
|
||||
"operand and matching constraint operand");
|
||||
error_seen = true;
|
||||
}
|
||||
else if (early_clobber_p
|
||||
&& i != match
|
||||
&& output_hregno == input_hregno)
|
||||
error ("invalid hard register usage between earlyclobber "
|
||||
"operand and input operand");
|
||||
{
|
||||
error ("invalid hard register usage between "
|
||||
"earlyclobber operand and input operand");
|
||||
error_seen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3301,7 +3312,10 @@ expand_asm_stmt (gasm *stmt)
|
||||
op = validize_mem (op);
|
||||
|
||||
if (! allows_reg && !MEM_P (op))
|
||||
error ("output number %d not directly addressable", i);
|
||||
{
|
||||
error ("output number %d not directly addressable", i);
|
||||
error_seen = true;
|
||||
}
|
||||
if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode)
|
||||
|| GET_CODE (op) == CONCAT)
|
||||
{
|
||||
@ -3341,6 +3355,19 @@ expand_asm_stmt (gasm *stmt)
|
||||
inout_opnum.safe_push (i);
|
||||
}
|
||||
|
||||
const char *str = gimple_asm_string (stmt);
|
||||
if (error_seen)
|
||||
{
|
||||
ninputs = 0;
|
||||
noutputs = 0;
|
||||
inout_opnum.truncate (0);
|
||||
output_rvec.truncate (0);
|
||||
clobber_rvec.truncate (0);
|
||||
constraints.truncate (0);
|
||||
CLEAR_HARD_REG_SET (clobbered_regs);
|
||||
str = "";
|
||||
}
|
||||
|
||||
auto_vec<rtx, MAX_RECOG_OPERANDS> input_rvec;
|
||||
auto_vec<machine_mode, MAX_RECOG_OPERANDS> input_mode;
|
||||
|
||||
@ -3399,7 +3426,7 @@ expand_asm_stmt (gasm *stmt)
|
||||
}
|
||||
|
||||
/* For in-out operands, copy output rtx to input rtx. */
|
||||
unsigned ninout = inout_opnum.length();
|
||||
unsigned ninout = inout_opnum.length ();
|
||||
for (i = 0; i < ninout; i++)
|
||||
{
|
||||
int j = inout_opnum[i];
|
||||
@ -3453,7 +3480,7 @@ expand_asm_stmt (gasm *stmt)
|
||||
|
||||
rtx body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
|
||||
: GET_MODE (output_rvec[0])),
|
||||
ggc_strdup (gimple_asm_string (stmt)),
|
||||
ggc_strdup (str),
|
||||
"", 0, argvec, constraintvec,
|
||||
labelvec, locus);
|
||||
MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt);
|
||||
|
@ -7081,9 +7081,14 @@ cxx_mark_addressable (tree exp, bool array_ref_p)
|
||||
&& TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
|
||||
&& VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
|
||||
return true;
|
||||
x = TREE_OPERAND (x, 0);
|
||||
break;
|
||||
|
||||
case COMPONENT_REF:
|
||||
if (bitfield_p (x))
|
||||
error ("attempt to take address of bit-field");
|
||||
/* FALLTHRU */
|
||||
case ADDR_EXPR:
|
||||
case COMPONENT_REF:
|
||||
case ARRAY_REF:
|
||||
case REALPART_EXPR:
|
||||
case IMAGPART_EXPR:
|
||||
|
21
gcc/testsuite/c-c++-common/pr100785.c
Normal file
21
gcc/testsuite/c-c++-common/pr100785.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* PR inline-asm/100785 */
|
||||
|
||||
struct S { int a : 1; };
|
||||
|
||||
void
|
||||
foo (struct S *x)
|
||||
{
|
||||
__asm__ ("" : "+m" (x->a)); /* { dg-error "address of bit-field" } */
|
||||
} /* { dg-error "invalid lvalue in 'asm' output 0" "" { target c } .-1 } */
|
||||
/* { dg-error "memory input 1 is not directly addressable" "" { target c } .-2 } */
|
||||
void
|
||||
bar (struct S *x)
|
||||
{
|
||||
__asm__ ("" : "=m" (x->a)); /* { dg-error "address of bit-field" } */
|
||||
} /* { dg-error "invalid lvalue in 'asm' output 0" "" { target c } .-1 } */
|
||||
|
||||
void
|
||||
baz (struct S *x)
|
||||
{
|
||||
__asm__ ("" : : "m" (x->a)); /* { dg-error "address of bit-field" } */
|
||||
} /* { dg-error "memory input 0 is not directly addressable" "" { target c } .-1 } */
|
Loading…
Reference in New Issue
Block a user