/* Forward declarations for functions defined in this file. */
-static char *stripattributes PROTO((char *));
-static char *dwarf_cfi_name PROTO((unsigned));
+static char *stripattributes PROTO((const char *));
+static const char *dwarf_cfi_name PROTO((unsigned));
static dw_cfi_ref new_cfi PROTO((void));
static void add_cfi PROTO((dw_cfi_ref *, dw_cfi_ref));
static unsigned long size_of_uleb128 PROTO((unsigned long));
static void output_call_frame_info PROTO((int));
static unsigned reg_number PROTO((rtx));
static void dwarf2out_stack_adjust PROTO((rtx));
+static void dwarf2out_frame_debug_expr PROTO((rtx, char *));
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx_MINUS (HImode, \
- gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
- gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
2, 1)
#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx_MINUS (SImode, \
- gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
- gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
4, 1)
#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \
assemble_integer (gen_rtx_MINUS (Pmode, \
- gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
- gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL1), \
+ gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \
PTR_SIZE, 1)
#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
do { \
register int slen = strlen(P); \
- register char *p = (P); \
+ register const char *p = (P); \
register int i; \
fprintf (FILE, "\t.ascii \""); \
for (i = 0; i < slen; i++) \
register int c = p[i]; \
if (c == '\"' || c == '\\') \
putc ('\\', FILE); \
- if (c >= ' ' && c < 0177) \
+ if (ISPRINT(c)) \
putc (c, FILE); \
else \
{ \
static inline char *
stripattributes (s)
- char *s;
+ const char *s;
{
char *stripped = xmalloc (strlen (s) + 2);
char *p = stripped;
/* Convert a DWARF call frame info. operation to its string name */
-static char *
+static const char *
dwarf_cfi_name (cfi_opc)
register unsigned cfi_opc;
{
}
}
-#if !defined (EH_FRAME_SECTION)
-#if defined (EH_FRAME_SECTION_ASM_OP)
-#define EH_FRAME_SECTION() eh_frame_section();
-#else
-#if defined (ASM_OUTPUT_SECTION_NAME)
-#define EH_FRAME_SECTION() \
- do { \
- named_section (NULL_TREE, ".eh_frame", 0); \
- } while (0)
-#endif
-#endif
-#endif
-
-/* If we aren't using crtstuff to run ctors, don't use it for EH. */
-#if !defined (HAS_INIT_SECTION) && !defined (INIT_SECTION_ASM_OP)
-#undef EH_FRAME_SECTION
-#endif
-
/* Output the call frame information used to used to record information
that relates to calculating the frame pointer, and records the
location of saved registers. */
dwarf2out_frame_init ()
{
/* Allocate the initial hunk of the fde_table. */
- fde_table
- = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
- bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
+ fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node));
fde_table_allocated = FDE_TABLE_INCREMENT;
fde_table_in_use = 0;
/* And now, the support for symbolic debugging information. */
#ifdef DWARF2_DEBUGGING_INFO
-extern char *getpwd PROTO((void));
-
/* NOTE: In the comments in this file, many references are made to
"Debugging Information Entries". This term is abbreviated as `DIE'
throughout the remainder of this file. */
extern int flag_traditional;
extern char *version_string;
-extern char *language_string;
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
#define DWARF_ARANGES_HEADER_SIZE \
(DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
+/* The default is to have gcc emit the line number tables. */
+#ifndef DWARF2_ASM_LINE_DEBUG_INFO
+#define DWARF2_ASM_LINE_DEBUG_INFO 0
+#endif
+
/* Define the architecture-dependent minimum instruction length (in bytes).
In this implementation of DWARF, this field is used for information
purposes only. Since GCC generates assembly language, we have
static int is_pseudo_reg PROTO((rtx));
static tree type_main_variant PROTO((tree));
static int is_tagged_type PROTO((tree));
-static char *dwarf_tag_name PROTO((unsigned));
-static char *dwarf_attr_name PROTO((unsigned));
-static char *dwarf_form_name PROTO((unsigned));
-static char *dwarf_stack_op_name PROTO((unsigned));
+static const char *dwarf_tag_name PROTO((unsigned));
+static const char *dwarf_attr_name PROTO((unsigned));
+static const char *dwarf_form_name PROTO((unsigned));
+static const char *dwarf_stack_op_name PROTO((unsigned));
#if 0
-static char *dwarf_type_encoding_name PROTO((unsigned));
+static const char *dwarf_type_encoding_name PROTO((unsigned));
#endif
static tree decl_ultimate_origin PROTO((tree));
static tree block_ultimate_origin PROTO((tree));
enum dwarf_attribute,
unsigned, long *));
static void add_AT_string PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
+ enum dwarf_attribute,
+ const char *));
static void add_AT_die_ref PROTO((dw_die_ref,
enum dwarf_attribute,
dw_die_ref));
static unsigned long sibling_offset PROTO((dw_die_ref));
static void output_die PROTO((dw_die_ref));
static void output_compilation_unit_header PROTO((void));
-static char *dwarf2_name PROTO((tree, int));
+static const char *dwarf2_name PROTO((tree, int));
static void add_pubname PROTO((tree, dw_die_ref));
static void output_pubnames PROTO((void));
static void add_arange PROTO((tree, dw_die_ref));
static dw_loc_descr_ref reg_loc_descriptor PROTO((rtx));
static dw_loc_descr_ref based_loc_descr PROTO((unsigned, long));
static int is_based_loc PROTO((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx, enum machine_mode mode));
static dw_loc_descr_ref concat_loc_descriptor PROTO((rtx, rtx));
static dw_loc_descr_ref loc_descriptor PROTO((rtx));
static unsigned ceiling PROTO((unsigned, unsigned));
static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
static void add_const_value_attribute PROTO((dw_die_ref, rtx));
static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
-static void add_name_attribute PROTO((dw_die_ref, char *));
+static void add_name_attribute PROTO((dw_die_ref, const char *));
static void add_bound_info PROTO((dw_die_ref,
enum dwarf_attribute, tree));
static void add_subscript_info PROTO((dw_die_ref, tree));
static void decls_for_scope PROTO((tree, dw_die_ref, int));
static int is_redundant_typedef PROTO((tree));
static void gen_decl_die PROTO((tree, dw_die_ref));
-static unsigned lookup_filename PROTO((char *));
+static unsigned lookup_filename PROTO((const char *));
+static void add_incomplete_type PROTO((tree));
+static void retry_incomplete_types PROTO((void));
/* Section names used to hold DWARF debugging information. */
#ifndef DEBUG_INFO_SECTION
dyn_string_append (STR, NAME + 1); \
else \
{ \
- char *newstr; \
+ const char *newstr; \
STRIP_NAME_ENCODING (newstr, NAME); \
dyn_string_append (STR, user_label_prefix); \
dyn_string_append (STR, newstr); \
/* Convert a DIE tag into its string name. */
-static char *
+static const char *
dwarf_tag_name (tag)
register unsigned tag;
{
/* Convert a DWARF attribute code into its string name. */
-static char *
+static const char *
dwarf_attr_name (attr)
register unsigned attr;
{
/* Convert a DWARF value form code into its string name. */
-static char *
+static const char *
dwarf_form_name (form)
register unsigned form;
{
/* Convert a DWARF stack opcode into its string name. */
-static char *
+static const char *
dwarf_stack_op_name (op)
register unsigned op;
{
/* Convert a DWARF type code into its string name. */
#if 0
-static char *
+static const char *
dwarf_type_encoding_name (enc)
register unsigned enc;
{
add_AT_string (die, attr_kind, str)
register dw_die_ref die;
register enum dwarf_attribute attr_kind;
- register char *str;
+ register const char *str;
{
register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
register enum dwarf_attribute attr_kind;
{
register dw_attr_ref a;
- register dw_attr_ref removed = NULL;;
+ register dw_attr_ref removed = NULL;
if (die != NULL)
{
{
print_indent = 0;
print_die (comp_unit_die, stderr);
- print_dwarf_line_table (stderr);
+ if (! DWARF2_ASM_LINE_DEBUG_INFO)
+ print_dwarf_line_table (stderr);
}
\f
/* Traverse the DIE, and add a sibling attribute if it may have the
of decl_printable_name for C++ looks like "A::f(int)". Let's drop the
argument list, and maybe the scope. */
-static char *
+static const char *
dwarf2_name (decl, scope)
tree decl;
int scope;
ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 4);
- if (PTR_SIZE == 8)
+ /* We need to align to twice the pointer size here.
+ If DWARF_OFFSET_SIZE == 4, then we have emitted 12 bytes, and need 4
+ bytes of padding to align for either 4 or 8 byte pointers. */
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
+ /* If DWARF_OFFSET_SIZE == 8, then we have emitted 20 bytes, and need 12
+ bytes of padding to align for 8 byte pointers. We have already emitted
+ 4 bytes of padding, so emit 8 more here. */
+ if (DWARF_OFFSET_SIZE == 8)
fprintf (asm_out_file, ",0,0");
if (flag_debug_asm)
When creating memory location descriptors, we are effectively transforming
the RTL for a memory-resident object into its Dwarf postfix expression
equivalent. This routine recursively descends an RTL tree, turning
- it into Dwarf postfix code as it goes. */
+ it into Dwarf postfix code as it goes.
+
+ MODE is the mode of the memory reference, needed to handle some
+ autoincrement addressing modes. */
static dw_loc_descr_ref
-mem_loc_descriptor (rtl)
+mem_loc_descriptor (rtl, mode)
register rtx rtl;
+ enum machine_mode mode;
{
dw_loc_descr_ref mem_loc_result = NULL;
/* Note that for a dynamically sized array, the location we will generate a
switch (GET_CODE (rtl))
{
+ case POST_INC:
+ case POST_DEC:
+ /* POST_INC and POST_DEC can be handled just like a SUBREG. So we
+ just fall into the SUBREG code. */
+
+ /* ... fall through ... */
+
case SUBREG:
/* The case of a subreg may arise when we have a local (register)
variable or a formal (register) parameter which doesn't quite fill
break;
case MEM:
- mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode);
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0));
break;
+ case LABEL_REF:
+ /* Some ports can transform a symbol ref into a label ref, because
+ the symbol ref is too far away and has to be dumped into a constant
+ pool. */
case CONST:
case SYMBOL_REF:
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
mem_loc_result->dw_loc_oprnd1.v.val_addr = addr_to_string (rtl);
break;
+ case PRE_INC:
+ case PRE_DEC:
+ /* Turn these into a PLUS expression and fall into the PLUS code
+ below. */
+ rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0),
+ GEN_INT (GET_CODE (rtl) == PRE_INC
+ ? GET_MODE_UNIT_SIZE (mode)
+ : - GET_MODE_UNIT_SIZE (mode)));
+
+ /* ... fall through ... */
+
case PLUS:
if (is_based_loc (rtl))
mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)),
INTVAL (XEXP (rtl, 1)));
else
{
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0),
+ mode));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1),
+ mode));
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0));
}
break;
case MULT:
/* If a pseudo-reg is optimized away, it is possible for it to
be replaced with a MEM containing a multiply. */
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0)));
- add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1)));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0), mode));
+ add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1), mode));
add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0));
break;
break;
case MEM:
- loc_result = mem_loc_descriptor (XEXP (rtl, 0));
+ loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl));
break;
case CONCAT:
rtl = DECL_INCOMING_RTL (decl);
else if (! BYTES_BIG_ENDIAN
&& TREE_CODE (declared_type) == INTEGER_TYPE
- && TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+ && (GET_MODE_SIZE (TYPE_MODE (declared_type))
+ <= GET_MODE_SIZE (TYPE_MODE (passed_type))))
rtl = DECL_INCOMING_RTL (decl);
}
static inline void
add_name_attribute (die, name_string)
register dw_die_ref die;
- register char *name_string;
+ register const char *name_string;
{
if (name_string != NULL && *name_string != 0)
add_AT_string (die, DW_AT_name, name_string);
rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound);
if (XEXP (loc, 0) != new_addr)
- loc = gen_rtx (MEM, GET_MODE (loc), new_addr);
+ loc = gen_rtx_MEM (GET_MODE (loc), new_addr);
}
add_AT_flag (decl_die, DW_AT_artificial, 1);
we should detect this case and ignore it. For now, if we have
already reported an error, any error at all, then assume that
we got here because of a input error, not a dwarf2 bug. */
- extern int errorcount;
if (errorcount)
return;
abort ();
static unsigned
lookup_filename (file_name)
- char *file_name;
+ const char *file_name;
{
static unsigned last_file_lookup_index = 0;
register unsigned i;
void
dwarf2out_line (filename, line)
- register char *filename;
+ register const char *filename;
register unsigned line;
{
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
function_section (current_function_decl);
- if (DECL_SECTION_NAME (current_function_decl))
+ if (DWARF2_ASM_LINE_DEBUG_INFO)
+ {
+ static const char *lastfile;
+
+ /* Emit the .file and .loc directives understood by GNU as. */
+ if (lastfile == 0 || strcmp (filename, lastfile))
+ {
+ fprintf (asm_out_file, "\t.file 0 \"%s\"\n", filename);
+ lastfile = filename;
+ }
+
+ fprintf (asm_out_file, "\t.loc 0 %d 0\n", line);
+
+ /* Indicate that line number info exists. */
+ ++line_info_table_in_use;
+
+ /* Indicate that multiple line number tables exist. */
+ if (DECL_SECTION_NAME (current_function_decl))
+ ++separate_line_info_table_in_use;
+ }
+ else if (DECL_SECTION_NAME (current_function_decl))
{
register dw_separate_line_info_ref line_info;
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL,
void
dwarf2out_start_source_file (filename)
- register char *filename ATTRIBUTE_UNUSED;
+ register const char *filename ATTRIBUTE_UNUSED;
{
}
void
dwarf2out_define (lineno, buffer)
register unsigned lineno ATTRIBUTE_UNUSED;
- register char *buffer ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
static int initialized = 0;
if (!initialized)
void
dwarf2out_undef (lineno, buffer)
register unsigned lineno ATTRIBUTE_UNUSED;
- register char *buffer ATTRIBUTE_UNUSED;
+ register const char *buffer ATTRIBUTE_UNUSED;
{
}
primary_filename = main_input_filename;
/* Allocate the initial hunk of the file_table. */
- file_table = (char **) xmalloc (FILE_TABLE_INCREMENT * sizeof (char *));
- bzero ((char *) file_table, FILE_TABLE_INCREMENT * sizeof (char *));
+ file_table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *));
file_table_allocated = FILE_TABLE_INCREMENT;
/* Skip the first entry - file numbers begin at 1. */
/* Allocate the initial hunk of the decl_die_table. */
decl_die_table
- = (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
- bzero ((char *) decl_die_table,
- DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+ = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref));
decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT;
decl_die_table_in_use = 0;
/* Allocate the initial hunk of the decl_scope_table. */
decl_scope_table
- = (decl_scope_node *) xmalloc (DECL_SCOPE_TABLE_INCREMENT
- * sizeof (decl_scope_node));
- bzero ((char *) decl_scope_table,
- DECL_SCOPE_TABLE_INCREMENT * sizeof (decl_scope_node));
+ = (decl_scope_node *) xcalloc (DECL_SCOPE_TABLE_INCREMENT,
+ sizeof (decl_scope_node));
decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT;
decl_scope_depth = 0;
/* Allocate the initial hunk of the abbrev_die_table. */
abbrev_die_table
- = (dw_die_ref *) xmalloc (ABBREV_DIE_TABLE_INCREMENT
- * sizeof (dw_die_ref));
- bzero ((char *) abbrev_die_table,
- ABBREV_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
+ = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT,
+ sizeof (dw_die_ref));
abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
abbrev_die_table_in_use = 1;
/* Allocate the initial hunk of the line_info_table. */
line_info_table
- = (dw_line_info_ref) xmalloc (LINE_INFO_TABLE_INCREMENT
- * sizeof (dw_line_info_entry));
- bzero ((char *) line_info_table,
- LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry));
+ = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
+ sizeof (dw_line_info_entry));
line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
/* Zero-th entry is allocated, but unused */
line_info_table_in_use = 1;
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0);
- ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
+ if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+ ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0);
+ else
+ strcpy (text_section_label, stripattributes (TEXT_SECTION));
ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label,
DEBUG_INFO_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label,
ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION);
- ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
+ if (DWARF2_GENERATE_TEXT_SECTION_LABEL)
+ ASM_OUTPUT_LABEL (asm_out_file, text_section_label);
ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
/* Output the source line correspondence table. */
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
- output_line_info ();
+ if (! DWARF2_ASM_LINE_DEBUG_INFO)
+ {
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION);
+ output_line_info ();
+ }
/* We can only use the low/high_pc attributes if all of the code
was in .text. */