This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] stabs format for symbols in .comm
- From: George Helffrich +44 117 954 5437 <george at geology dot bristol dot ac dot uk>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 25 Jun 2004 20:05:58 +0100 (BST)
- Subject: [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.