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] stabs format for symbols in .comm


Here is a re-engineered patch for the problem reported previously
stemming from .stabs format for symbols located in .comm (principally
Fortran common blocks).  It wraps any .stabs for symbols offset
within a .comm allocation with a N_BCOMM/N_ECOMM pair, and changes
the .stabs code to N_GSYM.  Though inspired by Darwin targets, the
change in behavior affects all targets.  Any need to warn gdb
maintainers?

For review of discussion, see

http://gcc.gnu.org/ml/gcc-patches/2003-10/msg01297.html
http://gcc.gnu.org/ml/gcc-patches/2004-04/msg01719.html
http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00039.html
http://gcc.gnu.org/ml/gcc-patches/2004-06/msg00180.html

Elision of redundant N_ECOMM/N_BCOMM for the same .comm name results
in about 22% stabs storage reduction for programs intensively using
common storage.

                                       George Helffrich
                                       (george@geology.bristol.ac.uk)

Index: gcc/dbxout.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/dbxout.c,v
retrieving revision 1.172
diff -u -r1.172 dbxout.c
--- gcc/dbxout.c	16 Jan 2004 01:44:06 -0000	1.172
+++ gcc/dbxout.c	25 Jun 2004 17:03:10 -0000
@@ -355,6 +355,8 @@
 static void dbxout_class_name_qualifiers (tree);
 static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
+static void dbxout_common_name (tree, const char *, STAB_CODE_TYPE);
+static const char *dbxout_common_check (tree, int *);
 static void dbxout_prepare_symbol (tree);
 static void dbxout_finish_symbol (tree);
 static void dbxout_block (tree, int, tree);
@@ -2383,6 +2385,7 @@
 {
   int letter = 0;
   int regno = -1;
+  int offs;
 
   emit_pending_bincls_if_required ();
 
@@ -2446,7 +2449,15 @@
 	  if (DECL_INITIAL (decl) == 0
 	      || (!strcmp (lang_hooks.name, "GNU C++")
 		  && DECL_INITIAL (decl) == error_mark_node))
-	    current_sym_code = N_LCSYM;
+	    {
+	      current_sym_code = N_LCSYM;
+	      if (NULL != dbxout_common_check (decl, &offs))
+		{
+		  current_sym_addr = 0;
+		  current_sym_value = offs;
+		  current_sym_code = N_GSYM;
+		}
+	    }
 	  else if (DECL_IN_TEXT_SECTION (decl))
 	    /* This is not quite right, but it's the closest
 	       of all the codes that Unix defines.  */
@@ -2554,7 +2565,14 @@
 	 this variable was itself `static'.  */
       current_sym_code = N_LCSYM;
       letter = 'V';
-      current_sym_addr = XEXP (XEXP (home, 0), 0);
+      if (NULL == dbxout_common_check (decl, &offs))
+        current_sym_addr = XEXP (XEXP (home, 0), 0);
+      else
+        {
+ 	  current_sym_addr = 0;
+          current_sym_value = offs;
+	  current_sym_code = N_GSYM;
+        }
     }
   else if (GET_CODE (home) == CONCAT)
     {
@@ -2591,7 +2609,7 @@
 
   /* Ok, start a symtab entry and output the variable name.  */
   FORCE_TEXT;
-
+ 
 #ifdef DBX_STATIC_BLOCK_START
   DBX_STATIC_BLOCK_START (asmfile, current_sym_code);
 #endif
@@ -2603,6 +2621,7 @@
 #ifdef DBX_STATIC_BLOCK_END
   DBX_STATIC_BLOCK_END (asmfile, current_sym_code);
 #endif
+ 
   return 1;
 }
 
@@ -2635,6 +2654,104 @@
   if (letter)
     putc (letter, asmfile);
 }
+ 
+/* Output the common block name for DECL in a stabs.
+
+   Symbols in global common (.comm) get wrapped with an N_BCOMM/N_ECOMM pair
+   around each group of symbols in the same .comm area.  The N_GSYM stabs
+   that are emitted only contain the offset in the common area.  This routine
+   emits the N_BCOMM and N_ECOMM stabs. */
+
+static void
+dbxout_common_name (tree decl, const char *name, STAB_CODE_TYPE op)
+{
+  fprintf (asmfile, "%s\"%s", ASM_STABS_OP, name);
+  current_sym_addr = NULL_RTX;
+  current_sym_value = 0;
+  current_sym_code = op;
+  dbxout_finish_symbol (decl);
+}
+
+/* Check decl to determine whether it is a VAR_DECL destined for storage in a
+   common area.  If it is, the return value will be a non-null string giving
+   the name of the common storage block it will go into.  If non-null, the
+   value is the offset into the common block for that symbol's storage. */
+
+static const char *
+dbxout_common_check(tree decl, int *value)
+{
+  rtx home;
+  rtx sym_addr;
+  const char *name;
+
+  if (TREE_CODE (decl) != VAR_DECL
+      || !DECL_COMMON (decl)
+      || !TREE_STATIC (decl))
+    return NULL;
+
+  home = DECL_RTL (decl);
+  if (GET_CODE (home) != MEM)
+    return NULL;
+
+  sym_addr = XEXP (home, 0);
+  if (GET_CODE (sym_addr) == CONST)
+    sym_addr = XEXP (sym_addr, 0);
+  if ((GET_CODE (sym_addr) == SYMBOL_REF || GET_CODE (sym_addr) == PLUS)
+      && !TREE_PUBLIC (decl)
+      && (DECL_INITIAL (decl) == 0
+            || (!strcmp (lang_hooks.name, "GNU C++")
+                 && DECL_INITIAL (decl) == error_mark_node)))
+    {
+
+      /* We have sym that will go into a common area, meaning that it
+	 will get storage reserved with a .comm/.lcomm assembler pseudo-op.
+
+         Determine name of common area this symbol will be an offset into,
+	 and offset into that area.  Also retrieve the decl for the area
+	 that the symbol is offset into. */
+      tree cdecl;
+
+      switch (GET_CODE (sym_addr))
+        {       
+          case PLUS:
+            if (GET_CODE (XEXP (sym_addr, 0)) == CONST_INT)
+              {
+                name =
+	          (* targetm.strip_name_encoding)(XSTR (XEXP (sym_addr, 1), 0));
+                *value = INTVAL (XEXP (sym_addr, 0));
+		cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
+              }
+            else
+              {
+                name =
+	          (* targetm.strip_name_encoding)(XSTR (XEXP (sym_addr, 0), 0));
+                *value = INTVAL (XEXP (sym_addr, 1));
+		cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
+              }
+            break;
+          
+          case SYMBOL_REF:
+            name = (* targetm.strip_name_encoding)(XSTR (sym_addr, 0));
+            *value = 0;
+	    cdecl = SYMBOL_REF_DECL (sym_addr);
+            break;
+
+          default:
+            error ("common symbol debug info is not structured as "
+	           "symbol+offset");
+        }
+
+      /* Check area common symbol is offset into.  If this is not public, then
+	 it is not a symbol in a common block.  It must be a .lcomm symbol, not
+	 a .comm symbol.  */
+      if (cdecl == NULL || !TREE_PUBLIC(cdecl))
+	name = NULL;
+    }
+  else
+    name = NULL;
+
+  return name;
+}
 
 static void
 dbxout_prepare_symbol (tree decl ATTRIBUTE_UNUSED)
@@ -2673,18 +2790,45 @@
 #endif
 }
 
-/* Output definitions of all the decls in a chain. Return nonzero if
-   anything was output */
+/* Output definitions of all the decls in a chain.  Bracket each group of
+   common symbols with N_BCOMM/N_ECOMM bracketing stabs.  Return nonzero if
+   anything was output. */
 
 int
 dbxout_syms (tree syms)
 {
   int result = 0;
+  const char *comm_prev = NULL;
+  tree syms_prev;
   while (syms)
     {
+      int temp, copen, cclos;
+      const char *comm_new;
+
+      /* Check for common symbol, and then progression into a new/different
+	 block of common symbols.  Emit closing/opening common bracket if
+	 necessary. */
+      comm_new = dbxout_common_check (syms, &temp);
+      copen = comm_new != NULL
+	      && (comm_prev == NULL || strcmp (comm_new, comm_prev));
+      cclos = comm_prev != NULL
+	      && (comm_new == NULL || strcmp (comm_new, comm_prev));
+      if (cclos)
+	dbxout_common_name (syms, comm_prev, N_ECOMM);
+      if (copen)
+	{
+	  dbxout_common_name (syms, comm_new, N_BCOMM);
+	  syms_prev = syms;
+	}
+      comm_prev = comm_new;
+
       result += dbxout_symbol (syms, 1);
       syms = TREE_CHAIN (syms);
     }
+
+  if (comm_prev != NULL)
+    dbxout_common_name (syms_prev, comm_prev, N_ECOMM);
+
   return result;
 }
 
Index: gcc/ChangeLog
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/ChangeLog,v
retrieving revision 2.2326.2.399
diff -u -r2.2326.2.399 ChangeLog
--- gcc/ChangeLog	19 Apr 2004 01:58:10 -0000	2.2326.2.399
+++ gcc/ChangeLog	25 Jun 2004 17:09:05 -0000
@@ -1,3 +1,10 @@
+2004-06-25  George Helffrich <george@gly.bris.ac.uk>
+
+	* dbxout.c: Change .stabs output for symbols in .comm (Fortran common)
+	to 1) bracket .stabs group of symbols with N_BCOMM/N_ECOMM; and
+	2) change N_LCSYM to N_GSYM for .comm symbols for compatibility with
+	Sun Fortran and "official" .stabs documentation.
+
 2004-04-18  Release Manager
 
 	* GCC 3.4.0 released.


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