X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdbxout.c;h=eb0fceee52b6b09b58c9de78a635e1b1cf5d5cfc;hb=cfdd36083f84d7b553fec99b223fb765b17e2942;hp=c595a84cb6f8b8397227e5fafb8464b4e0d223e5;hpb=65b91e5b4bdf76add8289345c50974955b0adc0c;p=pf3gnuchains%2Fgcc-fork.git
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index c595a84cb6f..eb0fceee52b 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -1,12 +1,13 @@
/* Output dbx-format symbol table information from GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+. */
/* Output dbx-format symbol table data.
@@ -89,6 +89,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "langhooks.h"
#include "obstack.h"
+#include "expr.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h"
@@ -170,8 +171,7 @@ enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
The file_number and type_number elements are used if DBX_USE_BINCL
is defined. */
-struct typeinfo GTY(())
-{
+struct GTY(()) typeinfo {
enum typestatus status;
int file_number;
int type_number;
@@ -241,13 +241,6 @@ static GTY(()) int scope_labelno;
static GTY(()) int dbxout_source_line_counter;
-/* Nonzero if we have actually used any of the GDB extensions
- to the debugging format. The idea is that we use them for the
- first time only if there's a strong reason, but once we have done that,
- we use them whenever convenient. */
-
-static GTY(()) int have_used_extensions = 0;
-
/* Number for the next N_SOL filename stabs label. The number 0 is reserved
for the N_SO filename stabs label. */
@@ -275,7 +268,7 @@ static int pending_bincls = 0;
static const char *base_input_file;
#ifdef DEBUG_SYMS_TEXT
-#define FORCE_TEXT function_section (current_function_decl);
+#define FORCE_TEXT switch_to_section (current_function_section ())
#else
#define FORCE_TEXT
#endif
@@ -325,14 +318,16 @@ static void dbxout_args (tree);
static void dbxout_type_fields (tree);
static void dbxout_type_method_1 (tree);
static void dbxout_type_methods (tree);
-static void dbxout_range_type (tree);
+static void dbxout_range_type (tree, tree, tree);
static void dbxout_type (tree, int);
-static bool print_int_cst_bounds_in_octal_p (tree);
+static bool print_int_cst_bounds_in_octal_p (tree, tree, tree);
+static bool is_fortran (void);
static void dbxout_type_name (tree);
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_block (tree, int, tree);
+static void dbxout_common_name (tree, const char *, STAB_CODE_TYPE);
+static const char *dbxout_common_check (tree, int *);
static void dbxout_global_decl (tree);
static void dbxout_type_decl (tree, int);
static void dbxout_handle_pch (unsigned);
@@ -343,7 +338,7 @@ static void dbxout_handle_pch (unsigned);
static void dbxout_source_line (unsigned int, const char *);
static void dbxout_begin_prologue (unsigned int, const char *);
static void dbxout_source_file (const char *);
-static void dbxout_function_end (void);
+static void dbxout_function_end (tree);
static void dbxout_begin_function (tree);
static void dbxout_begin_block (unsigned, unsigned);
static void dbxout_end_block (unsigned, unsigned);
@@ -359,7 +354,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_end_source_file,
dbxout_begin_block,
dbxout_end_block,
- debug_true_tree, /* ignore_block */
+ debug_true_const_tree, /* ignore_block */
dbxout_source_line, /* source_line */
dbxout_begin_prologue, /* begin_prologue */
debug_nothing_int_charstar, /* end_prologue */
@@ -373,12 +368,15 @@ const struct gcc_debug_hooks dbx_debug_hooks =
dbxout_function_decl,
dbxout_global_decl, /* global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx, /* label */
dbxout_handle_pch, /* handle_pch */
- debug_nothing_rtx /* var_location */
+ debug_nothing_rtx, /* var_location */
+ debug_nothing_void, /* switch_text_section */
+ debug_nothing_tree_tree, /* set_name */
+ 0 /* start_end_main_source_file */
};
#endif /* DBX_DEBUGGING_INFO */
@@ -393,7 +391,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
dbxout_end_source_file,
xcoffout_begin_block,
xcoffout_end_block,
- debug_true_tree, /* ignore_block */
+ debug_true_const_tree, /* ignore_block */
xcoffout_source_line,
xcoffout_begin_prologue, /* begin_prologue */
debug_nothing_int_charstar, /* end_prologue */
@@ -403,12 +401,15 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
debug_nothing_tree, /* function_decl */
dbxout_global_decl, /* global_decl */
dbxout_type_decl, /* type_decl */
- debug_nothing_tree_tree, /* imported_module_or_decl */
+ debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
debug_nothing_tree, /* deferred_inline_function */
debug_nothing_tree, /* outlining_inline_function */
debug_nothing_rtx, /* label */
dbxout_handle_pch, /* handle_pch */
- debug_nothing_rtx /* var_location */
+ debug_nothing_rtx, /* var_location */
+ debug_nothing_void, /* switch_text_section */
+ debug_nothing_tree_tree, /* set_name */
+ 0 /* start_end_main_source_file */
};
#endif /* XCOFF_DEBUGGING_INFO */
@@ -859,7 +860,7 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
obstack_1grow (&stabstr_ob, '\0');
len = obstack_object_size (&stabstr_ob);
- chunk = str = obstack_finish (&stabstr_ob);
+ chunk = str = XOBFINISH (&stabstr_ob, char *);
/* Within the buffer are a sequence of NUL-separated strings,
each of which is to be written out as a separate stab
@@ -892,7 +893,7 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
comma than to do a two-character fputs. */
obstack_grow (&stabstr_ob, "\",", 2);
len = obstack_object_size (&stabstr_ob);
- str = obstack_finish (&stabstr_ob);
+ str = XOBFINISH (&stabstr_ob, char *);
fwrite (str, 1, len, asm_out_file);
DBX_FINISH_STABS (sym, code, line, addr, label, number);
@@ -903,39 +904,48 @@ dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
#if defined (DBX_DEBUGGING_INFO)
static void
-dbxout_function_end (void)
+dbxout_function_end (tree decl)
{
char lscope_label_name[100];
/* The Lscope label must be emitted even if we aren't doing anything
else; dbxout_block needs it. */
- function_section (current_function_decl);
+ switch_to_section (function_section (current_function_decl));
/* Convert Lscope into the appropriate format for local labels in case
the system doesn't insert underscores in front of user generated
labels. */
ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
targetm.asm_out.internal_label (asm_out_file, "Lscope", scope_labelno);
- scope_labelno++;
/* The N_FUN tag at the end of the function is a GNU extension,
which may be undesirable, and is unnecessary if we do not have
named sections. */
if (!use_gnu_debug_info_extensions
|| NO_DBX_FUNCTION_END
- || !targetm.have_named_sections)
+ || !targetm.have_named_sections
+ || DECL_IGNORED_P (decl))
return;
/* By convention, GCC will mark the end of a function with an N_FUN
symbol and an empty string. */
-#ifdef DBX_OUTPUT_NFUN
- DBX_OUTPUT_NFUN (asm_out_file, lscope_label_name, current_function_decl);
-#else
- dbxout_begin_empty_stabs (N_FUN);
- dbxout_stab_value_label_diff (lscope_label_name,
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
-
-#endif
+ if (flag_reorder_blocks_and_partition)
+ {
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label,
+ crtl->subsections.hot_section_label);
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label,
+ crtl->subsections.cold_section_label);
+ }
+ else
+ {
+ char begin_label[20];
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
+ dbxout_begin_empty_stabs (N_FUN);
+ dbxout_stab_value_label_diff (lscope_label_name, begin_label);
+ }
if (!NO_DBX_BNSYM_ENSYM && !flag_debug_only_used_symbols)
dbxout_stabd (N_ENSYM, 0);
@@ -954,17 +964,27 @@ get_lang_number (void)
return N_SO_CC;
else if (strcmp (language_string, "GNU F77") == 0)
return N_SO_FORTRAN;
- else if (strcmp (language_string, "GNU F95") == 0)
+ else if (strcmp (language_string, "GNU Fortran") == 0)
return N_SO_FORTRAN90; /* CHECKME */
else if (strcmp (language_string, "GNU Pascal") == 0)
return N_SO_PASCAL;
else if (strcmp (language_string, "GNU Objective-C") == 0)
return N_SO_OBJC;
+ else if (strcmp (language_string, "GNU Objective-C++") == 0)
+ return N_SO_OBJCPLUS;
else
return 0;
}
+static bool
+is_fortran (void)
+{
+ unsigned int lang = get_lang_number ();
+
+ return (lang == N_SO_FORTRAN) || (lang == N_SO_FORTRAN90);
+}
+
/* At the beginning of compilation, start writing the symbol table.
Initialize `typevec' and output the standard data types of C. */
@@ -974,9 +994,10 @@ dbxout_init (const char *input_file_name)
char ltext_label_name[100];
bool used_ltext_label_name = false;
tree syms = lang_hooks.decls.getdecls ();
+ const char *mapped_name;
typevec_len = 100;
- typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
+ typevec = GGC_CNEWVEC (struct typeinfo, typevec_len);
/* stabstr_ob contains one string, which will be just fine with
1-byte alignment. */
@@ -999,6 +1020,7 @@ dbxout_init (const char *input_file_name)
cwd = "/";
else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
cwd = concat (cwd, "/", NULL);
+ cwd = remap_debug_filename (cwd);
}
#ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
@@ -1009,17 +1031,18 @@ dbxout_init (const char *input_file_name)
#endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
}
+ mapped_name = remap_debug_filename (input_file_name);
#ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
- DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, input_file_name);
+ DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name);
#else
- dbxout_begin_simple_stabs_desc (input_file_name, N_SO, get_lang_number ());
+ dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ());
dbxout_stab_value_label (ltext_label_name);
used_ltext_label_name = true;
#endif
if (used_ltext_label_name)
{
- text_section ();
+ switch_to_section (text_section);
targetm.asm_out.internal_label (asm_out_file, "Ltext", 0);
}
@@ -1035,7 +1058,7 @@ dbxout_init (const char *input_file_name)
next_type_number = 1;
#ifdef DBX_USE_BINCL
- current_file = xmalloc (sizeof *current_file);
+ current_file = XNEW (struct dbx_file);
current_file->next = NULL;
current_file->file_number = 0;
current_file->next_type_number = 1;
@@ -1144,7 +1167,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
const char *filename ATTRIBUTE_UNUSED)
{
#ifdef DBX_USE_BINCL
- struct dbx_file *n = xmalloc (sizeof *n);
+ struct dbx_file *n = XNEW (struct dbx_file);
n->next = current_file;
n->next_type_number = 1;
@@ -1154,7 +1177,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
n->prev = NULL;
current_file->prev = n;
n->bincl_status = BINCL_PENDING;
- n->pending_bincl_name = filename;
+ n->pending_bincl_name = remap_debug_filename (filename);
pending_bincls = 1;
current_file = n;
#endif
@@ -1203,6 +1226,9 @@ dbxout_handle_pch (unsigned at_end)
}
#if defined (DBX_DEBUGGING_INFO)
+
+static void dbxout_block (tree, int, tree);
+
/* Output debugging info to FILE to switch to sourcefile FILENAME. */
static void
@@ -1218,15 +1244,16 @@ dbxout_source_file (const char *filename)
{
/* Don't change section amid function. */
if (current_function_decl == NULL_TREE)
- text_section ();
+ switch_to_section (text_section);
- dbxout_begin_simple_stabs (filename, N_SOL);
+ dbxout_begin_simple_stabs (remap_debug_filename (filename), N_SOL);
dbxout_stab_value_internal_label ("Ltext", &source_label_number);
lastfile = filename;
}
}
-/* Output N_BNSYM and line number symbol entry. */
+/* Output N_BNSYM, line number symbol entry, and local symbol at
+ function scope */
static void
dbxout_begin_prologue (unsigned int lineno, const char *filename)
@@ -1237,7 +1264,14 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename)
&& !flag_debug_only_used_symbols)
dbxout_stabd (N_BNSYM, 0);
+ /* pre-increment the scope counter */
+ scope_labelno++;
+
dbxout_source_line (lineno, filename);
+ /* Output function begin block at function scope, referenced
+ by dbxout_block, dbxout_source_line and dbxout_function_end. */
+ emit_pending_bincls_if_required ();
+ targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
}
/* Output a line number symbol entry for source file FILENAME and line
@@ -1253,11 +1287,12 @@ dbxout_source_line (unsigned int lineno, const char *filename)
#else
if (DBX_LINES_FUNCTION_RELATIVE)
{
- rtx begin_label = XEXP (DECL_RTL (current_function_decl), 0);
+ char begin_label[20];
dbxout_begin_stabn_sline (lineno);
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
dbxout_stab_value_internal_label_diff ("LM", &dbxout_source_line_counter,
- XSTR (begin_label, 0));
-
+ begin_label);
}
else
dbxout_stabd (N_SLINE, lineno);
@@ -1296,7 +1331,7 @@ dbxout_function_decl (tree decl)
dbxout_begin_function (decl);
#endif
dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
- dbxout_function_end ();
+ dbxout_function_end (decl);
}
#endif /* DBX_DEBUGGING_INFO */
@@ -1306,9 +1341,7 @@ dbxout_function_decl (tree decl)
static void
dbxout_global_decl (tree decl)
{
- if (TREE_CODE (decl) == VAR_DECL
- && ! DECL_EXTERNAL (decl)
- && DECL_RTL_SET_P (decl)) /* Not necessary? */
+ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
{
int saved_tree_used = TREE_USED (decl);
TREE_USED (decl) = 1;
@@ -1335,7 +1368,7 @@ dbxout_finish (const char *filename ATTRIBUTE_UNUSED)
DBX_OUTPUT_MAIN_SOURCE_FILE_END (asm_out_file, filename);
#elif defined DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
{
- text_section ();
+ switch_to_section (text_section);
dbxout_begin_empty_stabs (N_SO);
dbxout_stab_value_internal_label ("Letext", 0);
}
@@ -1387,14 +1420,14 @@ dbxout_type_fields (tree type)
/* Omit here local type decls until we know how to support them. */
if (TREE_CODE (tem) == TYPE_DECL
+ /* Omit here the nameless fields that are used to skip bits. */
+ || DECL_IGNORED_P (tem)
/* Omit fields whose position or size are variable or too large to
represent. */
|| (TREE_CODE (tem) == FIELD_DECL
&& (! host_integerp (bit_position (tem), 0)
|| ! DECL_SIZE (tem)
- || ! host_integerp (DECL_SIZE (tem), 1)))
- /* Omit here the nameless fields that are used to skip bits. */
- || DECL_IGNORED_P (tem))
+ || ! host_integerp (DECL_SIZE (tem), 1))))
continue;
else if (TREE_CODE (tem) != CONST_DECL)
@@ -1412,7 +1445,6 @@ dbxout_type_fields (tree type)
&& (TREE_PRIVATE (tem) || TREE_PROTECTED (tem)
|| TREE_CODE (tem) != FIELD_DECL))
{
- have_used_extensions = 1;
stabstr_C ('/');
stabstr_C (DECL_ACCESSIBILITY_CHAR (tem));
}
@@ -1427,7 +1459,6 @@ dbxout_type_fields (tree type)
{
tree name = DECL_ASSEMBLER_NAME (tem);
- have_used_extensions = 1;
stabstr_C (':');
stabstr_I (name);
stabstr_C (';');
@@ -1562,10 +1593,10 @@ dbxout_type_methods (tree type)
/* Emit a "range" type specification, which has the form:
"r;;;".
- TYPE is an INTEGER_TYPE. */
+ TYPE is an INTEGER_TYPE, LOW and HIGH are the bounds. */
static void
-dbxout_range_type (tree type)
+dbxout_range_type (tree type, tree low, tree high)
{
stabstr_C ('r');
if (TREE_TYPE (type))
@@ -1593,25 +1624,23 @@ dbxout_range_type (tree type)
}
stabstr_C (';');
- if (TYPE_MIN_VALUE (type) != 0
- && host_integerp (TYPE_MIN_VALUE (type), 0))
+ if (low && host_integerp (low, 0))
{
- if (print_int_cst_bounds_in_octal_p (type))
- stabstr_O (TYPE_MIN_VALUE (type));
+ if (print_int_cst_bounds_in_octal_p (type, low, high))
+ stabstr_O (low);
else
- stabstr_D (tree_low_cst (TYPE_MIN_VALUE (type), 0));
+ stabstr_D (tree_low_cst (low, 0));
}
else
stabstr_C ('0');
stabstr_C (';');
- if (TYPE_MAX_VALUE (type) != 0
- && host_integerp (TYPE_MAX_VALUE (type), 0))
+ if (high && host_integerp (high, 0))
{
- if (print_int_cst_bounds_in_octal_p (type))
- stabstr_O (TYPE_MAX_VALUE (type));
+ if (print_int_cst_bounds_in_octal_p (type, low, high))
+ stabstr_O (high);
else
- stabstr_D (tree_low_cst (TYPE_MAX_VALUE (type), 0));
+ stabstr_D (tree_low_cst (high, 0));
stabstr_C (';');
}
else
@@ -1632,14 +1661,38 @@ dbxout_range_type (tree type)
static void
dbxout_type (tree type, int full)
{
- tree tem;
- tree main_variant;
static int anonymous_type_number = 0;
+ bool vector_type = false;
+ tree tem, main_variant, low, high;
if (TREE_CODE (type) == VECTOR_TYPE)
- /* The frontend feeds us a representation for the vector as a struct
- containing an array. Pull out the array type. */
- type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+ {
+ /* The frontend feeds us a representation for the vector as a struct
+ containing an array. Pull out the array type. */
+ type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+ vector_type = true;
+ }
+
+ if (TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (TREE_TYPE (type) == 0)
+ {
+ low = TYPE_MIN_VALUE (type);
+ high = TYPE_MAX_VALUE (type);
+ }
+
+ else if (subrange_type_for_debug_p (type, &low, &high))
+ ;
+
+ /* If this is a subtype that should not be emitted as a subrange type,
+ use the base type. */
+ else
+ {
+ type = TREE_TYPE (type);
+ low = TYPE_MIN_VALUE (type);
+ high = TYPE_MAX_VALUE (type);
+ }
+ }
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
@@ -1675,8 +1728,7 @@ dbxout_type (tree type, int full)
if (next_type_number == typevec_len)
{
- typevec
- = ggc_realloc (typevec, (typevec_len * 2 * sizeof typevec[0]));
+ typevec = GGC_RESIZEVEC (struct typeinfo, typevec, typevec_len * 2);
memset (typevec + typevec_len, 0, typevec_len * sizeof typevec[0]);
typevec_len *= 2;
}
@@ -1838,13 +1890,12 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- have_used_extensions = 1;
stabstr_S ("@s");
stabstr_D (TYPE_PRECISION (type));
stabstr_C (';');
}
- dbxout_range_type (type);
+ dbxout_range_type (type, low, high);
}
else
@@ -1855,13 +1906,12 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- have_used_extensions = 1;
stabstr_S ("@s");
stabstr_D (TYPE_PRECISION (type));
stabstr_C (';');
}
- if (print_int_cst_bounds_in_octal_p (type))
+ if (print_int_cst_bounds_in_octal_p (type, low, high))
{
stabstr_C ('r');
@@ -1876,20 +1926,21 @@ dbxout_type (tree type, int full)
dbxout_type_index (type);
stabstr_C (';');
- stabstr_O (TYPE_MIN_VALUE (type));
+ stabstr_O (low);
stabstr_C (';');
- stabstr_O (TYPE_MAX_VALUE (type));
+ stabstr_O (high);
stabstr_C (';');
}
else
/* Output other integer types as subranges of `int'. */
- dbxout_range_type (type);
+ dbxout_range_type (type, low, high);
}
break;
case REAL_TYPE:
+ case FIXED_POINT_TYPE:
/* This used to say `r1' and we used to take care
to make sure that `int' was type number 1. */
stabstr_C ('r');
@@ -1899,28 +1950,9 @@ dbxout_type (tree type, int full)
stabstr_S (";0;");
break;
- case CHAR_TYPE:
- if (use_gnu_debug_info_extensions)
- {
- have_used_extensions = 1;
- stabstr_S ("@s");
- stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
- stabstr_S (";-20;");
- }
- else
- {
- /* Output the type `char' as a subrange of itself.
- That is what pcc seems to do. */
- stabstr_C ('r');
- dbxout_type_index (char_type_node);
- stabstr_S (TYPE_UNSIGNED (type) ? ";0;255;" : ";0;127;");
- }
- break;
-
case BOOLEAN_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_S ("@s");
stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
stabstr_S (";-16;");
@@ -1929,11 +1961,6 @@ dbxout_type (tree type, int full)
stabstr_S ("eFalse:0,True:1,;");
break;
- case FILE_TYPE:
- stabstr_C ('d');
- dbxout_type (TREE_TYPE (type), 0);
- break;
-
case COMPLEX_TYPE:
/* Differs from the REAL_TYPE by its new data type number.
R3 is NF_COMPLEX. We don't try to use any of the other NF_*
@@ -1971,7 +1998,6 @@ dbxout_type (tree type, int full)
/* Make arrays of packed bits look like bitstrings for chill. */
if (TYPE_PACKED (type) && use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_S ("@s");
stabstr_D (BITS_PER_UNIT * int_size_in_bytes (type));
stabstr_S (";@S;S");
@@ -1979,6 +2005,9 @@ dbxout_type (tree type, int full)
break;
}
+ if (use_gnu_debug_info_extensions && vector_type)
+ stabstr_S ("@V;");
+
/* Output "a" followed by a range type definition
for the index type of the array
followed by a reference to the target-type.
@@ -1987,7 +2016,6 @@ dbxout_type (tree type, int full)
different from an array of characters. */
if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_S ("@S;");
}
tem = TYPE_DOMAIN (type);
@@ -2000,7 +2028,7 @@ dbxout_type (tree type, int full)
else
{
stabstr_C ('a');
- dbxout_range_type (tem);
+ dbxout_range_type (tem, TYPE_MIN_VALUE (tem), TYPE_MAX_VALUE (tem));
}
dbxout_type (TREE_TYPE (type), 0);
@@ -2030,7 +2058,11 @@ dbxout_type (tree type, int full)
another type's definition; instead, output an xref
and let the definition come when the name is defined. */
stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
- if (TYPE_NAME (type) != 0)
+ if (TYPE_NAME (type) != 0
+ /* The C frontend creates for anonymous variable length
+ records/unions TYPE_NAME with DECL_NAME NULL. */
+ && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
+ || DECL_NAME (TYPE_NAME (type))))
dbxout_type_name (type);
else
{
@@ -2051,13 +2083,12 @@ dbxout_type (tree type, int full)
{
int i;
tree child;
- VEC (tree) *accesses = BINFO_BASE_ACCESSES (binfo);
+ VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
if (use_gnu_debug_info_extensions)
{
if (BINFO_N_BASE_BINFOS (binfo))
{
- have_used_extensions = 1;
stabstr_C ('!');
stabstr_U (BINFO_N_BASE_BINFOS (binfo));
stabstr_C (',');
@@ -2070,13 +2101,13 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_C (BINFO_VIRTUAL_P (child) ? '1' : '0');
stabstr_C (access == access_public_node ? '2' :
access == access_protected_node
? '1' :'0');
if (BINFO_VIRTUAL_P (child)
- && strcmp (lang_hooks.name, "GNU C++") == 0)
+ && (strcmp (lang_hooks.name, "GNU C++") == 0
+ || strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
/* For a virtual base, print the (negative)
offset within the vtable where we must look
to find the necessary adjustment. */
@@ -2115,7 +2146,6 @@ dbxout_type (tree type, int full)
dbxout_type_fields (type);
if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
{
- have_used_extensions = 1;
dbxout_type_methods (type);
}
@@ -2125,7 +2155,6 @@ dbxout_type (tree type, int full)
/* Avoid the ~ if we don't really need it--it confuses dbx. */
&& TYPE_VFIELD (type))
{
- have_used_extensions = 1;
/* We need to write out info about what field this class
uses as its "main" vtable pointer field, because if this
@@ -2156,7 +2185,6 @@ dbxout_type (tree type, int full)
if (use_gnu_debug_info_extensions
&& TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node))
{
- have_used_extensions = 1;
stabstr_S ("@s");
stabstr_D (TYPE_PRECISION (type));
stabstr_C (';');
@@ -2165,16 +2193,21 @@ dbxout_type (tree type, int full)
stabstr_C ('e');
for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem))
{
+ tree value = TREE_VALUE (tem);
+
stabstr_I (TREE_PURPOSE (tem));
stabstr_C (':');
- if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0)
- stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
- else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1
- && (HOST_WIDE_INT) TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0)
- stabstr_D (TREE_INT_CST_LOW (TREE_VALUE (tem)));
+ if (TREE_CODE (value) == CONST_DECL)
+ value = DECL_INITIAL (value);
+
+ if (TREE_INT_CST_HIGH (value) == 0)
+ stabstr_D (TREE_INT_CST_LOW (value));
+ else if (TREE_INT_CST_HIGH (value) == -1
+ && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+ stabstr_D (TREE_INT_CST_LOW (value));
else
- stabstr_O (TREE_VALUE (tem));
+ stabstr_O (value);
stabstr_C (',');
if (TREE_CHAIN (tem) != 0)
@@ -2192,7 +2225,6 @@ dbxout_type (tree type, int full)
case METHOD_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_C ('#');
/* Write the argument types out longhand. */
@@ -2210,7 +2242,6 @@ dbxout_type (tree type, int full)
case OFFSET_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_C ('@');
dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
stabstr_C (',');
@@ -2224,7 +2255,6 @@ dbxout_type (tree type, int full)
case REFERENCE_TYPE:
if (use_gnu_debug_info_extensions)
{
- have_used_extensions = 1;
stabstr_C ('&');
}
else
@@ -2246,7 +2276,7 @@ dbxout_type (tree type, int full)
should be printed in octal format. */
static bool
-print_int_cst_bounds_in_octal_p (tree type)
+print_int_cst_bounds_in_octal_p (tree type, tree low, tree high)
{
/* If we can use GDB extensions and the size is wider than a long
(the size used by GDB to read them) or we may have trouble writing
@@ -2260,10 +2290,8 @@ print_int_cst_bounds_in_octal_p (tree type)
can't span same size unsigned types. */
if (use_gnu_debug_info_extensions
- && TYPE_MIN_VALUE (type) != 0
- && TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
- && TYPE_MAX_VALUE (type) != 0
- && TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
+ && low && TREE_CODE (low) == INTEGER_CST
+ && high && TREE_CODE (high) == INTEGER_CST
&& (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
|| ((TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
&& TYPE_UNSIGNED (type))
@@ -2325,6 +2353,149 @@ dbxout_class_name_qualifiers (tree decl)
}
}
+/* This is a specialized subset of expand_expr for use by dbxout_symbol in
+ evaluating DECL_VALUE_EXPR. In particular, we stop if we find decls that
+ haven't been expanded, or if the expression is getting so complex we won't
+ be able to represent it in stabs anyway. Returns NULL on failure. */
+
+static rtx
+dbxout_expand_expr (tree expr)
+{
+ switch (TREE_CODE (expr))
+ {
+ case VAR_DECL:
+ /* We can't handle emulated tls variables, because the address is an
+ offset to the return value of __emutls_get_address, and there is no
+ way to express that in stabs. Also, there are name mangling issues
+ here. We end up with references to undefined symbols if we don't
+ disable debug info for these variables. */
+ if (!targetm.have_tls && DECL_THREAD_LOCAL_P (expr))
+ return NULL;
+ /* FALLTHRU */
+
+ case PARM_DECL:
+ if (DECL_HAS_VALUE_EXPR_P (expr))
+ return dbxout_expand_expr (DECL_VALUE_EXPR (expr));
+ /* FALLTHRU */
+
+ case CONST_DECL:
+ case RESULT_DECL:
+ return DECL_RTL_IF_SET (expr);
+
+ case INTEGER_CST:
+ return expand_expr (expr, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case BIT_FIELD_REF:
+ {
+ enum machine_mode mode;
+ HOST_WIDE_INT bitsize, bitpos;
+ tree offset, tem;
+ int volatilep = 0, unsignedp = 0;
+ rtx x;
+
+ tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
+ &mode, &unsignedp, &volatilep, true);
+
+ x = dbxout_expand_expr (tem);
+ if (x == NULL || !MEM_P (x))
+ return NULL;
+ if (offset != NULL)
+ {
+ if (!host_integerp (offset, 0))
+ return NULL;
+ x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
+ }
+ if (bitpos != 0)
+ x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
+
+ return x;
+ }
+
+ default:
+ return NULL;
+ }
+}
+
+/* Helper function for output_used_types. Queue one entry from the
+ used types hash to be output. */
+
+static int
+output_used_types_helper (void **slot, void *data)
+{
+ tree type = (tree) *slot;
+ VEC(tree, heap) **types_p = (VEC(tree, heap) **) data;
+
+ if ((TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE
+ || TREE_CODE (type) == QUAL_UNION_TYPE
+ || TREE_CODE (type) == ENUMERAL_TYPE)
+ && TYPE_STUB_DECL (type)
+ && DECL_P (TYPE_STUB_DECL (type))
+ && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
+ VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type));
+ else if (TYPE_NAME (type)
+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ VEC_quick_push (tree, *types_p, TYPE_NAME (type));
+
+ return 1;
+}
+
+/* This is a qsort callback which sorts types and declarations into a
+ predictable order (types, then declarations, sorted by UID
+ within). */
+
+static int
+output_types_sort (const void *pa, const void *pb)
+{
+ const tree lhs = *((const tree *)pa);
+ const tree rhs = *((const tree *)pb);
+
+ if (TYPE_P (lhs))
+ {
+ if (TYPE_P (rhs))
+ return TYPE_UID (lhs) - TYPE_UID (rhs);
+ else
+ return 1;
+ }
+ else
+ {
+ if (TYPE_P (rhs))
+ return -1;
+ else
+ return DECL_UID (lhs) - DECL_UID (rhs);
+ }
+}
+
+
+/* Force all types used by this function to be output in debug
+ information. */
+
+static void
+output_used_types (void)
+{
+ if (cfun && cfun->used_types_hash)
+ {
+ VEC(tree, heap) *types;
+ int i;
+ tree type;
+
+ types = VEC_alloc (tree, heap, htab_elements (cfun->used_types_hash));
+ htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
+
+ /* Sort by UID to prevent dependence on hash table ordering. */
+ qsort (VEC_address (tree, types), VEC_length (tree, types),
+ sizeof (tree), output_types_sort);
+
+ for (i = 0; VEC_iterate (tree, types, i, type); i++)
+ debug_queue_symbol (type);
+
+ VEC_free (tree, heap, types);
+ }
+}
+
/* Output a .stabs for the symbol defined by DECL,
which must be a ..._DECL node in the normal namespace.
It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL.
@@ -2337,6 +2508,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
tree type = TREE_TYPE (decl);
tree context = NULL_TREE;
int result = 0;
+ rtx decl_rtl;
/* "Intercept" dbxout_symbol() calls like we do all debug_hooks. */
++debug_nesting;
@@ -2348,8 +2520,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
DBXOUT_DECR_NESTING_AND_RETURN (0);
/* If we are to generate only the symbols actually used then such
- symbol nodees are flagged with TREE_USED. Ignore any that
- aren't flaged as TREE_USED. */
+ symbol nodes are flagged with TREE_USED. Ignore any that
+ aren't flagged as TREE_USED. */
if (flag_debug_only_used_symbols
&& (!TREE_USED (decl)
@@ -2421,7 +2593,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
break;
case FUNCTION_DECL:
- if (DECL_RTL (decl) == 0)
+ decl_rtl = DECL_RTL_IF_SET (decl);
+ if (!decl_rtl)
DBXOUT_DECR_NESTING_AND_RETURN (0);
if (DECL_EXTERNAL (decl))
break;
@@ -2429,10 +2602,16 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
context = decl_function_context (decl);
if (context == current_function_decl)
break;
- if (!MEM_P (DECL_RTL (decl))
- || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
+ /* Don't mention an inline instance of a nested function. */
+ if (context && DECL_FROM_INLINE (decl))
+ break;
+ if (!MEM_P (decl_rtl)
+ || GET_CODE (XEXP (decl_rtl, 0)) != SYMBOL_REF)
break;
+ if (flag_debug_only_used_symbols)
+ output_used_types ();
+
dbxout_begin_complex_stabs ();
stabstr_I (DECL_ASSEMBLER_NAME (decl));
stabstr_S (TREE_PUBLIC (decl) ? ":F" : ":f");
@@ -2454,8 +2633,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
stabstr_I (DECL_NAME (context));
}
- dbxout_finish_complex_stabs (decl, N_FUN, XEXP (DECL_RTL (decl), 0),
- 0, 0);
+ dbxout_finish_complex_stabs (decl, N_FUN, XEXP (decl_rtl, 0), 0, 0);
break;
case TYPE_DECL:
@@ -2497,7 +2675,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
&& TYPE_NAME (type) == decl
- && !(use_gnu_debug_info_extensions && have_used_extensions)
+ && !use_gnu_debug_info_extensions
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
@@ -2523,11 +2701,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
dbxout_begin_complex_stabs ();
- /* Output leading class/struct qualifiers.
- ??? why not set have_used_extensions here ... because
- then the test of it below would always be true, I
- guess. But it's not clear to me why we shouldn't do
- that always in extended mode. */
+ /* Output leading class/struct qualifiers. */
if (use_gnu_debug_info_extensions)
dbxout_class_name_qualifiers (decl);
@@ -2544,7 +2718,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
from explicit ones that might be found in C. */
&& DECL_ARTIFICIAL (decl))
{
- if (use_gnu_debug_info_extensions && have_used_extensions)
+ if (use_gnu_debug_info_extensions)
{
stabstr_C ('T');
TREE_ASM_WRITTEN (TYPE_NAME (type)) = 1;
@@ -2609,10 +2783,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
gcc_unreachable ();
case RESULT_DECL:
- /* Named return value, treat like a VAR_DECL. */
case VAR_DECL:
- if (! DECL_RTL_SET_P (decl))
- DBXOUT_DECR_NESTING_AND_RETURN (0);
/* Don't mention a variable that is external.
Let the file that defines it describe it. */
if (DECL_EXTERNAL (decl))
@@ -2627,7 +2798,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
&& host_integerp (DECL_INITIAL (decl), 0)
&& ! TREE_ASM_WRITTEN (decl)
&& (DECL_CONTEXT (decl) == NULL_TREE
- || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK)
+ || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
+ || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
&& TREE_PUBLIC (decl) == 0)
{
/* The sun4 assembler does not grok this. */
@@ -2638,8 +2810,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
dbxout_begin_complex_stabs ();
- stabstr_I (DECL_NAME (decl));
- stabstr_S (":c=i");
+ dbxout_symbol_name (decl, NULL, 'c');
+ stabstr_S ("=i");
stabstr_D (ival);
dbxout_finish_complex_stabs (0, N_LSYM, 0, 0, 0);
DBXOUT_DECR_NESTING;
@@ -2650,13 +2822,17 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
}
/* else it is something we handle like a normal variable. */
- SET_DECL_RTL (decl, eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
+ decl_rtl = dbxout_expand_expr (decl);
+ if (!decl_rtl)
+ DBXOUT_DECR_NESTING_AND_RETURN (0);
+
+ decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
- leaf_renumber_regs_insn (DECL_RTL (decl));
+ leaf_renumber_regs_insn (decl_rtl);
#endif
- result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+ result = dbxout_symbol_location (decl, type, 0, decl_rtl);
break;
default:
@@ -2724,8 +2900,15 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
{
if (TREE_PUBLIC (decl))
{
+ int offs;
letter = 'G';
code = N_GSYM;
+ if (NULL != dbxout_common_check (decl, &offs))
+ {
+ letter = 'V';
+ addr = 0;
+ number = offs;
+ }
}
else
{
@@ -2771,7 +2954,17 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
if (DECL_INITIAL (decl) == 0
|| (!strcmp (lang_hooks.name, "GNU C++")
&& DECL_INITIAL (decl) == error_mark_node))
- code = N_LCSYM;
+ {
+ int offs;
+ code = N_LCSYM;
+ if (NULL != dbxout_common_check (decl, &offs))
+ {
+ addr = 0;
+ number = offs;
+ letter = 'V';
+ 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. */
@@ -2780,7 +2973,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
{
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
- data_section ();
+ switch_to_section (data_section);
#endif
code = N_STSYM;
}
@@ -2860,9 +3053,17 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
variable, thereby avoiding the need for a register. In such
cases we're forced to lie to debuggers and tell them that
this variable was itself `static'. */
+ int offs;
code = N_LCSYM;
letter = 'V';
- addr = XEXP (XEXP (home, 0), 0);
+ if (NULL == dbxout_common_check (decl, &offs))
+ addr = XEXP (XEXP (home, 0), 0);
+ else
+ {
+ addr = 0;
+ number = offs;
+ code = N_GSYM;
+ }
}
else if (GET_CODE (home) == CONCAT)
{
@@ -2947,6 +3148,115 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter)
stabstr_C (letter);
}
+
+/* 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)
+{
+ dbxout_begin_complex_stabs ();
+ stabstr_S (name);
+ dbxout_finish_complex_stabs (decl, op, NULL_RTX, NULL, 0);
+}
+
+/* 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 = NULL;
+
+ /* If the decl isn't a VAR_DECL, or if it isn't public or static, or if
+ it does not have a value (the offset into the common area), or if it
+ is thread local (as opposed to global) then it isn't common, and shouldn't
+ be handled as such.
+
+ ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs
+ for thread-local symbols. Can be handled via same mechanism as used
+ in dwarf2out.c. */
+ if (TREE_CODE (decl) != VAR_DECL
+ || !TREE_PUBLIC(decl)
+ || !TREE_STATIC(decl)
+ || !DECL_HAS_VALUE_EXPR_P(decl)
+ || DECL_THREAD_LOCAL_P (decl)
+ || !is_fortran ())
+ return NULL;
+
+ home = DECL_RTL (decl);
+ if (home == NULL_RTX || GET_CODE (home) != MEM)
+ return NULL;
+
+ sym_addr = dbxout_expand_expr (DECL_VALUE_EXPR (decl));
+ if (sym_addr == NULL_RTX || GET_CODE (sym_addr) != MEM)
+ return NULL;
+
+ sym_addr = XEXP (sym_addr, 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)
+ && DECL_INITIAL (decl) == 0)
+ {
+
+ /* We have a 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 = NULL;
+
+ 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;
+}
+
/* Output definitions of all the decls in a chain. Return nonzero if
anything was output */
@@ -2954,11 +3264,38 @@ int
dbxout_syms (tree syms)
{
int result = 0;
+ const char *comm_prev = NULL;
+ tree syms_prev = NULL;
+
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_prev, 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;
}
@@ -2994,8 +3331,9 @@ dbxout_parms (tree parms)
/* Perform any necessary register eliminations on the parameter's rtl,
so that the debugging output will be accurate. */
DECL_INCOMING_RTL (parms)
- = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
- SET_DECL_RTL (parms, eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));
+ = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX);
+ SET_DECL_RTL (parms,
+ eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX));
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
{
@@ -3056,6 +3394,8 @@ dbxout_parms (tree parms)
was passed. */
if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
best_rtl = DECL_RTL (parms);
+ else if (GET_CODE (DECL_INCOMING_RTL (parms)) == PARALLEL)
+ best_rtl = XEXP (XVECEXP (DECL_INCOMING_RTL (parms), 0, 0), 0);
else
best_rtl = DECL_INCOMING_RTL (parms);
@@ -3214,6 +3554,8 @@ dbxout_args (tree args)
}
}
+#if defined (DBX_DEBUGGING_INFO)
+
/* Subroutine of dbxout_block. Emit an N_LBRAC stab referencing LABEL.
BEGIN_LABEL is the name of the beginning of the function, which may
be required. */
@@ -3221,15 +3563,11 @@ static void
dbx_output_lbrac (const char *label,
const char *begin_label ATTRIBUTE_UNUSED)
{
-#ifdef DBX_OUTPUT_LBRAC
- DBX_OUTPUT_LBRAC (asm_out_file, label);
-#else
dbxout_begin_stabn (N_LBRAC);
if (DBX_BLOCKS_FUNCTION_RELATIVE)
dbxout_stab_value_label_diff (label, begin_label);
else
dbxout_stab_value_label (label);
-#endif
}
/* Subroutine of dbxout_block. Emit an N_RBRAC stab referencing LABEL.
@@ -3239,15 +3577,11 @@ static void
dbx_output_rbrac (const char *label,
const char *begin_label ATTRIBUTE_UNUSED)
{
-#ifdef DBX_OUTPUT_RBRAC
- DBX_OUTPUT_RBRAC (asm_out_file, label);
-#else
dbxout_begin_stabn (N_RBRAC);
if (DBX_BLOCKS_FUNCTION_RELATIVE)
dbxout_stab_value_label_diff (label, begin_label);
else
dbxout_stab_value_label (label);
-#endif
}
/* Output everything about a symbol block (a BLOCK node
@@ -3270,8 +3604,9 @@ dbx_output_rbrac (const char *label,
static void
dbxout_block (tree block, int depth, tree args)
{
- const char *begin_label
- = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ char begin_label[20];
+ /* Reference current function start using LFBB. */
+ ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
while (block)
{
@@ -3300,7 +3635,7 @@ dbxout_block (tree block, int depth, tree args)
if (depth == 0)
/* The outermost block doesn't get LBB labels; use
- the function symbol. */
+ the LFBB local symbol emitted by dbxout_begin_prologue. */
scope_start = begin_label;
else
{
@@ -3308,20 +3643,6 @@ dbxout_block (tree block, int depth, tree args)
scope_start = buf;
}
- if (BLOCK_HANDLER_BLOCK (block))
- {
- /* A catch block. Must precede N_LBRAC. */
- tree decl = BLOCK_VARS (block);
- while (decl)
- {
- dbxout_begin_complex_stabs ();
- stabstr_I (DECL_NAME (decl));
- stabstr_S (":C1");
- dbxout_finish_complex_stabs (0, N_CATCH, 0,
- scope_start, 0);
- decl = TREE_CHAIN (decl);
- }
- }
dbx_output_lbrac (scope_start, begin_label);
}
@@ -3351,11 +3672,15 @@ dbxout_block (tree block, int depth, tree args)
Usually this follows the function's code,
but on some systems, it comes before. */
-#if defined (DBX_DEBUGGING_INFO)
static void
dbxout_begin_function (tree decl)
{
- int saved_tree_used1 = TREE_USED (decl);
+ int saved_tree_used1;
+
+ if (DECL_IGNORED_P (decl))
+ return;
+
+ saved_tree_used1 = TREE_USED (decl);
TREE_USED (decl) = 1;
if (DECL_NAME (DECL_RESULT (decl)) != 0)
{