#include "dwarf2.h"
#include "dwarf2out.h"
#include "toplev.h"
+#include "dyn-string.h"
/* We cannot use <assert.h> in GCC source, since that would include
GCC's assert.h, which may not be compatible with the host compiler. */
dwarf2out_do_frame ()
{
return (write_symbols == DWARF2_DEBUG
+#ifdef DWARF2_FRAME_INFO
+ || DWARF2_FRAME_INFO
+#endif
#ifdef DWARF2_UNWIND_INFO
|| (flag_exceptions && ! exceptions_via_longjmp)
#endif
} while (0)
#endif
+/* ??? This macro takes an RTX in dwarfout.c and a string in dwarf2out.c.
+ We resolve the conflict by creating a new macro ASM_OUTPUT_DWARF2_ADDR_CONST
+ for ports that want to support both DWARF1 and DWARF2. This needs a better
+ solution. See also the comments in sparc/sp64-elf.h. */
+#ifdef ASM_OUTPUT_DWARF2_ADDR_CONST
+#undef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
+ ASM_OUTPUT_DWARF2_ADDR_CONST (FILE, ADDR)
+#endif
+
#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \
fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR))
}
else
{
+ /* Initialize last_end to be larger than any possible
+ DWARF_FRAME_REGNUM. */
+ int last_end = 0x7fffffff;
--n_ranges;
t = build_int_2 (ranges[n_ranges].size, 0);
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
- for (; n_ranges--; )
+ do
{
- if ((DWARF_FRAME_REGNUM (ranges[n_ranges].end)
- - DWARF_FRAME_REGNUM (ranges[n_ranges].beg))
- != ranges[n_ranges].end - ranges[n_ranges].beg)
+ int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
+ int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end);
+ if (beg < 0)
+ continue;
+ if (end >= last_end)
abort ();
- if (DWARF_FRAME_REGNUM (ranges[n_ranges].beg) >= size)
+ last_end = end;
+ if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg)
abort ();
- size = DWARF_FRAME_REGNUM (ranges[n_ranges].beg);
t2 = fold (build (LE_EXPR, integer_type_node, reg_tree,
- build_int_2 (DWARF_FRAME_REGNUM
- (ranges[n_ranges].end), 0)));
+ build_int_2 (end, 0)));
t = fold (build (COND_EXPR, integer_type_node, t2,
build_int_2 (ranges[n_ranges].size, 0), t));
}
+ while (--n_ranges >= 0);
}
return expand_expr (t, target, Pmode, 0);
}
label = dwarf2out_cfi_label ();
- insn = PATTERN (insn);
+ src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+ if (src)
+ insn = XEXP (src, 0);
+ else
+ insn = PATTERN (insn);
+
/* Assume that in a PARALLEL prologue insn, only the first elt is
significant. Currently this is true. */
if (GET_CODE (insn) == PARALLEL)
{
/* Setting FP from SP. */
case REG:
- if (cfa_reg != REGNO (src))
+ if (cfa_reg != (unsigned) REGNO (src))
abort ();
if (REGNO (dest) != STACK_POINTER_REGNUM
&& !(frame_pointer_needed
offset = INTVAL (XEXP (src, 1));
break;
case REG:
- if (REGNO (XEXP (src, 1)) != cfa_temp_reg)
+ if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg)
abort ();
offset = cfa_temp_value;
break;
if (XEXP (src, 0) == hard_frame_pointer_rtx)
{
/* Restoring SP from FP in the epilogue. */
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
abort ();
cfa_reg = STACK_POINTER_REGNUM;
}
else if (XEXP (src, 0) == hard_frame_pointer_rtx
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
{
- if (cfa_reg != HARD_FRAME_POINTER_REGNUM)
+ if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
abort ();
offset = INTVAL (XEXP (src, 1));
if (GET_CODE (src) == PLUS)
|| XEXP (src, 1) != stack_pointer_rtx)
abort ();
if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg)
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
abort ();
if (cfa_reg != STACK_POINTER_REGNUM)
abort ();
case IOR:
if (GET_CODE (XEXP (src, 0)) != REG
- || REGNO (XEXP (src, 0)) != cfa_temp_reg
- || REGNO (dest) != cfa_temp_reg
+ || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg
+ || (unsigned) REGNO (dest) != cfa_temp_reg
|| GET_CODE (XEXP (src, 1)) != CONST_INT)
abort ();
cfa_temp_value |= INTVAL (XEXP (src, 1));
if (GET_CODE (src) == MINUS)
offset = -offset;
- if (cfa_store_reg != REGNO (XEXP (XEXP (dest, 0), 0)))
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
abort ();
offset -= cfa_store_offset;
break;
+ /* Without an offset. */
+ case REG:
+ if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0)))
+ abort();
+ offset = -cfa_store_offset;
+ break;
+
default:
abort ();
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_LABEL (asm_out_file, l1);
+ /* ??? This always emits a 4 byte offset when for_eh is true, but it
+ emits a target dependent sized offset when for_eh is not true.
+ This inconsistency may confuse gdb. The only case where we need a
+ non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI
+ compatibility if we emit a 4 byte offset. We need a 4 byte offset
+ though in order to be compatible with the dwarf_fde struct in frame.c.
+ If the for_eh case is changed, then the struct in frame.c has
+ to be adjusted appropriately. */
if (for_eh)
- ASM_OUTPUT_DWARF_DELTA (asm_out_file, l1, "__FRAME_BEGIN__");
+ ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l1, "__FRAME_BEGIN__");
else
ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
if (flag_debug_asm)
/* Forward declarations for functions defined in this file. */
-static void addr_const_to_string PROTO((char *, rtx));
+static void addr_const_to_string PROTO((dyn_string_t, rtx));
static char *addr_to_string PROTO((rtx));
static int is_pseudo_reg PROTO((rtx));
static tree type_main_variant PROTO((tree));
macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
a string rather than writing to a file. */
#ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
- do { \
- if ((NAME)[0] == '*') \
- strcpy (STR, NAME+1); \
- else \
- strcpy (STR, NAME); \
- } \
+#define ASM_NAME_TO_STRING(STR, NAME) \
+ do { \
+ if ((NAME)[0] == '*') \
+ dyn_string_append (STR, NAME + 1); \
+ else \
+ { \
+ dyn_string_append (STR, user_label_prefix); \
+ dyn_string_append (STR, NAME); \
+ } \
+ } \
while (0)
#endif
\f
static void
addr_const_to_string (str, x)
- char *str;
+ dyn_string_t str;
rtx x;
{
char buf1[256];
- char buf2[256];
restart:
- str[0] = '\0';
switch (GET_CODE (x))
{
case PC:
if (flag_pic)
- strcat (str, ",");
+ dyn_string_append (str, ",");
else
abort ();
break;
case SYMBOL_REF:
- ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
- strcat (str, buf1);
+ ASM_NAME_TO_STRING (str, XSTR (x, 0));
break;
case LABEL_REF:
ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
+ ASM_NAME_TO_STRING (str, buf1);
break;
case CODE_LABEL:
ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
+ ASM_NAME_TO_STRING (str, buf1);
break;
case CONST_INT:
sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- strcat (str, buf1);
+ dyn_string_append (str, buf1);
break;
case CONST:
/* This used to output parentheses around the expression, but that does
not work on the 386 (either ATT or BSD assembler). */
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
break;
case CONST_DOUBLE:
else
sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
CONST_DOUBLE_LOW (x));
- strcat (str, buf1);
+ dyn_string_append (str, buf1);
}
else
/* We can't handle floating point constants; PRINT_OPERAND must
/* Some assemblers need integer constants to appear last (eg masm). */
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
{
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 1));
if (INTVAL (XEXP (x, 0)) >= 0)
- strcat (str, "+");
+ dyn_string_append (str, "+");
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
}
else
{
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
if (INTVAL (XEXP (x, 1)) >= 0)
- strcat (str, "+");
+ dyn_string_append (str, "+");
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 1));
}
break;
if (GET_CODE (x) != MINUS)
goto restart;
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- strcat (str, "-");
+ addr_const_to_string (str, XEXP (x, 0));
+ dyn_string_append (str, "-");
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) < 0)
{
- strcat (str, ASM_OPEN_PAREN);
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- strcat (str, ASM_CLOSE_PAREN);
+ dyn_string_append (str, ASM_OPEN_PAREN);
+ addr_const_to_string (str, XEXP (x, 1));
+ dyn_string_append (str, ASM_CLOSE_PAREN);
}
else
- {
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- }
+ addr_const_to_string (str, XEXP (x, 1));
break;
case ZERO_EXTEND:
case SIGN_EXTEND:
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
+ addr_const_to_string (str, XEXP (x, 0));
break;
default:
addr_to_string (x)
rtx x;
{
- char buf[1024];
- addr_const_to_string (buf, x);
- return xstrdup (buf);
+ dyn_string_t ds = dyn_string_new (256);
+ char *s;
+
+ addr_const_to_string (ds, x);
+
+ /* Return the dynamically allocated string, but free the
+ dyn_string_t itself. */
+ s = ds->s;
+ free (ds);
+ return s;
}
/* Test if rtl node points to a pseudo register. */
decl_ultimate_origin (decl)
register tree decl;
{
- register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
-
- if (immediate_origin == NULL_TREE)
- return NULL_TREE;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
-
- do
- {
- ret_val = lookahead;
- lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
- }
- while (lookahead != NULL && lookahead != ret_val);
+#ifdef ENABLE_CHECKING
+ if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
+ /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
+ most distant ancestor, this should never happen. */
+ abort ();
+#endif
- return ret_val;
- }
+ return DECL_ABSTRACT_ORIGIN (decl);
}
/* Determine the "ultimate origin" of a block. The block may be an inlined
register unsigned long ref_offset;
register unsigned long size;
register dw_loc_descr_ref loc;
- register int i;
output_uleb128 (die->die_abbrev);
if (flag_debug_asm)
break;
case dw_val_class_float:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- a->dw_attr_val.v.val_float.length * 4);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
- fputc ('\n', asm_out_file);
- for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
- {
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
- a->dw_attr_val.v.val_float.array[i]);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s fp constant word %d",
- ASM_COMMENT_START, i);
+ {
+ register unsigned int i;
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ a->dw_attr_val.v.val_float.length * 4);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
+
+ fputc ('\n', asm_out_file);
+ for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
+ {
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ a->dw_attr_val.v.val_float.array[i]);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s fp constant word %u",
+ ASM_COMMENT_START, i);
- fputc ('\n', asm_out_file);
- }
+ fputc ('\n', asm_out_file);
+ }
break;
+ }
case dw_val_class_flag:
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
else
ASM_OUTPUT_ASCII (asm_out_file,
a->dw_attr_val.v.val_str,
- strlen (a->dw_attr_val.v.val_str) + 1);
+ (int) strlen (a->dw_attr_val.v.val_str) + 1);
break;
default:
}
else
{
- ASM_OUTPUT_ASCII (asm_out_file, pub->name, strlen (pub->name) + 1);
+ ASM_OUTPUT_ASCII (asm_out_file, pub->name,
+ (int) strlen (pub->name) + 1);
}
fputc ('\n', asm_out_file);
ASM_COMMENT_START, 2 * PTR_SIZE);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, stripattributes (TEXT_SECTION));
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label,
+ stripattributes (TEXT_SECTION));
if (flag_debug_asm)
fprintf (asm_out_file, "%s Length", ASM_COMMENT_START);
{
ASM_OUTPUT_ASCII (asm_out_file,
file_table[ft_index],
- strlen (file_table[ft_index]) + 1);
+ (int) strlen (file_table[ft_index]) + 1);
}
fputc ('\n', asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_SECTION);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, stripattributes (TEXT_SECTION));
fputc ('\n', asm_out_file);
/* Generate the line number to PC correspondence table, encoded as
a series of state machine operations. */
current_file = 1;
current_line = 1;
- strcpy (prev_line_label, TEXT_SECTION);
+ strcpy (prev_line_label, stripattributes (TEXT_SECTION));
for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
register dw_line_info_ref line_info;
= lookup_filename (DECL_SOURCE_FILE (decl));
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
- abort ();
+ {
+ /* ??? This can happen if there is a bug in the program, for
+ instance, if it has duplicate function definitions. Ideally,
+ 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 ();
+ }
/* If the definition comes from the same place as the declaration,
maybe use the old DIE. We always want the DIE for this function
}
/* Generate all of the decls declared within a given scope and (recursively)
- all of it's sub-blocks. */
+ all of its sub-blocks. */
static void
decls_for_scope (stmt, context_die, depth)
if (DECL_IGNORED_P (decl))
{
if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl) != NULL)
+ && DECL_INITIAL (decl) != NULL)
abort ();
return;
was in .text. */
if (separate_line_info_table_in_use == 0)
{
- add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, TEXT_SECTION);
+ add_AT_lbl_id (comp_unit_die, DW_AT_low_pc,
+ stripattributes (TEXT_SECTION));
add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label);
}