This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, GCC/ARM] Fix PR77933: stack corruption on ARM when using high registers and lr


Hi,

When saving registers, function thumb1_expand_prologue () aims at minimizing the number of push instructions. One of the optimization it does is to push lr alongside high register(s) (after having moved them to low register(s)) when there is no low register to save. The way this is implemented is to add lr to the list of registers that can be pushed just before the push happens. This would then push lr and allows it to be used for further push if there was not enough registers to push all high registers to be pushed.

However, the logic that decides what register to move high registers to before being pushed only looks at low registers (see for loop initialization). This means not only that lr is not used for pushing high registers but also that lr is not removed from the list of registers to be pushed when it's not used. This extra lr push is not poped in epilogue leading in stack corruption.

This patch changes the loop to iterate over register r0 to lr so as to both fix the stack corruption and reuse lr to push some high register when possible.

ChangeLog entry are as follow:

*** gcc/ChangeLog ***

2016-11-01  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        PR target/77933
        * config/arm/arm.c (thumb1_expand_prologue): Also check for lr being a
        pushable register.


*** gcc/testsuite/ChangeLog ***

2016-11-01  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        PR target/77933
        * gcc.target/arm/pr77933.c: New test.


Testing: no regression on arm-none-eabi GCC cross-compiler targeting Cortex-M0

Is this ok for trunk?

Best regards,

Thomas
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index dd8d5e5db8ca50daab648e58df290969aa794862..22a20caf42389748fc64ee0a3f880c6bea4c8f49 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -24990,7 +24990,7 @@ thumb1_expand_prologue (void)
 	{
 	  unsigned long real_regs_mask = 0;
 
-	  for (regno = LAST_LO_REGNUM; regno >= 0; regno --)
+	  for (regno = LR_REGNUM; regno >= 0; regno --)
 	    {
 	      if (pushable_regs & (1 << regno))
 		{
diff --git a/gcc/testsuite/gcc.target/arm/pr77933.c b/gcc/testsuite/gcc.target/arm/pr77933.c
new file mode 100644
index 0000000000000000000000000000000000000000..cba7e9bb9aa57c6755f79b5ec2ea1a8744e23599
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr77933.c
@@ -0,0 +1,9 @@
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+int
+main (void)
+{
+  __asm__ volatile ("" : : : "r8", "r9", "lr");
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]