diff mbox series

[2/3] Define __LIBGCC_DWARF_REG_SIZES_CONSTANT__ if DWARF register size is constant

Message ID f08400a5054aadb4fa6e2da62a2768700944b591.1667930077.git.fweimer@redhat.com
State New
Headers show
Series Further libgcc unwinder improvements | expand

Commit Message

Florian Weimer Nov. 8, 2022, 6:05 p.m. UTC
And use that to speed up the libgcc unwinder.

	* gcc/debug.h (dwarf_reg_sizes_constant): Declare.
	* gcc/dwarf2cfi.cc (dwarf_reg_sizes_constant): New function.
	* gcc/c-family/c-cppbuiltin.c
	(__LIBGCC_DWARF_REG_SIZES_CONSTANT__): Define if constant is
	known.

libgcc/

	* unwind-dw2.c (dwarf_reg_size): New function.
	(_Unwind_GetGR, _Unwind_SetGR, _Unwind_SetGRPtr)
	(_Unwind_SetSpColumn, uw_install_context_1): Use it.
	(uw_init_context_1): Do not initialize dwarf_reg_size_table
	if not in use.
---
 gcc/c-family/c-cppbuiltin.cc |  6 ++++++
 gcc/debug.h                  |  2 ++
 gcc/dwarf2cfi.cc             | 23 ++++++++++++++++++++
 libgcc/unwind-dw2.c          | 41 +++++++++++++++++++++++++-----------
 4 files changed, 60 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index cdb658f6ac9..ab98bf3b059 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1515,6 +1515,12 @@  c_cpp_builtins (cpp_reader *pfile)
 #endif
       builtin_define_with_int_value ("__LIBGCC_DWARF_FRAME_REGISTERS__",
 				     DWARF_FRAME_REGISTERS);
+      {
+	int value = dwarf_reg_sizes_constant ();
+	if (value > 0)
+	  builtin_define_with_int_value ("__LIBGCC_DWARF_REG_SIZES_CONSTANT__",
+					 value);
+      }
 #ifdef EH_RETURN_STACKADJ_RTX
       cpp_define (pfile, "__LIBGCC_EH_RETURN_STACKADJ_RTX__");
 #endif
diff --git a/gcc/debug.h b/gcc/debug.h
index fe85115d5f3..6bcc8da1f76 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -245,6 +245,8 @@  extern const struct gcc_debug_hooks vmsdbg_debug_hooks;
 
 /* Dwarf2 frame information.  */
 
+extern int dwarf_reg_sizes_constant ();
+
 extern void dwarf2out_begin_prologue (unsigned int, unsigned int,
 				      const char *);
 extern void dwarf2out_vms_end_prologue (unsigned int, const char *);
diff --git a/gcc/dwarf2cfi.cc b/gcc/dwarf2cfi.cc
index b29173b2156..d45d20478b4 100644
--- a/gcc/dwarf2cfi.cc
+++ b/gcc/dwarf2cfi.cc
@@ -334,6 +334,29 @@  generate_dwarf_reg_sizes (poly_uint16 *sizes)
     targetm.init_dwarf_reg_sizes_extra (sizes);
 }
 
+/* Return 0 if the DWARF register sizes are not constant, otherwise
+   return the size constant.  */
+
+int
+dwarf_reg_sizes_constant ()
+{
+  poly_uint16 *sizes = XALLOCAVEC (poly_uint16, DWARF_FRAME_REGISTERS);
+  generate_dwarf_reg_sizes (sizes);
+
+  int result;
+  for (unsigned int i = 0; i < DWARF_FRAME_REGISTERS; i++)
+    {
+      unsigned short value;
+      if (!sizes[i].is_constant (&value))
+	return 0;
+      if (i == 0)
+	result = value;
+      else if (result != value)
+	return 0;
+    }
+  return result;
+}
+
 /* Generate code to initialize the dwarf register size table located
    at the provided ADDRESS.  */
 
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index eaceace2029..c370121bb29 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -148,9 +148,25 @@  struct _Unwind_Context
   char by_value[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
 };
 
+#ifdef __LIBGCC_DWARF_REG_SIZES_CONSTANT__
+static inline unsigned char
+dwarf_reg_size (int index __attribute__ ((__unused__)))
+{
+  return __LIBGCC_DWARF_REG_SIZES_CONSTANT__;
+}
+#else
 /* Byte size of every register managed by these routines.  */
 static unsigned char dwarf_reg_size_table[__LIBGCC_DWARF_FRAME_REGISTERS__+1];
 
+
+static inline unsigned char
+dwarf_reg_size (unsigned index)
+{
+  gcc_assert (index < sizeof (dwarf_reg_size_table));
+  return dwarf_reg_size_table[index];
+}
+#endif
+
 
 /* Read unaligned data from the instruction buffer.  */
 
@@ -232,8 +248,7 @@  _Unwind_GetGR (struct _Unwind_Context *context, int regno)
 #endif
 
   index = DWARF_REG_TO_UNWIND_COLUMN (regno);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
-  size = dwarf_reg_size_table[index];
+  size = dwarf_reg_size (index);
   val = context->reg[index];
 
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
@@ -280,8 +295,7 @@  _Unwind_SetGR (struct _Unwind_Context *context, int index, _Unwind_Word val)
   void *ptr;
 
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
-  size = dwarf_reg_size_table[index];
+  size = dwarf_reg_size (index);
 
   if (_Unwind_IsExtendedContext (context) && context->by_value[index])
     {
@@ -329,9 +343,8 @@  _Unwind_SetGRValue (struct _Unwind_Context *context, int index,
 		    _Unwind_Word val)
 {
   index = DWARF_REG_TO_UNWIND_COLUMN (index);
-  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
   /* Return column size may be smaller than _Unwind_Context_Reg_Val.  */
-  gcc_assert (dwarf_reg_size_table[index] <= sizeof (_Unwind_Context_Reg_Val));
+  gcc_assert (dwarf_reg_size (index) <= sizeof (_Unwind_Context_Reg_Val));
 
   context->by_value[index] = 1;
   context->reg[index] = _Unwind_Get_Unwind_Context_Reg_Val (val);
@@ -1387,7 +1400,7 @@  static inline void
 _Unwind_SetSpColumn (struct _Unwind_Context *context, void *cfa,
 		     _Unwind_SpTmp *tmp_sp)
 {
-  int size = dwarf_reg_size_table[__builtin_dwarf_sp_column ()];
+  int size = dwarf_reg_size (__builtin_dwarf_sp_column ());
 
   if (size == sizeof(_Unwind_Ptr))
     tmp_sp->ptr = (_Unwind_Ptr) cfa;
@@ -1573,11 +1586,13 @@  uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
     }									   \
   while (0)
 
+#ifndef __LIBGCC_DWARF_REG_SIZES_CONSTANT__
 static inline void
 init_dwarf_reg_size_table (void)
 {
   __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
 }
+#endif
 
 static void __attribute__((noinline))
 uw_init_context_1 (struct _Unwind_Context *context,
@@ -1596,16 +1611,18 @@  uw_init_context_1 (struct _Unwind_Context *context,
   code = uw_frame_state_for (context, &fs);
   gcc_assert (code == _URC_NO_REASON);
 
-#if __GTHREADS
+#ifndef __LIBGCC_DWARF_REG_SIZES_CONSTANT__
+# if __GTHREADS
   {
     static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
     if (__gthread_once (&once_regsizes, init_dwarf_reg_size_table) != 0
 	&& dwarf_reg_size_table[0] == 0)
       init_dwarf_reg_size_table ();
   }
-#else
+# else
   if (dwarf_reg_size_table[0] == 0)
     init_dwarf_reg_size_table ();
+# endif
 #endif
 
   /* Force the frame state to use the known cfa value.  */
@@ -1682,20 +1699,20 @@  uw_install_context_1 (struct _Unwind_Context *current,
 	{
 	  _Unwind_Word w;
 	  _Unwind_Ptr p;
-	  if (dwarf_reg_size_table[i] == sizeof (_Unwind_Word))
+	  if (dwarf_reg_size (i) == sizeof (_Unwind_Word))
 	    {
 	      w = (_Unwind_Internal_Ptr) t;
 	      memcpy (c, &w, sizeof (_Unwind_Word));
 	    }
 	  else
 	    {
-	      gcc_assert (dwarf_reg_size_table[i] == sizeof (_Unwind_Ptr));
+	      gcc_assert (dwarf_reg_size (i) == sizeof (_Unwind_Ptr));
 	      p = (_Unwind_Internal_Ptr) t;
 	      memcpy (c, &p, sizeof (_Unwind_Ptr));
 	    }
 	}
       else if (t && c && t != c)
-	memcpy (c, t, dwarf_reg_size_table[i]);
+	memcpy (c, t, dwarf_reg_size (i));
     }
 
   /* If the current frame doesn't have a saved stack pointer, then we