#define FILE_NAME_JOINER "/"
#endif
-/* Nonzero means if the type has methods, only output debugging
- information if methods are actually written to the asm file. This
- optimization only works if the debugger can detect the special C++
- marker. */
-
-#define MINIMAL_DEBUG 1
-
-#ifdef NO_DOLLAR_IN_LABEL
-#ifdef NO_DOT_IN_LABEL
-#undef MINIMAL_DEBUG
-#define MINIMAL_DEBUG 0
-#endif
+/* GDB needs to know that the stabs were generated by GCC. We emit an
+ N_OPT stab at the beginning of the source file to indicate this.
+ The string is historical, and different on a very few targets. */
+#ifndef STABS_GCC_MARKER
+#define STABS_GCC_MARKER "gcc2_compiled."
#endif
/* Typical USG systems don't have stab.h, and they also have
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-static int flag_minimal_debug = MINIMAL_DEBUG;
-
/* 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,
#define FORCE_TEXT
#endif
-/* If there is a system stab.h, use it. Otherwise, use our own. */
-/* ??? This is supposed to describe the target's stab format, so using
- the host HAVE_STAB_H appears to be wrong. For now, we use our own file
- when cross compiling. */
-#if defined (USG) || !defined (HAVE_STAB_H) || defined (CROSS_COMPILE)
-#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
-#else
-#include <stab.h>
-
-/* This is a GNU extension we need to reference in this file. */
-#ifndef N_CATCH
-#define N_CATCH 0x54
-#endif
-#endif
+#include "gstab.h"
-#ifdef __GNU_STAB__
#define STAB_CODE_TYPE enum __stab_debug_code
-#else
-#define STAB_CODE_TYPE int
-#endif
/* 1 if PARM is passed to this function in memory. */
static void dbxout_type_method_1 PARAMS ((tree, const char *));
static void dbxout_type_methods PARAMS ((tree));
static void dbxout_range_type PARAMS ((tree));
-static void dbxout_type PARAMS ((tree, int, int));
+static void dbxout_type PARAMS ((tree, int));
static void print_int_cst_octal PARAMS ((tree));
static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int));
static void dbxout_type_name PARAMS ((tree));
#endif
{
if (!cwd && (cwd = getpwd ()) && (!*cwd || cwd[strlen (cwd) - 1] != '/'))
- {
- char *wdslash = xmalloc (strlen (cwd) + sizeof (FILE_NAME_JOINER));
- sprintf (wdslash, "%s%s", cwd, FILE_NAME_JOINER);
- cwd = wdslash;
- }
+ cwd = concat (cwd, FILE_NAME_JOINER, NULL);
if (cwd)
{
#ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Ltext", 0);
#endif /* no DBX_OUTPUT_MAIN_SOURCE_FILENAME */
- /* Possibly output something to inform GDB that this compilation was by
- GCC. It's easier for GDB to parse it when after the N_SO's. This
- is used in Solaris 2. */
-#ifdef ASM_IDENTIFY_GCC_AFTER_SOURCE
- ASM_IDENTIFY_GCC_AFTER_SOURCE (asmfile);
+#ifdef DBX_OUTPUT_GCC_MARKER
+ DBX_OUTPUT_GCC_MARKER (asmfile);
+#else
+ /* Emit an N_OPT stab to indicate that this file was compiled by GCC. */
+ fprintf (asmfile, "%s\"%s\",%d,0,0,0\n",
+ ASM_STABS_OP, STABS_GCC_MARKER, N_OPT);
#endif
lastfile = input_file_name;
if (tem != TYPE_FIELDS (type))
CONTIN;
- if (use_gnu_debug_info_extensions
- && flag_minimal_debug
- && TREE_CODE (tem) == FIELD_DECL
- && DECL_VIRTUAL_P (tem)
- && DECL_ASSEMBLER_NAME (tem))
- {
- have_used_extensions = 1;
- CHARS (3 + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (tem)));
- fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem)), asmfile);
- dbxout_type (DECL_FCONTEXT (tem), 0, 0);
- fprintf (asmfile, ":");
- dbxout_type (TREE_TYPE (tem), 0, 0);
- fputc (',', asmfile);
- fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
- int_bit_position (tem));
- fputc (';', asmfile);
- continue;
- }
-
if (DECL_NAME (tem))
{
fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem)));
dbxout_type ((TREE_CODE (tem) == FIELD_DECL
&& DECL_BIT_FIELD_TYPE (tem))
- ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0, 0);
+ ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0);
if (TREE_CODE (tem) == VAR_DECL)
{
fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (DECL_VINDEX (decl), 0));
fputc (';', asmfile);
- dbxout_type (DECL_CONTEXT (decl), 0, 0);
+ dbxout_type (DECL_CONTEXT (decl), 0);
fprintf (asmfile, ";");
CHARS (8);
}
type_identifier_length = IDENTIFIER_LENGTH (type_encoding);
- sprintf(formatted_type_identifier_length, "%d", type_identifier_length);
+ sprintf (formatted_type_identifier_length, "%d", type_identifier_length);
if (TREE_CODE (methods) != TREE_VEC)
fndecl = methods;
while (fndecl)
{
- tree name = DECL_NAME (fndecl);
int need_prefix = 1;
/* Group together all the methods for the same operation.
{
/* This is the "mangled" name of the method.
It encodes the argument types. */
- const char *debug_name =
+ const char *debug_name;
+
+ /* Skip methods that aren't FUNCTION_DECLs. (In C++, these
+ include TEMPLATE_DECLs.) The debugger doesn't know what
+ to do with such entities anyhow. */
+ if (TREE_CODE (fndecl) != FUNCTION_DECL)
+ continue;
+
+ debug_name =
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
- int show_arg_types = 0;
CONTIN;
if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
continue;
- if (flag_minimal_debug)
+ /* Redundantly output the plain name, since that's what gdb
+ expects. */
+ if (need_prefix)
{
- char marker;
-
- /* We can't optimize a method which uses an anonymous
- class, because the debugger will not be able to
- associate the arbitrary class name with the actual
- class. */
-#ifndef NO_DOLLAR_IN_LABEL
- marker = '$';
-#else
- marker = '.';
-#endif
- if (strchr (debug_name, marker))
- show_arg_types = 1;
- /* Detect ordinary methods because their mangled names
- start with the operation name. */
- else if (!strncmp (IDENTIFIER_POINTER (name), debug_name,
- IDENTIFIER_LENGTH (name)))
- {
- debug_name += IDENTIFIER_LENGTH (name);
- if (debug_name[0] == '_' && debug_name[1] == '_')
- {
- const char *method_name = debug_name + 2;
- const char *length_ptr =
- formatted_type_identifier_length;
- /* Get past const and volatile qualifiers. */
- while (*method_name == 'C' || *method_name == 'V')
- method_name++;
- /* Skip digits for length of type_encoding. */
- while (*method_name == *length_ptr && *length_ptr)
- length_ptr++, method_name++;
- if (! strncmp (method_name,
- IDENTIFIER_POINTER (type_encoding),
- type_identifier_length))
- method_name += type_identifier_length;
- debug_name = method_name;
- }
- }
- /* Detect constructors by their style of name mangling. */
- else if (debug_name[0] == '_' && debug_name[1] == '_')
- {
- const char *ctor_name = debug_name + 2;
- const char *length_ptr = formatted_type_identifier_length;
- while (*ctor_name == 'C' || *ctor_name == 'V')
- ctor_name++;
- /* Skip digits for length of type_encoding. */
- while (*ctor_name == *length_ptr && *length_ptr)
- length_ptr++, ctor_name++;
- if (!strncmp (IDENTIFIER_POINTER (type_encoding), ctor_name,
- type_identifier_length))
- debug_name = ctor_name + type_identifier_length;
- }
- /* The other alternative is a destructor. */
- else
- show_arg_types = 1;
-
- /* Output the operation name just once, for the first method
- that we output. */
- if (need_prefix)
- {
- fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
- CHARS (IDENTIFIER_LENGTH (name) + 2);
- need_prefix = 0;
- }
+ tree name = DECL_NAME (fndecl);
+ fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
+ CHARS (IDENTIFIER_LENGTH (name) + 2);
+ need_prefix = 0;
}
- dbxout_type (TREE_TYPE (fndecl), 0, show_arg_types);
+ dbxout_type (TREE_TYPE (fndecl), 0);
dbxout_type_method_1 (fndecl, debug_name);
}
{
fprintf (asmfile, "r");
if (TREE_TYPE (type))
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
else if (TREE_CODE (type) != INTEGER_TYPE)
- dbxout_type (type, 0, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
+ dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
else
{
/* Traditionally, we made sure 'int' was type 1, and builtin types
If FULL is nonzero, and the type has been described only with
a forward-reference, output the definition now.
If FULL is zero in this case, just refer to the forward-reference
- using the number previously allocated.
-
- If SHOW_ARG_TYPES is nonzero, we output a description of the argument
- types for a METHOD_TYPE. */
+ using the number previously allocated. */
static void
-dbxout_type (type, full, show_arg_types)
+dbxout_type (type, full)
tree type;
int full;
- int show_arg_types;
{
register tree tem;
static int anonymous_type_number = 0;
Sun dbx crashes if we do. */
if (! full || !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ || ! host_integerp (TYPE_SIZE (type), 1))
return;
break;
case TYPE_DEFINED:
&& !full)
|| !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ || ! host_integerp (TYPE_SIZE (type), 1))
{
typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
return;
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
- dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0, 0);
+ dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0);
return;
}
/* If this is a subtype of another integer type, always prefer to
write it as a subtype. */
else if (TREE_TYPE (type) != 0
- && TREE_CODE (TREE_TYPE (type)) == INTEGER_CST)
+ && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
dbxout_range_type (type);
else
&& TYPE_MAX_VALUE (type) != 0
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST
&& (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
- || (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
+ || ((TYPE_PRECISION (type)
+ == TYPE_PRECISION (integer_type_node))
&& TREE_UNSIGNED (type))
|| TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT
|| (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT
case FILE_TYPE:
putc ('d', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
case COMPLEX_TYPE:
fprintf (asmfile, "real:");
CHARS (10);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
fprintf (asmfile, ",%d,%d;",
0, TYPE_PRECISION (TREE_TYPE (type)));
CHARS (8);
fprintf (asmfile, "imag:");
CHARS (5);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
fprintf (asmfile, ",%d,%d;;",
TYPE_PRECISION (TREE_TYPE (type)),
TYPE_PRECISION (TREE_TYPE (type)));
}
putc ('S', asmfile);
CHARS (1);
- dbxout_type (TYPE_DOMAIN (type), 0, 0);
+ dbxout_type (TYPE_DOMAIN (type), 0);
break;
case ARRAY_TYPE:
fprintf (asmfile, "@S;");
putc ('S', asmfile);
CHARS (1);
- dbxout_type (TYPE_DOMAIN (type), 0, 0);
+ dbxout_type (TYPE_DOMAIN (type), 0);
break;
}
/* Output "a" followed by a range type definition
dbxout_range_type (tem);
}
CHARS (14);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
case RECORD_TYPE:
&& !full)
|| !COMPLETE_TYPE_P (type)
/* No way in DBX fmt to describe a variable size. */
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ || ! host_integerp (TYPE_SIZE (type), 1))
{
/* If the type is just a cross reference, output one
and mark the type as partially described.
* BITS_PER_UNIT));
fputc (',', asmfile);
CHARS (15);
- dbxout_type (BINFO_TYPE (child), 0, 0);
+ dbxout_type (BINFO_TYPE (child), 0);
putc (';', asmfile);
}
else
which have the same names at the types they hold. */
dbxout_type_name (BINFO_TYPE (child));
putc (':', asmfile);
- dbxout_type (BINFO_TYPE (child), full, 0);
+ dbxout_type (BINFO_TYPE (child), full);
fputc (',', asmfile);
fprintf (asmfile, HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (BINFO_OFFSET (child), 0)
if (TYPE_VFIELD (type))
{
putc ('%', asmfile);
- dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0, 0);
+ dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0);
}
putc (';', asmfile);
CHARS (3);
case POINTER_TYPE:
putc ('*', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
case METHOD_TYPE:
have_used_extensions = 1;
putc ('#', asmfile);
CHARS (1);
- if (flag_minimal_debug && !show_arg_types)
- {
- /* Normally, just output the return type.
- The argument types are encoded in the method name. */
- putc ('#', asmfile);
- CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
- putc (';', asmfile);
- CHARS (1);
- }
- else
- {
- /* When outputting destructors, we need to write
- the argument types out longhand. */
- dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0);
- putc (',', asmfile);
- CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
- dbxout_args (TYPE_ARG_TYPES (type));
- putc (';', asmfile);
- CHARS (1);
- }
+
+ /* Write the argument types out longhand. */
+ dbxout_type (TYPE_METHOD_BASETYPE (type), 0);
+ putc (',', asmfile);
+ CHARS (1);
+ dbxout_type (TREE_TYPE (type), 0);
+ dbxout_args (TYPE_ARG_TYPES (type));
+ putc (';', asmfile);
+ CHARS (1);
}
else
{
/* Treat it as a function type. */
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
}
break;
have_used_extensions = 1;
putc ('@', asmfile);
CHARS (1);
- dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0);
+ dbxout_type (TYPE_OFFSET_BASETYPE (type), 0);
putc (',', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
}
else
{
/* Should print as an int, because it is really
just an offset. */
- dbxout_type (integer_type_node, 0, 0);
+ dbxout_type (integer_type_node, 0);
}
break;
have_used_extensions = 1;
putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
case FUNCTION_TYPE:
putc ('f', asmfile);
CHARS (1);
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
break;
default:
current_sym_addr = XEXP (DECL_RTL (decl), 0);
if (TREE_TYPE (type))
- dbxout_type (TREE_TYPE (type), 0, 0);
+ dbxout_type (TREE_TYPE (type), 0);
else
- dbxout_type (void_type_node, 0, 0);
+ dbxout_type (void_type_node, 0);
/* For a nested function, when that function is compiled,
mention the containing function name
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && DECL_ARTIFICIAL (decl))
+ && DECL_ARTIFICIAL (decl)
+ /* Do not generate a tag for records of variable size,
+ since this type can not be properly described in the
+ DBX format, and it confuses some tools such as objdump. */
+ && host_integerp (TYPE_SIZE (type), 1))
{
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
IDENTIFIER_POINTER (name));
- dbxout_type (type, 1, 0);
+ dbxout_type (type, 1);
dbxout_finish_symbol (NULL_TREE);
}
putc ('t', asmfile);
current_sym_code = DBX_TYPE_DECL_STABS_CODE;
- dbxout_type (type, 1, 0);
+ dbxout_type (type, 1);
dbxout_finish_symbol (decl);
did_output = 1;
}
- /* Don't output a tag if this is an incomplete type (TYPE_SIZE is
- zero). This prevents the sun4 Sun OS 4.x dbx from crashing. */
+ /* Don't output a tag if this is an incomplete type. This prevents
+ the sun4 Sun OS 4.x dbx from crashing. */
if (tag_needed && TYPE_NAME (type) != 0
&& (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE
fprintf (asmfile, "%s\"%s:T", ASM_STABS_OP,
IDENTIFIER_POINTER (name));
- dbxout_type (type, 1, 0);
+ dbxout_type (type, 1);
dbxout_finish_symbol (NULL_TREE);
did_output = 1;
}
/* Some debuggers fail when given NULL names, so give this a
harmless name of ` '. */
fprintf (asmfile, "%s\" :T", ASM_STABS_OP);
- dbxout_type (type, 1, 0);
+ dbxout_type (type, 1);
dbxout_finish_symbol (NULL_TREE);
}
else if (GET_CODE (home) == SUBREG)
{
rtx value = home;
- int offset = 0;
+
while (GET_CODE (value) == SUBREG)
- {
- offset += SUBREG_WORD (value);
- value = SUBREG_REG (value);
- }
+ value = SUBREG_REG (value);
if (GET_CODE (value) == REG)
{
- regno = REGNO (value);
- if (regno >= FIRST_PSEUDO_REGISTER)
+ if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
return 0;
- regno += offset;
}
- alter_subreg (home);
+ regno = REGNO (alter_subreg (home));
}
/* The kind-of-variable letter depends on where
}
else if (GET_CODE (home) == CONCAT)
{
- tree subtype = TREE_TYPE (type);
+ tree subtype;
+
+ /* If TYPE is not a COMPLEX_TYPE (it might be a RECORD_TYPE,
+ for example), then there is no easy way to figure out
+ what SUBTYPE should be. So, we give up. */
+ if (TREE_CODE (type) != COMPLEX_TYPE)
+ return 0;
+
+ subtype = TREE_TYPE (type);
/* If the variable's storage is in two parts,
output each as a separate stab with a modified name. */
#endif
dbxout_symbol_name (decl, suffix, letter);
- dbxout_type (type, 0, 0);
+ dbxout_type (type, 0);
dbxout_finish_symbol (decl);
#ifdef DBX_STATIC_BLOCK_END
/* It is quite tempting to use:
- dbxout_type (TREE_TYPE (parms), 0, 0);
+ dbxout_type (TREE_TYPE (parms), 0);
as the next statement, rather than using DECL_ARG_TYPE(), so
that gcc reports the actual type of the parameter, rather
double on the stack, but if we emit a stab saying the type is a
float, then gdb will only read in a single value, and this will
produce an erropneous value. */
- dbxout_type (DECL_ARG_TYPE (parms), 0, 0);
+ dbxout_type (DECL_ARG_TYPE (parms), 0);
current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
dbxout_finish_symbol (parms);
}
regparm_letter);
}
- dbxout_type (parm_type, 0, 0);
+ dbxout_type (parm_type, 0);
dbxout_finish_symbol (parms);
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
regparm_letter);
}
- dbxout_type (TREE_TYPE (parms), 0, 0);
+ dbxout_type (TREE_TYPE (parms), 0);
dbxout_finish_symbol (parms);
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
FORCE_TEXT;
fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
- dbxout_type (TREE_TYPE (parms), 0, 0);
+ dbxout_type (TREE_TYPE (parms), 0);
dbxout_finish_symbol (parms);
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
current_sym_value
= DEBUGGER_ARG_OFFSET (current_sym_value,
XEXP (DECL_RTL (parms), 0));
- dbxout_type (TREE_TYPE (parms), 0, 0);
+ dbxout_type (TREE_TYPE (parms), 0);
dbxout_finish_symbol (parms);
}
}
while (args)
{
putc (',', asmfile);
- dbxout_type (TREE_VALUE (args), 0, 0);
+ dbxout_type (TREE_VALUE (args), 0);
CHARS (1);
args = TREE_CHAIN (args);
}