|
|
The Arm port uses %? in format strings to generate mnemonic suffixes for
conditionally executed instructions. These expand to different things
depending on the value of current_insn_predicate.
It turns out that there's a fair amount of kernel code that includes %? in
inline assembly fragments. This is arguably a bug in the kernel. However,
given gcc never conditionaly executes inline asm it's not entirely
unreasonable to expect this to "work". i.e. should expand to the
unconditional form.
Currently final_scan_insn doesn't set current_insn_predicate until after asm
fragments have been output. This means inline asm incorrectly inherits its
conditionalness from the previous insn.
The attached patch resets current_insn_predicate earlier, so inline asm output
is unconditional. It fixes an arm-linux kernel miscompilation.
Tested with cross to arm-none-eabi.
Ok for mainline and 4.1?
Paul
2006-08-09 Paul Brook <paul@xxxxxxxxxxxxxxxx>
gcc/
* final.c (final_scan_insn): Clear current_insn_predicate before
outputting inline asm.
gcc/testsuite/
* gcc.target/arm/cond-asm.c: New test.
Index: gcc/final.c
===================================================================
--- gcc/final.c (revision 116034)
+++ gcc/final.c (working copy)
@@ -1985,6 +1985,10 @@ final_scan_insn (rtx insn, FILE *file, i
int insn_code_number;
const char *template;
+#ifdef HAVE_conditional_execution
+ /* Reset this early so it is correct for ASM statements. */
+ current_insn_predicate = NULL_RTX;
+#endif
/* An INSN, JUMP_INSN or CALL_INSN.
First check for special kinds that recog doesn't recognize. */
@@ -2419,8 +2423,6 @@ final_scan_insn (rtx insn, FILE *file, i
#ifdef HAVE_conditional_execution
if (GET_CODE (PATTERN (insn)) == COND_EXEC)
current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));
- else
- current_insn_predicate = NULL_RTX;
#endif
#ifdef HAVE_cc0
Index: gcc/testsuite/gcc.target/arm/cond-asm.c
===================================================================
--- gcc/testsuite/gcc.target/arm/cond-asm.c (revision 0)
+++ gcc/testsuite/gcc.target/arm/cond-asm.c (revision 0)
@@ -0,0 +1,13 @@
+/* Check that %? in inline asm expands to nothing. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target arm32 } */
+int b;
+int foo(int a)
+{
+ if (a)
+ b = 42;
+ asm ("test%?me":"=r"(a):"0"(a));
+ return a;
+}
+/* { dg-final { scan-assembler "testme" } } */
|
|