public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* CFI for saved argument registers
@ 2022-05-16  6:29 Andreas Krebbel
  2022-05-16 13:25 ` Florian Weimer
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Andreas Krebbel @ 2022-05-16  6:29 UTC (permalink / raw)
  To: gcc

Hi,

I'm trying to provide a simple dwarf unwinder with access to the
argument register content. The goal is to make this information
available for optimized code without having to access debug
information for things like call site args. The extra overhead
of saving the values to the stack is acceptable in that case.

For that purpose I save the argument registers to the stack as we
would do for a variable argument lists. But this time I also provide
the CFI to allow the unwinder to locate the save slots.  Since I never
actually intend to restore the content there is no matching
cfi_restore for the cfi_offset and dwarf2cfi complains about the
traces being inconsistent because of that. I couldn't find a way to
prevent this.

The only way I see right now is adding a new reg note to invalidate
the save information in the reg_save array in dwarf2cfi.

Would this be acceptable? Is there perhaps an easier way to achieve that?

Bye,

Andreas

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: CFI for saved argument registers
  2022-05-16  6:29 CFI for saved argument registers Andreas Krebbel
@ 2022-05-16 13:25 ` Florian Weimer
  2022-05-16 14:39 ` Andreas Schwab
  2022-05-31 12:11 ` Andreas Krebbel
  2 siblings, 0 replies; 5+ messages in thread
From: Florian Weimer @ 2022-05-16 13:25 UTC (permalink / raw)
  To: Andreas Krebbel via Gcc

* Andreas Krebbel via Gcc:

> For that purpose I save the argument registers to the stack as we
> would do for a variable argument lists. But this time I also provide
> the CFI to allow the unwinder to locate the save slots.  Since I never
> actually intend to restore the content there is no matching
> cfi_restore for the cfi_offset and dwarf2cfi complains about the
> traces being inconsistent because of that. I couldn't find a way to
> prevent this.
>
> The only way I see right now is adding a new reg note to invalidate
> the save information in the reg_save array in dwarf2cfi.
>
> Would this be acceptable? Is there perhaps an easier way to achieve that?

This is very interesting.  I think we should do this in glibc for abort
and __assert_fail for as many registers as possible, hopefully
preserving more information for debuggers.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: CFI for saved argument registers
  2022-05-16  6:29 CFI for saved argument registers Andreas Krebbel
  2022-05-16 13:25 ` Florian Weimer
@ 2022-05-16 14:39 ` Andreas Schwab
  2022-05-17  6:19   ` Andreas Krebbel
  2022-05-31 12:11 ` Andreas Krebbel
  2 siblings, 1 reply; 5+ messages in thread
From: Andreas Schwab @ 2022-05-16 14:39 UTC (permalink / raw)
  To: Andreas Krebbel via Gcc

On Mai 16 2022, Andreas Krebbel via Gcc wrote:

> The only way I see right now is adding a new reg note to invalidate
> the save information in the reg_save array in dwarf2cfi.
>
> Would this be acceptable? Is there perhaps an easier way to achieve that?

Doesn't it work to use .cfi_remember_state/.cfi_restore_state?

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: CFI for saved argument registers
  2022-05-16 14:39 ` Andreas Schwab
@ 2022-05-17  6:19   ` Andreas Krebbel
  0 siblings, 0 replies; 5+ messages in thread
From: Andreas Krebbel @ 2022-05-17  6:19 UTC (permalink / raw)
  To: Andreas Schwab, Andreas Krebbel via Gcc

On 5/16/22 16:39, Andreas Schwab wrote:
> On Mai 16 2022, Andreas Krebbel via Gcc wrote:
> 
>> The only way I see right now is adding a new reg note to invalidate
>> the save information in the reg_save array in dwarf2cfi.
>>
>> Would this be acceptable? Is there perhaps an easier way to achieve that?
> 
> Doesn't it work to use .cfi_remember_state/.cfi_restore_state?
> 
This might work but I think also for that I would have to implement means to trigger it explicitely
with an RTX somehow.

Also I rather would avoid emitting special CFI for that purpose. I think the CFI I currently have
(with more .cfi_offset's than .cfi_restore's) is valid. I only have to convince the validation step
in dwarf2cfi to accept this. Therefore the idea was to introduce a new regnote to say that at a
certain point it is intentional that there is no .cfi_restore for a register. The action in
dwarf2cfi should only be to remove the reg from reg_save and be done with it.

Bye,

Andreas


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: CFI for saved argument registers
  2022-05-16  6:29 CFI for saved argument registers Andreas Krebbel
  2022-05-16 13:25 ` Florian Weimer
  2022-05-16 14:39 ` Andreas Schwab
@ 2022-05-31 12:11 ` Andreas Krebbel
  2 siblings, 0 replies; 5+ messages in thread
From: Andreas Krebbel @ 2022-05-31 12:11 UTC (permalink / raw)
  To: gcc

On 5/16/22 08:29, Andreas Krebbel via Gcc wrote:
> Hi,
> 
> I'm trying to provide a simple dwarf unwinder with access to the
> argument register content. The goal is to make this information
> available for optimized code without having to access debug
> information for things like call site args. The extra overhead
> of saving the values to the stack is acceptable in that case.
> 
> For that purpose I save the argument registers to the stack as we
> would do for a variable argument lists. But this time I also provide
> the CFI to allow the unwinder to locate the save slots.  Since I never
> actually intend to restore the content there is no matching
> cfi_restore for the cfi_offset and dwarf2cfi complains about the
> traces being inconsistent because of that. I couldn't find a way to
> prevent this.
> 
> The only way I see right now is adding a new reg note to invalidate
> the save information in the reg_save array in dwarf2cfi.
> 
> Would this be acceptable? Is there perhaps an easier way to achieve that?

Attached is a small patch adding a new reg note REG_CFA_NORESTORE.

I would attach that new note to the register save insn to indicate that this register will not be
restored. I'll have to emit the REG_CFA_OFFSET note as well then.

An insn saving r2-r6 without restoring them would look like this then:

(insn/f 31 21 32 2 (parallel [
            (set/f (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                        (const_int 16 [0x10])) [4  S8 A8])
                (reg:DI 2 %r2))
            (set/f (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                        (const_int 24 [0x18])) [4  S8 A8])
                (reg:DI 3 %r3))
            (set/f (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                        (const_int 32 [0x20])) [4  S8 A8])
                (reg:DI 4 %r4))
            (set/f (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                        (const_int 40 [0x28])) [4  S8 A8])
                (reg:DI 5 %r5))
            (set/f (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                        (const_int 48 [0x30])) [4  S8 A8])
                (reg:DI 6 %r6))
        ]) "/home/andreas/preserveargs/reduce2/t.c":2:51 -1
     (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                    (const_int 48 [0x30])) [4  S8 A8])
            (reg:DI 6 %r6))
        (expr_list:REG_CFA_NO_RESTORE (reg:DI 6 %r6)
            (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                            (const_int 40 [0x28])) [4  S8 A8])
                    (reg:DI 5 %r5))
                (expr_list:REG_CFA_NO_RESTORE (reg:DI 5 %r5)
                    (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                                    (const_int 32 [0x20])) [4  S8 A8])
                            (reg:DI 4 %r4))
                        (expr_list:REG_CFA_NO_RESTORE (reg:DI 4 %r4)
                            (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                                            (const_int 24 [0x18])) [4  S8 A8])
                                    (reg:DI 3 %r3))
                                (expr_list:REG_CFA_NO_RESTORE (reg:DI 3 %r3)
                                    (expr_list:REG_CFA_OFFSET (set (mem/c:DI (plus:DI (reg/f:DI 15 %r15)
                                                    (const_int 16 [0x10])) [4  S8 A8])
                                            (reg:DI 2 %r2))
                                        (expr_list:REG_CFA_NO_RESTORE (reg:DI 2 %r2)
                                            (nil))))))))))))

diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 362ff3fdac27..2cbc2465c3a7 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -1346,7 +1346,7 @@ dwarf2out_frame_debug_cfa_val_expression (rtx set)
 /* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note.  */

 static void
-dwarf2out_frame_debug_cfa_restore (rtx reg)
+dwarf2out_frame_debug_cfa_restore (rtx reg, bool emit_cfi)
 {
   gcc_assert (REG_P (reg));

@@ -1354,7 +1354,8 @@ dwarf2out_frame_debug_cfa_restore (rtx reg)
   if (!span)
     {
       unsigned int regno = dwf_regno (reg);
-      add_cfi_restore (regno);
+      if (emit_cfi)
+	add_cfi_restore (regno);
       update_row_reg_save (cur_row, regno, NULL);
     }
   else
@@ -1369,7 +1370,8 @@ dwarf2out_frame_debug_cfa_restore (rtx reg)
 	  reg = XVECEXP (span, 0, par_index);
 	  gcc_assert (REG_P (reg));
 	  unsigned int regno = dwf_regno (reg);
-	  add_cfi_restore (regno);
+	  if (emit_cfi)
+	    add_cfi_restore (regno);
 	  update_row_reg_save (cur_row, regno, NULL);
 	}
     }
@@ -2155,6 +2157,7 @@ dwarf2out_frame_debug (rtx_insn *insn)
 	break;

       case REG_CFA_RESTORE:
+      case REG_CFA_NO_RESTORE:
 	n = XEXP (note, 0);
 	if (n == NULL)
 	  {
@@ -2163,7 +2166,7 @@ dwarf2out_frame_debug (rtx_insn *insn)
 	      n = XVECEXP (n, 0, 0);
 	    n = XEXP (n, 0);
 	  }
-	dwarf2out_frame_debug_cfa_restore (n);
+	dwarf2out_frame_debug_cfa_restore (n, REG_NOTE_KIND (note) == REG_CFA_RESTORE);
 	handled_one = true;
 	break;

diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 995052ebc28e..3e8cc189301c 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -167,6 +167,8 @@ REG_CFA_NOTE (CFA_VAL_EXPRESSION)
    first pattern is the register to be restored.  */
 REG_CFA_NOTE (CFA_RESTORE)

+REG_CFA_NOTE (CFA_NO_RESTORE)
+
 /* Attached to insns that are RTX_FRAME_RELATED_P, marks insn that sets
    vDRAP from DRAP.  If vDRAP is a register, vdrap_reg is initalized
    to the argument, if it is a MEM, it is ignored.  */

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-05-31 12:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-16  6:29 CFI for saved argument registers Andreas Krebbel
2022-05-16 13:25 ` Florian Weimer
2022-05-16 14:39 ` Andreas Schwab
2022-05-17  6:19   ` Andreas Krebbel
2022-05-31 12:11 ` Andreas Krebbel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).