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]

[AArch64] fix missing Dwarf call frame information in the epilogue


This patch fixes a bug in the AArch64 epilogue expander which failed to generate consistent information of REG_FRAME_RELATED_EXPR reg notes in some cases; for instance, given the following C source code:

int bar (unsigned int);

int foo (void)
{
   return bar (0xcafe);
}
------------------- CUT -------------------

The -O0 -g code gen for the function 'foo' is:

         .cfi_startproc
         stp     x29, x30, [sp, -16]!
.LCFI0:
         .cfi_def_cfa_offset 16
         .cfi_offset 29, -16
         .cfi_offset 30, -8
         add     x29, sp, 0
.LCFI1:
         .cfi_def_cfa_register 29
.LM2:
         mov     w0, 57005
         bl      bar
.LM3:
         ldp     x29, x30, [sp], 16
         .cfi_restore 30
         .cfi_restore 29
         ret
         .cfi_endproc
------------------- CUT -------------------

As can be seen, the CFA reg is X29 from the ADD instruction until the
end of the func; this is wrong as the LDP instruction restores X29;
the CFA reg should be set to SP after LDP.

The patch passes the gcc and g++ testsuites. Is it OK for the aarch64 branch?


Thanks, Yufeng


gcc/ChangeLog


2012-09-12 Yufeng Zhang <yufeng.zhang@arm.com>

        * config/aarch64/aarch64.c (aarch64_expand_prologue): Add new local
        variable 'cfa_reg' and replace stack_pointer_rtx with it in the
        REG_FRAME_RELATED_EXPR reg note for the load-pair with writeback
        instruction.

gcc/testsuite/ChangeLog

2012-09-12 Yufeng Zhang <yufeng.zhang@arm.com>

* gcc.target/aarch64/dwarf-cfa-reg.c: New file.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 2d7eba7..f452d3d 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -1786,7 +1786,7 @@ aarch64_expand_prologue (void)
 	       - original_frame_size
 	       - cfun->machine->frame.saved_regs_size);
 
-  /* Store pairs and load pairs have a range only of +/- 512.  */
+  /* Store pairs and load pairs have a range only -512 to 504.  */
   if (offset >= 512)
     {
       /* When the frame has a large size, an initial decrease is done on
@@ -1934,6 +1934,7 @@ aarch64_expand_epilogue (bool for_sibcall)
   HOST_WIDE_INT original_frame_size, frame_size, offset;
   HOST_WIDE_INT fp_offset;
   rtx insn;
+  rtx cfa_reg;
 
   aarch64_layout_frame ();
   original_frame_size = get_frame_size () + cfun->machine->saved_varargs_size;
@@ -1946,7 +1947,9 @@ aarch64_expand_epilogue (bool for_sibcall)
 	       - original_frame_size
 	       - cfun->machine->frame.saved_regs_size);
 
-  /* Store pairs and load pairs have a range only of +/- 512.  */
+  cfa_reg = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx;
+
+  /* Store pairs and load pairs have a range only -512 to 504.  */
   if (offset >= 512)
     {
       offset = original_frame_size + cfun->machine->frame.saved_regs_size;
@@ -1977,6 +1980,10 @@ aarch64_expand_epilogue (bool for_sibcall)
 				       hard_frame_pointer_rtx,
 				       GEN_INT (- fp_offset)));
       RTX_FRAME_RELATED_P (insn) = 1;
+      /* As SP is set to (FP - fp_offset), according to the rules in
+	 dwarf2cfi.c:dwarf2out_frame_debug_expr, CFA should be calculated
+	 from the value of SP from now on.  */
+      cfa_reg = stack_pointer_rtx;
     }
 
   aarch64_save_or_restore_callee_save_registers
@@ -2016,10 +2023,15 @@ aarch64_expand_epilogue (bool for_sibcall)
 				 GEN_INT (offset),
 				 GEN_INT (GET_MODE_SIZE (DImode) + offset)));
 	      RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 2)) = 1;
+	      /* The REG_FRAME_RELATED_EXPR to be attached to the above insn
+		 is either SP = SP + offset or SP = FP + offset, depending on
+		 which register had been used to calculate the CFA before
+		 the insn; note that FP had the same value as SP before the
+		 above insn.  */
 	      aarch64_set_frame_expr (gen_rtx_SET
 				      (Pmode,
 				       stack_pointer_rtx,
-				       gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+				       gen_rtx_PLUS (Pmode, cfa_reg,
 						     GEN_INT (offset))));
 	    }
 
@@ -2040,7 +2052,6 @@ aarch64_expand_epilogue (bool for_sibcall)
 	      RTX_FRAME_RELATED_P (insn) = 1;
 	    }
 	}
-
       else
 	{
 	  insn = emit_insn (gen_add2_insn (stack_pointer_rtx,
diff --git a/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c b/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c
new file mode 100644
index 0000000..cce8815
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/dwarf-cfa-reg.c
@@ -0,0 +1,14 @@
+/* Verify that CFA register is restored to SP after FP is restored.  */
+/* { dg-do compile } */
+/* { dg-options "-O0 -gdwarf-2" } */
+/* { dg-final { scan-assembler ".cfi_restore 30" } } */
+/* { dg-final { scan-assembler ".cfi_restore 29" } } */
+/* { dg-final { scan-assembler ".cfi_def_cfa 31, 0" } } */
+/* { dg-final { scan-assembler "ret" } } */
+
+int bar (unsigned int);
+
+int foo (void)
+{
+  return bar (0xcafe);
+}

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