This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

dynamically disable leb128 for relaxation


The exceptions regions range's size in the FDEs are compressed by the assembler into ULEB128 when available. However the linker can post modify those size when relaxing code. Since the label relocations are not available anymore, no reparation can be done, and the exceptions handler are not associated with the correct range labels which leads to runtime failures.

The "correct" answer would be to delay the LEB128 compression from the assembler to the linker, after the labels are resolved and the difference computed, however this is a non trivial work, and the C++ relaxed code is today broken for targets supporting relaxation.

(see http://sourceware.org/ml/binutils/2009-08/msg00124.html and (http://sourceware.org/ml/binutils/2009-08/msg00192.html. threads)

This patch is a conservative approach before the LEB128 support is added into the linker to dynamically test the LEB128 support instead of having it a compile time parameter. Ideally, only ULEB128 differences between labels should be discarted, but since the FDE call site format doesn't distinguish it, all constants must be impacted. Consequently, with this scheme relaxation, exceptions and optimizing for size do not go well together :-( ) but this is better than false code gen.

We have used this workaround for SH4 during our current relaxation developments, but if it can help also the other targets that are facing the same issue, I'd like to receive comments or OK to ci.

tested for regression on i686-pc-linux-gnu and sh-superh-elf.

Best Regards

-c



Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 150822)
+++ gcc/doc/tm.texi	(working copy)
@@ -3488,6 +3488,13 @@
 linkage is necessary.  The default is @code{0}.
 @end defmac
 
+@defmac TARGET_USES_LEB128
+A C expression that evaluates to true if the target requires leb128
+to be used for dwarf compression.  Define it to be @code{1} if leb128
+linkage is necessary.  The default is @code{1} if @code{HAVE_AS_LEB128}
+is defined.
+@end defmac
+
 @node Stack Checking
 @subsection Specifying How Stack Checking is Done
 
Index: gcc/dwarf2asm.c
===================================================================
--- gcc/dwarf2asm.c	(revision 150822)
+++ gcc/dwarf2asm.c	(working copy)
@@ -564,52 +564,54 @@
 
   va_start (ap, comment);
 
-#ifdef HAVE_AS_LEB128
-  fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
+  if (TARGET_USES_LEB128)
+    {
+      fprintf (asm_out_file, "\t.uleb128 " HOST_WIDE_INT_PRINT_HEX , value);
 
-  if (flag_debug_asm && comment)
+      if (flag_debug_asm && comment)
+	{
+	  fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+	  vfprintf (asm_out_file, comment, ap);
+	}
+    }
+  else
     {
-      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
-      vfprintf (asm_out_file, comment, ap);
-    }
-#else
-  {
-    unsigned HOST_WIDE_INT work = value;
-    const char *byte_op = targetm.asm_out.byte_op;
+      unsigned HOST_WIDE_INT work = value;
+      const char *byte_op = targetm.asm_out.byte_op;
 
-    if (byte_op)
-      fputs (byte_op, asm_out_file);
-    do
-      {
-	int byte = (work & 0x7f);
-	work >>= 7;
-	if (work != 0)
-	  /* More bytes to follow.  */
-	  byte |= 0x80;
+      if (byte_op)
+	fputs (byte_op, asm_out_file);
+      do
+	{
+	  int byte = (work & 0x7f);
+	  work >>= 7;
+	  if (work != 0)
+	    /* More bytes to follow.  */
+	    byte |= 0x80;
 
-	if (byte_op)
-	  {
-	    fprintf (asm_out_file, "0x%x", byte);
-	    if (work != 0)
-	      fputc (',', asm_out_file);
-	  }
-	else
-	  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-      }
-    while (work != 0);
-
-  if (flag_debug_asm)
-    {
-      fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
-	       ASM_COMMENT_START, value);
-      if (comment)
+	  if (byte_op)
+	    {
+	      fprintf (asm_out_file, "0x%x", byte);
+	      if (work != 0)
+		fputc (',', asm_out_file);
+	    }
+	  else
+	    assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
+	}
+      while (work != 0);
+      
+      if (flag_debug_asm)
 	{
-	  fputs ("; ", asm_out_file);
-	  vfprintf (asm_out_file, comment, ap);
+	  fprintf (asm_out_file, "\t%s uleb128 " HOST_WIDE_INT_PRINT_HEX,
+		   ASM_COMMENT_START, value);
+	  if (comment)
+	    {
+	      fputs ("; ", asm_out_file);
+	      vfprintf (asm_out_file, comment, ap);
+	    }
 	}
     }
-  }
-#endif
+
   fputc ('\n', asm_out_file);
 
   va_end (ap);
@@ -648,55 +650,57 @@
 
   va_start (ap, comment);
 
-#ifdef HAVE_AS_LEB128
-  fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
+  if (TARGET_USES_LEB128)
+    {
+      fprintf (asm_out_file, "\t.sleb128 " HOST_WIDE_INT_PRINT_DEC, value);
 
-  if (flag_debug_asm && comment)
+      if (flag_debug_asm && comment)
+	{
+	  fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+	  vfprintf (asm_out_file, comment, ap);
+	}
+    }
+  else
     {
-      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
-      vfprintf (asm_out_file, comment, ap);
-    }
-#else
-  {
-    HOST_WIDE_INT work = value;
-    int more, byte;
-    const char *byte_op = targetm.asm_out.byte_op;
+      HOST_WIDE_INT work = value;
+      int more, byte;
+      const char *byte_op = targetm.asm_out.byte_op;
 
-    if (byte_op)
-      fputs (byte_op, asm_out_file);
-    do
-      {
-	byte = (work & 0x7f);
-	/* arithmetic shift */
-	work >>= 7;
-	more = !((work == 0 && (byte & 0x40) == 0)
-		 || (work == -1 && (byte & 0x40) != 0));
-	if (more)
-	  byte |= 0x80;
+      if (byte_op)
+	fputs (byte_op, asm_out_file);
+      do
+	{
+	  byte = (work & 0x7f);
+	  /* arithmetic shift */
+	  work >>= 7;
+	  more = !((work == 0 && (byte & 0x40) == 0)
+		   || (work == -1 && (byte & 0x40) != 0));
+	  if (more)
+	    byte |= 0x80;
 
-	if (byte_op)
-	  {
-	    fprintf (asm_out_file, "0x%x", byte);
-	    if (more)
-	      fputc (',', asm_out_file);
-	  }
-	else
-	  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
-      }
-    while (more);
+	  if (byte_op)
+	    {
+	      fprintf (asm_out_file, "0x%x", byte);
+	      if (more)
+		fputc (',', asm_out_file);
+	    }
+	  else
+	    assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
+	}
+      while (more);
 
-  if (flag_debug_asm)
-    {
-      fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
-	       ASM_COMMENT_START, value);
-      if (comment)
+      if (flag_debug_asm)
 	{
-	  fputs ("; ", asm_out_file);
-	  vfprintf (asm_out_file, comment, ap);
+	  fprintf (asm_out_file, "\t%s sleb128 " HOST_WIDE_INT_PRINT_DEC,
+		   ASM_COMMENT_START, value);
+	  if (comment)
+	    {
+	      fputs ("; ", asm_out_file);
+	      vfprintf (asm_out_file, comment, ap);
+	    }
 	}
     }
-  }
-#endif
+
   fputc ('\n', asm_out_file);
 
   va_end (ap);
@@ -711,14 +715,15 @@
 
   va_start (ap, comment);
 
-#ifdef HAVE_AS_LEB128
-  fputs ("\t.uleb128 ", asm_out_file);
-  assemble_name (asm_out_file, lab1);
-  fputc ('-', asm_out_file);
-  assemble_name (asm_out_file, lab2);
-#else
-  gcc_unreachable ();
-#endif
+  if (TARGET_USES_LEB128)
+    {
+      fputs ("\t.uleb128 ", asm_out_file);
+      assemble_name (asm_out_file, lab1);
+      fputc ('-', asm_out_file);
+      assemble_name (asm_out_file, lab2);
+    }
+  else
+    gcc_unreachable ();
 
   if (flag_debug_asm && comment)
     {
@@ -741,14 +746,15 @@
 
   va_start (ap, comment);
 
-#ifdef HAVE_AS_LEB128
-  fputs ("\t.sleb128 ", asm_out_file);
-  assemble_name (asm_out_file, lab1);
-  fputc ('-', asm_out_file);
-  assemble_name (asm_out_file, lab2);
-#else
-  gcc_unreachable ();
-#endif
+  if (TARGET_USES_LEB128)
+    {
+      fputs ("\t.sleb128 ", asm_out_file);
+      assemble_name (asm_out_file, lab1);
+      fputc ('-', asm_out_file);
+      assemble_name (asm_out_file, lab2);
+    }
+  else
+    gcc_unreachable ();
 
   if (flag_debug_asm && comment)
     {
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h	(revision 150822)
+++ gcc/defaults.h	(working copy)
@@ -288,6 +288,15 @@
 #define TARGET_USES_WEAK_UNWIND_INFO 0
 #endif
 
+/* Use leb128 encoding based on dynamic parameters.  */
+#ifndef TARGET_USES_LEB128
+#ifdef HAVE_AS_LEB128
+#define TARGET_USES_LEB128 1
+#else
+#define TARGET_USES_LEB128 0
+#endif
+#endif
+
 /* By default, there is no prefix on user-defined symbols.  */
 #ifndef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX ""
Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 150822)
+++ gcc/except.c	(working copy)
@@ -173,10 +173,10 @@
 
 static void push_uleb128 (varray_type *, unsigned int);
 static void push_sleb128 (varray_type *, int);
-#ifndef HAVE_AS_LEB128
+
 static int dw2_size_of_call_site_table (int);
 static int sjlj_size_of_call_site_table (void);
-#endif
+
 static void dw2_output_call_site_table (int, int);
 static void sjlj_output_call_site_table (void);
 
@@ -4139,7 +4139,6 @@
 }
 
 
-#ifndef HAVE_AS_LEB128
 static int
 dw2_size_of_call_site_table (int section)
 {
@@ -4174,7 +4173,6 @@
 
   return size;
 }
-#endif
 
 static void
 dw2_output_call_site_table (int cs_format, int section)
@@ -4364,13 +4362,10 @@
 				     int section)
 {
   int tt_format, cs_format, lp_format, i, n;
-#ifdef HAVE_AS_LEB128
   char ttype_label[32];
   char cs_after_size_label[32];
   char cs_end_label[32];
-#else
   int call_site_len;
-#endif
   int have_tt_data;
   int tt_format_size = 0;
 
@@ -4397,11 +4392,11 @@
   else
     {
       tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
-#ifdef HAVE_AS_LEB128
-      ASM_GENERATE_INTERNAL_LABEL (ttype_label,
-				   section ? "LLSDATTC" : "LLSDATT",
-				   current_function_funcdef_no);
-#endif
+      if (TARGET_USES_LEB128)
+	ASM_GENERATE_INTERNAL_LABEL (ttype_label,
+				     section ? "LLSDATTC" : "LLSDATT",
+				     current_function_funcdef_no);
+
       tt_format_size = size_of_encoded_value (tt_format);
 
       assemble_align (tt_format_size * BITS_PER_UNIT);
@@ -4427,86 +4422,93 @@
   dw2_asm_output_data (1, tt_format, "@TType format (%s)",
 		       eh_data_format_name (tt_format));
 
-#ifndef HAVE_AS_LEB128
-  if (USING_SJLJ_EXCEPTIONS)
-    call_site_len = sjlj_size_of_call_site_table ();
-  else
-    call_site_len = dw2_size_of_call_site_table (section);
-#endif
+  if (! TARGET_USES_LEB128)
+    {
+      if (USING_SJLJ_EXCEPTIONS)
+	call_site_len = sjlj_size_of_call_site_table ();
+      else
+	call_site_len = dw2_size_of_call_site_table (section);
+    }
 
   /* A pc-relative 4-byte displacement to the @TType data.  */
   if (have_tt_data)
     {
-#ifdef HAVE_AS_LEB128
-      char ttype_after_disp_label[32];
-      ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
-				   section ? "LLSDATTDC" : "LLSDATTD",
-				   current_function_funcdef_no);
-      dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
-				    "@TType base offset");
-      ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
-#else
-      /* Ug.  Alignment queers things.  */
-      unsigned int before_disp, after_disp, last_disp, disp;
+      if (TARGET_USES_LEB128)
+	{
+	  char ttype_after_disp_label[32];
+	  ASM_GENERATE_INTERNAL_LABEL (ttype_after_disp_label,
+				       section ? "LLSDATTDC" : "LLSDATTD",
+				       current_function_funcdef_no);
+	  dw2_asm_output_delta_uleb128 (ttype_label, ttype_after_disp_label,
+					"@TType base offset");
+	  ASM_OUTPUT_LABEL (asm_out_file, ttype_after_disp_label);
+	}
+      else
+	{
+	  /* Ug.  Alignment queers things.  */
+	  unsigned int before_disp, after_disp, last_disp, disp;
 
-      before_disp = 1 + 1;
-      after_disp = (1 + size_of_uleb128 (call_site_len)
-		    + call_site_len
-		    + VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data)
-		    + (VEC_length (tree, crtl->eh.ttype_data)
-		       * tt_format_size));
+	  before_disp = 1 + 1;
+	  after_disp = (1 + size_of_uleb128 (call_site_len)
+			+ call_site_len
+			+ VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data)
+			+ (VEC_length (tree, crtl->eh.ttype_data)
+			   * tt_format_size));
 
-      disp = after_disp;
-      do
-	{
-	  unsigned int disp_size, pad;
+	  disp = after_disp;
+	  do
+	    {
+	      unsigned int disp_size, pad;
 
-	  last_disp = disp;
-	  disp_size = size_of_uleb128 (disp);
-	  pad = before_disp + disp_size + after_disp;
-	  if (pad % tt_format_size)
-	    pad = tt_format_size - (pad % tt_format_size);
-	  else
-	    pad = 0;
-	  disp = after_disp + pad;
+	      last_disp = disp;
+	      disp_size = size_of_uleb128 (disp);
+	      pad = before_disp + disp_size + after_disp;
+	      if (pad % tt_format_size)
+		pad = tt_format_size - (pad % tt_format_size);
+	      else
+		pad = 0;
+	      disp = after_disp + pad;
+	    }
+	  while (disp != last_disp);
+
+	  dw2_asm_output_data_uleb128 (disp, "@TType base offset");
 	}
-      while (disp != last_disp);
-
-      dw2_asm_output_data_uleb128 (disp, "@TType base offset");
-#endif
     }
 
   /* Indicate the format of the call-site offsets.  */
-#ifdef HAVE_AS_LEB128
-  cs_format = DW_EH_PE_uleb128;
-#else
-  cs_format = DW_EH_PE_udata4;
-#endif
+  if (TARGET_USES_LEB128)
+    cs_format = DW_EH_PE_uleb128;
+  else
+    cs_format = DW_EH_PE_udata4;
+
   dw2_asm_output_data (1, cs_format, "call-site format (%s)",
 		       eh_data_format_name (cs_format));
 
-#ifdef HAVE_AS_LEB128
-  ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
-			       section ? "LLSDACSBC" : "LLSDACSB",
-			       current_function_funcdef_no);
-  ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
-			       section ? "LLSDACSEC" : "LLSDACSE",
-			       current_function_funcdef_no);
-  dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
-				"Call-site table length");
-  ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
-  if (USING_SJLJ_EXCEPTIONS)
-    sjlj_output_call_site_table ();
+  if (TARGET_USES_LEB128)
+    {
+      ASM_GENERATE_INTERNAL_LABEL (cs_after_size_label,
+				   section ? "LLSDACSBC" : "LLSDACSB",
+				   current_function_funcdef_no);
+      ASM_GENERATE_INTERNAL_LABEL (cs_end_label,
+				   section ? "LLSDACSEC" : "LLSDACSE",
+				   current_function_funcdef_no);
+      dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
+				    "Call-site table length");
+      ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
+      if (USING_SJLJ_EXCEPTIONS)
+	sjlj_output_call_site_table ();
+      else
+	dw2_output_call_site_table (cs_format, section);
+      ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
+    }
   else
-    dw2_output_call_site_table (cs_format, section);
-  ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
-#else
-  dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
-  if (USING_SJLJ_EXCEPTIONS)
-    sjlj_output_call_site_table ();
-  else
-    dw2_output_call_site_table (cs_format, section);
-#endif
+    {
+      dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
+      if (USING_SJLJ_EXCEPTIONS)
+	sjlj_output_call_site_table ();
+      else
+	dw2_output_call_site_table (cs_format, section);
+    }
 
   /* ??? Decode and interpret the data for flag_debug_asm.  */
   n = VARRAY_ACTIVE_SIZE (crtl->eh.action_record_data);
@@ -4524,10 +4526,8 @@
       output_ttype (type, tt_format, tt_format_size);
     }
 
-#ifdef HAVE_AS_LEB128
-  if (have_tt_data)
-      ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
-#endif
+  if (TARGET_USES_LEB128 && have_tt_data)
+    ASM_OUTPUT_LABEL (asm_out_file, ttype_label);
 
   /* ??? Decode and interpret the data for flag_debug_asm.  */
   n = VARRAY_ACTIVE_SIZE (crtl->eh.ehspec_data);
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	(revision 150822)
+++ gcc/config/sh/sh.h	(working copy)
@@ -2847,4 +2847,7 @@
 /* FIXME: middle-end support for highpart optimizations is missing.  */
 #define high_life_started reload_in_progress
 
+#define TARGET_USES_LEB128 \
+  (! TARGET_RELAX || (!flag_unwind_tables && !flag_exceptions))
+
 #endif /* ! GCC_SH_H */
2009-04-12  Christian Bruel  <christian.bruel@st.com>

	* default.h (TARGET_USES_LEB128): New macro.
	* doc/tm.texi (TARGET_USES_LEB128): Likewise.
	* config/sh/sh.h (TARGET_USES_LEB128): Redefine.
	* dwarf2asm.c (TARGET_USES_LEB128): Use instead of HAVE_AS_LEB128.
	* except.c: Likewise.

	
	

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