unsigned long dw_cfi_reg_num;
long int dw_cfi_offset;
const char *dw_cfi_addr;
+ struct dw_loc_descr_struct *dw_cfi_loc;
}
dw_cfi_oprnd;
}
dw_cfi_node;
+/* This is how we define the location of the CFA. We use to handle it
+ as REG + OFFSET all the time, but now it can be more complex.
+ It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
+ Instead of passing around REG and OFFSET, we pass a copy
+ of this structure. */
+typedef struct cfa_loc
+{
+ unsigned long reg;
+ long offset;
+ long base_offset;
+ int indirect; /* 1 if CFA is accessed via a dereference. */
+} dw_cfa_location;
+
/* All call frame descriptions (FDE's) in the GCC generated DWARF
refer to a single Common Information Entry (CIE), defined at
the beginning of the .debug_frame section. This used of a single
static void output_uleb128 PARAMS ((unsigned long));
static void output_sleb128 PARAMS ((long));
static void add_fde_cfi PARAMS ((const char *, dw_cfi_ref));
-static void lookup_cfa_1 PARAMS ((dw_cfi_ref, unsigned long *,
- long *));
-static void lookup_cfa PARAMS ((unsigned long *, long *));
+static void lookup_cfa_1 PARAMS ((dw_cfi_ref, dw_cfa_location *));
+static void lookup_cfa PARAMS ((dw_cfa_location *));
static void reg_save PARAMS ((const char *, unsigned,
unsigned, long));
static void initial_return_save PARAMS ((rtx));
static void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref));
static void output_call_frame_info PARAMS ((int));
-static unsigned int reg_number PARAMS ((rtx));
static void dwarf2out_stack_adjust PARAMS ((rtx));
static void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *));
+/* Support for complex CFA locations. */
+static void output_cfa_loc PARAMS ((dw_cfi_ref));
+static void get_cfa_from_loc_descr PARAMS ((dw_cfa_location *,
+ struct dw_loc_descr_struct *));
+static struct dw_loc_descr_struct *build_cfa_loc
+ PARAMS ((dw_cfa_location *));
+static void def_cfa_1 PARAMS ((const char *, dw_cfa_location *));
+
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
Theses may be overridden in the tm.h file (if necessary) for a particular
fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) (VALUE))
#endif
+#ifndef ASM_OUTPUT_DWARF_DATA8
+#define ASM_OUTPUT_DWARF_DATA8(FILE,VALUE) \
+ fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_DOUBLE_INT_ASM_OP, \
+ (unsigned long) (VALUE))
+#endif
+
#ifndef ASM_OUTPUT_DWARF_DATA
#define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \
(unsigned long) (VALUE))
#endif
-#ifndef ASM_OUTPUT_DWARF_DATA8
-#define ASM_OUTPUT_DWARF_DATA8(FILE,HIGH_VALUE,LOW_VALUE) \
+#ifndef ASM_OUTPUT_DWARF_CONST_DOUBLE
+#define ASM_OUTPUT_DWARF_CONST_DOUBLE(FILE,HIGH_VALUE,LOW_VALUE) \
do { \
if (WORDS_BIG_ENDIAN) \
{ \
/* We don't have unaligned support, let's hope the normal output works for
.debug_frame. */
+#ifndef ASM_OUTPUT_DWARF_ADDR
#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, LABEL), DWARF2_ADDR_SIZE, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
+#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) ASM_OUTPUT_DWARF_ADDR (FILE,RTX)
+#endif
+
+#ifndef ASM_OUTPUT_DWARF_OFFSET4
#define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \
assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_OFFSET
#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \
assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_DELTA2
#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)), \
2, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_DELTA4
#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)), \
4, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_ADDR_DELTA
#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)), \
DWARF2_ADDR_SIZE, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_DELTA
#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \
ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2)
+#endif
+
+#ifndef ASM_OUTPUT_DWARF_DATA2
+#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
+ assemble_integer (GEN_INT (VALUE), 2, 1)
+#endif
+#ifndef ASM_OUTPUT_DWARF_DATA4
#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
assemble_integer (GEN_INT (VALUE), 4, 1)
+#endif
#endif /* UNALIGNED_INT_ASM_OP */
return stripped;
}
-/* Return the register number described by a given RTL node. */
-
-static unsigned int
-reg_number (rtl)
- register rtx rtl;
-{
- register unsigned regno = REGNO (rtl);
-
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- warning ("internal regno botch: regno = %d\n", regno);
- regno = 0;
- }
-
- regno = DBX_REGISTER_NUMBER (regno);
- return regno;
-}
-
/* Generate code to initialize the register size table. */
void
for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
{
- int offset = i * GET_MODE_SIZE (mode);
+ int offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode);
int size = GET_MODE_SIZE (reg_raw_mode[i]);
+ if (offset < 0)
+ continue;
+
emit_move_insn (change_address (mem, mode,
plus_constant (addr, offset)),
GEN_INT (size));
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+ case DW_CFA_def_cfa_expression:
+ return "DW_CFA_def_cfa_expression";
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
/* Subroutine of lookup_cfa. */
static inline void
-lookup_cfa_1 (cfi, regp, offsetp)
+lookup_cfa_1 (cfi, loc)
register dw_cfi_ref cfi;
- register unsigned long *regp;
- register long *offsetp;
+ register dw_cfa_location *loc;
{
switch (cfi->dw_cfi_opc)
{
case DW_CFA_def_cfa_offset:
- *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
+ loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset;
break;
case DW_CFA_def_cfa_register:
- *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+ loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
break;
case DW_CFA_def_cfa:
- *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
- *offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+ loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
+ loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset;
+ break;
+ case DW_CFA_def_cfa_expression:
+ get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
break;
default:
break;
/* Find the previous value for the CFA. */
static void
-lookup_cfa (regp, offsetp)
- register unsigned long *regp;
- register long *offsetp;
+lookup_cfa (loc)
+ register dw_cfa_location *loc;
{
register dw_cfi_ref cfi;
- *regp = (unsigned long) -1;
- *offsetp = 0;
+ loc->reg = (unsigned long) -1;
+ loc->offset = 0;
+ loc->indirect = 0;
+ loc->base_offset = 0;
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, regp, offsetp);
+ lookup_cfa_1 (cfi, loc);
if (fde_table_in_use)
{
register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, regp, offsetp);
+ lookup_cfa_1 (cfi, loc);
}
}
/* The current rule for calculating the DWARF2 canonical frame address. */
-static unsigned long cfa_reg;
-static long cfa_offset;
+dw_cfa_location cfa;
/* The register used for saving registers to the stack, and its offset
from the CFA. */
-static unsigned cfa_store_reg;
-static long cfa_store_offset;
+dw_cfa_location cfa_store;
/* The running total of the size of arguments pushed onto the stack. */
static long args_size;
void
dwarf2out_def_cfa (label, reg, offset)
register const char *label;
- register unsigned reg;
- register long offset;
+ unsigned reg;
+ long offset;
+{
+ dw_cfa_location loc;
+ loc.indirect = 0;
+ loc.base_offset = 0;
+ loc.reg = reg;
+ loc.offset = offset;
+ def_cfa_1 (label, &loc);
+}
+
+/* This routine does the actual work. The CFA is now calculated from
+ the dw_cfa_location structure. */
+static void
+def_cfa_1 (label, loc_p)
+ register const char *label;
+ dw_cfa_location *loc_p;
{
register dw_cfi_ref cfi;
- unsigned long old_reg;
- long old_offset;
+ dw_cfa_location old_cfa, loc;
- cfa_reg = reg;
- cfa_offset = offset;
- if (cfa_store_reg == reg)
- cfa_store_offset = offset;
+ cfa = *loc_p;
+ loc = *loc_p;
- reg = DWARF_FRAME_REGNUM (reg);
- lookup_cfa (&old_reg, &old_offset);
+ if (cfa_store.reg == loc.reg && loc.indirect == 0)
+ cfa_store.offset = loc.offset;
- if (reg == old_reg && offset == old_offset)
- return;
+ loc.reg = DWARF_FRAME_REGNUM (loc.reg);
+ lookup_cfa (&old_cfa);
+
+ if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset &&
+ loc.indirect == old_cfa.indirect)
+ {
+ if (loc.indirect == 0)
+ return;
+ else
+ if (loc.base_offset == old_cfa.base_offset)
+ return;
+ }
cfi = new_cfi ();
- if (reg == old_reg)
+ if (loc.reg == old_cfa.reg && loc.indirect == old_cfa.indirect)
{
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
- cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
+ cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset;
}
#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
- else if (offset == old_offset && old_reg != (unsigned long) -1)
+ else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1
+ && loc.indirect == old_cfa.indirect)
{
cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
}
#endif
- else
+ else if (loc.indirect == 0)
{
cfi->dw_cfi_opc = DW_CFA_def_cfa;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
- cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg;
+ cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset;
+ }
+ else
+ {
+ struct dw_loc_descr_struct * loc_list;
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_expression;
+ loc_list = build_cfa_loc (&loc);
+ cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list;
}
add_fde_cfi (label, cfi);
abort ();
}
- reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset);
+ reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset);
}
/* Check INSN to see if it looks like a push or a stack adjustment, and
/* If only calls can throw, and we have a frame pointer,
save up adjustments until we see the CALL_INSN. */
else if (! asynchronous_exceptions
- && cfa_reg != STACK_POINTER_REGNUM)
+ && cfa.reg != STACK_POINTER_REGNUM)
return;
if (GET_CODE (insn) == BARRIER)
if (offset == 0)
return;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset += offset;
+ if (cfa.reg == STACK_POINTER_REGNUM)
+ cfa.offset += offset;
#ifndef STACK_GROWS_DOWNWARD
offset = -offset;
args_size = 0;
label = dwarf2out_cfi_label ();
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ def_cfa_1 (label, &cfa);
dwarf2out_args_size (label, args_size);
}
/* A temporary value used in adjusting SP or setting up the store_reg. */
static long cfa_temp_value;
+/* If we see a store of the CFA register, remember it in case we later also
+ copy it into another register. The ARM saves the old SP in the stack,
+ but it also has a usable FP. */
+static unsigned cfa_old_reg;
+
/* Record call frame debugging information for an expression, which either
sets SP or FP (adjusting how we calculate the frame address) or saves a
register to the stack. */
{
/* Setting FP from SP. */
case REG:
- if (cfa_reg != (unsigned) REGNO (src))
+ if (cfa.reg == (unsigned) REGNO (src)
+ || (cfa.indirect && cfa_old_reg == (unsigned) REGNO (src)))
+ /* OK */;
+ else
abort ();
/* We used to require that dest be either SP or FP, but the
ARM copies SP to a temporary register, and from there to
FP. So we just rely on the backends to only set
RTX_FRAME_RELATED_P on appropriate insns. */
- cfa_reg = REGNO (dest);
+ cfa.reg = REGNO (dest);
+ cfa.indirect = 0;
break;
case PLUS:
if (XEXP (src, 0) == hard_frame_pointer_rtx)
{
/* Restoring SP from FP in the epilogue. */
- if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
+ if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM)
abort ();
- cfa_reg = STACK_POINTER_REGNUM;
+ cfa.reg = STACK_POINTER_REGNUM;
}
else if (XEXP (src, 0) != stack_pointer_rtx)
abort ();
if (GET_CODE (src) == PLUS)
offset = -offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset += offset;
- if (cfa_store_reg == STACK_POINTER_REGNUM)
- cfa_store_offset += offset;
+ if (cfa.reg == STACK_POINTER_REGNUM)
+ cfa.offset += offset;
+ if (cfa_store.reg == STACK_POINTER_REGNUM)
+ cfa_store.offset += offset;
}
else if (dest == hard_frame_pointer_rtx)
{
abort ();
if (GET_CODE (XEXP (src, 0)) == REG
- && (unsigned) REGNO (XEXP (src, 0)) == cfa_reg
+ && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
{
offset = INTVAL (XEXP (src, 1));
if (GET_CODE (src) == PLUS)
offset = -offset;
- cfa_offset += offset;
- cfa_reg = HARD_FRAME_POINTER_REGNUM;
+ cfa.offset += offset;
+ cfa.reg = HARD_FRAME_POINTER_REGNUM;
}
else
abort();
if (GET_CODE (XEXP (src, 0)) != REG
|| (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg)
abort ();
- if (cfa_reg != STACK_POINTER_REGNUM)
+ if (cfa.reg != STACK_POINTER_REGNUM)
abort ();
- cfa_store_reg = REGNO (dest);
- cfa_store_offset = cfa_offset - cfa_temp_value;
+ cfa_store.reg = REGNO (dest);
+ cfa_store.offset = cfa.offset - cfa_temp_value;
}
break;
default:
abort ();
}
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ def_cfa_1 (label, &cfa);
+ break;
+
+ /* Skip over HIGH, assuming it will be followed by a LO_SUM, which
+ will fill in all of the bits. */
+ case HIGH:
+ break;
+
+ case LO_SUM:
+ cfa_temp_reg = REGNO (dest);
+ cfa_temp_value = INTVAL (XEXP (src, 1));
break;
case MEM:
- /* Saving a register to the stack. Make sure dest is relative to the
- CFA register. */
if (GET_CODE (src) != REG)
abort ();
+
+ /* If the src is our current CFA, and it isn't the SP or FP, then we're
+ going to have to use an indrect mechanism. */
+ if (REGNO (src) != STACK_POINTER_REGNUM
+ && REGNO (src) != HARD_FRAME_POINTER_REGNUM
+ && (unsigned) REGNO (src) == cfa.reg
+ /* Temporary KLUDGE to make ARM work. */
+ && GET_CODE (XEXP (dest, 0)) != PRE_DEC)
+ {
+ /* We currently allow this to be ONLY a MEM or MEM + offset. */
+ rtx x = XEXP (dest, 0);
+ int offset = 0;
+ if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS)
+ {
+ offset = INTVAL (XEXP (x, 1));
+ if (GET_CODE (x) == MINUS)
+ offset = -offset;
+ x = XEXP (x, 0);
+ }
+ if (GET_CODE (x) != REG)
+ abort ();
+ cfa_old_reg = cfa.reg;
+ cfa.reg = (unsigned) REGNO (x);
+ cfa.base_offset = offset;
+ cfa.indirect = 1;
+ def_cfa_1 (label, &cfa);
+ break;
+ }
+
+ /* Saving a register to the stack. Make sure dest is relative to the
+ CFA register. */
switch (GET_CODE (XEXP (dest, 0)))
{
/* With a push. */
offset = -offset;
if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
- || cfa_store_reg != STACK_POINTER_REGNUM)
+ || cfa_store.reg != STACK_POINTER_REGNUM)
abort ();
- cfa_store_offset += offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset = cfa_store_offset;
+ cfa_store.offset += offset;
+ if (cfa.reg == STACK_POINTER_REGNUM)
+ cfa.offset = cfa_store.offset;
- offset = -cfa_store_offset;
+ offset = -cfa_store.offset;
break;
/* With an offset. */
if (GET_CODE (XEXP (dest, 0)) == MINUS)
offset = -offset;
- if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
+ if (cfa_store.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0)))
abort ();
- offset -= cfa_store_offset;
+ offset -= cfa_store.offset;
break;
/* Without an offset. */
case REG:
- if (cfa_store_reg != REGNO (XEXP (dest, 0)))
+ if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0)))
abort();
- offset = -cfa_store_offset;
+ offset = -cfa_store.offset;
break;
default:
abort ();
}
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ def_cfa_1 (label, &cfa);
dwarf2out_reg_save (label, REGNO (src), offset);
break;
if (insn == NULL_RTX)
{
/* Set up state for generating call frame debug info. */
- lookup_cfa (&cfa_reg, &cfa_offset);
- if (cfa_reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
+ lookup_cfa (&cfa);
+ if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM))
abort ();
- cfa_reg = STACK_POINTER_REGNUM;
- cfa_store_reg = cfa_reg;
- cfa_store_offset = cfa_offset;
+ cfa.reg = STACK_POINTER_REGNUM;
+ cfa_store = cfa;
cfa_temp_reg = -1;
cfa_temp_value = 0;
return;
output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
fputc ('\n', asm_out_file);
break;
+ case DW_CFA_def_cfa_expression:
+ output_cfa_loc (cfi);
+ break;
default:
break;
}
output_call_frame_info (1);
#endif
}
+\f
+/* And now, the subset of the debugging information support code necessary
+ for emitting location expressions. */
-#endif /* .debug_frame support */
-
-/* And now, the support for symbolic debugging information. */
-#ifdef DWARF2_DEBUGGING_INFO
-
-/* 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. */
-
-/* An internal representation of the DWARF output is built, and then
- walked to generate the DWARF debugging info. The walk of the internal
- representation is done after the entire program has been compiled.
- The types below are used to describe the internal representation. */
+typedef struct dw_val_struct *dw_val_ref;
+typedef struct die_struct *dw_die_ref;
+typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
/* Each DIE may have a series of attribute/value pairs. Values
can take on several forms. The forms that are used in this
}
dw_val_class;
-/* Various DIE's use offsets relative to the beginning of the
- .debug_info section to refer to each other. */
-
-typedef long int dw_offset;
-
-/* Define typedefs here to avoid circular dependencies. */
-
-typedef struct die_struct *dw_die_ref;
-typedef struct dw_attr_struct *dw_attr_ref;
-typedef struct dw_val_struct *dw_val_ref;
-typedef struct dw_line_info_struct *dw_line_info_ref;
-typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
-typedef struct dw_loc_descr_struct *dw_loc_descr_ref;
-typedef struct pubname_struct *pubname_ref;
-typedef dw_die_ref *arange_ref;
-
/* Describe a double word constant value. */
+/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */
typedef struct dw_long_long_struct
{
}
dw_float_const;
-/* Each entry in the line_info_table maintains the file and
- line number associated with the label generated for that
- entry. The label gives the PC value associated with
- the line number entry. */
-
-typedef struct dw_line_info_struct
-{
- unsigned long dw_file_num;
- unsigned long dw_line_num;
-}
-dw_line_info_entry;
-
-/* Line information for functions in separate sections; each one gets its
- own sequence. */
-typedef struct dw_separate_line_info_struct
-{
- unsigned long dw_file_num;
- unsigned long dw_line_num;
- unsigned long function;
-}
-dw_separate_line_info_entry;
-
/* The dw_val_node describes an attribute's value, as it is
represented internally. */
}
dw_loc_descr_node;
-/* Each DIE attribute has a field specifying the attribute kind,
- a link to the next attribute in the chain, and an attribute value.
- Attributes are typically linked below the DIE they modify. */
-
-typedef struct dw_attr_struct
-{
- enum dwarf_attribute dw_attr;
- dw_attr_ref dw_attr_next;
- dw_val_node dw_attr_val;
-}
-dw_attr_node;
-
-/* The Debugging Information Entry (DIE) structure */
-
-typedef struct die_struct
-{
- enum dwarf_tag die_tag;
- dw_attr_ref die_attr;
- dw_die_ref die_parent;
- dw_die_ref die_child;
- dw_die_ref die_sib;
- dw_offset die_offset;
- unsigned long die_abbrev;
-}
-die_node;
-
-/* The pubname structure */
+static const char *dwarf_stack_op_name PARAMS ((unsigned));
+static dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom,
+ unsigned long,
+ unsigned long));
+static void add_loc_descr PARAMS ((dw_loc_descr_ref *,
+ dw_loc_descr_ref));
+static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref));
+static unsigned long size_of_locs PARAMS ((dw_loc_descr_ref));
+static void output_loc_operands PARAMS ((dw_loc_descr_ref));
+static void output_loc_sequence PARAMS ((dw_loc_descr_ref));
-typedef struct pubname_struct
-{
- dw_die_ref die;
- char * name;
-}
-pubname_entry;
+/* Convert a DWARF stack opcode into its string name. */
-/* The limbo die list structure. */
-typedef struct limbo_die_struct
+static const char *
+dwarf_stack_op_name (op)
+ register unsigned op;
{
- dw_die_ref die;
- struct limbo_die_struct *next;
-}
-limbo_die_node;
-
-/* How to start an assembler comment. */
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START ";#"
-#endif
-
-/* Define a macro which returns non-zero for a TYPE_DECL which was
- implicitly generated for a tagged type.
-
- Note that unlike the gcc front end (which generates a NULL named
- TYPE_DECL node for each complete tagged type, each array type, and
- each function type node created) the g++ front end generates a
- _named_ TYPE_DECL node for each tagged type node created.
- These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
- generate a DW_TAG_typedef DIE for them. */
-
-#define TYPE_DECL_IS_STUB(decl) \
- (DECL_NAME (decl) == NULL_TREE \
- || (DECL_ARTIFICIAL (decl) \
- && is_tagged_type (TREE_TYPE (decl)) \
- && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
- /* This is necessary for stub decls that \
- appear in nested inline functions. */ \
- || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
- && (decl_ultimate_origin (decl) \
- == TYPE_STUB_DECL (TREE_TYPE (decl)))))))
-
-/* Information concerning the compilation unit's programming
- language, and compiler version. */
-
-extern int flag_traditional;
-
-/* Fixed size portion of the DWARF compilation unit header. */
-#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
-
-/* Fixed size portion of debugging line information prolog. */
-#define DWARF_LINE_PROLOG_HEADER_SIZE 5
-
-/* Fixed size portion of public names info. */
-#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
-
-/* Fixed size portion of the address range info. */
-#define DWARF_ARANGES_HEADER_SIZE \
- (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
- - DWARF_OFFSET_SIZE)
-
-/* Size of padding portion in the address range info. It must be
- aligned to twice the pointer size. */
-#define DWARF_ARANGES_PAD_SIZE \
- (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
- - (2 * DWARF_OFFSET_SIZE + 4))
-
-/* 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
- no a priori knowledge of how many instruction bytes are generated
- for each source line, and therefore can use only the DW_LNE_set_address
- and DW_LNS_fixed_advance_pc line information commands. */
-
-#ifndef DWARF_LINE_MIN_INSTR_LENGTH
-#define DWARF_LINE_MIN_INSTR_LENGTH 4
-#endif
-
-/* Minimum line offset in a special line info. opcode.
- This value was chosen to give a reasonable range of values. */
-#define DWARF_LINE_BASE -10
-
-/* First special line opcde - leave room for the standard opcodes. */
-#define DWARF_LINE_OPCODE_BASE 10
-
-/* Range of line offsets in a special line info. opcode. */
-#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1)
-
-/* Flag that indicates the initial value of the is_stmt_start flag.
- In the present implementation, we do not mark any lines as
- the beginning of a source statement, because that information
- is not made available by the GCC front-end. */
-#define DWARF_LINE_DEFAULT_IS_STMT_START 1
-
-/* This location is used by calc_die_sizes() to keep track
- the offset of each DIE within the .debug_info section. */
-static unsigned long next_die_offset;
-
-/* Record the root of the DIE's built for the current compilation unit. */
-static dw_die_ref comp_unit_die;
-
-/* A list of DIEs with a NULL parent waiting to be relocated. */
-static limbo_die_node *limbo_die_list = 0;
-
-/* Pointer to an array of filenames referenced by this compilation unit. */
-static char **file_table;
-
-/* Total number of entries in the table (i.e. array) pointed to by
- `file_table'. This is the *total* and includes both used and unused
- slots. */
-static unsigned file_table_allocated;
-
-/* Number of entries in the file_table which are actually in use. */
-static unsigned file_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the filename
- table. */
-#define FILE_TABLE_INCREMENT 64
-
-/* Local pointer to the name of the main input file. Initialized in
- dwarf2out_init. */
-static const char *primary_filename;
-
-/* A pointer to the base of a table of references to DIE's that describe
- declarations. The table is indexed by DECL_UID() which is a unique
- number identifying each decl. */
-static dw_die_ref *decl_die_table;
-
-/* Number of elements currently allocated for the decl_die_table. */
-static unsigned decl_die_table_allocated;
-
-/* Number of elements in decl_die_table currently in use. */
-static unsigned decl_die_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- decl_die_table. */
-#define DECL_DIE_TABLE_INCREMENT 256
-
-/* A pointer to the base of a table of references to declaration
- scopes. This table is a display which tracks the nesting
- of declaration scopes at the current scope and containing
- scopes. This table is used to find the proper place to
- define type declaration DIE's. */
-static tree *decl_scope_table;
-
-/* Number of elements currently allocated for the decl_scope_table. */
-static int decl_scope_table_allocated;
-
-/* Current level of nesting of declaration scopes. */
-static int decl_scope_depth;
-
-/* Size (in elements) of increments by which we may expand the
- decl_scope_table. */
-#define DECL_SCOPE_TABLE_INCREMENT 64
-
-/* A pointer to the base of a list of references to DIE's that
- are uniquely identified by their tag, presence/absence of
- children DIE's, and list of attribute/value pairs. */
-static dw_die_ref *abbrev_die_table;
-
-/* Number of elements currently allocated for abbrev_die_table. */
-static unsigned abbrev_die_table_allocated;
-
-/* Number of elements in type_die_table currently in use. */
-static unsigned abbrev_die_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- abbrev_die_table. */
-#define ABBREV_DIE_TABLE_INCREMENT 256
-
-/* A pointer to the base of a table that contains line information
- for each source code line in .text in the compilation unit. */
-static dw_line_info_ref line_info_table;
-
-/* Number of elements currently allocated for line_info_table. */
-static unsigned line_info_table_allocated;
-
-/* Number of elements in separate_line_info_table currently in use. */
-static unsigned separate_line_info_table_in_use;
-
-/* A pointer to the base of a table that contains line information
- for each source code line outside of .text in the compilation unit. */
-static dw_separate_line_info_ref separate_line_info_table;
-
-/* Number of elements currently allocated for separate_line_info_table. */
-static unsigned separate_line_info_table_allocated;
-
-/* Number of elements in line_info_table currently in use. */
-static unsigned line_info_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- line_info_table. */
-#define LINE_INFO_TABLE_INCREMENT 1024
-
-/* A pointer to the base of a table that contains a list of publicly
- accessible names. */
-static pubname_ref pubname_table;
-
-/* Number of elements currently allocated for pubname_table. */
-static unsigned pubname_table_allocated;
-
-/* Number of elements in pubname_table currently in use. */
-static unsigned pubname_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- pubname_table. */
-#define PUBNAME_TABLE_INCREMENT 64
-
-/* A pointer to the base of a table that contains a list of publicly
- accessible names. */
-static arange_ref arange_table;
-
-/* Number of elements currently allocated for arange_table. */
-static unsigned arange_table_allocated;
-
-/* Number of elements in arange_table currently in use. */
-static unsigned arange_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- arange_table. */
-#define ARANGE_TABLE_INCREMENT 64
-
-/* A pointer to the base of a list of incomplete types which might be
- completed at some later time. */
-
-static tree *incomplete_types_list;
-
-/* Number of elements currently allocated for the incomplete_types_list. */
-static unsigned incomplete_types_allocated;
-
-/* Number of elements of incomplete_types_list currently in use. */
-static unsigned incomplete_types;
-
-/* Size (in elements) of increments by which we may expand the incomplete
- types list. Actually, a single hunk of space of this size should
- be enough for most typical programs. */
-#define INCOMPLETE_TYPES_INCREMENT 64
-
-/* Record whether the function being analyzed contains inlined functions. */
-static int current_function_has_inlines;
-#if 0 && defined (MIPS_DEBUGGING_INFO)
-static int comp_unit_has_inlines;
-#endif
-
-/* Array of RTXes referenced by the debugging information, which therefore
- must be kept around forever. We do this rather than perform GC on
- the dwarf info because almost all of the dwarf info lives forever, and
- it's easier to support non-GC frontends this way. */
-static varray_type used_rtx_varray;
-
-/* Forward declarations for functions defined in this file. */
-
-static int is_pseudo_reg PARAMS ((rtx));
-static tree type_main_variant PARAMS ((tree));
-static int is_tagged_type PARAMS ((tree));
-static const char *dwarf_tag_name PARAMS ((unsigned));
-static const char *dwarf_attr_name PARAMS ((unsigned));
-static const char *dwarf_form_name PARAMS ((unsigned));
-static const char *dwarf_stack_op_name PARAMS ((unsigned));
-#if 0
-static const char *dwarf_type_encoding_name PARAMS ((unsigned));
-#endif
-static tree decl_ultimate_origin PARAMS ((tree));
-static tree block_ultimate_origin PARAMS ((tree));
-static tree decl_class_context PARAMS ((tree));
-static void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref));
-static void add_AT_flag PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- unsigned));
-static void add_AT_int PARAMS ((dw_die_ref,
- enum dwarf_attribute, long));
-static void add_AT_unsigned PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- unsigned long));
-static void add_AT_long_long PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- unsigned long,
- unsigned long));
-static void add_AT_float PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- unsigned, long *));
-static void add_AT_string PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- const char *));
-static void add_AT_die_ref PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- dw_die_ref));
-static void add_AT_fde_ref PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- unsigned));
-static void add_AT_loc PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- dw_loc_descr_ref));
-static void add_AT_addr PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- rtx));
-static void add_AT_lbl_id PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- const char *));
-static void add_AT_lbl_offset PARAMS ((dw_die_ref,
- enum dwarf_attribute,
- const char *));
-static dw_attr_ref get_AT PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static const char *get_AT_low_pc PARAMS ((dw_die_ref));
-static const char *get_AT_hi_pc PARAMS ((dw_die_ref));
-static const char *get_AT_string PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static int get_AT_flag PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static unsigned get_AT_unsigned PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static int is_c_family PARAMS ((void));
-static int is_fortran PARAMS ((void));
-static void remove_AT PARAMS ((dw_die_ref,
- enum dwarf_attribute));
-static void remove_children PARAMS ((dw_die_ref));
-static void add_child_die PARAMS ((dw_die_ref, dw_die_ref));
-static dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref));
-static dw_die_ref lookup_type_die PARAMS ((tree));
-static void equate_type_number_to_die PARAMS ((tree, dw_die_ref));
-static dw_die_ref lookup_decl_die PARAMS ((tree));
-static void equate_decl_number_to_die PARAMS ((tree, dw_die_ref));
-static dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom,
- unsigned long,
- unsigned long));
-static void add_loc_descr PARAMS ((dw_loc_descr_ref *,
- dw_loc_descr_ref));
-static void print_spaces PARAMS ((FILE *));
-static void print_die PARAMS ((dw_die_ref, FILE *));
-static void print_dwarf_line_table PARAMS ((FILE *));
-static void add_sibling_attributes PARAMS ((dw_die_ref));
-static void build_abbrev_table PARAMS ((dw_die_ref));
-static unsigned long size_of_string PARAMS ((const char *));
-static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref));
-static unsigned long size_of_locs PARAMS ((dw_loc_descr_ref));
-static int constant_size PARAMS ((long unsigned));
-static unsigned long size_of_die PARAMS ((dw_die_ref));
-static void calc_die_sizes PARAMS ((dw_die_ref));
-static unsigned long size_of_line_prolog PARAMS ((void));
-static unsigned long size_of_pubnames PARAMS ((void));
-static unsigned long size_of_aranges PARAMS ((void));
-static enum dwarf_form value_format PARAMS ((dw_attr_ref));
-static void output_value_format PARAMS ((dw_attr_ref));
-static void output_abbrev_section PARAMS ((void));
-static void output_loc_operands PARAMS ((dw_loc_descr_ref));
-static void output_die PARAMS ((dw_die_ref));
-static void output_compilation_unit_header PARAMS ((void));
-static const char *dwarf2_name PARAMS ((tree, int));
-static void add_pubname PARAMS ((tree, dw_die_ref));
-static void output_pubnames PARAMS ((void));
-static void add_arange PARAMS ((tree, dw_die_ref));
-static void output_aranges PARAMS ((void));
-static void output_line_info PARAMS ((void));
-static dw_die_ref base_type_die PARAMS ((tree));
-static tree root_type PARAMS ((tree));
-static int is_base_type PARAMS ((tree));
-static dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref));
-static int type_is_enum PARAMS ((tree));
-static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
-static dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long));
-static int is_based_loc PARAMS ((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
-static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
-static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
-static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int));
-static tree field_type PARAMS ((tree));
-static unsigned int simple_type_align_in_bits PARAMS ((tree));
-static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
-static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
-static void add_AT_location_description PARAMS ((dw_die_ref,
- enum dwarf_attribute, rtx));
-static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
-static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
-static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
-static void add_name_attribute PARAMS ((dw_die_ref, const char *));
-static void add_bound_info PARAMS ((dw_die_ref,
- enum dwarf_attribute, tree));
-static void add_subscript_info PARAMS ((dw_die_ref, tree));
-static void add_byte_size_attribute PARAMS ((dw_die_ref, tree));
-static void add_bit_offset_attribute PARAMS ((dw_die_ref, tree));
-static void add_bit_size_attribute PARAMS ((dw_die_ref, tree));
-static void add_prototyped_attribute PARAMS ((dw_die_ref, tree));
-static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree));
-static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree));
-static void add_src_coords_attributes PARAMS ((dw_die_ref, tree));
-static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree));
-static void push_decl_scope PARAMS ((tree));
-static dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref));
-static void pop_decl_scope PARAMS ((void));
-static void add_type_attribute PARAMS ((dw_die_ref, tree, int, int,
- dw_die_ref));
-static const char *type_tag PARAMS ((tree));
-static tree member_declared_type PARAMS ((tree));
-#if 0
-static const char *decl_start_label PARAMS ((tree));
-#endif
-static void gen_array_type_die PARAMS ((tree, dw_die_ref));
-static void gen_set_type_die PARAMS ((tree, dw_die_ref));
-#if 0
-static void gen_entry_point_die PARAMS ((tree, dw_die_ref));
-#endif
-static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_enumeration_type_die PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref));
-static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref));
-static void gen_formal_types_die PARAMS ((tree, dw_die_ref));
-static void gen_subprogram_die PARAMS ((tree, dw_die_ref));
-static void gen_variable_die PARAMS ((tree, dw_die_ref));
-static void gen_label_die PARAMS ((tree, dw_die_ref));
-static void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int));
-static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int));
-static void gen_field_die PARAMS ((tree, dw_die_ref));
-static void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref));
-static dw_die_ref gen_compile_unit_die PARAMS ((const char *));
-static void gen_string_type_die PARAMS ((tree, dw_die_ref));
-static void gen_inheritance_die PARAMS ((tree, dw_die_ref));
-static void gen_member_die PARAMS ((tree, dw_die_ref));
-static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
-static void gen_subroutine_type_die PARAMS ((tree, dw_die_ref));
-static void gen_typedef_die PARAMS ((tree, dw_die_ref));
-static void gen_type_die PARAMS ((tree, dw_die_ref));
-static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref));
-static void gen_block_die PARAMS ((tree, dw_die_ref, int));
-static void decls_for_scope PARAMS ((tree, dw_die_ref, int));
-static int is_redundant_typedef PARAMS ((tree));
-static void gen_decl_die PARAMS ((tree, dw_die_ref));
-static unsigned lookup_filename PARAMS ((const char *));
-static void add_incomplete_type PARAMS ((tree));
-static void retry_incomplete_types PARAMS ((void));
-static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
-static void gen_abstract_function PARAMS ((tree));
-static rtx save_rtx PARAMS ((rtx));
-static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
-static void reverse_die_lists PARAMS ((dw_die_ref));
-
-/* Section names used to hold DWARF debugging information. */
-#ifndef DEBUG_INFO_SECTION
-#define DEBUG_INFO_SECTION ".debug_info"
-#endif
-#ifndef ABBREV_SECTION
-#define ABBREV_SECTION ".debug_abbrev"
-#endif
-#ifndef ARANGES_SECTION
-#define ARANGES_SECTION ".debug_aranges"
-#endif
-#ifndef DW_MACINFO_SECTION
-#define DW_MACINFO_SECTION ".debug_macinfo"
-#endif
-#ifndef DEBUG_LINE_SECTION
-#define DEBUG_LINE_SECTION ".debug_line"
-#endif
-#ifndef LOC_SECTION
-#define LOC_SECTION ".debug_loc"
-#endif
-#ifndef PUBNAMES_SECTION
-#define PUBNAMES_SECTION ".debug_pubnames"
-#endif
-#ifndef STR_SECTION
-#define STR_SECTION ".debug_str"
-#endif
-
-/* Standard ELF section names for compiled code and data. */
-#ifndef TEXT_SECTION
-#define TEXT_SECTION ".text"
-#endif
-#ifndef DATA_SECTION
-#define DATA_SECTION ".data"
-#endif
-#ifndef BSS_SECTION
-#define BSS_SECTION ".bss"
-#endif
-
-/* Labels we insert at beginning sections we can reference instead of
- the section names themselves. */
-
-#ifndef TEXT_SECTION_LABEL
-#define TEXT_SECTION_LABEL "Ltext"
-#endif
-#ifndef DEBUG_LINE_SECTION_LABEL
-#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
-#endif
-#ifndef DEBUG_INFO_SECTION_LABEL
-#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
-#endif
-#ifndef ABBREV_SECTION_LABEL
-#define ABBREV_SECTION_LABEL "Ldebug_abbrev"
-#endif
-
-
-/* Definitions of defaults for formats and names of various special
- (artificial) labels which may be generated within this file (when the -g
- options is used and DWARF_DEBUGGING_INFO is in effect.
- If necessary, these may be overridden from within the tm.h file, but
- typically, overriding these defaults is unnecessary. */
-
-static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-#ifndef TEXT_END_LABEL
-#define TEXT_END_LABEL "Letext"
-#endif
-#ifndef DATA_END_LABEL
-#define DATA_END_LABEL "Ledata"
-#endif
-#ifndef BSS_END_LABEL
-#define BSS_END_LABEL "Lebss"
-#endif
-#ifndef INSN_LABEL_FMT
-#define INSN_LABEL_FMT "LI%u_"
-#endif
-#ifndef BLOCK_BEGIN_LABEL
-#define BLOCK_BEGIN_LABEL "LBB"
-#endif
-#ifndef BLOCK_END_LABEL
-#define BLOCK_END_LABEL "LBE"
-#endif
-#ifndef BODY_BEGIN_LABEL
-#define BODY_BEGIN_LABEL "Lbb"
-#endif
-#ifndef BODY_END_LABEL
-#define BODY_END_LABEL "Lbe"
-#endif
-#ifndef LINE_CODE_LABEL
-#define LINE_CODE_LABEL "LM"
-#endif
-#ifndef SEPARATE_LINE_CODE_LABEL
-#define SEPARATE_LINE_CODE_LABEL "LSM"
-#endif
-\f
-/* We allow a language front-end to designate a function that is to be
- called to "demangle" any name before it it put into a DIE. */
-
-static const char *(*demangle_name_func) PARAMS ((const char *));
-
-void
-dwarf2out_set_demangle_name_func (func)
- const char *(*func) PARAMS ((const char *));
-{
- demangle_name_func = func;
-}
-\f
-/* Return an rtx like ORIG which lives forever. If we're doing GC,
- that means adding it to used_rtx_varray. If not, that means making
- a copy on the permanent_obstack. */
-
-static rtx
-save_rtx (orig)
- register rtx orig;
-{
- if (ggc_p)
- VARRAY_PUSH_RTX (used_rtx_varray, orig);
- else
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- orig = copy_rtx (orig);
- pop_obstacks ();
- }
-
- return orig;
-}
-
-/* Test if rtl node points to a pseudo register. */
-
-static inline int
-is_pseudo_reg (rtl)
- register rtx rtl;
-{
- return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
- || (GET_CODE (rtl) == SUBREG
- && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
-}
-
-/* Return a reference to a type, with its const and volatile qualifiers
- removed. */
-
-static inline tree
-type_main_variant (type)
- register tree type;
-{
- type = TYPE_MAIN_VARIANT (type);
-
- /* There really should be only one main variant among any group of variants
- of a given type (and all of the MAIN_VARIANT values for all members of
- the group should point to that one type) but sometimes the C front-end
- messes this up for array types, so we work around that bug here. */
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- while (type != TYPE_MAIN_VARIANT (type))
- type = TYPE_MAIN_VARIANT (type);
-
- return type;
-}
-
-/* Return non-zero if the given type node represents a tagged type. */
-
-static inline int
-is_tagged_type (type)
- register tree type;
-{
- register enum tree_code code = TREE_CODE (type);
-
- return (code == RECORD_TYPE || code == UNION_TYPE
- || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
-}
-
-/* Convert a DIE tag into its string name. */
-
-static const char *
-dwarf_tag_name (tag)
- register unsigned tag;
-{
- switch (tag)
- {
- case DW_TAG_padding:
- return "DW_TAG_padding";
- case DW_TAG_array_type:
- return "DW_TAG_array_type";
- case DW_TAG_class_type:
- return "DW_TAG_class_type";
- case DW_TAG_entry_point:
- return "DW_TAG_entry_point";
- case DW_TAG_enumeration_type:
- return "DW_TAG_enumeration_type";
- case DW_TAG_formal_parameter:
- return "DW_TAG_formal_parameter";
- case DW_TAG_imported_declaration:
- return "DW_TAG_imported_declaration";
- case DW_TAG_label:
- return "DW_TAG_label";
- case DW_TAG_lexical_block:
- return "DW_TAG_lexical_block";
- case DW_TAG_member:
- return "DW_TAG_member";
- case DW_TAG_pointer_type:
- return "DW_TAG_pointer_type";
- case DW_TAG_reference_type:
- return "DW_TAG_reference_type";
- case DW_TAG_compile_unit:
- return "DW_TAG_compile_unit";
- case DW_TAG_string_type:
- return "DW_TAG_string_type";
- case DW_TAG_structure_type:
- return "DW_TAG_structure_type";
- case DW_TAG_subroutine_type:
- return "DW_TAG_subroutine_type";
- case DW_TAG_typedef:
- return "DW_TAG_typedef";
- case DW_TAG_union_type:
- return "DW_TAG_union_type";
- case DW_TAG_unspecified_parameters:
- return "DW_TAG_unspecified_parameters";
- case DW_TAG_variant:
- return "DW_TAG_variant";
- case DW_TAG_common_block:
- return "DW_TAG_common_block";
- case DW_TAG_common_inclusion:
- return "DW_TAG_common_inclusion";
- case DW_TAG_inheritance:
- return "DW_TAG_inheritance";
- case DW_TAG_inlined_subroutine:
- return "DW_TAG_inlined_subroutine";
- case DW_TAG_module:
- return "DW_TAG_module";
- case DW_TAG_ptr_to_member_type:
- return "DW_TAG_ptr_to_member_type";
- case DW_TAG_set_type:
- return "DW_TAG_set_type";
- case DW_TAG_subrange_type:
- return "DW_TAG_subrange_type";
- case DW_TAG_with_stmt:
- return "DW_TAG_with_stmt";
- case DW_TAG_access_declaration:
- return "DW_TAG_access_declaration";
- case DW_TAG_base_type:
- return "DW_TAG_base_type";
- case DW_TAG_catch_block:
- return "DW_TAG_catch_block";
- case DW_TAG_const_type:
- return "DW_TAG_const_type";
- case DW_TAG_constant:
- return "DW_TAG_constant";
- case DW_TAG_enumerator:
- return "DW_TAG_enumerator";
- case DW_TAG_file_type:
- return "DW_TAG_file_type";
- case DW_TAG_friend:
- return "DW_TAG_friend";
- case DW_TAG_namelist:
- return "DW_TAG_namelist";
- case DW_TAG_namelist_item:
- return "DW_TAG_namelist_item";
- case DW_TAG_packed_type:
- return "DW_TAG_packed_type";
- case DW_TAG_subprogram:
- return "DW_TAG_subprogram";
- case DW_TAG_template_type_param:
- return "DW_TAG_template_type_param";
- case DW_TAG_template_value_param:
- return "DW_TAG_template_value_param";
- case DW_TAG_thrown_type:
- return "DW_TAG_thrown_type";
- case DW_TAG_try_block:
- return "DW_TAG_try_block";
- case DW_TAG_variant_part:
- return "DW_TAG_variant_part";
- case DW_TAG_variable:
- return "DW_TAG_variable";
- case DW_TAG_volatile_type:
- return "DW_TAG_volatile_type";
- case DW_TAG_MIPS_loop:
- return "DW_TAG_MIPS_loop";
- case DW_TAG_format_label:
- return "DW_TAG_format_label";
- case DW_TAG_function_template:
- return "DW_TAG_function_template";
- case DW_TAG_class_template:
- return "DW_TAG_class_template";
- default:
- return "DW_TAG_<unknown>";
- }
-}
-
-/* Convert a DWARF attribute code into its string name. */
-
-static const char *
-dwarf_attr_name (attr)
- register unsigned attr;
-{
- switch (attr)
- {
- case DW_AT_sibling:
- return "DW_AT_sibling";
- case DW_AT_location:
- return "DW_AT_location";
- case DW_AT_name:
- return "DW_AT_name";
- case DW_AT_ordering:
- return "DW_AT_ordering";
- case DW_AT_subscr_data:
- return "DW_AT_subscr_data";
- case DW_AT_byte_size:
- return "DW_AT_byte_size";
- case DW_AT_bit_offset:
- return "DW_AT_bit_offset";
- case DW_AT_bit_size:
- return "DW_AT_bit_size";
- case DW_AT_element_list:
- return "DW_AT_element_list";
- case DW_AT_stmt_list:
- return "DW_AT_stmt_list";
- case DW_AT_low_pc:
- return "DW_AT_low_pc";
- case DW_AT_high_pc:
- return "DW_AT_high_pc";
- case DW_AT_language:
- return "DW_AT_language";
- case DW_AT_member:
- return "DW_AT_member";
- case DW_AT_discr:
- return "DW_AT_discr";
- case DW_AT_discr_value:
- return "DW_AT_discr_value";
- case DW_AT_visibility:
- return "DW_AT_visibility";
- case DW_AT_import:
- return "DW_AT_import";
- case DW_AT_string_length:
- return "DW_AT_string_length";
- case DW_AT_common_reference:
- return "DW_AT_common_reference";
- case DW_AT_comp_dir:
- return "DW_AT_comp_dir";
- case DW_AT_const_value:
- return "DW_AT_const_value";
- case DW_AT_containing_type:
- return "DW_AT_containing_type";
- case DW_AT_default_value:
- return "DW_AT_default_value";
- case DW_AT_inline:
- return "DW_AT_inline";
- case DW_AT_is_optional:
- return "DW_AT_is_optional";
- case DW_AT_lower_bound:
- return "DW_AT_lower_bound";
- case DW_AT_producer:
- return "DW_AT_producer";
- case DW_AT_prototyped:
- return "DW_AT_prototyped";
- case DW_AT_return_addr:
- return "DW_AT_return_addr";
- case DW_AT_start_scope:
- return "DW_AT_start_scope";
- case DW_AT_stride_size:
- return "DW_AT_stride_size";
- case DW_AT_upper_bound:
- return "DW_AT_upper_bound";
- case DW_AT_abstract_origin:
- return "DW_AT_abstract_origin";
- case DW_AT_accessibility:
- return "DW_AT_accessibility";
- case DW_AT_address_class:
- return "DW_AT_address_class";
- case DW_AT_artificial:
- return "DW_AT_artificial";
- case DW_AT_base_types:
- return "DW_AT_base_types";
- case DW_AT_calling_convention:
- return "DW_AT_calling_convention";
- case DW_AT_count:
- return "DW_AT_count";
- case DW_AT_data_member_location:
- return "DW_AT_data_member_location";
- case DW_AT_decl_column:
- return "DW_AT_decl_column";
- case DW_AT_decl_file:
- return "DW_AT_decl_file";
- case DW_AT_decl_line:
- return "DW_AT_decl_line";
- case DW_AT_declaration:
- return "DW_AT_declaration";
- case DW_AT_discr_list:
- return "DW_AT_discr_list";
- case DW_AT_encoding:
- return "DW_AT_encoding";
- case DW_AT_external:
- return "DW_AT_external";
- case DW_AT_frame_base:
- return "DW_AT_frame_base";
- case DW_AT_friend:
- return "DW_AT_friend";
- case DW_AT_identifier_case:
- return "DW_AT_identifier_case";
- case DW_AT_macro_info:
- return "DW_AT_macro_info";
- case DW_AT_namelist_items:
- return "DW_AT_namelist_items";
- case DW_AT_priority:
- return "DW_AT_priority";
- case DW_AT_segment:
- return "DW_AT_segment";
- case DW_AT_specification:
- return "DW_AT_specification";
- case DW_AT_static_link:
- return "DW_AT_static_link";
- case DW_AT_type:
- return "DW_AT_type";
- case DW_AT_use_location:
- return "DW_AT_use_location";
- case DW_AT_variable_parameter:
- return "DW_AT_variable_parameter";
- case DW_AT_virtuality:
- return "DW_AT_virtuality";
- case DW_AT_vtable_elem_location:
- return "DW_AT_vtable_elem_location";
-
- case DW_AT_MIPS_fde:
- return "DW_AT_MIPS_fde";
- case DW_AT_MIPS_loop_begin:
- return "DW_AT_MIPS_loop_begin";
- case DW_AT_MIPS_tail_loop_begin:
- return "DW_AT_MIPS_tail_loop_begin";
- case DW_AT_MIPS_epilog_begin:
- return "DW_AT_MIPS_epilog_begin";
- case DW_AT_MIPS_loop_unroll_factor:
- return "DW_AT_MIPS_loop_unroll_factor";
- case DW_AT_MIPS_software_pipeline_depth:
- return "DW_AT_MIPS_software_pipeline_depth";
- case DW_AT_MIPS_linkage_name:
- return "DW_AT_MIPS_linkage_name";
- case DW_AT_MIPS_stride:
- return "DW_AT_MIPS_stride";
- case DW_AT_MIPS_abstract_name:
- return "DW_AT_MIPS_abstract_name";
- case DW_AT_MIPS_clone_origin:
- return "DW_AT_MIPS_clone_origin";
- case DW_AT_MIPS_has_inlines:
- return "DW_AT_MIPS_has_inlines";
-
- case DW_AT_sf_names:
- return "DW_AT_sf_names";
- case DW_AT_src_info:
- return "DW_AT_src_info";
- case DW_AT_mac_info:
- return "DW_AT_mac_info";
- case DW_AT_src_coords:
- return "DW_AT_src_coords";
- case DW_AT_body_begin:
- return "DW_AT_body_begin";
- case DW_AT_body_end:
- return "DW_AT_body_end";
- default:
- return "DW_AT_<unknown>";
- }
-}
-
-/* Convert a DWARF value form code into its string name. */
-
-static const char *
-dwarf_form_name (form)
- register unsigned form;
-{
- switch (form)
+ switch (op)
{
- case DW_FORM_addr:
- return "DW_FORM_addr";
- case DW_FORM_block2:
- return "DW_FORM_block2";
- case DW_FORM_block4:
- return "DW_FORM_block4";
- case DW_FORM_data2:
- return "DW_FORM_data2";
- case DW_FORM_data4:
- return "DW_FORM_data4";
- case DW_FORM_data8:
- return "DW_FORM_data8";
- case DW_FORM_string:
- return "DW_FORM_string";
- case DW_FORM_block:
- return "DW_FORM_block";
- case DW_FORM_block1:
- return "DW_FORM_block1";
- case DW_FORM_data1:
- return "DW_FORM_data1";
- case DW_FORM_flag:
- return "DW_FORM_flag";
- case DW_FORM_sdata:
- return "DW_FORM_sdata";
- case DW_FORM_strp:
- return "DW_FORM_strp";
- case DW_FORM_udata:
- return "DW_FORM_udata";
- case DW_FORM_ref_addr:
- return "DW_FORM_ref_addr";
- case DW_FORM_ref1:
- return "DW_FORM_ref1";
- case DW_FORM_ref2:
- return "DW_FORM_ref2";
- case DW_FORM_ref4:
- return "DW_FORM_ref4";
- case DW_FORM_ref8:
- return "DW_FORM_ref8";
- case DW_FORM_ref_udata:
- return "DW_FORM_ref_udata";
- case DW_FORM_indirect:
- return "DW_FORM_indirect";
+ case DW_OP_addr:
+ return "DW_OP_addr";
+ case DW_OP_deref:
+ return "DW_OP_deref";
+ case DW_OP_const1u:
+ return "DW_OP_const1u";
+ case DW_OP_const1s:
+ return "DW_OP_const1s";
+ case DW_OP_const2u:
+ return "DW_OP_const2u";
+ case DW_OP_const2s:
+ return "DW_OP_const2s";
+ case DW_OP_const4u:
+ return "DW_OP_const4u";
+ case DW_OP_const4s:
+ return "DW_OP_const4s";
+ case DW_OP_const8u:
+ return "DW_OP_const8u";
+ case DW_OP_const8s:
+ return "DW_OP_const8s";
+ case DW_OP_constu:
+ return "DW_OP_constu";
+ case DW_OP_consts:
+ return "DW_OP_consts";
+ case DW_OP_dup:
+ return "DW_OP_dup";
+ case DW_OP_drop:
+ return "DW_OP_drop";
+ case DW_OP_over:
+ return "DW_OP_over";
+ case DW_OP_pick:
+ return "DW_OP_pick";
+ case DW_OP_swap:
+ return "DW_OP_swap";
+ case DW_OP_rot:
+ return "DW_OP_rot";
+ case DW_OP_xderef:
+ return "DW_OP_xderef";
+ case DW_OP_abs:
+ return "DW_OP_abs";
+ case DW_OP_and:
+ return "DW_OP_and";
+ case DW_OP_div:
+ return "DW_OP_div";
+ case DW_OP_minus:
+ return "DW_OP_minus";
+ case DW_OP_mod:
+ return "DW_OP_mod";
+ case DW_OP_mul:
+ return "DW_OP_mul";
+ case DW_OP_neg:
+ return "DW_OP_neg";
+ case DW_OP_not:
+ return "DW_OP_not";
+ case DW_OP_or:
+ return "DW_OP_or";
+ case DW_OP_plus:
+ return "DW_OP_plus";
+ case DW_OP_plus_uconst:
+ return "DW_OP_plus_uconst";
+ case DW_OP_shl:
+ return "DW_OP_shl";
+ case DW_OP_shr:
+ return "DW_OP_shr";
+ case DW_OP_shra:
+ return "DW_OP_shra";
+ case DW_OP_xor:
+ return "DW_OP_xor";
+ case DW_OP_bra:
+ return "DW_OP_bra";
+ case DW_OP_eq:
+ return "DW_OP_eq";
+ case DW_OP_ge:
+ return "DW_OP_ge";
+ case DW_OP_gt:
+ return "DW_OP_gt";
+ case DW_OP_le:
+ return "DW_OP_le";
+ case DW_OP_lt:
+ return "DW_OP_lt";
+ case DW_OP_ne:
+ return "DW_OP_ne";
+ case DW_OP_skip:
+ return "DW_OP_skip";
+ case DW_OP_lit0:
+ return "DW_OP_lit0";
+ case DW_OP_lit1:
+ return "DW_OP_lit1";
+ case DW_OP_lit2:
+ return "DW_OP_lit2";
+ case DW_OP_lit3:
+ return "DW_OP_lit3";
+ case DW_OP_lit4:
+ return "DW_OP_lit4";
+ case DW_OP_lit5:
+ return "DW_OP_lit5";
+ case DW_OP_lit6:
+ return "DW_OP_lit6";
+ case DW_OP_lit7:
+ return "DW_OP_lit7";
+ case DW_OP_lit8:
+ return "DW_OP_lit8";
+ case DW_OP_lit9:
+ return "DW_OP_lit9";
+ case DW_OP_lit10:
+ return "DW_OP_lit10";
+ case DW_OP_lit11:
+ return "DW_OP_lit11";
+ case DW_OP_lit12:
+ return "DW_OP_lit12";
+ case DW_OP_lit13:
+ return "DW_OP_lit13";
+ case DW_OP_lit14:
+ return "DW_OP_lit14";
+ case DW_OP_lit15:
+ return "DW_OP_lit15";
+ case DW_OP_lit16:
+ return "DW_OP_lit16";
+ case DW_OP_lit17:
+ return "DW_OP_lit17";
+ case DW_OP_lit18:
+ return "DW_OP_lit18";
+ case DW_OP_lit19:
+ return "DW_OP_lit19";
+ case DW_OP_lit20:
+ return "DW_OP_lit20";
+ case DW_OP_lit21:
+ return "DW_OP_lit21";
+ case DW_OP_lit22:
+ return "DW_OP_lit22";
+ case DW_OP_lit23:
+ return "DW_OP_lit23";
+ case DW_OP_lit24:
+ return "DW_OP_lit24";
+ case DW_OP_lit25:
+ return "DW_OP_lit25";
+ case DW_OP_lit26:
+ return "DW_OP_lit26";
+ case DW_OP_lit27:
+ return "DW_OP_lit27";
+ case DW_OP_lit28:
+ return "DW_OP_lit28";
+ case DW_OP_lit29:
+ return "DW_OP_lit29";
+ case DW_OP_lit30:
+ return "DW_OP_lit30";
+ case DW_OP_lit31:
+ return "DW_OP_lit31";
+ case DW_OP_reg0:
+ return "DW_OP_reg0";
+ case DW_OP_reg1:
+ return "DW_OP_reg1";
+ case DW_OP_reg2:
+ return "DW_OP_reg2";
+ case DW_OP_reg3:
+ return "DW_OP_reg3";
+ case DW_OP_reg4:
+ return "DW_OP_reg4";
+ case DW_OP_reg5:
+ return "DW_OP_reg5";
+ case DW_OP_reg6:
+ return "DW_OP_reg6";
+ case DW_OP_reg7:
+ return "DW_OP_reg7";
+ case DW_OP_reg8:
+ return "DW_OP_reg8";
+ case DW_OP_reg9:
+ return "DW_OP_reg9";
+ case DW_OP_reg10:
+ return "DW_OP_reg10";
+ case DW_OP_reg11:
+ return "DW_OP_reg11";
+ case DW_OP_reg12:
+ return "DW_OP_reg12";
+ case DW_OP_reg13:
+ return "DW_OP_reg13";
+ case DW_OP_reg14:
+ return "DW_OP_reg14";
+ case DW_OP_reg15:
+ return "DW_OP_reg15";
+ case DW_OP_reg16:
+ return "DW_OP_reg16";
+ case DW_OP_reg17:
+ return "DW_OP_reg17";
+ case DW_OP_reg18:
+ return "DW_OP_reg18";
+ case DW_OP_reg19:
+ return "DW_OP_reg19";
+ case DW_OP_reg20:
+ return "DW_OP_reg20";
+ case DW_OP_reg21:
+ return "DW_OP_reg21";
+ case DW_OP_reg22:
+ return "DW_OP_reg22";
+ case DW_OP_reg23:
+ return "DW_OP_reg23";
+ case DW_OP_reg24:
+ return "DW_OP_reg24";
+ case DW_OP_reg25:
+ return "DW_OP_reg25";
+ case DW_OP_reg26:
+ return "DW_OP_reg26";
+ case DW_OP_reg27:
+ return "DW_OP_reg27";
+ case DW_OP_reg28:
+ return "DW_OP_reg28";
+ case DW_OP_reg29:
+ return "DW_OP_reg29";
+ case DW_OP_reg30:
+ return "DW_OP_reg30";
+ case DW_OP_reg31:
+ return "DW_OP_reg31";
+ case DW_OP_breg0:
+ return "DW_OP_breg0";
+ case DW_OP_breg1:
+ return "DW_OP_breg1";
+ case DW_OP_breg2:
+ return "DW_OP_breg2";
+ case DW_OP_breg3:
+ return "DW_OP_breg3";
+ case DW_OP_breg4:
+ return "DW_OP_breg4";
+ case DW_OP_breg5:
+ return "DW_OP_breg5";
+ case DW_OP_breg6:
+ return "DW_OP_breg6";
+ case DW_OP_breg7:
+ return "DW_OP_breg7";
+ case DW_OP_breg8:
+ return "DW_OP_breg8";
+ case DW_OP_breg9:
+ return "DW_OP_breg9";
+ case DW_OP_breg10:
+ return "DW_OP_breg10";
+ case DW_OP_breg11:
+ return "DW_OP_breg11";
+ case DW_OP_breg12:
+ return "DW_OP_breg12";
+ case DW_OP_breg13:
+ return "DW_OP_breg13";
+ case DW_OP_breg14:
+ return "DW_OP_breg14";
+ case DW_OP_breg15:
+ return "DW_OP_breg15";
+ case DW_OP_breg16:
+ return "DW_OP_breg16";
+ case DW_OP_breg17:
+ return "DW_OP_breg17";
+ case DW_OP_breg18:
+ return "DW_OP_breg18";
+ case DW_OP_breg19:
+ return "DW_OP_breg19";
+ case DW_OP_breg20:
+ return "DW_OP_breg20";
+ case DW_OP_breg21:
+ return "DW_OP_breg21";
+ case DW_OP_breg22:
+ return "DW_OP_breg22";
+ case DW_OP_breg23:
+ return "DW_OP_breg23";
+ case DW_OP_breg24:
+ return "DW_OP_breg24";
+ case DW_OP_breg25:
+ return "DW_OP_breg25";
+ case DW_OP_breg26:
+ return "DW_OP_breg26";
+ case DW_OP_breg27:
+ return "DW_OP_breg27";
+ case DW_OP_breg28:
+ return "DW_OP_breg28";
+ case DW_OP_breg29:
+ return "DW_OP_breg29";
+ case DW_OP_breg30:
+ return "DW_OP_breg30";
+ case DW_OP_breg31:
+ return "DW_OP_breg31";
+ case DW_OP_regx:
+ return "DW_OP_regx";
+ case DW_OP_fbreg:
+ return "DW_OP_fbreg";
+ case DW_OP_bregx:
+ return "DW_OP_bregx";
+ case DW_OP_piece:
+ return "DW_OP_piece";
+ case DW_OP_deref_size:
+ return "DW_OP_deref_size";
+ case DW_OP_xderef_size:
+ return "DW_OP_xderef_size";
+ case DW_OP_nop:
+ return "DW_OP_nop";
default:
- return "DW_FORM_<unknown>";
+ return "OP_<unknown>";
}
}
-/* Convert a DWARF stack opcode into its string name. */
-static const char *
-dwarf_stack_op_name (op)
- register unsigned op;
+/* Return a pointer to a newly allocated location description. Location
+ descriptions are simple expression terms that can be strung
+ together to form more complicated location (address) descriptions. */
+
+static inline dw_loc_descr_ref
+new_loc_descr (op, oprnd1, oprnd2)
+ register enum dwarf_location_atom op;
+ register unsigned long oprnd1;
+ register unsigned long oprnd2;
{
- switch (op)
+ register dw_loc_descr_ref descr
+ = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node));
+
+ descr->dw_loc_next = NULL;
+ descr->dw_loc_opc = op;
+ descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
+ descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
+ descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
+ descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
+
+ return descr;
+}
+
+/* Add a location description term to a location description expression. */
+
+static inline void
+add_loc_descr (list_head, descr)
+ register dw_loc_descr_ref *list_head;
+ register dw_loc_descr_ref descr;
+{
+ register dw_loc_descr_ref *d;
+
+ /* Find the end of the chain. */
+ for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
+ ;
+
+ *d = descr;
+}
+
+/* Return the size of a location descriptor. */
+
+static unsigned long
+size_of_loc_descr (loc)
+ register dw_loc_descr_ref loc;
+{
+ register unsigned long size = 1;
+
+ switch (loc->dw_loc_opc)
{
case DW_OP_addr:
- return "DW_OP_addr";
- case DW_OP_deref:
- return "DW_OP_deref";
+ size += DWARF2_ADDR_SIZE;
+ break;
case DW_OP_const1u:
- return "DW_OP_const1u";
case DW_OP_const1s:
- return "DW_OP_const1s";
+ size += 1;
+ break;
case DW_OP_const2u:
- return "DW_OP_const2u";
case DW_OP_const2s:
- return "DW_OP_const2s";
+ size += 2;
+ break;
case DW_OP_const4u:
- return "DW_OP_const4u";
case DW_OP_const4s:
- return "DW_OP_const4s";
+ size += 4;
+ break;
case DW_OP_const8u:
- return "DW_OP_const8u";
case DW_OP_const8s:
- return "DW_OP_const8s";
+ size += 8;
+ break;
case DW_OP_constu:
- return "DW_OP_constu";
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+ break;
case DW_OP_consts:
- return "DW_OP_consts";
- case DW_OP_dup:
- return "DW_OP_dup";
- case DW_OP_drop:
- return "DW_OP_drop";
- case DW_OP_over:
- return "DW_OP_over";
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+ break;
case DW_OP_pick:
- return "DW_OP_pick";
- case DW_OP_swap:
- return "DW_OP_swap";
- case DW_OP_rot:
- return "DW_OP_rot";
- case DW_OP_xderef:
- return "DW_OP_xderef";
- case DW_OP_abs:
- return "DW_OP_abs";
- case DW_OP_and:
- return "DW_OP_and";
- case DW_OP_div:
- return "DW_OP_div";
- case DW_OP_minus:
- return "DW_OP_minus";
- case DW_OP_mod:
- return "DW_OP_mod";
- case DW_OP_mul:
- return "DW_OP_mul";
- case DW_OP_neg:
- return "DW_OP_neg";
- case DW_OP_not:
- return "DW_OP_not";
- case DW_OP_or:
- return "DW_OP_or";
- case DW_OP_plus:
- return "DW_OP_plus";
+ size += 1;
+ break;
case DW_OP_plus_uconst:
- return "DW_OP_plus_uconst";
- case DW_OP_shl:
- return "DW_OP_shl";
- case DW_OP_shr:
- return "DW_OP_shr";
- case DW_OP_shra:
- return "DW_OP_shra";
- case DW_OP_xor:
- return "DW_OP_xor";
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+ break;
+ case DW_OP_skip:
case DW_OP_bra:
- return "DW_OP_bra";
- case DW_OP_eq:
- return "DW_OP_eq";
- case DW_OP_ge:
- return "DW_OP_ge";
- case DW_OP_gt:
- return "DW_OP_gt";
- case DW_OP_le:
- return "DW_OP_le";
- case DW_OP_lt:
- return "DW_OP_lt";
- case DW_OP_ne:
- return "DW_OP_ne";
+ size += 2;
+ break;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+ break;
+ case DW_OP_regx:
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+ break;
+ case DW_OP_fbreg:
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
+ break;
+ case DW_OP_bregx:
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+ size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
+ break;
+ case DW_OP_piece:
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
+ break;
+ case DW_OP_deref_size:
+ case DW_OP_xderef_size:
+ size += 1;
+ break;
+ default:
+ break;
+ }
+
+ return size;
+}
+
+/* Return the size of a series of location descriptors. */
+
+static unsigned long
+size_of_locs (loc)
+ register dw_loc_descr_ref loc;
+{
+ register unsigned long size = 0;
+
+ for (; loc != NULL; loc = loc->dw_loc_next)
+ size += size_of_loc_descr (loc);
+
+ return size;
+}
+
+/* Output location description stack opcode's operands (if any). */
+
+static void
+output_loc_operands (loc)
+ register dw_loc_descr_ref loc;
+{
+ register dw_val_ref val1 = &loc->dw_loc_oprnd1;
+ register dw_val_ref val2 = &loc->dw_loc_oprnd2;
+
+ switch (loc->dw_loc_opc)
+ {
+#ifdef DWARF2_DEBUGGING_INFO
+ case DW_OP_addr:
+ ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_const4u:
+ case DW_OP_const4s:
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_const8u:
+ case DW_OP_const8s:
+ abort ();
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_skip:
+ case DW_OP_bra:
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
+#else
+ case DW_OP_addr:
+ case DW_OP_const2u:
+ case DW_OP_const2s:
+ case DW_OP_const4u:
+ case DW_OP_const4s:
+ case DW_OP_const8u:
+ case DW_OP_const8s:
case DW_OP_skip:
- return "DW_OP_skip";
- case DW_OP_lit0:
- return "DW_OP_lit0";
- case DW_OP_lit1:
- return "DW_OP_lit1";
- case DW_OP_lit2:
- return "DW_OP_lit2";
- case DW_OP_lit3:
- return "DW_OP_lit3";
- case DW_OP_lit4:
- return "DW_OP_lit4";
- case DW_OP_lit5:
- return "DW_OP_lit5";
- case DW_OP_lit6:
- return "DW_OP_lit6";
- case DW_OP_lit7:
- return "DW_OP_lit7";
- case DW_OP_lit8:
- return "DW_OP_lit8";
- case DW_OP_lit9:
- return "DW_OP_lit9";
- case DW_OP_lit10:
- return "DW_OP_lit10";
- case DW_OP_lit11:
- return "DW_OP_lit11";
- case DW_OP_lit12:
- return "DW_OP_lit12";
- case DW_OP_lit13:
- return "DW_OP_lit13";
- case DW_OP_lit14:
- return "DW_OP_lit14";
- case DW_OP_lit15:
- return "DW_OP_lit15";
- case DW_OP_lit16:
- return "DW_OP_lit16";
- case DW_OP_lit17:
- return "DW_OP_lit17";
- case DW_OP_lit18:
- return "DW_OP_lit18";
- case DW_OP_lit19:
- return "DW_OP_lit19";
- case DW_OP_lit20:
- return "DW_OP_lit20";
- case DW_OP_lit21:
- return "DW_OP_lit21";
- case DW_OP_lit22:
- return "DW_OP_lit22";
- case DW_OP_lit23:
- return "DW_OP_lit23";
- case DW_OP_lit24:
- return "DW_OP_lit24";
- case DW_OP_lit25:
- return "DW_OP_lit25";
- case DW_OP_lit26:
- return "DW_OP_lit26";
- case DW_OP_lit27:
- return "DW_OP_lit27";
- case DW_OP_lit28:
- return "DW_OP_lit28";
- case DW_OP_lit29:
- return "DW_OP_lit29";
- case DW_OP_lit30:
- return "DW_OP_lit30";
- case DW_OP_lit31:
- return "DW_OP_lit31";
- case DW_OP_reg0:
- return "DW_OP_reg0";
- case DW_OP_reg1:
- return "DW_OP_reg1";
- case DW_OP_reg2:
- return "DW_OP_reg2";
- case DW_OP_reg3:
- return "DW_OP_reg3";
- case DW_OP_reg4:
- return "DW_OP_reg4";
- case DW_OP_reg5:
- return "DW_OP_reg5";
- case DW_OP_reg6:
- return "DW_OP_reg6";
- case DW_OP_reg7:
- return "DW_OP_reg7";
- case DW_OP_reg8:
- return "DW_OP_reg8";
- case DW_OP_reg9:
- return "DW_OP_reg9";
- case DW_OP_reg10:
- return "DW_OP_reg10";
- case DW_OP_reg11:
- return "DW_OP_reg11";
- case DW_OP_reg12:
- return "DW_OP_reg12";
- case DW_OP_reg13:
- return "DW_OP_reg13";
- case DW_OP_reg14:
- return "DW_OP_reg14";
- case DW_OP_reg15:
- return "DW_OP_reg15";
- case DW_OP_reg16:
- return "DW_OP_reg16";
- case DW_OP_reg17:
- return "DW_OP_reg17";
- case DW_OP_reg18:
- return "DW_OP_reg18";
- case DW_OP_reg19:
- return "DW_OP_reg19";
- case DW_OP_reg20:
- return "DW_OP_reg20";
- case DW_OP_reg21:
- return "DW_OP_reg21";
- case DW_OP_reg22:
- return "DW_OP_reg22";
- case DW_OP_reg23:
- return "DW_OP_reg23";
- case DW_OP_reg24:
- return "DW_OP_reg24";
- case DW_OP_reg25:
- return "DW_OP_reg25";
- case DW_OP_reg26:
- return "DW_OP_reg26";
- case DW_OP_reg27:
- return "DW_OP_reg27";
- case DW_OP_reg28:
- return "DW_OP_reg28";
- case DW_OP_reg29:
- return "DW_OP_reg29";
- case DW_OP_reg30:
- return "DW_OP_reg30";
- case DW_OP_reg31:
- return "DW_OP_reg31";
+ case DW_OP_bra:
+ /* We currently don't make any attempt to make sure these are
+ aligned properly like we do for the main unwind info, so
+ don't support emitting things larger than a byte if we're
+ only doing unwinding. */
+ abort ();
+#endif
+ case DW_OP_const1u:
+ case DW_OP_const1s:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_constu:
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_consts:
+ output_sleb128 (val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_pick:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_OP_plus_uconst:
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_breg0:
- return "DW_OP_breg0";
case DW_OP_breg1:
- return "DW_OP_breg1";
case DW_OP_breg2:
- return "DW_OP_breg2";
case DW_OP_breg3:
- return "DW_OP_breg3";
case DW_OP_breg4:
- return "DW_OP_breg4";
case DW_OP_breg5:
- return "DW_OP_breg5";
case DW_OP_breg6:
- return "DW_OP_breg6";
case DW_OP_breg7:
- return "DW_OP_breg7";
case DW_OP_breg8:
- return "DW_OP_breg8";
case DW_OP_breg9:
- return "DW_OP_breg9";
case DW_OP_breg10:
- return "DW_OP_breg10";
case DW_OP_breg11:
- return "DW_OP_breg11";
case DW_OP_breg12:
- return "DW_OP_breg12";
case DW_OP_breg13:
- return "DW_OP_breg13";
case DW_OP_breg14:
- return "DW_OP_breg14";
case DW_OP_breg15:
- return "DW_OP_breg15";
case DW_OP_breg16:
- return "DW_OP_breg16";
case DW_OP_breg17:
- return "DW_OP_breg17";
case DW_OP_breg18:
- return "DW_OP_breg18";
case DW_OP_breg19:
- return "DW_OP_breg19";
case DW_OP_breg20:
- return "DW_OP_breg20";
case DW_OP_breg21:
- return "DW_OP_breg21";
case DW_OP_breg22:
- return "DW_OP_breg22";
case DW_OP_breg23:
- return "DW_OP_breg23";
case DW_OP_breg24:
- return "DW_OP_breg24";
case DW_OP_breg25:
- return "DW_OP_breg25";
case DW_OP_breg26:
- return "DW_OP_breg26";
case DW_OP_breg27:
- return "DW_OP_breg27";
case DW_OP_breg28:
- return "DW_OP_breg28";
case DW_OP_breg29:
- return "DW_OP_breg29";
case DW_OP_breg30:
- return "DW_OP_breg30";
case DW_OP_breg31:
- return "DW_OP_breg31";
+ output_sleb128 (val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_regx:
- return "DW_OP_regx";
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_fbreg:
- return "DW_OP_fbreg";
+ output_sleb128 (val1->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_bregx:
- return "DW_OP_bregx";
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
+ output_sleb128 (val2->v.val_int);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_piece:
- return "DW_OP_piece";
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
+ break;
case DW_OP_deref_size:
- return "DW_OP_deref_size";
case DW_OP_xderef_size:
- return "DW_OP_xderef_size";
- case DW_OP_nop:
- return "DW_OP_nop";
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
+ fputc ('\n', asm_out_file);
+ break;
+ default:
+ /* Other codes have no operands. */
+ break;
+ }
+}
+
+/* Output a sequence of location operations. */
+
+static void
+output_loc_sequence (loc)
+ dw_loc_descr_ref loc;
+{
+ for (; loc != NULL; loc = loc->dw_loc_next)
+ {
+ /* Output the opcode. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
+ dwarf_stack_op_name (loc->dw_loc_opc));
+
+ fputc ('\n', asm_out_file);
+
+ /* Output the operand(s) (if any). */
+ output_loc_operands (loc);
+ }
+}
+
+/* This routine will generate the correct assembly data for a location
+ description based on a cfi entry with a complex address. */
+
+static void
+output_cfa_loc (cfi)
+ dw_cfi_ref cfi;
+{
+ dw_loc_descr_ref loc;
+ unsigned long size;
+
+ /* Output the size of the block. */
+ loc = cfi->dw_cfi_oprnd1.dw_cfi_loc;
+ size = size_of_locs (loc);
+ output_uleb128 (size);
+ fputc ('\n', asm_out_file);
+
+ /* Now output the operations themselves. */
+ output_loc_sequence (loc);
+}
+
+/* This function builds a dwarf location descriptor seqeunce from
+ a dw_cfa_location. */
+
+static struct dw_loc_descr_struct *
+build_cfa_loc (cfa)
+ dw_cfa_location *cfa;
+{
+ struct dw_loc_descr_struct *head, *tmp;
+
+ if (cfa->indirect == 0)
+ abort ();
+
+ if (cfa->base_offset)
+ head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0);
+ else
+ head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0);
+ head->dw_loc_oprnd1.val_class = dw_val_class_const;
+ tmp = new_loc_descr (DW_OP_deref, 0, 0);
+ add_loc_descr (&head, tmp);
+ if (cfa->offset != 0)
+ {
+ tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0);
+ add_loc_descr (&head, tmp);
+ }
+ return head;
+}
+
+/* This function fills in aa dw_cfa_location structure from a
+ dwarf location descriptor sequence. */
+
+static void
+get_cfa_from_loc_descr (cfa, loc)
+ dw_cfa_location *cfa;
+ struct dw_loc_descr_struct * loc;
+{
+ struct dw_loc_descr_struct * ptr;
+ cfa->offset = 0;
+ cfa->base_offset = 0;
+ cfa->indirect = 0;
+ cfa->reg = -1;
+
+ for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next)
+ {
+ enum dwarf_location_atom op = ptr->dw_loc_opc;
+ switch (op)
+ {
+ case DW_OP_reg0:
+ case DW_OP_reg1:
+ case DW_OP_reg2:
+ case DW_OP_reg3:
+ case DW_OP_reg4:
+ case DW_OP_reg5:
+ case DW_OP_reg6:
+ case DW_OP_reg7:
+ case DW_OP_reg8:
+ case DW_OP_reg9:
+ case DW_OP_reg10:
+ case DW_OP_reg11:
+ case DW_OP_reg12:
+ case DW_OP_reg13:
+ case DW_OP_reg14:
+ case DW_OP_reg15:
+ case DW_OP_reg16:
+ case DW_OP_reg17:
+ case DW_OP_reg18:
+ case DW_OP_reg19:
+ case DW_OP_reg20:
+ case DW_OP_reg21:
+ case DW_OP_reg22:
+ case DW_OP_reg23:
+ case DW_OP_reg24:
+ case DW_OP_reg25:
+ case DW_OP_reg26:
+ case DW_OP_reg27:
+ case DW_OP_reg28:
+ case DW_OP_reg29:
+ case DW_OP_reg30:
+ case DW_OP_reg31:
+ cfa->reg = op - DW_OP_reg0;
+ break;
+ case DW_OP_regx:
+ cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
+ break;
+ case DW_OP_breg0:
+ case DW_OP_breg1:
+ case DW_OP_breg2:
+ case DW_OP_breg3:
+ case DW_OP_breg4:
+ case DW_OP_breg5:
+ case DW_OP_breg6:
+ case DW_OP_breg7:
+ case DW_OP_breg8:
+ case DW_OP_breg9:
+ case DW_OP_breg10:
+ case DW_OP_breg11:
+ case DW_OP_breg12:
+ case DW_OP_breg13:
+ case DW_OP_breg14:
+ case DW_OP_breg15:
+ case DW_OP_breg16:
+ case DW_OP_breg17:
+ case DW_OP_breg18:
+ case DW_OP_breg19:
+ case DW_OP_breg20:
+ case DW_OP_breg21:
+ case DW_OP_breg22:
+ case DW_OP_breg23:
+ case DW_OP_breg24:
+ case DW_OP_breg25:
+ case DW_OP_breg26:
+ case DW_OP_breg27:
+ case DW_OP_breg28:
+ case DW_OP_breg29:
+ case DW_OP_breg30:
+ case DW_OP_breg31:
+ cfa->reg = op - DW_OP_breg0;
+ cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int;
+ break;
+ case DW_OP_bregx:
+ cfa->reg = ptr->dw_loc_oprnd1.v.val_int;
+ cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int;
+ break;
+ case DW_OP_deref:
+ cfa->indirect = 1;
+ break;
+ case DW_OP_plus_uconst:
+ cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned;
+ break;
+ default:
+ fatal ("DW_LOC_OP %s not implememnted yet.\n",
+ dwarf_stack_op_name (ptr->dw_loc_opc));
+ }
+ }
+}
+#endif /* .debug_frame support */
+\f
+/* And now, the support for symbolic debugging information. */
+#ifdef DWARF2_DEBUGGING_INFO
+
+/* 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. */
+
+/* An internal representation of the DWARF output is built, and then
+ walked to generate the DWARF debugging info. The walk of the internal
+ representation is done after the entire program has been compiled.
+ The types below are used to describe the internal representation. */
+
+/* Various DIE's use offsets relative to the beginning of the
+ .debug_info section to refer to each other. */
+
+typedef long int dw_offset;
+
+/* Define typedefs here to avoid circular dependencies. */
+
+typedef struct dw_attr_struct *dw_attr_ref;
+typedef struct dw_line_info_struct *dw_line_info_ref;
+typedef struct dw_separate_line_info_struct *dw_separate_line_info_ref;
+typedef struct pubname_struct *pubname_ref;
+typedef dw_die_ref *arange_ref;
+
+/* Each entry in the line_info_table maintains the file and
+ line number associated with the label generated for that
+ entry. The label gives the PC value associated with
+ the line number entry. */
+
+typedef struct dw_line_info_struct
+{
+ unsigned long dw_file_num;
+ unsigned long dw_line_num;
+}
+dw_line_info_entry;
+
+/* Line information for functions in separate sections; each one gets its
+ own sequence. */
+typedef struct dw_separate_line_info_struct
+{
+ unsigned long dw_file_num;
+ unsigned long dw_line_num;
+ unsigned long function;
+}
+dw_separate_line_info_entry;
+
+/* Each DIE attribute has a field specifying the attribute kind,
+ a link to the next attribute in the chain, and an attribute value.
+ Attributes are typically linked below the DIE they modify. */
+
+typedef struct dw_attr_struct
+{
+ enum dwarf_attribute dw_attr;
+ dw_attr_ref dw_attr_next;
+ dw_val_node dw_attr_val;
+}
+dw_attr_node;
+
+/* The Debugging Information Entry (DIE) structure */
+
+typedef struct die_struct
+{
+ enum dwarf_tag die_tag;
+ dw_attr_ref die_attr;
+ dw_die_ref die_parent;
+ dw_die_ref die_child;
+ dw_die_ref die_sib;
+ dw_offset die_offset;
+ unsigned long die_abbrev;
+}
+die_node;
+
+/* The pubname structure */
+
+typedef struct pubname_struct
+{
+ dw_die_ref die;
+ char * name;
+}
+pubname_entry;
+
+/* The limbo die list structure. */
+typedef struct limbo_die_struct
+{
+ dw_die_ref die;
+ struct limbo_die_struct *next;
+}
+limbo_die_node;
+
+/* How to start an assembler comment. */
+#ifndef ASM_COMMENT_START
+#define ASM_COMMENT_START ";#"
+#endif
+
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+ implicitly generated for a tagged type.
+
+ Note that unlike the gcc front end (which generates a NULL named
+ TYPE_DECL node for each complete tagged type, each array type, and
+ each function type node created) the g++ front end generates a
+ _named_ TYPE_DECL node for each tagged type node created.
+ These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+ generate a DW_TAG_typedef DIE for them. */
+
+#define TYPE_DECL_IS_STUB(decl) \
+ (DECL_NAME (decl) == NULL_TREE \
+ || (DECL_ARTIFICIAL (decl) \
+ && is_tagged_type (TREE_TYPE (decl)) \
+ && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \
+ /* This is necessary for stub decls that \
+ appear in nested inline functions. */ \
+ || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \
+ && (decl_ultimate_origin (decl) \
+ == TYPE_STUB_DECL (TREE_TYPE (decl)))))))
+
+/* Information concerning the compilation unit's programming
+ language, and compiler version. */
+
+extern int flag_traditional;
+
+/* Fixed size portion of the DWARF compilation unit header. */
+#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
+
+/* Fixed size portion of debugging line information prolog. */
+#define DWARF_LINE_PROLOG_HEADER_SIZE 5
+
+/* Fixed size portion of public names info. */
+#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
+
+/* Fixed size portion of the address range info. */
+#define DWARF_ARANGES_HEADER_SIZE \
+ (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
+ - DWARF_OFFSET_SIZE)
+
+/* Size of padding portion in the address range info. It must be
+ aligned to twice the pointer size. */
+#define DWARF_ARANGES_PAD_SIZE \
+ (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \
+ - (2 * DWARF_OFFSET_SIZE + 4))
+
+/* 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
+ no a priori knowledge of how many instruction bytes are generated
+ for each source line, and therefore can use only the DW_LNE_set_address
+ and DW_LNS_fixed_advance_pc line information commands. */
+
+#ifndef DWARF_LINE_MIN_INSTR_LENGTH
+#define DWARF_LINE_MIN_INSTR_LENGTH 4
+#endif
+
+/* Minimum line offset in a special line info. opcode.
+ This value was chosen to give a reasonable range of values. */
+#define DWARF_LINE_BASE -10
+
+/* First special line opcde - leave room for the standard opcodes. */
+#define DWARF_LINE_OPCODE_BASE 10
+
+/* Range of line offsets in a special line info. opcode. */
+#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1)
+
+/* Flag that indicates the initial value of the is_stmt_start flag.
+ In the present implementation, we do not mark any lines as
+ the beginning of a source statement, because that information
+ is not made available by the GCC front-end. */
+#define DWARF_LINE_DEFAULT_IS_STMT_START 1
+
+/* This location is used by calc_die_sizes() to keep track
+ the offset of each DIE within the .debug_info section. */
+static unsigned long next_die_offset;
+
+/* Record the root of the DIE's built for the current compilation unit. */
+static dw_die_ref comp_unit_die;
+
+/* A list of DIEs with a NULL parent waiting to be relocated. */
+static limbo_die_node *limbo_die_list = 0;
+
+/* Pointer to an array of filenames referenced by this compilation unit. */
+static char **file_table;
+
+/* Total number of entries in the table (i.e. array) pointed to by
+ `file_table'. This is the *total* and includes both used and unused
+ slots. */
+static unsigned file_table_allocated;
+
+/* Number of entries in the file_table which are actually in use. */
+static unsigned file_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the filename
+ table. */
+#define FILE_TABLE_INCREMENT 64
+
+/* Local pointer to the name of the main input file. Initialized in
+ dwarf2out_init. */
+static const char *primary_filename;
+
+/* A pointer to the base of a table of references to DIE's that describe
+ declarations. The table is indexed by DECL_UID() which is a unique
+ number identifying each decl. */
+static dw_die_ref *decl_die_table;
+
+/* Number of elements currently allocated for the decl_die_table. */
+static unsigned decl_die_table_allocated;
+
+/* Number of elements in decl_die_table currently in use. */
+static unsigned decl_die_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+ decl_die_table. */
+#define DECL_DIE_TABLE_INCREMENT 256
+
+/* A pointer to the base of a table of references to declaration
+ scopes. This table is a display which tracks the nesting
+ of declaration scopes at the current scope and containing
+ scopes. This table is used to find the proper place to
+ define type declaration DIE's. */
+static tree *decl_scope_table;
+
+/* Number of elements currently allocated for the decl_scope_table. */
+static int decl_scope_table_allocated;
+
+/* Current level of nesting of declaration scopes. */
+static int decl_scope_depth;
+
+/* Size (in elements) of increments by which we may expand the
+ decl_scope_table. */
+#define DECL_SCOPE_TABLE_INCREMENT 64
+
+/* A pointer to the base of a list of references to DIE's that
+ are uniquely identified by their tag, presence/absence of
+ children DIE's, and list of attribute/value pairs. */
+static dw_die_ref *abbrev_die_table;
+
+/* Number of elements currently allocated for abbrev_die_table. */
+static unsigned abbrev_die_table_allocated;
+
+/* Number of elements in type_die_table currently in use. */
+static unsigned abbrev_die_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+ abbrev_die_table. */
+#define ABBREV_DIE_TABLE_INCREMENT 256
+
+/* A pointer to the base of a table that contains line information
+ for each source code line in .text in the compilation unit. */
+static dw_line_info_ref line_info_table;
+
+/* Number of elements currently allocated for line_info_table. */
+static unsigned line_info_table_allocated;
+
+/* Number of elements in separate_line_info_table currently in use. */
+static unsigned separate_line_info_table_in_use;
+
+/* A pointer to the base of a table that contains line information
+ for each source code line outside of .text in the compilation unit. */
+static dw_separate_line_info_ref separate_line_info_table;
+
+/* Number of elements currently allocated for separate_line_info_table. */
+static unsigned separate_line_info_table_allocated;
+
+/* Number of elements in line_info_table currently in use. */
+static unsigned line_info_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+ line_info_table. */
+#define LINE_INFO_TABLE_INCREMENT 1024
+
+/* A pointer to the base of a table that contains a list of publicly
+ accessible names. */
+static pubname_ref pubname_table;
+
+/* Number of elements currently allocated for pubname_table. */
+static unsigned pubname_table_allocated;
+
+/* Number of elements in pubname_table currently in use. */
+static unsigned pubname_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+ pubname_table. */
+#define PUBNAME_TABLE_INCREMENT 64
+
+/* A pointer to the base of a table that contains a list of publicly
+ accessible names. */
+static arange_ref arange_table;
+
+/* Number of elements currently allocated for arange_table. */
+static unsigned arange_table_allocated;
+
+/* Number of elements in arange_table currently in use. */
+static unsigned arange_table_in_use;
+
+/* Size (in elements) of increments by which we may expand the
+ arange_table. */
+#define ARANGE_TABLE_INCREMENT 64
+
+/* A pointer to the base of a list of incomplete types which might be
+ completed at some later time. */
+
+static tree *incomplete_types_list;
+
+/* Number of elements currently allocated for the incomplete_types_list. */
+static unsigned incomplete_types_allocated;
+
+/* Number of elements of incomplete_types_list currently in use. */
+static unsigned incomplete_types;
+
+/* Size (in elements) of increments by which we may expand the incomplete
+ types list. Actually, a single hunk of space of this size should
+ be enough for most typical programs. */
+#define INCOMPLETE_TYPES_INCREMENT 64
+
+/* Record whether the function being analyzed contains inlined functions. */
+static int current_function_has_inlines;
+#if 0 && defined (MIPS_DEBUGGING_INFO)
+static int comp_unit_has_inlines;
+#endif
+
+/* Array of RTXes referenced by the debugging information, which therefore
+ must be kept around forever. We do this rather than perform GC on
+ the dwarf info because almost all of the dwarf info lives forever, and
+ it's easier to support non-GC frontends this way. */
+static varray_type used_rtx_varray;
+
+/* Forward declarations for functions defined in this file. */
+
+static int is_pseudo_reg PARAMS ((rtx));
+static tree type_main_variant PARAMS ((tree));
+static int is_tagged_type PARAMS ((tree));
+static const char *dwarf_tag_name PARAMS ((unsigned));
+static const char *dwarf_attr_name PARAMS ((unsigned));
+static const char *dwarf_form_name PARAMS ((unsigned));
+#if 0
+static const char *dwarf_type_encoding_name PARAMS ((unsigned));
+#endif
+static tree decl_ultimate_origin PARAMS ((tree));
+static tree block_ultimate_origin PARAMS ((tree));
+static tree decl_class_context PARAMS ((tree));
+static void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref));
+static void add_AT_flag PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned));
+static void add_AT_int PARAMS ((dw_die_ref,
+ enum dwarf_attribute, long));
+static void add_AT_unsigned PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned long));
+static void add_AT_long_long PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned long,
+ unsigned long));
+static void add_AT_float PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned, long *));
+static void add_AT_string PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ const char *));
+static void add_AT_die_ref PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ dw_die_ref));
+static void add_AT_fde_ref PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned));
+static void add_AT_loc PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ dw_loc_descr_ref));
+static void add_AT_addr PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ rtx));
+static void add_AT_lbl_id PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ const char *));
+static void add_AT_lbl_offset PARAMS ((dw_die_ref,
+ enum dwarf_attribute,
+ const char *));
+static dw_attr_ref get_AT PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static const char *get_AT_low_pc PARAMS ((dw_die_ref));
+static const char *get_AT_hi_pc PARAMS ((dw_die_ref));
+static const char *get_AT_string PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static int get_AT_flag PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static unsigned get_AT_unsigned PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static int is_c_family PARAMS ((void));
+static int is_fortran PARAMS ((void));
+static void remove_AT PARAMS ((dw_die_ref,
+ enum dwarf_attribute));
+static void remove_children PARAMS ((dw_die_ref));
+static void add_child_die PARAMS ((dw_die_ref, dw_die_ref));
+static dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref));
+static dw_die_ref lookup_type_die PARAMS ((tree));
+static void equate_type_number_to_die PARAMS ((tree, dw_die_ref));
+static dw_die_ref lookup_decl_die PARAMS ((tree));
+static void equate_decl_number_to_die PARAMS ((tree, dw_die_ref));
+static void print_spaces PARAMS ((FILE *));
+static void print_die PARAMS ((dw_die_ref, FILE *));
+static void print_dwarf_line_table PARAMS ((FILE *));
+static void add_sibling_attributes PARAMS ((dw_die_ref));
+static void build_abbrev_table PARAMS ((dw_die_ref));
+static unsigned long size_of_string PARAMS ((const char *));
+static int constant_size PARAMS ((long unsigned));
+static unsigned long size_of_die PARAMS ((dw_die_ref));
+static void calc_die_sizes PARAMS ((dw_die_ref));
+static unsigned long size_of_line_prolog PARAMS ((void));
+static unsigned long size_of_pubnames PARAMS ((void));
+static unsigned long size_of_aranges PARAMS ((void));
+static enum dwarf_form value_format PARAMS ((dw_attr_ref));
+static void output_value_format PARAMS ((dw_attr_ref));
+static void output_abbrev_section PARAMS ((void));
+static void output_die PARAMS ((dw_die_ref));
+static void output_compilation_unit_header PARAMS ((void));
+static const char *dwarf2_name PARAMS ((tree, int));
+static void add_pubname PARAMS ((tree, dw_die_ref));
+static void output_pubnames PARAMS ((void));
+static void add_arange PARAMS ((tree, dw_die_ref));
+static void output_aranges PARAMS ((void));
+static void output_line_info PARAMS ((void));
+static dw_die_ref base_type_die PARAMS ((tree));
+static tree root_type PARAMS ((tree));
+static int is_base_type PARAMS ((tree));
+static dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref));
+static int type_is_enum PARAMS ((tree));
+static unsigned int reg_number PARAMS ((rtx));
+static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx));
+static dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long));
+static int is_based_loc PARAMS ((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode));
+static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx));
+static dw_loc_descr_ref loc_descriptor PARAMS ((rtx));
+static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int));
+static tree field_type PARAMS ((tree));
+static unsigned int simple_type_align_in_bits PARAMS ((tree));
+static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree));
+static HOST_WIDE_INT field_byte_offset PARAMS ((tree));
+static void add_AT_location_description PARAMS ((dw_die_ref,
+ enum dwarf_attribute, rtx));
+static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree));
+static void add_const_value_attribute PARAMS ((dw_die_ref, rtx));
+static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree));
+static void add_name_attribute PARAMS ((dw_die_ref, const char *));
+static void add_bound_info PARAMS ((dw_die_ref,
+ enum dwarf_attribute, tree));
+static void add_subscript_info PARAMS ((dw_die_ref, tree));
+static void add_byte_size_attribute PARAMS ((dw_die_ref, tree));
+static void add_bit_offset_attribute PARAMS ((dw_die_ref, tree));
+static void add_bit_size_attribute PARAMS ((dw_die_ref, tree));
+static void add_prototyped_attribute PARAMS ((dw_die_ref, tree));
+static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree));
+static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree));
+static void add_src_coords_attributes PARAMS ((dw_die_ref, tree));
+static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree));
+static void push_decl_scope PARAMS ((tree));
+static dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref));
+static void pop_decl_scope PARAMS ((void));
+static void add_type_attribute PARAMS ((dw_die_ref, tree, int, int,
+ dw_die_ref));
+static const char *type_tag PARAMS ((tree));
+static tree member_declared_type PARAMS ((tree));
+#if 0
+static const char *decl_start_label PARAMS ((tree));
+#endif
+static void gen_array_type_die PARAMS ((tree, dw_die_ref));
+static void gen_set_type_die PARAMS ((tree, dw_die_ref));
+#if 0
+static void gen_entry_point_die PARAMS ((tree, dw_die_ref));
+#endif
+static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref));
+static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref));
+static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref));
+static void gen_enumeration_type_die PARAMS ((tree, dw_die_ref));
+static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref));
+static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref));
+static void gen_formal_types_die PARAMS ((tree, dw_die_ref));
+static void gen_subprogram_die PARAMS ((tree, dw_die_ref));
+static void gen_variable_die PARAMS ((tree, dw_die_ref));
+static void gen_label_die PARAMS ((tree, dw_die_ref));
+static void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int));
+static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int));
+static void gen_field_die PARAMS ((tree, dw_die_ref));
+static void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref));
+static dw_die_ref gen_compile_unit_die PARAMS ((const char *));
+static void gen_string_type_die PARAMS ((tree, dw_die_ref));
+static void gen_inheritance_die PARAMS ((tree, dw_die_ref));
+static void gen_member_die PARAMS ((tree, dw_die_ref));
+static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref));
+static void gen_subroutine_type_die PARAMS ((tree, dw_die_ref));
+static void gen_typedef_die PARAMS ((tree, dw_die_ref));
+static void gen_type_die PARAMS ((tree, dw_die_ref));
+static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref));
+static void gen_block_die PARAMS ((tree, dw_die_ref, int));
+static void decls_for_scope PARAMS ((tree, dw_die_ref, int));
+static int is_redundant_typedef PARAMS ((tree));
+static void gen_decl_die PARAMS ((tree, dw_die_ref));
+static unsigned lookup_filename PARAMS ((const char *));
+static void add_incomplete_type PARAMS ((tree));
+static void retry_incomplete_types PARAMS ((void));
+static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
+static void gen_abstract_function PARAMS ((tree));
+static rtx save_rtx PARAMS ((rtx));
+static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
+static void reverse_die_lists PARAMS ((dw_die_ref));
+
+/* Section names used to hold DWARF debugging information. */
+#ifndef DEBUG_INFO_SECTION
+#define DEBUG_INFO_SECTION ".debug_info"
+#endif
+#ifndef ABBREV_SECTION
+#define ABBREV_SECTION ".debug_abbrev"
+#endif
+#ifndef ARANGES_SECTION
+#define ARANGES_SECTION ".debug_aranges"
+#endif
+#ifndef DW_MACINFO_SECTION
+#define DW_MACINFO_SECTION ".debug_macinfo"
+#endif
+#ifndef DEBUG_LINE_SECTION
+#define DEBUG_LINE_SECTION ".debug_line"
+#endif
+#ifndef LOC_SECTION
+#define LOC_SECTION ".debug_loc"
+#endif
+#ifndef PUBNAMES_SECTION
+#define PUBNAMES_SECTION ".debug_pubnames"
+#endif
+#ifndef STR_SECTION
+#define STR_SECTION ".debug_str"
+#endif
+
+/* Standard ELF section names for compiled code and data. */
+#ifndef TEXT_SECTION
+#define TEXT_SECTION ".text"
+#endif
+#ifndef DATA_SECTION
+#define DATA_SECTION ".data"
+#endif
+#ifndef BSS_SECTION
+#define BSS_SECTION ".bss"
+#endif
+
+/* Labels we insert at beginning sections we can reference instead of
+ the section names themselves. */
+
+#ifndef TEXT_SECTION_LABEL
+#define TEXT_SECTION_LABEL "Ltext"
+#endif
+#ifndef DEBUG_LINE_SECTION_LABEL
+#define DEBUG_LINE_SECTION_LABEL "Ldebug_line"
+#endif
+#ifndef DEBUG_INFO_SECTION_LABEL
+#define DEBUG_INFO_SECTION_LABEL "Ldebug_info"
+#endif
+#ifndef ABBREV_SECTION_LABEL
+#define ABBREV_SECTION_LABEL "Ldebug_abbrev"
+#endif
+
+
+/* Definitions of defaults for formats and names of various special
+ (artificial) labels which may be generated within this file (when the -g
+ options is used and DWARF_DEBUGGING_INFO is in effect.
+ If necessary, these may be overridden from within the tm.h file, but
+ typically, overriding these defaults is unnecessary. */
+
+static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+#ifndef TEXT_END_LABEL
+#define TEXT_END_LABEL "Letext"
+#endif
+#ifndef DATA_END_LABEL
+#define DATA_END_LABEL "Ledata"
+#endif
+#ifndef BSS_END_LABEL
+#define BSS_END_LABEL "Lebss"
+#endif
+#ifndef INSN_LABEL_FMT
+#define INSN_LABEL_FMT "LI%u_"
+#endif
+#ifndef BLOCK_BEGIN_LABEL
+#define BLOCK_BEGIN_LABEL "LBB"
+#endif
+#ifndef BLOCK_END_LABEL
+#define BLOCK_END_LABEL "LBE"
+#endif
+#ifndef BODY_BEGIN_LABEL
+#define BODY_BEGIN_LABEL "Lbb"
+#endif
+#ifndef BODY_END_LABEL
+#define BODY_END_LABEL "Lbe"
+#endif
+#ifndef LINE_CODE_LABEL
+#define LINE_CODE_LABEL "LM"
+#endif
+#ifndef SEPARATE_LINE_CODE_LABEL
+#define SEPARATE_LINE_CODE_LABEL "LSM"
+#endif
+\f
+/* We allow a language front-end to designate a function that is to be
+ called to "demangle" any name before it it put into a DIE. */
+
+static const char *(*demangle_name_func) PARAMS ((const char *));
+
+void
+dwarf2out_set_demangle_name_func (func)
+ const char *(*func) PARAMS ((const char *));
+{
+ demangle_name_func = func;
+}
+\f
+/* Return an rtx like ORIG which lives forever. If we're doing GC,
+ that means adding it to used_rtx_varray. If not, that means making
+ a copy on the permanent_obstack. */
+
+static rtx
+save_rtx (orig)
+ register rtx orig;
+{
+ if (ggc_p)
+ VARRAY_PUSH_RTX (used_rtx_varray, orig);
+ else
+ {
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ orig = copy_rtx (orig);
+ pop_obstacks ();
+ }
+
+ return orig;
+}
+
+/* Test if rtl node points to a pseudo register. */
+
+static inline int
+is_pseudo_reg (rtl)
+ register rtx rtl;
+{
+ return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER)
+ || (GET_CODE (rtl) == SUBREG
+ && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER));
+}
+
+/* Return a reference to a type, with its const and volatile qualifiers
+ removed. */
+
+static inline tree
+type_main_variant (type)
+ register tree type;
+{
+ type = TYPE_MAIN_VARIANT (type);
+
+ /* There really should be only one main variant among any group of variants
+ of a given type (and all of the MAIN_VARIANT values for all members of
+ the group should point to that one type) but sometimes the C front-end
+ messes this up for array types, so we work around that bug here. */
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ while (type != TYPE_MAIN_VARIANT (type))
+ type = TYPE_MAIN_VARIANT (type);
+
+ return type;
+}
+
+/* Return non-zero if the given type node represents a tagged type. */
+
+static inline int
+is_tagged_type (type)
+ register tree type;
+{
+ register enum tree_code code = TREE_CODE (type);
+
+ return (code == RECORD_TYPE || code == UNION_TYPE
+ || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
+}
+
+/* Convert a DIE tag into its string name. */
+
+static const char *
+dwarf_tag_name (tag)
+ register unsigned tag;
+{
+ switch (tag)
+ {
+ case DW_TAG_padding:
+ return "DW_TAG_padding";
+ case DW_TAG_array_type:
+ return "DW_TAG_array_type";
+ case DW_TAG_class_type:
+ return "DW_TAG_class_type";
+ case DW_TAG_entry_point:
+ return "DW_TAG_entry_point";
+ case DW_TAG_enumeration_type:
+ return "DW_TAG_enumeration_type";
+ case DW_TAG_formal_parameter:
+ return "DW_TAG_formal_parameter";
+ case DW_TAG_imported_declaration:
+ return "DW_TAG_imported_declaration";
+ case DW_TAG_label:
+ return "DW_TAG_label";
+ case DW_TAG_lexical_block:
+ return "DW_TAG_lexical_block";
+ case DW_TAG_member:
+ return "DW_TAG_member";
+ case DW_TAG_pointer_type:
+ return "DW_TAG_pointer_type";
+ case DW_TAG_reference_type:
+ return "DW_TAG_reference_type";
+ case DW_TAG_compile_unit:
+ return "DW_TAG_compile_unit";
+ case DW_TAG_string_type:
+ return "DW_TAG_string_type";
+ case DW_TAG_structure_type:
+ return "DW_TAG_structure_type";
+ case DW_TAG_subroutine_type:
+ return "DW_TAG_subroutine_type";
+ case DW_TAG_typedef:
+ return "DW_TAG_typedef";
+ case DW_TAG_union_type:
+ return "DW_TAG_union_type";
+ case DW_TAG_unspecified_parameters:
+ return "DW_TAG_unspecified_parameters";
+ case DW_TAG_variant:
+ return "DW_TAG_variant";
+ case DW_TAG_common_block:
+ return "DW_TAG_common_block";
+ case DW_TAG_common_inclusion:
+ return "DW_TAG_common_inclusion";
+ case DW_TAG_inheritance:
+ return "DW_TAG_inheritance";
+ case DW_TAG_inlined_subroutine:
+ return "DW_TAG_inlined_subroutine";
+ case DW_TAG_module:
+ return "DW_TAG_module";
+ case DW_TAG_ptr_to_member_type:
+ return "DW_TAG_ptr_to_member_type";
+ case DW_TAG_set_type:
+ return "DW_TAG_set_type";
+ case DW_TAG_subrange_type:
+ return "DW_TAG_subrange_type";
+ case DW_TAG_with_stmt:
+ return "DW_TAG_with_stmt";
+ case DW_TAG_access_declaration:
+ return "DW_TAG_access_declaration";
+ case DW_TAG_base_type:
+ return "DW_TAG_base_type";
+ case DW_TAG_catch_block:
+ return "DW_TAG_catch_block";
+ case DW_TAG_const_type:
+ return "DW_TAG_const_type";
+ case DW_TAG_constant:
+ return "DW_TAG_constant";
+ case DW_TAG_enumerator:
+ return "DW_TAG_enumerator";
+ case DW_TAG_file_type:
+ return "DW_TAG_file_type";
+ case DW_TAG_friend:
+ return "DW_TAG_friend";
+ case DW_TAG_namelist:
+ return "DW_TAG_namelist";
+ case DW_TAG_namelist_item:
+ return "DW_TAG_namelist_item";
+ case DW_TAG_packed_type:
+ return "DW_TAG_packed_type";
+ case DW_TAG_subprogram:
+ return "DW_TAG_subprogram";
+ case DW_TAG_template_type_param:
+ return "DW_TAG_template_type_param";
+ case DW_TAG_template_value_param:
+ return "DW_TAG_template_value_param";
+ case DW_TAG_thrown_type:
+ return "DW_TAG_thrown_type";
+ case DW_TAG_try_block:
+ return "DW_TAG_try_block";
+ case DW_TAG_variant_part:
+ return "DW_TAG_variant_part";
+ case DW_TAG_variable:
+ return "DW_TAG_variable";
+ case DW_TAG_volatile_type:
+ return "DW_TAG_volatile_type";
+ case DW_TAG_MIPS_loop:
+ return "DW_TAG_MIPS_loop";
+ case DW_TAG_format_label:
+ return "DW_TAG_format_label";
+ case DW_TAG_function_template:
+ return "DW_TAG_function_template";
+ case DW_TAG_class_template:
+ return "DW_TAG_class_template";
+ default:
+ return "DW_TAG_<unknown>";
+ }
+}
+
+/* Convert a DWARF attribute code into its string name. */
+
+static const char *
+dwarf_attr_name (attr)
+ register unsigned attr;
+{
+ switch (attr)
+ {
+ case DW_AT_sibling:
+ return "DW_AT_sibling";
+ case DW_AT_location:
+ return "DW_AT_location";
+ case DW_AT_name:
+ return "DW_AT_name";
+ case DW_AT_ordering:
+ return "DW_AT_ordering";
+ case DW_AT_subscr_data:
+ return "DW_AT_subscr_data";
+ case DW_AT_byte_size:
+ return "DW_AT_byte_size";
+ case DW_AT_bit_offset:
+ return "DW_AT_bit_offset";
+ case DW_AT_bit_size:
+ return "DW_AT_bit_size";
+ case DW_AT_element_list:
+ return "DW_AT_element_list";
+ case DW_AT_stmt_list:
+ return "DW_AT_stmt_list";
+ case DW_AT_low_pc:
+ return "DW_AT_low_pc";
+ case DW_AT_high_pc:
+ return "DW_AT_high_pc";
+ case DW_AT_language:
+ return "DW_AT_language";
+ case DW_AT_member:
+ return "DW_AT_member";
+ case DW_AT_discr:
+ return "DW_AT_discr";
+ case DW_AT_discr_value:
+ return "DW_AT_discr_value";
+ case DW_AT_visibility:
+ return "DW_AT_visibility";
+ case DW_AT_import:
+ return "DW_AT_import";
+ case DW_AT_string_length:
+ return "DW_AT_string_length";
+ case DW_AT_common_reference:
+ return "DW_AT_common_reference";
+ case DW_AT_comp_dir:
+ return "DW_AT_comp_dir";
+ case DW_AT_const_value:
+ return "DW_AT_const_value";
+ case DW_AT_containing_type:
+ return "DW_AT_containing_type";
+ case DW_AT_default_value:
+ return "DW_AT_default_value";
+ case DW_AT_inline:
+ return "DW_AT_inline";
+ case DW_AT_is_optional:
+ return "DW_AT_is_optional";
+ case DW_AT_lower_bound:
+ return "DW_AT_lower_bound";
+ case DW_AT_producer:
+ return "DW_AT_producer";
+ case DW_AT_prototyped:
+ return "DW_AT_prototyped";
+ case DW_AT_return_addr:
+ return "DW_AT_return_addr";
+ case DW_AT_start_scope:
+ return "DW_AT_start_scope";
+ case DW_AT_stride_size:
+ return "DW_AT_stride_size";
+ case DW_AT_upper_bound:
+ return "DW_AT_upper_bound";
+ case DW_AT_abstract_origin:
+ return "DW_AT_abstract_origin";
+ case DW_AT_accessibility:
+ return "DW_AT_accessibility";
+ case DW_AT_address_class:
+ return "DW_AT_address_class";
+ case DW_AT_artificial:
+ return "DW_AT_artificial";
+ case DW_AT_base_types:
+ return "DW_AT_base_types";
+ case DW_AT_calling_convention:
+ return "DW_AT_calling_convention";
+ case DW_AT_count:
+ return "DW_AT_count";
+ case DW_AT_data_member_location:
+ return "DW_AT_data_member_location";
+ case DW_AT_decl_column:
+ return "DW_AT_decl_column";
+ case DW_AT_decl_file:
+ return "DW_AT_decl_file";
+ case DW_AT_decl_line:
+ return "DW_AT_decl_line";
+ case DW_AT_declaration:
+ return "DW_AT_declaration";
+ case DW_AT_discr_list:
+ return "DW_AT_discr_list";
+ case DW_AT_encoding:
+ return "DW_AT_encoding";
+ case DW_AT_external:
+ return "DW_AT_external";
+ case DW_AT_frame_base:
+ return "DW_AT_frame_base";
+ case DW_AT_friend:
+ return "DW_AT_friend";
+ case DW_AT_identifier_case:
+ return "DW_AT_identifier_case";
+ case DW_AT_macro_info:
+ return "DW_AT_macro_info";
+ case DW_AT_namelist_items:
+ return "DW_AT_namelist_items";
+ case DW_AT_priority:
+ return "DW_AT_priority";
+ case DW_AT_segment:
+ return "DW_AT_segment";
+ case DW_AT_specification:
+ return "DW_AT_specification";
+ case DW_AT_static_link:
+ return "DW_AT_static_link";
+ case DW_AT_type:
+ return "DW_AT_type";
+ case DW_AT_use_location:
+ return "DW_AT_use_location";
+ case DW_AT_variable_parameter:
+ return "DW_AT_variable_parameter";
+ case DW_AT_virtuality:
+ return "DW_AT_virtuality";
+ case DW_AT_vtable_elem_location:
+ return "DW_AT_vtable_elem_location";
+
+ case DW_AT_MIPS_fde:
+ return "DW_AT_MIPS_fde";
+ case DW_AT_MIPS_loop_begin:
+ return "DW_AT_MIPS_loop_begin";
+ case DW_AT_MIPS_tail_loop_begin:
+ return "DW_AT_MIPS_tail_loop_begin";
+ case DW_AT_MIPS_epilog_begin:
+ return "DW_AT_MIPS_epilog_begin";
+ case DW_AT_MIPS_loop_unroll_factor:
+ return "DW_AT_MIPS_loop_unroll_factor";
+ case DW_AT_MIPS_software_pipeline_depth:
+ return "DW_AT_MIPS_software_pipeline_depth";
+ case DW_AT_MIPS_linkage_name:
+ return "DW_AT_MIPS_linkage_name";
+ case DW_AT_MIPS_stride:
+ return "DW_AT_MIPS_stride";
+ case DW_AT_MIPS_abstract_name:
+ return "DW_AT_MIPS_abstract_name";
+ case DW_AT_MIPS_clone_origin:
+ return "DW_AT_MIPS_clone_origin";
+ case DW_AT_MIPS_has_inlines:
+ return "DW_AT_MIPS_has_inlines";
+
+ case DW_AT_sf_names:
+ return "DW_AT_sf_names";
+ case DW_AT_src_info:
+ return "DW_AT_src_info";
+ case DW_AT_mac_info:
+ return "DW_AT_mac_info";
+ case DW_AT_src_coords:
+ return "DW_AT_src_coords";
+ case DW_AT_body_begin:
+ return "DW_AT_body_begin";
+ case DW_AT_body_end:
+ return "DW_AT_body_end";
+ default:
+ return "DW_AT_<unknown>";
+ }
+}
+
+/* Convert a DWARF value form code into its string name. */
+
+static const char *
+dwarf_form_name (form)
+ register unsigned form;
+{
+ switch (form)
+ {
+ case DW_FORM_addr:
+ return "DW_FORM_addr";
+ case DW_FORM_block2:
+ return "DW_FORM_block2";
+ case DW_FORM_block4:
+ return "DW_FORM_block4";
+ case DW_FORM_data2:
+ return "DW_FORM_data2";
+ case DW_FORM_data4:
+ return "DW_FORM_data4";
+ case DW_FORM_data8:
+ return "DW_FORM_data8";
+ case DW_FORM_string:
+ return "DW_FORM_string";
+ case DW_FORM_block:
+ return "DW_FORM_block";
+ case DW_FORM_block1:
+ return "DW_FORM_block1";
+ case DW_FORM_data1:
+ return "DW_FORM_data1";
+ case DW_FORM_flag:
+ return "DW_FORM_flag";
+ case DW_FORM_sdata:
+ return "DW_FORM_sdata";
+ case DW_FORM_strp:
+ return "DW_FORM_strp";
+ case DW_FORM_udata:
+ return "DW_FORM_udata";
+ case DW_FORM_ref_addr:
+ return "DW_FORM_ref_addr";
+ case DW_FORM_ref1:
+ return "DW_FORM_ref1";
+ case DW_FORM_ref2:
+ return "DW_FORM_ref2";
+ case DW_FORM_ref4:
+ return "DW_FORM_ref4";
+ case DW_FORM_ref8:
+ return "DW_FORM_ref8";
+ case DW_FORM_ref_udata:
+ return "DW_FORM_ref_udata";
+ case DW_FORM_indirect:
+ return "DW_FORM_indirect";
default:
- return "OP_<unknown>";
+ return "DW_FORM_<unknown>";
}
}
lookup_type_die (type)
register tree type;
{
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
}
decl_die_table[decl_id] = decl_die;
}
-
-/* Return a pointer to a newly allocated location description. Location
- descriptions are simple expression terms that can be strung
- together to form more complicated location (address) descriptions. */
-
-static inline dw_loc_descr_ref
-new_loc_descr (op, oprnd1, oprnd2)
- register enum dwarf_location_atom op;
- register unsigned long oprnd1;
- register unsigned long oprnd2;
-{
- register dw_loc_descr_ref descr
- = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node));
-
- descr->dw_loc_next = NULL;
- descr->dw_loc_opc = op;
- descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
- descr->dw_loc_oprnd1.v.val_unsigned = oprnd1;
- descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const;
- descr->dw_loc_oprnd2.v.val_unsigned = oprnd2;
-
- return descr;
-}
-
-/* Add a location description term to a location description expression. */
-
-static inline void
-add_loc_descr (list_head, descr)
- register dw_loc_descr_ref *list_head;
- register dw_loc_descr_ref descr;
-{
- register dw_loc_descr_ref *d;
-
- /* Find the end of the chain. */
- for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
- ;
-
- *d = descr;
-}
\f
/* Keep track of the number of spaces used to indent the
output of the debugging routines that print the structure of
/* Traverse the DIE, reverse its lists of attributes and children, and
add a sibling attribute if it may have the effect of speeding up
- access to siblings. To save some space, avoid generating sibling
- attributes for DIE's without children. */
-
-static void
-add_sibling_attributes (die)
- register dw_die_ref die;
-{
- register dw_die_ref c;
-
- reverse_die_lists (die);
-
- if (die != comp_unit_die && die->die_sib && die->die_child != NULL)
- /* Add the sibling link to the front of the attribute list. */
- add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
-
- for (c = die->die_child; c != NULL; c = c->die_sib)
- add_sibling_attributes (c);
-}
-
-/* The format of each DIE (and its attribute value pairs)
- is encoded in an abbreviation table. This routine builds the
- abbreviation table and assigns a unique abbreviation id for
- each abbreviation entry. The children of each die are visited
- recursively. */
-
-static void
-build_abbrev_table (die)
- register dw_die_ref die;
-{
- register unsigned long abbrev_id;
- register unsigned long n_alloc;
- register dw_die_ref c;
- register dw_attr_ref d_attr, a_attr;
- for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
- {
- register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
-
- if (abbrev->die_tag == die->die_tag)
- {
- if ((abbrev->die_child != NULL) == (die->die_child != NULL))
- {
- a_attr = abbrev->die_attr;
- d_attr = die->die_attr;
-
- while (a_attr != NULL && d_attr != NULL)
- {
- if ((a_attr->dw_attr != d_attr->dw_attr)
- || (value_format (a_attr) != value_format (d_attr)))
- break;
-
- a_attr = a_attr->dw_attr_next;
- d_attr = d_attr->dw_attr_next;
- }
-
- if (a_attr == NULL && d_attr == NULL)
- break;
- }
- }
- }
-
- if (abbrev_id >= abbrev_die_table_in_use)
- {
- if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
- {
- n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
- abbrev_die_table
- = (dw_die_ref *) xrealloc (abbrev_die_table,
- sizeof (dw_die_ref) * n_alloc);
-
- bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
- (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
- abbrev_die_table_allocated = n_alloc;
- }
-
- ++abbrev_die_table_in_use;
- abbrev_die_table[abbrev_id] = die;
- }
-
- die->die_abbrev = abbrev_id;
- for (c = die->die_child; c != NULL; c = c->die_sib)
- build_abbrev_table (c);
-}
-\f
-/* Return the size of a string, including the null byte.
-
- This used to treat backslashes as escapes, and hence they were not included
- in the count. However, that conflicts with what ASM_OUTPUT_ASCII does,
- which treats a backslash as a backslash, escaping it if necessary, and hence
- we must include them in the count. */
-
-static unsigned long
-size_of_string (str)
- register const char *str;
-{
- return strlen (str) + 1;
-}
-
-/* Return the size of a location descriptor. */
-
-static unsigned long
-size_of_loc_descr (loc)
- register dw_loc_descr_ref loc;
-{
- register unsigned long size = 1;
-
- switch (loc->dw_loc_opc)
- {
- case DW_OP_addr:
- size += DWARF2_ADDR_SIZE;
- break;
- case DW_OP_const1u:
- case DW_OP_const1s:
- size += 1;
- break;
- case DW_OP_const2u:
- case DW_OP_const2s:
- size += 2;
- break;
- case DW_OP_const4u:
- case DW_OP_const4s:
- size += 4;
- break;
- case DW_OP_const8u:
- case DW_OP_const8s:
- size += 8;
- break;
- case DW_OP_constu:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
- break;
- case DW_OP_consts:
- size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
- break;
- case DW_OP_pick:
- size += 1;
- break;
- case DW_OP_plus_uconst:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
- break;
- case DW_OP_skip:
- case DW_OP_bra:
- size += 2;
- break;
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
- break;
- case DW_OP_regx:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
- break;
- case DW_OP_fbreg:
- size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
- break;
- case DW_OP_bregx:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
- size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
- break;
- case DW_OP_piece:
- size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
- break;
- case DW_OP_deref_size:
- case DW_OP_xderef_size:
- size += 1;
- break;
- default:
- break;
- }
+ access to siblings. To save some space, avoid generating sibling
+ attributes for DIE's without children. */
- return size;
+static void
+add_sibling_attributes (die)
+ register dw_die_ref die;
+{
+ register dw_die_ref c;
+
+ reverse_die_lists (die);
+
+ if (die != comp_unit_die && die->die_sib && die->die_child != NULL)
+ /* Add the sibling link to the front of the attribute list. */
+ add_AT_die_ref (die, DW_AT_sibling, die->die_sib);
+
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ add_sibling_attributes (c);
}
-/* Return the size of a series of location descriptors. */
+/* The format of each DIE (and its attribute value pairs)
+ is encoded in an abbreviation table. This routine builds the
+ abbreviation table and assigns a unique abbreviation id for
+ each abbreviation entry. The children of each die are visited
+ recursively. */
-static unsigned long
-size_of_locs (loc)
- register dw_loc_descr_ref loc;
+static void
+build_abbrev_table (die)
+ register dw_die_ref die;
{
- register unsigned long size = 0;
+ register unsigned long abbrev_id;
+ register unsigned long n_alloc;
+ register dw_die_ref c;
+ register dw_attr_ref d_attr, a_attr;
+ for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+ {
+ register dw_die_ref abbrev = abbrev_die_table[abbrev_id];
- for (; loc != NULL; loc = loc->dw_loc_next)
- size += size_of_loc_descr (loc);
+ if (abbrev->die_tag == die->die_tag)
+ {
+ if ((abbrev->die_child != NULL) == (die->die_child != NULL))
+ {
+ a_attr = abbrev->die_attr;
+ d_attr = die->die_attr;
- return size;
+ while (a_attr != NULL && d_attr != NULL)
+ {
+ if ((a_attr->dw_attr != d_attr->dw_attr)
+ || (value_format (a_attr) != value_format (d_attr)))
+ break;
+
+ a_attr = a_attr->dw_attr_next;
+ d_attr = d_attr->dw_attr_next;
+ }
+
+ if (a_attr == NULL && d_attr == NULL)
+ break;
+ }
+ }
+ }
+
+ if (abbrev_id >= abbrev_die_table_in_use)
+ {
+ if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
+ {
+ n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
+ abbrev_die_table
+ = (dw_die_ref *) xrealloc (abbrev_die_table,
+ sizeof (dw_die_ref) * n_alloc);
+
+ bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated],
+ (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
+ abbrev_die_table_allocated = n_alloc;
+ }
+
+ ++abbrev_die_table_in_use;
+ abbrev_die_table[abbrev_id] = die;
+ }
+
+ die->die_abbrev = abbrev_id;
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ build_abbrev_table (c);
+}
+\f
+/* Return the size of a string, including the null byte.
+
+ This used to treat backslashes as escapes, and hence they were not included
+ in the count. However, that conflicts with what ASM_OUTPUT_ASCII does,
+ which treats a backslash as a backslash, escaping it if necessary, and hence
+ we must include them in the count. */
+
+static unsigned long
+size_of_string (str)
+ register const char *str;
+{
+ return strlen (str) + 1;
}
/* Return the power-of-two number of bytes necessary to represent VALUE. */
}
break;
case dw_val_class_const:
- size += 4;
+ size += size_of_sleb128 (AT_int (a));
break;
case dw_val_class_unsigned_const:
size += constant_size (AT_unsigned (a));
abort ();
}
case dw_val_class_const:
- return DW_FORM_data4;
+ return DW_FORM_sdata;
case dw_val_class_unsigned_const:
switch (constant_size (AT_unsigned (a)))
{
fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP);
}
-/* Output location description stack opcode's operands (if any). */
-
-static void
-output_loc_operands (loc)
- register dw_loc_descr_ref loc;
-{
- register dw_val_ref val1 = &loc->dw_loc_oprnd1;
- register dw_val_ref val2 = &loc->dw_loc_oprnd2;
-
- switch (loc->dw_loc_opc)
- {
- case DW_OP_addr:
- ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_const1u:
- case DW_OP_const1s:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_const2u:
- case DW_OP_const2s:
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_const4u:
- case DW_OP_const4s:
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_const8u:
- case DW_OP_const8s:
- abort ();
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_constu:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_consts:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_pick:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_plus_uconst:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_skip:
- case DW_OP_bra:
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_regx:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_fbreg:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_bregx:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
- output_sleb128 (val2->v.val_int);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_piece:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
- break;
- case DW_OP_deref_size:
- case DW_OP_xderef_size:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag);
- fputc ('\n', asm_out_file);
- break;
- default:
- break;
- }
-}
-
/* Output the DIE and its attributes. Called recursively to generate
the definitions of each child DIE. */
register dw_attr_ref a;
register dw_die_ref c;
register unsigned long size;
- register dw_loc_descr_ref loc;
output_uleb128 (die->die_abbrev);
if (flag_debug_asm)
ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
fputc ('\n', asm_out_file);
- for (loc = AT_loc (a); loc != NULL; loc = loc->dw_loc_next)
- {
- /* Output the opcode. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
- if (flag_debug_asm)
- fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
- dwarf_stack_op_name (loc->dw_loc_opc));
-
- fputc ('\n', asm_out_file);
- /* Output the operand(s) (if any). */
- output_loc_operands (loc);
- }
+ output_loc_sequence (AT_loc (a));
break;
case dw_val_class_const:
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, AT_int (a));
+ /* ??? It would be slightly more efficient to use a scheme like is
+ used for unsigned constants below, but gdb 4.x does not sign
+ extend. Gdb 5.x does sign extend. */
+ output_sleb128 (AT_int (a));
break;
case dw_val_class_unsigned_const:
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, AT_unsigned (a));
break;
case 8:
- ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
- a->dw_attr_val.v.val_long_long.hi,
- a->dw_attr_val.v.val_long_long.low);
+ ASM_OUTPUT_DWARF_DATA8 (asm_out_file, AT_unsigned (a));
break;
default:
abort ();
ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
- a->dw_attr_val.v.val_long_long.hi,
- a->dw_attr_val.v.val_long_long.low);
+ ASM_OUTPUT_DWARF_CONST_DOUBLE (asm_out_file,
+ a->dw_attr_val.v.val_long_long.hi,
+ a->dw_attr_val.v.val_long_long.low);
if (flag_debug_asm)
fprintf (asm_out_file,
return TREE_CODE (type) == ENUMERAL_TYPE;
}
+/* Return the register number described by a given RTL node. */
+
+static unsigned int
+reg_number (rtl)
+ register rtx rtl;
+{
+ register unsigned regno = REGNO (rtl);
+
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ warning ("internal regno botch: regno = %d\n", regno);
+ regno = 0;
+ }
+
+ regno = DBX_REGISTER_NUMBER (regno);
+ return regno;
+}
+
/* Return a location descriptor that designates a machine register. */
static dw_loc_descr_ref
if (declaration && ! local_scope_p (context_die))
abort ();
+ /* Fixup die_parent for the abstract instance of a nested
+ inline function. */
+ if (old_die && old_die->die_parent == NULL)
+ add_child_die (context_die, old_die);
+
subr_die = new_die (DW_TAG_subprogram, context_die);
add_abstract_origin_attribute (subr_die, origin);
}
gen_array_type_die (type, context_die);
break;
+ case VECTOR_TYPE:
+ gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die);
+ break;
+
case ENUMERAL_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
}
-/* We've decided not to emit any debugging information for BLOCK; make
- sure that we don't end up with orphans as a result. */
+/* Returns nonzero if it is appropriate not to emit any debugging
+ information for BLOCK, because it doesn't contain any instructions.
-void
+ Don't allow this for blocks with nested functions or local classes
+ as we would end up with orphans, and in the presence of scheduling
+ we may end up calling them anyway. */
+
+int
dwarf2out_ignore_block (block)
tree block;
{
tree decl;
for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
- {
- dw_die_ref die;
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- die = lookup_decl_die (decl);
- else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
- die = lookup_type_die (TREE_TYPE (decl));
- else
- die = NULL;
-
- /* Just give them a dummy value for parent so dwarf2out_finish
- doesn't blow up; we would use add_child_die if we really
- wanted to add them to comp_unit_die's children. */
- if (die && die->die_parent == 0)
- die->die_parent = comp_unit_die;
- }
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)))
+ return 0;
+ return 1;
}
/* Output a marker (i.e. a label) at a point in the assembly code which