#include "config.h"
-#ifdef DWARF2_DEBUGGING_INFO
+/* The first part of this file deals with the DWARF 2 frame unwind
+ information, which is also used by the GCC efficient exception handling
+ mechanism. The second part, controlled only by an #ifdef
+ DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging
+ information. */
+
+#if defined (DWARF2_DEBUGGING_INFO) || defined (INCOMING_RETURN_ADDR_RTX)
+
#include <stdio.h>
#include <setjmp.h>
#include "dwarf2.h"
#include "output.h"
#include "defaults.h"
#include "expr.h"
+#include "except.h"
/* #define NDEBUG 1 */
#include "assert.h"
-extern char *getpwd ();
-
-/* 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. */
-
#ifndef __GNUC__
#define inline
#endif
-/* 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. */
-
-/* Each DIE may have a series of attribute/value pairs. Values
- can take on several forms. The forms that are used in this
- implementation are listed below. */
-
-typedef enum
-{
- dw_val_class_addr,
- dw_val_class_loc,
- dw_val_class_const,
- dw_val_class_unsigned_const,
- dw_val_class_long_long,
- dw_val_class_float,
- dw_val_class_flag,
- dw_val_class_die_ref,
- dw_val_class_fde_ref,
- dw_val_class_lbl_id,
- dw_val_class_section_offset,
- dw_val_class_str
-}
-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 dw_cfi_struct *dw_cfi_ref;
typedef struct dw_fde_struct *dw_fde_ref;
typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref;
-typedef struct pubname_struct *pubname_ref;
-typedef dw_die_ref *arange_ref;
-
-/* Describe a double word constant value. */
-
-typedef struct dw_long_long_struct
-{
- unsigned long hi;
- unsigned long low;
-}
-dw_long_long_const;
-
-/* Describe a floating point constant value. */
-
-typedef struct dw_fp_struct
-{
- long *array;
- unsigned length;
-}
-dw_float_const;
-
-/* Each entry in the line_info_table maintains the file and
- line nuber 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 attibute's value, as it is
- represented internally. */
-
-typedef struct dw_val_struct
-{
- dw_val_class val_class;
- union
- {
- char *val_addr;
- dw_loc_descr_ref val_loc;
- long int val_int;
- long unsigned val_unsigned;
- dw_long_long_const val_long_long;
- dw_float_const val_float;
- dw_die_ref val_die_ref;
- unsigned val_fde_index;
- char *val_str;
- char *val_lbl_id;
- char *val_section;
- unsigned char val_flag;
- }
- v;
-}
-dw_val_node;
-
-/* Locations in memory are described using a sequence of stack machine
- operations. */
-
-typedef struct dw_loc_descr_struct
-{
- dw_loc_descr_ref dw_loc_next;
- enum dwarf_location_atom dw_loc_opc;
- dw_val_node dw_loc_oprnd1;
- dw_val_node dw_loc_oprnd2;
-}
-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;
/* Call frames are described using a sequence of Call Frame
Information instructions. The register number, offset
}
dw_fde_node;
-/* The Debugging Information Entry (DIE) structure */
-
-typedef struct die_struct
-{
- enum dwarf_tag die_tag;
- dw_attr_ref die_attr;
- dw_attr_ref die_attr_last;
- dw_die_ref die_parent;
- dw_die_ref die_child;
- dw_die_ref die_child_last;
- 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;
-
-/* 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))))
-
-/* Information concerning the compilation unit's programming
- language, and compiler version. */
-
-extern int flag_traditional;
-extern char *version_string;
-extern char *language_string;
-
/* Maximum size (in bytes) of an artificially generated label. */
#define MAX_ARTIFICIAL_LABEL_BYTES 30
#define DWARF_VERSION 2
-/* 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)
-
/* Round SIZE up to the nearest BOUNDARY. */
#define DWARF_ROUND(SIZE,BOUNDARY) \
(((SIZE) + (BOUNDARY) - 1) & ~((BOUNDARY) - 1))
-/* Fixed size portion of the address range info. */
-#define DWARF_ARANGES_HEADER_SIZE \
- (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
-
/* Fixed size portion of the CIE (including the length field). */
#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5)
/* Fixed size portion of the FDE. */
#define DWARF_FDE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2 * PTR_SIZE)
-/* 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;
-
/* This location is used by calc_fde_sizes() to keep track
the offset of each FDE within the .debug_frame section. */
static unsigned long next_fde_offset;
-/* Record the root of the DIE's built for the current compilation unit. */
-static dw_die_ref comp_unit_die;
+/* A pointer to the base of a table that contains frame description
+ information for each routine. */
+static dw_fde_ref fde_table;
-/* The number of DIEs with a NULL parent waiting to be relocated. */
-static int limbo_die_count;
+/* Number of elements currently allocated for fde_table. */
+static unsigned fde_table_allocated;
-/* Pointer to an array of filenames referenced by this compilation unit. */
-static char **file_table;
+/* Number of elements in fde_table currently in use. */
+static unsigned fde_table_in_use;
-/* 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 char *primary_filename;
-
-/* For Dwarf output, we must assign lexical-blocks id numbers in the order in
- which their beginnings are encountered. We output Dwarf debugging info
- that refers to the beginnings and ends of the ranges of code for each
- lexical block. The labels themselves are generated in final.c, which
- assigns numbers to the blocks in the same way. */
-static unsigned next_block_number = 2;
-
-/* 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, indentifying 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 unsigned decl_scope_table_allocated;
-
-/* Current level of nesting of declataion scopes. */
-static unsigned 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 frame description
- information for each routine. */
-static dw_fde_ref fde_table;
-
-/* Number of elements currently allocated for fde_table. */
-static unsigned fde_table_allocated;
-
-/* Number of elements in fde_table currently in use. */
-static unsigned fde_table_in_use;
-
-/* Size (in elements) of increments by which we may expand the
- fde_table. */
-#define FDE_TABLE_INCREMENT 256
+/* Size (in elements) of increments by which we may expand the
+ fde_table. */
+#define FDE_TABLE_INCREMENT 256
/* A list of call frame insns for the CIE. */
static dw_cfi_ref cie_cfi_head;
-/* 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 pending types which we haven't
- generated DIEs for yet, but which we will have to come back to
- later on. */
-
-static tree *pending_types_list;
-
-/* Number of elements currently allocated for the pending_types_list. */
-static unsigned pending_types_allocated;
-
-/* Number of elements of pending_types_list currently in use. */
-static unsigned pending_types;
-
-/* Size (in elements) of increments by which we may expand the pending
- types list. Actually, a single hunk of space of this size should
- be enough for most typical programs. */
-#define PENDING_TYPES_INCREMENT 64
-
/* The number of the current function definition for which debugging
information is being generated. These numbers range from 1 up to the
maximum number of function definitions contained within the current
associated with the current function (body) definition. */
static unsigned current_funcdef_fde;
-/* Record whether the function being analyzed contains inlined functions. */
-static int current_function_has_inlines;
-static int comp_unit_has_inlines;
-
-/* A pointer to the ..._DECL node which we have most recently been working
- on. We keep this around just in case something about it looks screwy and
- we want to tell the user what the source coordinates for the actual
- declaration are. */
-static tree dwarf_last_decl;
-
/* Forward declarations for functions defined in this file. */
static char *stripattributes PROTO((char *));
-static void addr_const_to_string PROTO((char *, rtx));
-static char *addr_to_string PROTO((rtx));
-static int is_pseudo_reg PROTO((rtx));
-static tree type_main_variant PROTO((tree));
-static int is_tagged_type PROTO((tree));
-static char *dwarf_tag_name PROTO((unsigned));
-static char *dwarf_attr_name PROTO((unsigned));
-static char *dwarf_form_name PROTO((unsigned));
-static char *dwarf_stack_op_name PROTO((unsigned));
-static char *dwarf_type_encoding_name PROTO((unsigned));
-static char *dward_cfi_name PROTO((unsigned));
-static tree decl_ultimate_origin PROTO((tree));
-static tree block_ultimate_origin PROTO((tree));
-static tree decl_class_context PROTO((tree));
-static void add_dwarf_attr PROTO((dw_die_ref, dw_attr_ref));
-static void add_AT_flag PROTO((dw_die_ref,
- enum dwarf_attribute,
- unsigned));
-static void add_AT_int PROTO((dw_die_ref,
- enum dwarf_attribute, long));
-static void add_AT_unsigned PROTO((dw_die_ref,
- enum dwarf_attribute,
- unsigned long));
-static void add_AT_long_long PROTO((dw_die_ref,
- enum dwarf_attribute,
- unsigned long, unsigned long));
-static void add_AT_float PROTO((dw_die_ref,
- enum dwarf_attribute,
- unsigned, long *));
-static void add_AT_string PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
-static void add_AT_die_ref PROTO((dw_die_ref,
- enum dwarf_attribute,
- dw_die_ref));
-static void add_AT_fde_ref PROTO((dw_die_ref,
- enum dwarf_attribute,
- unsigned));
-static void add_AT_loc PROTO((dw_die_ref,
- enum dwarf_attribute,
- dw_loc_descr_ref));
-static void add_AT_addr PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
-static void add_AT_lbl_id PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
-static void add_AT_setion_offset PROTO((dw_die_ref,
- enum dwarf_attribute, char *));
-static int is_extern_subr_die PROTO((dw_die_ref));
-static dw_attr_ref get_AT PROTO((dw_die_ref,
- enum dwarf_attribute));
-static char *get_AT_low_pc PROTO((dw_die_ref));
-static char *get_AT_hi_pc PROTO((dw_die_ref));
-static char *get_AT_string PROTO((dw_die_ref,
- enum dwarf_attribute));
-static int get_AT_flag PROTO((dw_die_ref,
- enum dwarf_attribute));
-static unsigned get_AT_unsigned PROTO((dw_die_ref,
- enum dwarf_attribute));
-static int is_c_family PROTO((void));
-static int is_fortran PROTO((void));
-static void remove_AT PROTO((dw_die_ref,
- enum dwarf_attribute));
-static void remove_children PROTO((dw_die_ref));
-static void add_child_die PROTO((dw_die_ref, dw_die_ref));
-static dw_die_ref new_die PROTO((enum dwarf_tag, dw_die_ref));
-static dw_die_ref lookup_type_die PROTO((tree));
-static void equate_type_number_to_die PROTO((tree, dw_die_ref));
-static dw_die_ref lookup_decl_die PROTO((tree));
-static void equate_decl_number_to_die PROTO((tree, dw_die_ref));
-static dw_loc_descr_ref new_loc_descr PROTO((enum dwarf_location_atom,
- unsigned long, unsigned long));
-static void add_loc_descr PROTO((dw_loc_descr_ref *,
- dw_loc_descr_ref));
-static dw_cfi_ref new_cfe PROTO((void));
-static void add_cfe PROTO((dw_cfi_ref *, dw_cfi_ref));
-static void print_spaces PROTO((FILE *));
-static void print_die PROTO((dw_die_ref, FILE *));
-static void print_dwarf_line_table PROTO((FILE *));
-static void add_sibling_atttributes PROTO((dw_die_ref));
-static void build_abbrev_table PROTO((dw_die_ref));
+static char *dwarf_cfi_name PROTO((unsigned));
+static dw_cfi_ref new_cfi PROTO((void));
+static void add_cfi PROTO((dw_cfi_ref *, dw_cfi_ref));
static unsigned long size_of_uleb128 PROTO((unsigned long));
static unsigned long size_of_sleb128 PROTO((long));
-static unsigned long size_of_string PROTO((char *));
-static unsigned long size_of_loc_descr PROTO((dw_loc_descr_ref));
-static unsigned long size_of_locs PROTO((dw_loc_descr_ref));
-static int constant_size PROTO((long unsigned));
-static unsigned long size_of_die PROTO((dw_die_ref));
-static void calc_die_sizes PROTO((dw_die_ref));
-static unsigned long size_of_prolog PROTO((void));
-static unsigned long size_of_line_info PROTO((void));
-static unsigned long size_of_pubnames PROTO((void));
-static unsigned long size_of_aranges PROTO((void));
static void output_uleb128 PROTO((unsigned long));
static void output_sleb128 PROTO((long));
-static enum dwarf_form value_format PROTO((dw_val_ref));
-static void output_value_format PROTO((dw_val_ref));
-static void output_abbrev_section PROTO((void));
-static void output_loc_operands PROTO((dw_loc_descr_ref));
-static unsigned long sibling_offset PROTO((dw_die_ref));
-static void output_die PROTO((dw_die_ref));
-static void output_compilation_unit_header PROTO((void));
static char *dwarf2out_cfi_label PROTO((void));
static void add_fde_cfi PROTO((char *, dw_cfi_ref));
static void lookup_cfa_1 PROTO((dw_cfi_ref, unsigned long *,
static unsigned long size_of_fde PROTO((dw_fde_ref, unsigned long *));
static void calc_fde_sizes PROTO((void));
static void output_cfi PROTO((dw_cfi_ref, dw_fde_ref));
-static void output_call_frame_info PROTO((void));
-static char *dwarf2_name PROTO((tree, int));
-static void add_pubname PROTO((tree, dw_die_ref));
-static void output_pubnames PROTO((void));
-static void add_arrange PROTO((tree, dw_die_ref));
-static void output_arranges PROTO((void));
-static void output_line_info PROTO((void));
-static int is_body_block PROTO((tree));
-static dw_die_ref base_type_die PROTO((tree));
-static tree root_type PROTO((tree));
-static int is_base_type PROTO((tree));
-static dw_die_ref modified_type_die PROTO((tree, int, int, dw_die_ref));
-static int type_is_enum PROTO((tree));
+static void output_call_frame_info PROTO((int));
static unsigned reg_number PROTO((rtx));
-static dw_loc_descr_ref reg_loc_descr_ref PROTO((rtx));
-static dw_loc_descr_ref based_loc_descr PROTO((unsigned, long));
-static int is_based_loc PROTO((rtx));
-static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx));
-static dw_loc_descr_ref loc_descriptor PROTO((rtx));
-static unsigned ceiling PROTO((unsigned, unsigned));
-static tree field_type PROTO((tree));
-static unsigned simple_type_align_in_bits PROTO((tree));
-static unsigned simple_type_size_in_bits PROTO((tree));
-static unsigned field_byte_offset PROTO((tree));
-static void add_location_attribute PROTO((dw_die_ref, rtx));
-static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
-static void add_const_value_attribute PROTO((dw_die_ref, rtx));
-static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
-static void add_name_attribute PROTO((dw_die_ref, char *));
-static void add_bound_info PROTO((dw_die_ref,
- enum dwarf_attribute, tree));
-static void add_subscript_info PROTO((dw_die_ref, tree));
-static void add_byte_size_attribute PROTO((dw_die_ref, tree));
-static void add_bit_offset_attribute PROTO((dw_die_ref, tree));
-static void add_bit_size_attribute PROTO((dw_die_ref, tree));
-static void add_prototyped_attribute PROTO((dw_die_ref, tree));
-static void add_abstract_origin_attribute PROTO((dw_die_ref, tree));
-static void add_pure_or_virtual_attribute PROTO((dw_die_ref, tree));
-static void add_src_coords_attributes PROTO((dw_die_ref, tree));
-static void ad_name_and_src_coords_attributes PROTO((dw_die_ref, tree));
-static void push_decl_scope PROTO((tree));
-static dw_die_ref scope_die_for PROTO((tree, dw_die_ref));
-static void pop_decl_scope PROTO((void));
-static void add_type_attribute PROTO((dw_die_ref, tree, int, int,
- dw_die_ref));
-static char *type_tag PROTO((tree));
-static tree member_declared_type PROTO((tree));
-static char *decl_start_label PROTO((tree));
-static void gen_arrqay_type_die PROTO((tree, dw_die_ref));
-static void gen_set_type_die PROTO((tree, dw_die_ref));
-static void gen_entry_point_die PROTO((tree, dw_die_ref));
-static void pend_type PROTO((tree));
-static void output_pending_types_for_scope PROTO((dw_die_ref));
-static void gen_inlined_enumeration_type_die PROTO((tree, dw_die_ref));
-static void gen_inlined_structure_type_die PROTO((tree, dw_die_ref));
-static void gen_inlined_union_type_die PROTO((tree, dw_die_ref));
-static void gen_enumeration_type_die PROTO((tree, dw_die_ref));
-static dw_die_ref gen_formal_parameter_die PROTO((tree, dw_die_ref));
-static void gen_unspecified_parameters_die PROTO((tree, dw_die_ref));
-static void gen_formal_types_die PROTO((tree, dw_die_ref));
-static void gen_subprogram_die PROTO((tree, dw_die_ref));
-static void gen_variable_die PROTO((tree, dw_die_ref));
-static void gen_labeld_die PROTO((tree, dw_die_ref));
-static void gen_lexical_block_die PROTO((tree, dw_die_ref, int));
-static void gen_inlined_subprogram_die PROTO((tree, dw_die_ref, int));
-static void gen_field_die PROTO((tree, dw_die_ref));
-static void gen_ptr_to_mbr_type_die PROTO((tree, dw_die_ref));
-static void gen_compile_unit_die PROTO((char *));
-static void gen_string_type_die PROTO((tree, dw_die_ref));
-static void gen_inheritance_die PROTO((tree, dw_die_ref));
-static void gen_member_die PROTO((tree, dw_die_ref));
-static void gen_struct_or_union_type_die PROTO((tree, dw_die_ref));
-static void gen_subroutine_type_die PROTO((tree, dw_die_ref));
-static void gen_typedef_die PROTO((tree, dw_die_ref));
-static void gen_type_die PROTO((tree, dw_die_ref));
-static void gen_tagged_type_instantiation_die PROTO((tree, dw_die_ref));
-static void gen_block_die PROTO((tree, dw_die_ref, int));
-static void decls_for_scope PROTO((tree, dw_die_ref, int));
-static int is_redundant_typedef PROTO((tree));
-static void gen_decl_die PROTO((tree, dw_die_ref));
-static unsigned lookup_filename PROTO((char *));
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
#define SECTION_FORMAT "\t%s\t%s\n"
#endif
-/* Section names used to hold DWARF debugging information. */
-#ifndef DEBUG_SECTION
-#define DEBUG_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 FRAME_SECTION
#define FRAME_SECTION ".debug_frame"
#endif
-#ifndef LINE_SECTION
-#define 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
-
-/* Standerd 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"
+#if !defined (EH_FRAME_SECTION) && defined (ASM_OUTPUT_SECTION_NAME)
+#define EH_FRAME_SECTION ".eh_frame"
#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. */
-
-char text_end_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 FUNC_BEGIN_LABEL
#define FUNC_BEGIN_LABEL "LFB"
#endif
#ifndef FUNC_END_LABEL
#define FUNC_END_LABEL "LFE"
#endif
-#ifndef LINE_CODE_LABEL
-#define LINE_CODE_LABEL "LM"
-#endif
-#ifndef SEPARATE_LINE_CODE_LABEL
-#define SEPARATE_LINE_CODE_LABEL "LSM"
-#endif
/* Definitions of defaults for various types of primitive assembly language
output operations. These may be overridden from within the tm.h file,
} while (0)
#endif
-/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
- newline is produced. When flag_verbose_asm is asserted, we add commnetary
- at the end of the line, so we must avoid output of a newline here. */
-#ifndef ASM_OUTPUT_DWARF_STRING
-#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
- do { \
- register int slen = strlen(P); \
- register char *p = (P); \
- register int i; \
- fprintf (FILE, "\t.ascii \""); \
- for (i = 0; i < slen; i++) \
- { \
- register int c = p[i]; \
- if (c == '\"' || c == '\\') \
- putc ('\\', FILE); \
- if (c >= ' ' && c < 0177) \
- putc (c, FILE); \
- else \
- { \
- fprintf (FILE, "\\%o", c); \
- } \
- } \
- fprintf (FILE, "\\0\""); \
- } \
- while (0)
-#endif
-
-/* Convert a reference to the assembler name of a C-level name. This
- macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
- a string rather than writing to a file. */
-#ifndef ASM_NAME_TO_STRING
-#define ASM_NAME_TO_STRING(STR, NAME) \
- do { \
- if ((NAME)[0] == '*') \
- strcpy (STR, NAME+1); \
- else \
- strcpy (STR, NAME); \
- } \
- while (0)
-#endif
-
/* The DWARF 2 CFA column which tracks the return address. Normally this
is the column for PC, or the first column after all of the hard
registers. */
#ifndef DWARF_FRAME_REGNUM
#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG)
#endif
-\f
+
/* Return a pointer to a copy of the section string name S with all
attributes stripped off. */
return stripped;
}
-/* Convert an integer constant expression into assembler syntax. Addition
- and subtraction are the only arithmetic that may appear in these
- expressions. This is an adaptation of output_addr_const in final.c.
- Here, the target of the conversion is a string buffer. We can't use
- output_addr_const directly, because it writes to a file. */
+/* Return the register number described by a given RTL node. */
-static void
-addr_const_to_string (str, x)
- char *str;
- rtx x;
+static unsigned
+reg_number (rtl)
+ register rtx rtl;
{
- char buf1[256];
- char buf2[256];
+ register unsigned regno = REGNO (rtl);
-restart:
- str[0] = '\0';
- switch (GET_CODE (x))
+ if (regno >= FIRST_PSEUDO_REGISTER)
{
- case PC:
- if (flag_pic)
- strcat (str, ",");
- else
- abort ();
- break;
-
- case SYMBOL_REF:
- ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
- strcat (str, buf1);
- break;
-
- case LABEL_REF:
- ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
- break;
-
- case CODE_LABEL:
- ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
- ASM_NAME_TO_STRING (buf2, buf1);
- strcat (str, buf2);
- break;
+ warning ("internal regno botch: regno = %d\n", regno);
+ regno = 0;
+ }
- case CONST_INT:
- sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- strcat (str, buf1);
- break;
+ regno = DBX_REGISTER_NUMBER (regno);
+ return regno;
+}
- case CONST:
- /* This used to output parentheses around the expression, but that does
- not work on the 386 (either ATT or BSD assembler). */
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- break;
+/* Convert a DWARF call frame info. operation to its string name */
- case CONST_DOUBLE:
- if (GET_MODE (x) == VOIDmode)
- {
- /* We can use %d if the number is one word and positive. */
- if (CONST_DOUBLE_HIGH (x))
- sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
- else if (CONST_DOUBLE_LOW (x) < 0)
- sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
- else
- sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
- CONST_DOUBLE_LOW (x));
- strcat (str, buf1);
- }
- else
- /* We can't handle floating point constants; PRINT_OPERAND must
- handle them. */
- output_operand_lossage ("floating constant misused");
- break;
+static char *
+dwarf_cfi_name (cfi_opc)
+ register unsigned cfi_opc;
+{
+ switch (cfi_opc)
+ {
+ case DW_CFA_advance_loc:
+ return "DW_CFA_advance_loc";
+ case DW_CFA_offset:
+ return "DW_CFA_offset";
+ case DW_CFA_restore:
+ return "DW_CFA_restore";
+ case DW_CFA_nop:
+ return "DW_CFA_nop";
+ case DW_CFA_set_loc:
+ return "DW_CFA_set_loc";
+ case DW_CFA_advance_loc1:
+ return "DW_CFA_advance_loc1";
+ case DW_CFA_advance_loc2:
+ return "DW_CFA_advance_loc2";
+ case DW_CFA_advance_loc4:
+ return "DW_CFA_advance_loc4";
+ case DW_CFA_offset_extended:
+ return "DW_CFA_offset_extended";
+ case DW_CFA_restore_extended:
+ return "DW_CFA_restore_extended";
+ case DW_CFA_undefined:
+ return "DW_CFA_undefined";
+ case DW_CFA_same_value:
+ return "DW_CFA_same_value";
+ case DW_CFA_register:
+ return "DW_CFA_register";
+ case DW_CFA_remember_state:
+ return "DW_CFA_remember_state";
+ case DW_CFA_restore_state:
+ return "DW_CFA_restore_state";
+ case DW_CFA_def_cfa:
+ return "DW_CFA_def_cfa";
+ case DW_CFA_def_cfa_register:
+ return "DW_CFA_def_cfa_register";
+ case DW_CFA_def_cfa_offset:
+ return "DW_CFA_def_cfa_offset";
+ /* SGI/MIPS specific */
+ case DW_CFA_MIPS_advance_loc8:
+ return "DW_CFA_MIPS_advance_loc8";
+ default:
+ return "DW_CFA_<unknown>";
+ }
+}
- case PLUS:
- /* Some assemblers need integer constants to appear last (eg masm). */
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- {
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- if (INTVAL (XEXP (x, 0)) >= 0)
- strcat (str, "+");
+/* Return a pointer to a newly allocated Call Frame Instruction. */
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- }
- else
- {
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- if (INTVAL (XEXP (x, 1)) >= 0)
- strcat (str, "+");
+static inline dw_cfi_ref
+new_cfi ()
+{
+ register dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- }
- break;
+ cfi->dw_cfi_next = NULL;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
+ cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
- case MINUS:
- /* Avoid outputting things like x-x or x+5-x, since some assemblers
- can't handle that. */
- x = simplify_subtraction (x);
- if (GET_CODE (x) != MINUS)
- goto restart;
+ return cfi;
+}
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- strcat (str, "-");
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) < 0)
- {
- strcat (str, ASM_OPEN_PAREN);
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- strcat (str, ASM_CLOSE_PAREN);
- }
- else
- {
- addr_const_to_string (buf1, XEXP (x, 1));
- strcat (str, buf1);
- }
- break;
+/* Add a Call Frame Instruction to list of instructions. */
- case ZERO_EXTEND:
- case SIGN_EXTEND:
- addr_const_to_string (buf1, XEXP (x, 0));
- strcat (str, buf1);
- break;
+static inline void
+add_cfi (list_head, cfi)
+ register dw_cfi_ref *list_head;
+ register dw_cfi_ref cfi;
+{
+ register dw_cfi_ref *p;
- default:
- output_operand_lossage ("invalid expression as operand");
- }
+ /* Find the end of the chain. */
+ for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next)
+ ;
+
+ *p = cfi;
}
-/* Convert an address constant to a string, and return a pointer to
- a copy of the result, located on the heap. */
+/* Generate a new label for the CFI info to refer to. */
static char *
-addr_to_string (x)
- rtx x;
+dwarf2out_cfi_label ()
{
- char buf[1024];
- addr_const_to_string (buf, x);
- return xstrdup (buf);
+ static char label[20];
+ static unsigned long label_num = 0;
+
+ ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
+ ASM_OUTPUT_LABEL (asm_out_file, label);
+
+ return label;
}
-/* Test if rtl node points to a psuedo register. */
+/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
+ or to the CIE if LABEL is NULL. */
-static inline int
-is_pseudo_reg (rtl)
- register rtx rtl;
+static void
+add_fde_cfi (label, cfi)
+ register char *label;
+ register dw_cfi_ref cfi;
{
- return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
- || ((GET_CODE (rtl) == SUBREG)
- && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
-}
+ if (label)
+ {
+ register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
-/* Return a reference to a type, with its const and volatile qualifiers
- removed. */
+ if (*label == 0)
+ label = dwarf2out_cfi_label ();
-static inline tree
-type_main_variant (type)
- register tree type;
-{
- type = TYPE_MAIN_VARIANT (type);
+ if (fde->dw_fde_current_label == NULL
+ || strcmp (label, fde->dw_fde_current_label) != 0)
+ {
+ register dw_cfi_ref xcfi;
- /* 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. */
+ fde->dw_fde_current_label = label = xstrdup (label);
- if (TREE_CODE (type) == ARRAY_TYPE)
- while (type != TYPE_MAIN_VARIANT (type))
- type = TYPE_MAIN_VARIANT (type);
+ /* Set the location counter to the new label. */
+ xcfi = new_cfi ();
+ xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
+ xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+ add_cfi (&fde->dw_fde_cfi, xcfi);
+ }
- return type;
+ add_cfi (&fde->dw_fde_cfi, cfi);
+ }
+
+ else
+ add_cfi (&cie_cfi_head, cfi);
}
-/* Return non-zero if the given type node represents a tagged type. */
+/* Subroutine of lookup_cfa. */
-static inline int
-is_tagged_type (type)
- register tree type;
+static inline void
+lookup_cfa_1 (cfi, regp, offsetp)
+ register dw_cfi_ref cfi;
+ register unsigned long *regp;
+ register long *offsetp;
{
- register enum tree_code code = TREE_CODE (type);
-
- return (code == RECORD_TYPE || code == UNION_TYPE
- || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_def_cfa_offset:
+ *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
+ break;
+ case DW_CFA_def_cfa_register:
+ *regp = 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;
+ break;
+ }
}
-/* Convert a DIE tag into its string name. */
+/* Find the previous value for the CFA. */
-static char *
-dwarf_tag_name (tag)
- register unsigned tag;
+static void
+lookup_cfa (regp, offsetp)
+ register unsigned long *regp;
+ register long *offsetp;
{
- switch (tag)
+ register dw_cfi_ref cfi;
+
+ *regp = (unsigned long) -1;
+ *offsetp = 0;
+
+ for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
+ lookup_cfa_1 (cfi, regp, offsetp);
+
+ if (fde_table_in_use)
{
- 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>";
+ 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);
}
}
-/* Convert a DWARF attribute code into its string name. */
+/* The current rule for calculating the DWARF2 canonical frame address. */
+static unsigned cfa_reg;
+static long cfa_offset;
-static char *
-dwarf_attr_name (attr)
- register unsigned attr;
+/* 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;
+
+/* Entry point to update the canonical frame address (CFA).
+ LABEL is passed to add_fde_cfi. The value of CFA is now to be
+ calculated from REG+OFFSET. */
+
+void
+dwarf2out_def_cfa (label, reg, offset)
+ register char *label;
+ register unsigned reg;
+ register long offset;
{
- switch (attr)
+ register dw_cfi_ref cfi;
+ unsigned long old_reg;
+ long old_offset;
+
+ reg = DWARF_FRAME_REGNUM (reg);
+ lookup_cfa (&old_reg, &old_offset);
+
+ if (reg == old_reg && offset == old_offset)
+ return;
+
+ cfi = new_cfi ();
+
+ if (reg == old_reg)
{
- 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";
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
+ cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
+ }
- 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";
+#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
+ else if (offset == old_offset && old_reg != (unsigned long) -1)
+ {
+ cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+ }
+#endif
- 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>";
+ else
+ {
+ 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;
}
+
+ add_fde_cfi (label, cfi);
+
+ cfa_reg = reg;
+ cfa_offset = offset;
+ if (cfa_store_reg == reg)
+ cfa_store_offset = offset;
}
-/* Convert a DWARF value form code into its string name. */
+/* Add the CFI for saving a register. REG is the CFA column number.
+ LABEL is passed to add_fde_cfi.
+ If SREG is -1, the register is saved at OFFSET from the CFA;
+ otherwise it is saved in SREG. */
-static char *
-dwarf_form_name (form)
- register unsigned form;
+static void
+reg_save (label, reg, sreg, offset)
+ register char * label;
+ register unsigned reg;
+ register unsigned sreg;
+ register long offset;
{
- switch (form)
+ register dw_cfi_ref cfi = new_cfi ();
+
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
+
+ if (sreg == -1)
{
- 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";
+ if (reg & ~0x3f)
+ /* The register number won't fit in 6 bits, so we have to use
+ the long form. */
+ cfi->dw_cfi_opc = DW_CFA_offset_extended;
+ else
+ cfi->dw_cfi_opc = DW_CFA_offset;
+
+ offset /= DWARF_CIE_DATA_ALIGNMENT;
+ assert (offset >= 0);
+ cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
+ }
+ else
+ {
+ cfi->dw_cfi_opc = DW_CFA_register;
+ cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
+ }
+
+ add_fde_cfi (label, cfi);
+}
+
+/* Entry point for saving a register. REG is the GCC register number.
+ LABEL and OFFSET are passed to reg_save. */
+
+void
+dwarf2out_reg_save (label, reg, offset)
+ register char * label;
+ register unsigned reg;
+ register long offset;
+{
+ reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
+}
+
+/* Record the initial position of the return address. RTL is
+ INCOMING_RETURN_ADDR_RTX. */
+
+static void
+initial_return_save (rtl)
+ register rtx rtl;
+{
+ unsigned reg = -1;
+ long offset = 0;
+
+ switch (GET_CODE (rtl))
+ {
+ case REG:
+ /* RA is in a register. */
+ reg = reg_number (rtl);
+ break;
+ case MEM:
+ /* RA is on the stack. */
+ rtl = XEXP (rtl, 0);
+ switch (GET_CODE (rtl))
+ {
+ case REG:
+ assert (REGNO (rtl) == STACK_POINTER_REGNUM);
+ offset = 0;
+ break;
+ case PLUS:
+ assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+ offset = INTVAL (XEXP (rtl, 1));
+ break;
+ case MINUS:
+ assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
+ offset = -INTVAL (XEXP (rtl, 1));
+ break;
+ default:
+ abort ();
+ }
+ break;
default:
- return "DW_FORM_<unknown>";
+ abort ();
}
+
+ reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
}
-/* Convert a DWARF stack opcode into its string name. */
+/* Record call frame debugging information for INSN, which either
+ sets SP or FP (adjusting how we calculate the frame address) or saves a
+ register to the stack. If INSN is NULL_RTX, initialize our state. */
-static char *
-dwarf_stack_op_name (op)
- register unsigned op;
+void
+dwarf2out_frame_debug (insn)
+ rtx insn;
{
- switch (op)
+ char *label;
+ rtx src, dest;
+ long offset;
+
+ /* A temporary register used in adjusting SP or setting up the store_reg. */
+ static unsigned cfa_temp_reg;
+ static long cfa_temp_value;
+
+ if (insn == NULL_RTX)
{
- 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";
+ /* Set up state for generating call frame debug info. */
+ cfa_reg = STACK_POINTER_REGNUM;
+ cfa_offset = 0;
+ cfa_store_reg = STACK_POINTER_REGNUM;
+ cfa_store_offset = 0;
+ cfa_temp_reg = -1;
+ cfa_temp_value = 0;
+ return;
+ }
+
+ label = dwarf2out_cfi_label ();
+
+ insn = PATTERN (insn);
+ assert (GET_CODE (insn) == SET);
+
+ src = SET_SRC (insn);
+ dest = SET_DEST (insn);
+
+ switch (GET_CODE (dest))
+ {
+ case REG:
+ /* Update the CFA rule wrt SP or FP. Make sure src is
+ relative to the current CFA register. */
+ switch (GET_CODE (src))
+ {
+ /* Setting FP from SP. */
+ case REG:
+ assert (cfa_reg == REGNO (src));
+ assert (REGNO (dest) == STACK_POINTER_REGNUM
+ || (frame_pointer_needed
+ && REGNO (dest) == HARD_FRAME_POINTER_REGNUM));
+ cfa_reg = REGNO (dest);
+ break;
+
+ case PLUS:
+ case MINUS:
+ if (dest == stack_pointer_rtx)
+ {
+ /* Adjusting SP. */
+ switch (GET_CODE (XEXP (src, 1)))
+ {
+ case CONST_INT:
+ offset = INTVAL (XEXP (src, 1));
+ break;
+ case REG:
+ assert (REGNO (XEXP (src, 1)) == cfa_temp_reg);
+ offset = cfa_temp_value;
+ break;
+ default:
+ 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;
+ assert (XEXP (src, 0) == stack_pointer_rtx);
+ }
+ else
+ {
+ /* Initializing the store base register. */
+ assert (GET_CODE (src) == PLUS);
+ assert (XEXP (src, 1) == stack_pointer_rtx);
+ assert (GET_CODE (XEXP (src, 0)) == REG
+ && REGNO (XEXP (src, 0)) == cfa_temp_reg);
+ assert (cfa_store_reg == STACK_POINTER_REGNUM);
+ cfa_store_reg = REGNO (dest);
+ cfa_store_offset -= cfa_temp_value;
+ }
+ break;
+
+ case CONST_INT:
+ cfa_temp_reg = REGNO (dest);
+ cfa_temp_value = INTVAL (src);
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ break;
+
+ case MEM:
+ /* Saving a register to the stack. Make sure dest is relative to the
+ CFA register. */
+ assert (GET_CODE (src) == REG);
+ switch (GET_CODE (XEXP (dest, 0)))
+ {
+ /* With a push. */
+ case PRE_INC:
+ case PRE_DEC:
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ if (GET_CODE (src) == PRE_INC)
+ offset = -offset;
+
+ assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
+ assert (cfa_store_reg == STACK_POINTER_REGNUM);
+ cfa_store_offset += offset;
+ if (cfa_reg == STACK_POINTER_REGNUM)
+ cfa_offset = cfa_store_offset;
+
+ offset = -cfa_store_offset;
+ break;
+
+ /* With an offset. */
+ case PLUS:
+ case MINUS:
+ offset = INTVAL (XEXP (XEXP (dest, 0), 1));
+ if (GET_CODE (src) == MINUS)
+ offset = -offset;
+
+ assert (cfa_store_reg == REGNO (XEXP (XEXP (dest, 0), 0)));
+ offset -= cfa_store_offset;
+ break;
+
+ default:
+ abort ();
+ }
+ dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
+ dwarf2out_reg_save (label, REGNO (src), offset);
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+/* Return the size of an unsigned LEB128 quantity. */
+
+static inline unsigned long
+size_of_uleb128 (value)
+ register unsigned long value;
+{
+ register unsigned long size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ value >>= 7;
+ size += 1;
+ }
+ while (value != 0);
+
+ return size;
+}
+
+/* Return the size of a signed LEB128 quantity. */
+
+static inline unsigned long
+size_of_sleb128 (value)
+ register long value;
+{
+ register unsigned long size = 0;
+ register unsigned byte;
+
+ do
+ {
+ byte = (value & 0x7f);
+ value >>= 7;
+ size += 1;
+ }
+ while (!(((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+
+ return size;
+}
+
+/* Return the size of a Call Frame Instruction. */
+
+static unsigned long
+size_of_cfi (cfi)
+ dw_cfi_ref cfi;
+{
+ register unsigned long size;
+
+ /* Count the 1-byte opcode */
+ size = 1;
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_offset:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ break;
+ case DW_CFA_set_loc:
+ size += PTR_SIZE;
+ break;
+ case DW_CFA_advance_loc1:
+ size += 1;
+ break;
+ case DW_CFA_advance_loc2:
+ size += 2;
+ break;
+ case DW_CFA_advance_loc4:
+ size += 4;
+ break;
+#ifdef MIPS_DEBUGGING_INFO
+ case DW_CFA_MIPS_advance_loc8:
+ size += 8;
+ break;
+#endif
+ case DW_CFA_offset_extended:
+ case DW_CFA_def_cfa:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ break;
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ break;
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ break;
+ case DW_CFA_register:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
+ break;
+ case DW_CFA_def_cfa_offset:
+ size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ break;
default:
- return "OP_<unknown>";
+ break;
+ }
+
+ return size;
+}
+
+/* Return the size of an FDE sans the length word. */
+
+static inline unsigned long
+size_of_fde (fde, npad)
+ dw_fde_ref fde;
+ unsigned long *npad;
+{
+ register dw_cfi_ref cfi;
+ register unsigned long aligned_size;
+ register unsigned long size;
+
+ size = DWARF_FDE_HEADER_SIZE;
+ for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
+ size += size_of_cfi(cfi);
+
+ /* Round the size up to a word boundary. */
+ aligned_size = DWARF_ROUND (size, PTR_SIZE);
+ *npad = aligned_size - size;
+ return aligned_size;
+}
+
+/* Calculate the size of the FDE table, and establish the offset
+ of each FDE in the .debug_frame section. */
+
+static void
+calc_fde_sizes ()
+{
+ register unsigned long i;
+ register dw_fde_ref fde;
+ register unsigned long fde_size;
+ register dw_cfi_ref cfi;
+ unsigned long fde_pad;
+
+ cie_size = DWARF_CIE_HEADER_SIZE;
+ for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
+ cie_size += size_of_cfi (cfi);
+
+ /* Initialize the beginning FDE offset. */
+ next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+
+ for (i = 0; i < fde_table_in_use; ++i)
+ {
+ fde = &fde_table[i];
+ fde->dw_fde_offset = next_fde_offset;
+ fde_size = size_of_fde (fde, &fde_pad);
+ next_fde_offset += fde_size;
+ }
+}
+
+/* Output an unsigned LEB128 quantity. */
+
+static void
+output_uleb128 (value)
+ register unsigned long value;
+{
+ unsigned long save_value = value;
+
+ fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP);
+ do
+ {
+ register unsigned byte = (value & 0x7f);
+ value >>= 7;
+ if (value != 0)
+ /* More bytes to follow. */
+ byte |= 0x80;
+
+ fprintf (asm_out_file, "0x%x", byte);
+ if (value != 0)
+ fprintf (asm_out_file, ",");
+ }
+ while (value != 0);
+
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s ULEB128 0x%x", ASM_COMMENT_START, save_value);
+}
+
+/* Output an signed LEB128 quantity. */
+
+static void
+output_sleb128 (value)
+ register long value;
+{
+ register int more;
+ register unsigned byte;
+ long save_value = value;
+
+ fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP);
+ do
+ {
+ byte = (value & 0x7f);
+ /* arithmetic shift */
+ value >>= 7;
+ more = !((((value == 0) && ((byte & 0x40) == 0))
+ || ((value == -1) && ((byte & 0x40) != 0))));
+ if (more)
+ byte |= 0x80;
+
+ fprintf (asm_out_file, "0x%x", byte);
+ if (more)
+ fprintf (asm_out_file, ",");
+ }
+
+ while (more);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s SLEB128 %d", ASM_COMMENT_START, save_value);
+}
+
+/* Output a Call Frame Information opcode and its operand(s). */
+
+static void
+output_cfi (cfi, fde)
+ register dw_cfi_ref cfi;
+ register dw_fde_ref fde;
+{
+ if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
+ {
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ cfi->dw_cfi_opc
+ | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
+ ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ fputc ('\n', asm_out_file);
+ }
+
+ else if (cfi->dw_cfi_opc == DW_CFA_offset)
+ {
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ cfi->dw_cfi_opc
+ | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
+ ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+
+ fputc ('\n', asm_out_file);
+ output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ fputc ('\n', asm_out_file);
+ }
+ else if (cfi->dw_cfi_opc == DW_CFA_restore)
+ {
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ cfi->dw_cfi_opc
+ | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
+ ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+
+ fputc ('\n', asm_out_file);
+ }
+ else
+ {
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, cfi->dw_cfi_opc);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
+ dwarf_cfi_name (cfi->dw_cfi_opc));
+
+ fputc ('\n', asm_out_file);
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_set_loc:
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, cfi->dw_cfi_oprnd1.dw_cfi_addr);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_CFA_advance_loc1:
+ /* TODO: not currently implemented. */
+ abort ();
+ break;
+ case DW_CFA_advance_loc2:
+ ASM_OUTPUT_DWARF_DELTA2 (asm_out_file,
+ cfi->dw_cfi_oprnd1.dw_cfi_addr,
+ fde->dw_fde_current_label);
+ fputc ('\n', asm_out_file);
+ fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+ break;
+ case DW_CFA_advance_loc4:
+ ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
+ cfi->dw_cfi_oprnd1.dw_cfi_addr,
+ fde->dw_fde_current_label);
+ fputc ('\n', asm_out_file);
+ fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+ break;
+#ifdef MIPS_DEBUGGING_INFO
+ case DW_CFA_MIPS_advance_loc8:
+ /* TODO: not currently implemented. */
+ abort ();
+ break;
+#endif
+ case DW_CFA_offset_extended:
+ case DW_CFA_def_cfa:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_CFA_register:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ break;
+ case DW_CFA_def_cfa_offset:
+ output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ fputc ('\n', asm_out_file);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/* Output the call frame information used to used to record information
+ that relates to calculating the frame pointer, and records the
+ location of saved registers. */
+
+static void
+output_call_frame_info (for_eh)
+ int for_eh;
+{
+ register unsigned long i, j;
+ register dw_fde_ref fde;
+ register unsigned long fde_size;
+ register dw_cfi_ref cfi;
+ unsigned long fde_pad;
+
+ /* Only output the info if it will be interesting. */
+ for (i = 0; i < fde_table_in_use; ++i)
+ if (fde_table[i].dw_fde_cfi != NULL)
+ break;
+ if (i == fde_table_in_use)
+ return;
+
+ /* (re-)initialize the beginning FDE offset. */
+ next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+
+ fputc ('\n', asm_out_file);
+ if (for_eh)
+ {
+#ifdef EH_FRAME_SECTION
+ ASM_OUTPUT_SECTION_NAME (asm_out_file, NULL_TREE, EH_FRAME_SECTION, 0);
+#else
+ data_section ();
+#endif
+ assemble_label ("__FRAME_BEGIN__");
+ }
+ else
+ ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
+
+ /* Output the CIE. */
+ ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s Length of Common Information Entry",
+ ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE Identifier Tag", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ if (DWARF_OFFSET_SIZE == 8)
+ {
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
+ fputc ('\n', asm_out_file);
+ }
+
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CIE_VERSION);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE Version", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE Augmentation (none)", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ output_uleb128 (1);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (CIE Code Alignment Factor)");
+
+ fputc ('\n', asm_out_file);
+ output_sleb128 (DWARF_CIE_DATA_ALIGNMENT);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (CIE Data Alignment Factor)");
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_FRAME_RETURN_COLUMN);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+
+ for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
+ output_cfi (cfi, NULL);
+
+ /* Pad the CIE out to an address sized boundary. */
+ for (i = next_fde_offset - cie_size; i; --i)
+ {
+ /* Pad out to a pointer size boundary */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ }
+
+ /* Loop through all of the FDE's. */
+ for (i = 0; i < fde_table_in_use; ++i)
+ {
+ fde = &fde_table[i];
+ if (fde->dw_fde_cfi == NULL)
+ continue;
+
+ fde_size = size_of_fde (fde, &fde_pad);
+ ASM_OUTPUT_DWARF_DATA (asm_out_file, fde_size - DWARF_OFFSET_SIZE);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s FDE Length", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ if (for_eh)
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__FRAME_BEGIN__");
+ else
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s FDE CIE offset", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, fde->dw_fde_begin);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s FDE initial location", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file,
+ fde->dw_fde_end, fde->dw_fde_begin);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s FDE address range", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+
+ /* Loop through the Call Frame Instructions associated with
+ this FDE. */
+ fde->dw_fde_current_label = fde->dw_fde_begin;
+ for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
+ output_cfi (cfi, fde);
+
+ /* Pad to a double word boundary. */
+ for (j = 0; j < fde_pad; ++j)
+ {
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)",
+ ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
+ }
+ }
+#ifndef EH_FRAME_SECTION
+ if (for_eh)
+ {
+ /* Emit terminating zero for table. */
+ ASM_OUTPUT_DWARF_DATA (asm_out_file, 0);
+ fputc ('\n', asm_out_file);
+ }
+#endif
+}
+
+/* Output a marker (i.e. a label) for the beginning of a function, before
+ the prologue. */
+
+void
+dwarf2out_begin_prologue ()
+{
+ char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ register dw_fde_ref fde;
+
+ function_section (current_function_decl);
+ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
+ current_funcdef_number);
+ ASM_OUTPUT_LABEL (asm_out_file, label);
+
+ /* Expand the fde table if necessary. */
+ if (fde_table_in_use == fde_table_allocated)
+ {
+ fde_table_allocated += FDE_TABLE_INCREMENT;
+ fde_table
+ = (dw_fde_ref) xrealloc (fde_table,
+ fde_table_allocated * sizeof (dw_fde_node));
}
+
+ /* Record the FDE associated with this function. */
+ current_funcdef_fde = fde_table_in_use;
+
+ /* Add the new FDE at the end of the fde_table. */
+ fde = &fde_table[fde_table_in_use++];
+ fde->dw_fde_begin = xstrdup (label);
+ fde->dw_fde_current_label = NULL;
+ fde->dw_fde_end = NULL;
+ fde->dw_fde_cfi = NULL;
+}
+
+/* Output a marker (i.e. a label) for the absolute end of the generated code
+ for a function definition. This gets called *after* the epilogue code has
+ been generated. */
+
+void
+dwarf2out_end_epilogue ()
+{
+ dw_fde_ref fde;
+ char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+ /* Output a label to mark the endpoint of the code generated for this
+ function. */
+ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
+ ASM_OUTPUT_LABEL (asm_out_file, label);
+ fde = &fde_table[fde_table_in_use - 1];
+ fde->dw_fde_end = xstrdup (label);
+
+ ++current_funcdef_number;
+}
+
+void
+dwarf2out_frame_init ()
+{
+ /* Allocate the initial hunk of the fde_table. */
+ fde_table
+ = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
+ bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
+ fde_table_allocated = FDE_TABLE_INCREMENT;
+ fde_table_in_use = 0;
+
+ /* Generate the CFA instructions common to all FDE's. Do it now for the
+ sake of lookup_cfa. */
+
+#ifdef INCOMING_RETURN_ADDR_RTX
+ /* On entry, the Canonical Frame Address is at SP+0. */
+ dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
+ initial_return_save (INCOMING_RETURN_ADDR_RTX);
+#endif
+}
+
+void
+dwarf2out_frame_finish ()
+{
+ /* calculate sizes/offsets for FDEs. */
+ calc_fde_sizes ();
+
+ /* Output call frame information. */
+ if (write_symbols == DWARF2_DEBUG)
+ output_call_frame_info (0);
+ if (flag_exceptions && ! exceptions_via_longjmp)
+ output_call_frame_info (1);
+}
+
+#endif /* .debug_frame support */
+
+/* And now, the support for symbolic debugging information. */
+#ifdef DWARF2_DEBUGGING_INFO
+
+extern char *getpwd ();
+
+/* 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. */
+
+/* Each DIE may have a series of attribute/value pairs. Values
+ can take on several forms. The forms that are used in this
+ implementation are listed below. */
+
+typedef enum
+{
+ dw_val_class_addr,
+ dw_val_class_loc,
+ dw_val_class_const,
+ dw_val_class_unsigned_const,
+ dw_val_class_long_long,
+ dw_val_class_float,
+ dw_val_class_flag,
+ dw_val_class_die_ref,
+ dw_val_class_fde_ref,
+ dw_val_class_lbl_id,
+ dw_val_class_section_offset,
+ dw_val_class_str
}
+dw_val_class;
-/* Convert a DWARF type code into its string name. */
+/* Various DIE's use offsets relative to the beginning of the
+ .debug_info section to refer to each other. */
-static char *
-dwarf_type_encoding_name (enc)
- register unsigned enc;
+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. */
+
+typedef struct dw_long_long_struct
{
- switch (enc)
+ unsigned long hi;
+ unsigned long low;
+}
+dw_long_long_const;
+
+/* Describe a floating point constant value. */
+
+typedef struct dw_fp_struct
+{
+ long *array;
+ unsigned length;
+}
+dw_float_const;
+
+/* Each entry in the line_info_table maintains the file and
+ line nuber 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 attibute's value, as it is
+ represented internally. */
+
+typedef struct dw_val_struct
+{
+ dw_val_class val_class;
+ union
{
- case DW_ATE_address:
- return "DW_ATE_address";
- case DW_ATE_boolean:
- return "DW_ATE_boolean";
- case DW_ATE_complex_float:
- return "DW_ATE_complex_float";
- case DW_ATE_float:
- return "DW_ATE_float";
- case DW_ATE_signed:
- return "DW_ATE_signed";
- case DW_ATE_signed_char:
- return "DW_ATE_signed_char";
- case DW_ATE_unsigned:
- return "DW_ATE_unsigned";
- case DW_ATE_unsigned_char:
- return "DW_ATE_unsigned_char";
- default:
- return "DW_ATE_<unknown>";
+ char *val_addr;
+ dw_loc_descr_ref val_loc;
+ long int val_int;
+ long unsigned val_unsigned;
+ dw_long_long_const val_long_long;
+ dw_float_const val_float;
+ dw_die_ref val_die_ref;
+ unsigned val_fde_index;
+ char *val_str;
+ char *val_lbl_id;
+ char *val_section;
+ unsigned char val_flag;
}
+ v;
+}
+dw_val_node;
+
+/* Locations in memory are described using a sequence of stack machine
+ operations. */
+
+typedef struct dw_loc_descr_struct
+{
+ dw_loc_descr_ref dw_loc_next;
+ enum dwarf_location_atom dw_loc_opc;
+ dw_val_node dw_loc_oprnd1;
+ dw_val_node dw_loc_oprnd2;
+}
+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_attr_ref die_attr_last;
+ dw_die_ref die_parent;
+ dw_die_ref die_child;
+ dw_die_ref die_child_last;
+ 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;
+
+/* 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))))
+
+/* Information concerning the compilation unit's programming
+ language, and compiler version. */
+
+extern int flag_traditional;
+extern char *version_string;
+extern char *language_string;
+
+/* Fixed size portion of the DWARF compilation unit header. */
+#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
+
+/* 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, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
+
+/* 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;
+
+/* The number of DIEs with a NULL parent waiting to be relocated. */
+static int limbo_die_count;
+
+/* 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;
-/* Convert a DWARF call frame info. operation to its string name */
+/* Number of entries in the file_table which are actually in use. */
+static unsigned file_table_in_use;
-static char *
-dwarf_cfi_name (cfi_opc)
- register unsigned cfi_opc;
-{
- switch (cfi_opc)
- {
- case DW_CFA_advance_loc:
- return "DW_CFA_advance_loc";
- case DW_CFA_offset:
- return "DW_CFA_offset";
- case DW_CFA_restore:
- return "DW_CFA_restore";
- case DW_CFA_nop:
- return "DW_CFA_nop";
- case DW_CFA_set_loc:
- return "DW_CFA_set_loc";
- case DW_CFA_advance_loc1:
- return "DW_CFA_advance_loc1";
- case DW_CFA_advance_loc2:
- return "DW_CFA_advance_loc2";
- case DW_CFA_advance_loc4:
- return "DW_CFA_advance_loc4";
- case DW_CFA_offset_extended:
- return "DW_CFA_offset_extended";
- case DW_CFA_restore_extended:
- return "DW_CFA_restore_extended";
- case DW_CFA_undefined:
- return "DW_CFA_undefined";
- case DW_CFA_same_value:
- return "DW_CFA_same_value";
- case DW_CFA_register:
- return "DW_CFA_register";
- case DW_CFA_remember_state:
- return "DW_CFA_remember_state";
- case DW_CFA_restore_state:
- return "DW_CFA_restore_state";
- case DW_CFA_def_cfa:
- return "DW_CFA_def_cfa";
- case DW_CFA_def_cfa_register:
- return "DW_CFA_def_cfa_register";
- case DW_CFA_def_cfa_offset:
- return "DW_CFA_def_cfa_offset";
- /* SGI/MIPS specific */
- case DW_CFA_MIPS_advance_loc8:
- return "DW_CFA_MIPS_advance_loc8";
- default:
- return "DW_CFA_<unknown>";
- }
-}
-\f
-/* Determine the "ultimate origin" of a decl. The decl may be an inlined
- instance of an inlined instance of a decl which is local to an inline
- function, so we have to trace all of the way back through the origin chain
- to find out what sort of node actually served as the original seed for the
- given block. */
+/* Size (in elements) of increments by which we may expand the filename
+ table. */
+#define FILE_TABLE_INCREMENT 64
-static tree
-decl_ultimate_origin (decl)
- register tree decl;
-{
- register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
+/* Local pointer to the name of the main input file. Initialized in
+ dwarf2out_init. */
+static char *primary_filename;
- if (immediate_origin == NULL_TREE)
- return NULL_TREE;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
+/* For Dwarf output, we must assign lexical-blocks id numbers in the order in
+ which their beginnings are encountered. We output Dwarf debugging info
+ that refers to the beginnings and ends of the ranges of code for each
+ lexical block. The labels themselves are generated in final.c, which
+ assigns numbers to the blocks in the same way. */
+static unsigned next_block_number = 2;
- do
- {
- ret_val = lookahead;
- lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
- }
- while (lookahead != NULL && lookahead != ret_val);
+/* 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, indentifying each decl. */
+static dw_die_ref *decl_die_table;
- return ret_val;
- }
-}
+/* Number of elements currently allocated for the decl_die_table. */
+static unsigned decl_die_table_allocated;
-/* Determine the "ultimate origin" of a block. The block may be an inlined
- instance of an inlined instance of a block which is local to an inline
- function, so we have to trace all of the way back through the origin chain
- to find out what sort of node actually served as the original seed for the
- given block. */
+/* Number of elements in decl_die_table currently in use. */
+static unsigned decl_die_table_in_use;
-static tree
-block_ultimate_origin (block)
- register tree block;
-{
- register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+/* Size (in elements) of increments by which we may expand the
+ decl_die_table. */
+#define DECL_DIE_TABLE_INCREMENT 256
- if (immediate_origin == NULL_TREE)
- return NULL_TREE;
- else
- {
- register tree ret_val;
- register tree lookahead = immediate_origin;
+/* 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;
- do
- {
- ret_val = lookahead;
- lookahead = (TREE_CODE (ret_val) == BLOCK)
- ? BLOCK_ABSTRACT_ORIGIN (ret_val)
- : NULL;
- }
- while (lookahead != NULL && lookahead != ret_val);
+/* Number of elements currently allocated for the decl_scope_table. */
+static unsigned decl_scope_table_allocated;
- return ret_val;
- }
-}
+/* Current level of nesting of declataion scopes. */
+static unsigned decl_scope_depth;
-/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT
- of a virtual function may refer to a base class, so we check the 'this'
- parameter. */
+/* Size (in elements) of increments by which we may expand the
+ decl_scope_table. */
+#define DECL_SCOPE_TABLE_INCREMENT 64
-static tree
-decl_class_context (decl)
- tree decl;
-{
- tree context = NULL_TREE;
+/* 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;
- if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
- context = DECL_CONTEXT (decl);
- else
- context = TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+/* Number of elements currently allocated for abbrev_die_table. */
+static unsigned abbrev_die_table_allocated;
- if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
- context = NULL_TREE;
+/* Number of elements in type_die_table currently in use. */
+static unsigned abbrev_die_table_in_use;
- return context;
-}
-\f
-/* Add an attribute/value pair to a DIE */
+/* Size (in elements) of increments by which we may expand the
+ abbrev_die_table. */
+#define ABBREV_DIE_TABLE_INCREMENT 256
-static inline void
-add_dwarf_attr (die, attr)
- register dw_die_ref die;
- register dw_attr_ref attr;
-{
- if (die != NULL && attr != NULL)
- {
- if (die->die_attr == NULL)
- {
- die->die_attr = attr;
- die->die_attr_last = attr;
- }
- else
- {
- die->die_attr_last->dw_attr_next = attr;
- die->die_attr_last = attr;
- }
- }
-}
+/* 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;
-/* Add a flag value attribute to a DIE. */
+/* Number of elements currently allocated for line_info_table. */
+static unsigned line_info_table_allocated;
-static inline void
-add_AT_flag (die, attr_kind, flag)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register unsigned flag;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* Number of elements in separate_line_info_table currently in use. */
+static unsigned separate_line_info_table_in_use;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_flag;
- attr->dw_attr_val.v.val_flag = flag;
- add_dwarf_attr (die, attr);
-}
+/* 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;
-/* Add a signed integer attribute value to a DIE. */
+/* Number of elements currently allocated for separate_line_info_table. */
+static unsigned separate_line_info_table_allocated;
-static inline void
-add_AT_int (die, attr_kind, int_val)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register long int int_val;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* Number of elements in line_info_table currently in use. */
+static unsigned line_info_table_in_use;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_const;
- attr->dw_attr_val.v.val_int = int_val;
- add_dwarf_attr (die, attr);
-}
+/* Size (in elements) of increments by which we may expand the
+ line_info_table. */
+#define LINE_INFO_TABLE_INCREMENT 1024
-/* Add an unsigned integer attribute value to a DIE. */
+/* A pointer to the base of a table that contains a list of publicly
+ accessible names. */
+static pubname_ref pubname_table;
-static inline void
-add_AT_unsigned (die, attr_kind, unsigned_val)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register unsigned long unsigned_val;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* 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;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_unsigned_const;
- attr->dw_attr_val.v.val_unsigned = unsigned_val;
- add_dwarf_attr (die, attr);
-}
+/* Number of elements currently allocated for arange_table. */
+static unsigned arange_table_allocated;
-/* Add an unsigned double integer attribute value to a DIE. */
+/* Number of elements in arange_table currently in use. */
+static unsigned arange_table_in_use;
-static inline void
-add_AT_long_long (die, attr_kind, val_hi, val_low)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register unsigned long val_hi;
- register unsigned long val_low;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* Size (in elements) of increments by which we may expand the
+ arange_table. */
+#define ARANGE_TABLE_INCREMENT 64
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_long_long;
- attr->dw_attr_val.v.val_long_long.hi = val_hi;
- attr->dw_attr_val.v.val_long_long.low = val_low;
- add_dwarf_attr (die, attr);
-}
+/* A pointer to the base of a list of pending types which we haven't
+ generated DIEs for yet, but which we will have to come back to
+ later on. */
-/* Add a floating point attribute value to a DIE and return it. */
+static tree *pending_types_list;
-static inline void
-add_AT_float (die, attr_kind, length, array)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register unsigned length;
- register long *array;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* Number of elements currently allocated for the pending_types_list. */
+static unsigned pending_types_allocated;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_float;
- attr->dw_attr_val.v.val_float.length = length;
- attr->dw_attr_val.v.val_float.array = array;
- add_dwarf_attr (die, attr);
-}
+/* Number of elements of pending_types_list currently in use. */
+static unsigned pending_types;
-/* Add a string attribute value to a DIE. */
+/* Size (in elements) of increments by which we may expand the pending
+ types list. Actually, a single hunk of space of this size should
+ be enough for most typical programs. */
+#define PENDING_TYPES_INCREMENT 64
-static inline void
-add_AT_string (die, attr_kind, str)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register char *str;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+/* Record whether the function being analyzed contains inlined functions. */
+static int current_function_has_inlines;
+static int comp_unit_has_inlines;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_str;
- attr->dw_attr_val.v.val_str = xstrdup (str);
- add_dwarf_attr (die, attr);
-}
+/* A pointer to the ..._DECL node which we have most recently been working
+ on. We keep this around just in case something about it looks screwy and
+ we want to tell the user what the source coordinates for the actual
+ declaration are. */
+static tree dwarf_last_decl;
-/* Add a DIE reference attribute value to a DIE. */
+/* Forward declarations for functions defined in this file. */
-static inline void
-add_AT_die_ref (die, attr_kind, targ_die)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register dw_die_ref targ_die;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+static void addr_const_to_string PROTO((char *, rtx));
+static char *addr_to_string PROTO((rtx));
+static int is_pseudo_reg PROTO((rtx));
+static tree type_main_variant PROTO((tree));
+static int is_tagged_type PROTO((tree));
+static char *dwarf_tag_name PROTO((unsigned));
+static char *dwarf_attr_name PROTO((unsigned));
+static char *dwarf_form_name PROTO((unsigned));
+static char *dwarf_stack_op_name PROTO((unsigned));
+static char *dwarf_type_encoding_name PROTO((unsigned));
+static tree decl_ultimate_origin PROTO((tree));
+static tree block_ultimate_origin PROTO((tree));
+static tree decl_class_context PROTO((tree));
+static void add_dwarf_attr PROTO((dw_die_ref, dw_attr_ref));
+static void add_AT_flag PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned));
+static void add_AT_int PROTO((dw_die_ref,
+ enum dwarf_attribute, long));
+static void add_AT_unsigned PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned long));
+static void add_AT_long_long PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned long, unsigned long));
+static void add_AT_float PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned, long *));
+static void add_AT_string PROTO((dw_die_ref,
+ enum dwarf_attribute, char *));
+static void add_AT_die_ref PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ dw_die_ref));
+static void add_AT_fde_ref PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ unsigned));
+static void add_AT_loc PROTO((dw_die_ref,
+ enum dwarf_attribute,
+ dw_loc_descr_ref));
+static void add_AT_addr PROTO((dw_die_ref,
+ enum dwarf_attribute, char *));
+static void add_AT_lbl_id PROTO((dw_die_ref,
+ enum dwarf_attribute, char *));
+static void add_AT_setion_offset PROTO((dw_die_ref,
+ enum dwarf_attribute, char *));
+static int is_extern_subr_die PROTO((dw_die_ref));
+static dw_attr_ref get_AT PROTO((dw_die_ref,
+ enum dwarf_attribute));
+static char *get_AT_low_pc PROTO((dw_die_ref));
+static char *get_AT_hi_pc PROTO((dw_die_ref));
+static char *get_AT_string PROTO((dw_die_ref,
+ enum dwarf_attribute));
+static int get_AT_flag PROTO((dw_die_ref,
+ enum dwarf_attribute));
+static unsigned get_AT_unsigned PROTO((dw_die_ref,
+ enum dwarf_attribute));
+static int is_c_family PROTO((void));
+static int is_fortran PROTO((void));
+static void remove_AT PROTO((dw_die_ref,
+ enum dwarf_attribute));
+static void remove_children PROTO((dw_die_ref));
+static void add_child_die PROTO((dw_die_ref, dw_die_ref));
+static dw_die_ref new_die PROTO((enum dwarf_tag, dw_die_ref));
+static dw_die_ref lookup_type_die PROTO((tree));
+static void equate_type_number_to_die PROTO((tree, dw_die_ref));
+static dw_die_ref lookup_decl_die PROTO((tree));
+static void equate_decl_number_to_die PROTO((tree, dw_die_ref));
+static dw_loc_descr_ref new_loc_descr PROTO((enum dwarf_location_atom,
+ unsigned long, unsigned long));
+static void add_loc_descr PROTO((dw_loc_descr_ref *,
+ dw_loc_descr_ref));
+static void print_spaces PROTO((FILE *));
+static void print_die PROTO((dw_die_ref, FILE *));
+static void print_dwarf_line_table PROTO((FILE *));
+static void add_sibling_atttributes PROTO((dw_die_ref));
+static void build_abbrev_table PROTO((dw_die_ref));
+static unsigned long size_of_string PROTO((char *));
+static unsigned long size_of_loc_descr PROTO((dw_loc_descr_ref));
+static unsigned long size_of_locs PROTO((dw_loc_descr_ref));
+static int constant_size PROTO((long unsigned));
+static unsigned long size_of_die PROTO((dw_die_ref));
+static void calc_die_sizes PROTO((dw_die_ref));
+static unsigned long size_of_prolog PROTO((void));
+static unsigned long size_of_line_info PROTO((void));
+static unsigned long size_of_pubnames PROTO((void));
+static unsigned long size_of_aranges PROTO((void));
+static enum dwarf_form value_format PROTO((dw_val_ref));
+static void output_value_format PROTO((dw_val_ref));
+static void output_abbrev_section PROTO((void));
+static void output_loc_operands PROTO((dw_loc_descr_ref));
+static unsigned long sibling_offset PROTO((dw_die_ref));
+static void output_die PROTO((dw_die_ref));
+static void output_compilation_unit_header PROTO((void));
+static char *dwarf2_name PROTO((tree, int));
+static void add_pubname PROTO((tree, dw_die_ref));
+static void output_pubnames PROTO((void));
+static void add_arrange PROTO((tree, dw_die_ref));
+static void output_arranges PROTO((void));
+static void output_line_info PROTO((void));
+static int is_body_block PROTO((tree));
+static dw_die_ref base_type_die PROTO((tree));
+static tree root_type PROTO((tree));
+static int is_base_type PROTO((tree));
+static dw_die_ref modified_type_die PROTO((tree, int, int, dw_die_ref));
+static int type_is_enum PROTO((tree));
+static dw_loc_descr_ref reg_loc_descr_ref PROTO((rtx));
+static dw_loc_descr_ref based_loc_descr PROTO((unsigned, long));
+static int is_based_loc PROTO((rtx));
+static dw_loc_descr_ref mem_loc_descriptor PROTO((rtx));
+static dw_loc_descr_ref loc_descriptor PROTO((rtx));
+static unsigned ceiling PROTO((unsigned, unsigned));
+static tree field_type PROTO((tree));
+static unsigned simple_type_align_in_bits PROTO((tree));
+static unsigned simple_type_size_in_bits PROTO((tree));
+static unsigned field_byte_offset PROTO((tree));
+static void add_location_attribute PROTO((dw_die_ref, rtx));
+static void add_data_member_location_attribute PROTO((dw_die_ref, tree));
+static void add_const_value_attribute PROTO((dw_die_ref, rtx));
+static void add_location_or_const_value_attribute PROTO((dw_die_ref, tree));
+static void add_name_attribute PROTO((dw_die_ref, char *));
+static void add_bound_info PROTO((dw_die_ref,
+ enum dwarf_attribute, tree));
+static void add_subscript_info PROTO((dw_die_ref, tree));
+static void add_byte_size_attribute PROTO((dw_die_ref, tree));
+static void add_bit_offset_attribute PROTO((dw_die_ref, tree));
+static void add_bit_size_attribute PROTO((dw_die_ref, tree));
+static void add_prototyped_attribute PROTO((dw_die_ref, tree));
+static void add_abstract_origin_attribute PROTO((dw_die_ref, tree));
+static void add_pure_or_virtual_attribute PROTO((dw_die_ref, tree));
+static void add_src_coords_attributes PROTO((dw_die_ref, tree));
+static void ad_name_and_src_coords_attributes PROTO((dw_die_ref, tree));
+static void push_decl_scope PROTO((tree));
+static dw_die_ref scope_die_for PROTO((tree, dw_die_ref));
+static void pop_decl_scope PROTO((void));
+static void add_type_attribute PROTO((dw_die_ref, tree, int, int,
+ dw_die_ref));
+static char *type_tag PROTO((tree));
+static tree member_declared_type PROTO((tree));
+static char *decl_start_label PROTO((tree));
+static void gen_arrqay_type_die PROTO((tree, dw_die_ref));
+static void gen_set_type_die PROTO((tree, dw_die_ref));
+static void gen_entry_point_die PROTO((tree, dw_die_ref));
+static void pend_type PROTO((tree));
+static void output_pending_types_for_scope PROTO((dw_die_ref));
+static void gen_inlined_enumeration_type_die PROTO((tree, dw_die_ref));
+static void gen_inlined_structure_type_die PROTO((tree, dw_die_ref));
+static void gen_inlined_union_type_die PROTO((tree, dw_die_ref));
+static void gen_enumeration_type_die PROTO((tree, dw_die_ref));
+static dw_die_ref gen_formal_parameter_die PROTO((tree, dw_die_ref));
+static void gen_unspecified_parameters_die PROTO((tree, dw_die_ref));
+static void gen_formal_types_die PROTO((tree, dw_die_ref));
+static void gen_subprogram_die PROTO((tree, dw_die_ref));
+static void gen_variable_die PROTO((tree, dw_die_ref));
+static void gen_label_die PROTO((tree, dw_die_ref));
+static void gen_lexical_block_die PROTO((tree, dw_die_ref, int));
+static void gen_inlined_subprogram_die PROTO((tree, dw_die_ref, int));
+static void gen_field_die PROTO((tree, dw_die_ref));
+static void gen_ptr_to_mbr_type_die PROTO((tree, dw_die_ref));
+static void gen_compile_unit_die PROTO((char *));
+static void gen_string_type_die PROTO((tree, dw_die_ref));
+static void gen_inheritance_die PROTO((tree, dw_die_ref));
+static void gen_member_die PROTO((tree, dw_die_ref));
+static void gen_struct_or_union_type_die PROTO((tree, dw_die_ref));
+static void gen_subroutine_type_die PROTO((tree, dw_die_ref));
+static void gen_typedef_die PROTO((tree, dw_die_ref));
+static void gen_type_die PROTO((tree, dw_die_ref));
+static void gen_tagged_type_instantiation_die PROTO((tree, dw_die_ref));
+static void gen_block_die PROTO((tree, dw_die_ref, int));
+static void decls_for_scope PROTO((tree, dw_die_ref, int));
+static int is_redundant_typedef PROTO((tree));
+static void gen_decl_die PROTO((tree, dw_die_ref));
+static unsigned lookup_filename PROTO((char *));
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_die_ref;
- attr->dw_attr_val.v.val_die_ref = targ_die;
- add_dwarf_attr (die, attr);
-}
+/* Section names used to hold DWARF debugging information. */
+#ifndef DEBUG_SECTION
+#define DEBUG_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 LINE_SECTION
+#define 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
-/* Add an FDE reference attribute value to a DIE. */
+/* Standerd 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
-static inline void
-add_AT_fde_ref (die, attr_kind, targ_fde)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register unsigned targ_fde;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_fde_ref;
- attr->dw_attr_val.v.val_fde_index = targ_fde;
- add_dwarf_attr (die, attr);
-}
+/* 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. */
-/* Add a location description attribute value to a DIE. */
+char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-static inline void
-add_AT_loc (die, attr_kind, loc)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register dw_loc_descr_ref loc;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+#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
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_loc;
- attr->dw_attr_val.v.val_loc = loc;
- add_dwarf_attr (die, attr);
-}
+/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
+ newline is produced. When flag_verbose_asm is asserted, we add commnetary
+ at the end of the line, so we must avoid output of a newline here. */
+#ifndef ASM_OUTPUT_DWARF_STRING
+#define ASM_OUTPUT_DWARF_STRING(FILE,P) \
+ do { \
+ register int slen = strlen(P); \
+ register char *p = (P); \
+ register int i; \
+ fprintf (FILE, "\t.ascii \""); \
+ for (i = 0; i < slen; i++) \
+ { \
+ register int c = p[i]; \
+ if (c == '\"' || c == '\\') \
+ putc ('\\', FILE); \
+ if (c >= ' ' && c < 0177) \
+ putc (c, FILE); \
+ else \
+ { \
+ fprintf (FILE, "\\%o", c); \
+ } \
+ } \
+ fprintf (FILE, "\\0\""); \
+ } \
+ while (0)
+#endif
-/* Add an address constant attribute value to a DIE. */
+/* Convert a reference to the assembler name of a C-level name. This
+ macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
+ a string rather than writing to a file. */
+#ifndef ASM_NAME_TO_STRING
+#define ASM_NAME_TO_STRING(STR, NAME) \
+ do { \
+ if ((NAME)[0] == '*') \
+ strcpy (STR, NAME+1); \
+ else \
+ strcpy (STR, NAME); \
+ } \
+ while (0)
+#endif
+\f
+/* Convert an integer constant expression into assembler syntax. Addition
+ and subtraction are the only arithmetic that may appear in these
+ expressions. This is an adaptation of output_addr_const in final.c.
+ Here, the target of the conversion is a string buffer. We can't use
+ output_addr_const directly, because it writes to a file. */
-static inline void
-add_AT_addr (die, attr_kind, addr)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- char *addr;
+static void
+addr_const_to_string (str, x)
+ char *str;
+ rtx x;
{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
-
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_addr;
- attr->dw_attr_val.v.val_addr = addr;
- add_dwarf_attr (die, attr);
-}
-
-/* Add a label identifier attribute value to a DIE. */
+ char buf1[256];
+ char buf2[256];
-static inline void
-add_AT_lbl_id (die, attr_kind, lbl_id)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register char *lbl_id;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+restart:
+ str[0] = '\0';
+ switch (GET_CODE (x))
+ {
+ case PC:
+ if (flag_pic)
+ strcat (str, ",");
+ else
+ abort ();
+ break;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_lbl_id;
- attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
- add_dwarf_attr (die, attr);
-}
+ case SYMBOL_REF:
+ ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
+ strcat (str, buf1);
+ break;
-/* Add a section offset attribute value to a DIE. */
+ case LABEL_REF:
+ ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
+ ASM_NAME_TO_STRING (buf2, buf1);
+ strcat (str, buf2);
+ break;
-static inline void
-add_AT_section_offset (die, attr_kind, section)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
- register char *section;
-{
- register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ case CODE_LABEL:
+ ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
+ ASM_NAME_TO_STRING (buf2, buf1);
+ strcat (str, buf2);
+ break;
- attr->dw_attr_next = NULL;
- attr->dw_attr = attr_kind;
- attr->dw_attr_val.val_class = dw_val_class_section_offset;
- attr->dw_attr_val.v.val_section = section;
- add_dwarf_attr (die, attr);
-
-}
+ case CONST_INT:
+ sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ strcat (str, buf1);
+ break;
-/* Test if die refers to an external subroutine. */
+ case CONST:
+ /* This used to output parentheses around the expression, but that does
+ not work on the 386 (either ATT or BSD assembler). */
+ addr_const_to_string (buf1, XEXP (x, 0));
+ strcat (str, buf1);
+ break;
-static inline int
-is_extern_subr_die (die)
- register dw_die_ref die;
-{
- register dw_attr_ref a;
- register int is_subr = FALSE;
- register int is_extern = FALSE;
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ {
+ /* We can use %d if the number is one word and positive. */
+ if (CONST_DOUBLE_HIGH (x))
+ sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
+ else if (CONST_DOUBLE_LOW (x) < 0)
+ sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
+ else
+ sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
+ CONST_DOUBLE_LOW (x));
+ strcat (str, buf1);
+ }
+ else
+ /* We can't handle floating point constants; PRINT_OPERAND must
+ handle them. */
+ output_operand_lossage ("floating constant misused");
+ break;
- if (die != NULL && die->die_tag == DW_TAG_subprogram)
- {
- is_subr = TRUE;
- for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+ case PLUS:
+ /* Some assemblers need integer constants to appear last (eg masm). */
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT)
{
- if (a->dw_attr == DW_AT_external
- && a->dw_attr_val.val_class == dw_val_class_flag
- && a->dw_attr_val.v.val_flag != 0)
- {
- is_extern = TRUE;
- break;
- }
+ addr_const_to_string (buf1, XEXP (x, 1));
+ strcat (str, buf1);
+ if (INTVAL (XEXP (x, 0)) >= 0)
+ strcat (str, "+");
+
+ addr_const_to_string (buf1, XEXP (x, 0));
+ strcat (str, buf1);
}
- }
+ else
+ {
+ addr_const_to_string (buf1, XEXP (x, 0));
+ strcat (str, buf1);
+ if (INTVAL (XEXP (x, 1)) >= 0)
+ strcat (str, "+");
- return is_subr && is_extern;
-}
+ addr_const_to_string (buf1, XEXP (x, 1));
+ strcat (str, buf1);
+ }
+ break;
-/* Get the attribute of type attr_kind. */
+ case MINUS:
+ /* Avoid outputting things like x-x or x+5-x, since some assemblers
+ can't handle that. */
+ x = simplify_subtraction (x);
+ if (GET_CODE (x) != MINUS)
+ goto restart;
-static inline dw_attr_ref
-get_AT (die, attr_kind)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
-{
- register dw_attr_ref a;
- register dw_die_ref spec = NULL;
-
- if (die != NULL)
- {
- for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+ addr_const_to_string (buf1, XEXP (x, 0));
+ strcat (str, buf1);
+ strcat (str, "-");
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) < 0)
{
- if (a->dw_attr == attr_kind)
- return a;
-
- if (a->dw_attr == DW_AT_specification
- || a->dw_attr == DW_AT_abstract_origin)
- spec = a->dw_attr_val.v.val_die_ref;
+ strcat (str, ASM_OPEN_PAREN);
+ addr_const_to_string (buf1, XEXP (x, 1));
+ strcat (str, buf1);
+ strcat (str, ASM_CLOSE_PAREN);
+ }
+ else
+ {
+ addr_const_to_string (buf1, XEXP (x, 1));
+ strcat (str, buf1);
}
+ break;
- if (spec)
- return get_AT (spec, attr_kind);
- }
+ case ZERO_EXTEND:
+ case SIGN_EXTEND:
+ addr_const_to_string (buf1, XEXP (x, 0));
+ strcat (str, buf1);
+ break;
- return NULL;
+ default:
+ output_operand_lossage ("invalid expression as operand");
+ }
}
-/* Return the "low pc" attribute value, typically associated with
- a subprogram DIE. Return null if the "low pc" attribute is
- either not prsent, or if it cannot be represented as an
- assembler label identifier. */
+/* Convert an address constant to a string, and return a pointer to
+ a copy of the result, located on the heap. */
-static inline char *
-get_AT_low_pc (die)
- register dw_die_ref die;
+static char *
+addr_to_string (x)
+ rtx x;
{
- register dw_attr_ref a = get_AT (die, DW_AT_low_pc);
-
- if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id)
- return a->dw_attr_val.v.val_lbl_id;
-
- return NULL;
+ char buf[1024];
+ addr_const_to_string (buf, x);
+ return xstrdup (buf);
}
-/* Return the "high pc" attribute value, typically associated with
- a subprogram DIE. Return null if the "high pc" attribute is
- either not prsent, or if it cannot be represented as an
- assembler label identifier. */
+/* Test if rtl node points to a psuedo register. */
-static inline char *
-get_AT_hi_pc (die)
- register dw_die_ref die;
+static inline int
+is_pseudo_reg (rtl)
+ register rtx rtl;
{
- register dw_attr_ref a = get_AT (die, DW_AT_high_pc);
-
- if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id)
- return a->dw_attr_val.v.val_lbl_id;
-
- return NULL;
+ return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
+ || ((GET_CODE (rtl) == SUBREG)
+ && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
}
-/* Return the value of the string attribute designated by ATTR_KIND, or
- NULL if it is not present. */
+/* Return a reference to a type, with its const and volatile qualifiers
+ removed. */
-static inline char *
-get_AT_string (die, attr_kind)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
+static inline tree
+type_main_variant (type)
+ register tree type;
{
- register dw_attr_ref a = get_AT (die, attr_kind);
+ type = TYPE_MAIN_VARIANT (type);
- if (a && a->dw_attr_val.val_class == dw_val_class_str)
- return a->dw_attr_val.v.val_str;
+ /* 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. */
- return NULL;
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ while (type != TYPE_MAIN_VARIANT (type))
+ type = TYPE_MAIN_VARIANT (type);
+
+ return type;
}
-/* Return the value of the flag attribute designated by ATTR_KIND, or -1
- if it is not present. */
+/* Return non-zero if the given type node represents a tagged type. */
static inline int
-get_AT_flag (die, attr_kind)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
+is_tagged_type (type)
+ register tree type;
{
- register dw_attr_ref a = get_AT (die, attr_kind);
-
- if (a && a->dw_attr_val.val_class == dw_val_class_flag)
- return a->dw_attr_val.v.val_flag;
+ register enum tree_code code = TREE_CODE (type);
- return -1;
+ return (code == RECORD_TYPE || code == UNION_TYPE
+ || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
}
-/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0
- if it is not present. */
+/* Convert a DIE tag into its string name. */
-static inline unsigned
-get_AT_unsigned (die, attr_kind)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
+static char *
+dwarf_tag_name (tag)
+ register unsigned tag;
{
- register dw_attr_ref a = get_AT (die, attr_kind);
-
- if (a && a->dw_attr_val.val_class == dw_val_class_unsigned_const)
- return a->dw_attr_val.v.val_unsigned;
-
- return 0;
+ 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>";
+ }
}
-static inline int
-is_c_family ()
-{
- register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
-
- return (lang == DW_LANG_C || lang == DW_LANG_C89
- || lang == DW_LANG_C_plus_plus);
-}
-
-static inline int
-is_fortran ()
-{
- register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
-
- return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90);
-}
-
-/* Remove the specified attribute if present. */
+/* Convert a DWARF attribute code into its string name. */
-static inline void
-remove_AT (die, attr_kind)
- register dw_die_ref die;
- register enum dwarf_attribute attr_kind;
+static char *
+dwarf_attr_name (attr)
+ register unsigned attr;
{
- register dw_attr_ref a;
- register dw_attr_ref removed = NULL;;
-
- if (die != NULL)
+ switch (attr)
{
- if (die->die_attr->dw_attr == attr_kind)
- {
- removed = die->die_attr;
- if (die->die_attr_last == die->die_attr)
- die->die_attr_last = NULL;
-
- die->die_attr = die->die_attr->dw_attr_next;
- }
-
- else
- for (a = die->die_attr; a->dw_attr_next != NULL;
- a = a->dw_attr_next)
- if (a->dw_attr_next->dw_attr == attr_kind)
- {
- removed = a->dw_attr_next;
- if (die->die_attr_last == a->dw_attr_next)
- die->die_attr_last = a;
+ 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";
- a->dw_attr_next = a->dw_attr_next->dw_attr_next;
- break;
- }
+ 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";
- if (removed != 0)
- free (removed);
+ 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>";
}
}
-/* Discard the children of this DIE. */
+/* Convert a DWARF value form code into its string name. */
-static inline void
-remove_children (die)
- register dw_die_ref die;
+static char *
+dwarf_form_name (form)
+ register unsigned form;
{
- register dw_die_ref child_die = die->die_child;
-
- die->die_child = NULL;
- die->die_child_last = NULL;
-
- while (child_die != NULL)
+ switch (form)
{
- register dw_die_ref tmp_die = child_die;
- register dw_attr_ref a;
-
- child_die = child_die->die_sib;
-
- for (a = tmp_die->die_attr; a != NULL; )
- {
- register dw_attr_ref tmp_a = a;
-
- a = a->dw_attr_next;
- free (tmp_a);
- }
-
- free (tmp_die);
+ 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 "DW_FORM_<unknown>";
}
}
-/* Add a child DIE below its parent. */
+/* Convert a DWARF stack opcode into its string name. */
-static inline void
-add_child_die (die, child_die)
- register dw_die_ref die;
- register dw_die_ref child_die;
+static char *
+dwarf_stack_op_name (op)
+ register unsigned op;
{
- if (die != NULL && child_die != NULL)
+ switch (op)
{
- assert (die != child_die);
- child_die->die_parent = die;
- child_die->die_sib = NULL;
-
- if (die->die_child == NULL)
- {
- die->die_child = child_die;
- die->die_child_last = child_die;
- }
- else
- {
- die->die_child_last->die_sib = child_die;
- die->die_child_last = child_die;
- }
+ 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 "OP_<unknown>";
}
}
-/* Return a pointer to a newly created DIE node. */
-
-static inline dw_die_ref
-new_die (tag_value, parent_die)
- register enum dwarf_tag tag_value;
- register dw_die_ref parent_die;
-{
- register dw_die_ref die = (dw_die_ref) xmalloc (sizeof (die_node));
-
- die->die_tag = tag_value;
- die->die_abbrev = 0;
- die->die_offset = 0;
- die->die_child = NULL;
- die->die_parent = NULL;
- die->die_sib = NULL;
- die->die_child_last = NULL;
- die->die_attr = NULL;
- die->die_attr_last = NULL;
-
- if (parent_die != NULL)
- add_child_die (parent_die, die);
- else
- ++limbo_die_count;
-
- return die;
-}
-
-/* Return the DIE associated with the given type specifier. */
-
-static inline dw_die_ref
-lookup_type_die (type)
- register tree type;
-{
- return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
-}
-
-/* Equate a DIE to a given type specifier. */
-
-static void
-equate_type_number_to_die (type, type_die)
- register tree type;
- register dw_die_ref type_die;
-{
- TYPE_SYMTAB_POINTER (type) = (char *) type_die;
-}
-
-/* Return the DIE associated with a given declaration. */
-
-static inline dw_die_ref
-lookup_decl_die (decl)
- register tree decl;
-{
- register unsigned decl_id = DECL_UID (decl);
-
- return (decl_id < decl_die_table_in_use
- ? decl_die_table[decl_id] : NULL);
-}
-
-/* Equate a DIE to a particular declaration. */
+/* Convert a DWARF type code into its string name. */
-static void
-equate_decl_number_to_die (decl, decl_die)
- register tree decl;
- register dw_die_ref decl_die;
+static char *
+dwarf_type_encoding_name (enc)
+ register unsigned enc;
{
- register unsigned decl_id = DECL_UID (decl);
- register unsigned i;
- register unsigned num_allocated;
-
- if (decl_id >= decl_die_table_allocated)
+ switch (enc)
{
- num_allocated
- = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1)
- / DECL_DIE_TABLE_INCREMENT)
- * DECL_DIE_TABLE_INCREMENT;
-
- decl_die_table
- = (dw_die_ref *) xrealloc (decl_die_table,
- sizeof (dw_die_ref) * num_allocated);
-
- bzero ((char *) &decl_die_table[decl_die_table_allocated],
- (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
- decl_die_table_allocated = num_allocated;
- }
-
- if (decl_id >= decl_die_table_in_use)
- decl_die_table_in_use = (decl_id + 1);
-
- 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;
+ case DW_ATE_address:
+ return "DW_ATE_address";
+ case DW_ATE_boolean:
+ return "DW_ATE_boolean";
+ case DW_ATE_complex_float:
+ return "DW_ATE_complex_float";
+ case DW_ATE_float:
+ return "DW_ATE_float";
+ case DW_ATE_signed:
+ return "DW_ATE_signed";
+ case DW_ATE_signed_char:
+ return "DW_ATE_signed_char";
+ case DW_ATE_unsigned:
+ return "DW_ATE_unsigned";
+ case DW_ATE_unsigned_char:
+ return "DW_ATE_unsigned_char";
+ default:
+ return "DW_ATE_<unknown>";
+ }
}
+\f
+/* Determine the "ultimate origin" of a decl. The decl may be an inlined
+ instance of an inlined instance of a decl which is local to an inline
+ function, so we have to trace all of the way back through the origin chain
+ to find out what sort of node actually served as the original seed for the
+ given block. */
-/* 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;
+static tree
+decl_ultimate_origin (decl)
+ register tree decl;
{
- register dw_loc_descr_ref *d;
+ register tree immediate_origin = DECL_ABSTRACT_ORIGIN (decl);
- /* Find the end of the chain. */
- for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
- ;
+ if (immediate_origin == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ register tree ret_val;
+ register tree lookahead = immediate_origin;
- *d = descr;
+ do
+ {
+ ret_val = lookahead;
+ lookahead = DECL_ABSTRACT_ORIGIN (ret_val);
+ }
+ while (lookahead != NULL && lookahead != ret_val);
+
+ return ret_val;
+ }
}
-/* Return a pointer to a newly allocated Call Frame Instruction. */
+/* Determine the "ultimate origin" of a block. The block may be an inlined
+ instance of an inlined instance of a block which is local to an inline
+ function, so we have to trace all of the way back through the origin chain
+ to find out what sort of node actually served as the original seed for the
+ given block. */
-static inline dw_cfi_ref
-new_cfi ()
+static tree
+block_ultimate_origin (block)
+ register tree block;
{
- register dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node));
+ register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
- cfi->dw_cfi_next = NULL;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
- cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
+ if (immediate_origin == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ register tree ret_val;
+ register tree lookahead = immediate_origin;
- return cfi;
+ do
+ {
+ ret_val = lookahead;
+ lookahead = (TREE_CODE (ret_val) == BLOCK)
+ ? BLOCK_ABSTRACT_ORIGIN (ret_val)
+ : NULL;
+ }
+ while (lookahead != NULL && lookahead != ret_val);
+
+ return ret_val;
+ }
}
-/* Add a Call Frame Instruction to list of instructions. */
+/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT
+ of a virtual function may refer to a base class, so we check the 'this'
+ parameter. */
-static inline void
-add_cfi (list_head, cfi)
- register dw_cfi_ref *list_head;
- register dw_cfi_ref cfi;
+static tree
+decl_class_context (decl)
+ tree decl;
{
- register dw_cfi_ref *p;
+ tree context = NULL_TREE;
- /* Find the end of the chain. */
- for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next)
- ;
+ if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
+ context = DECL_CONTEXT (decl);
+ else
+ context = TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
- *p = cfi;
+ if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
+ context = NULL_TREE;
+
+ return context;
}
\f
-/* Keep track of the number of spaces used to indent the
- output of the debugging routines that print the structure of
- the DIE internal representation. */
-static int print_indent;
-
-/* Indent the line the number of spaces given by print_indent. */
+/* Add an attribute/value pair to a DIE */
static inline void
-print_spaces (outfile)
- FILE *outfile;
-{
- fprintf (outfile, "%*s", print_indent, "");
-}
-
-/* Print the information assoaciated with a given DIE, and its children.
- This routine is a debugging aid only. */
-
-static void
-print_die (die, outfile)
- dw_die_ref die;
- FILE *outfile;
+add_dwarf_attr (die, attr)
+ register dw_die_ref die;
+ register dw_attr_ref attr;
{
- register dw_attr_ref a;
- register dw_die_ref c;
-
- print_spaces (outfile);
- fprintf (outfile, "DIE %4u: %s\n",
- die->die_offset, dwarf_tag_name (die->die_tag));
- print_spaces (outfile);
- fprintf (outfile, " abbrev id: %u", die->die_abbrev);
- fprintf (outfile, " offset: %u\n", die->die_offset);
-
- for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+ if (die != NULL && attr != NULL)
{
- print_spaces (outfile);
- fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr));
-
- switch (a->dw_attr_val.val_class)
+ if (die->die_attr == NULL)
{
- case dw_val_class_addr:
- fprintf (outfile, "address");
- break;
- case dw_val_class_loc:
- fprintf (outfile, "location descriptor");
- break;
- case dw_val_class_const:
- fprintf (outfile, "%d", a->dw_attr_val.v.val_int);
- break;
- case dw_val_class_unsigned_const:
- fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
- break;
- case dw_val_class_long_long:
- fprintf (outfile, "constant (%u,%u)",
- a->dw_attr_val.v.val_long_long.hi,
- a->dw_attr_val.v.val_long_long.low);
- break;
- case dw_val_class_float:
- fprintf (outfile, "floating-point constant");
- break;
- case dw_val_class_flag:
- fprintf (outfile, "%u", a->dw_attr_val.v.val_flag);
- break;
- case dw_val_class_die_ref:
- if (a->dw_attr_val.v.val_die_ref != NULL)
- fprintf (outfile, "die -> %u",
- a->dw_attr_val.v.val_die_ref->die_offset);
- else
- fprintf (outfile, "die -> <null>");
- break;
- case dw_val_class_lbl_id:
- fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id);
- break;
- case dw_val_class_section_offset:
- fprintf (outfile, "section: %s", a->dw_attr_val.v.val_section);
- break;
- case dw_val_class_str:
- if (a->dw_attr_val.v.val_str != NULL)
- fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str);
- else
- fprintf (outfile, "<null>");
- break;
+ die->die_attr = attr;
+ die->die_attr_last = attr;
+ }
+ else
+ {
+ die->die_attr_last->dw_attr_next = attr;
+ die->die_attr_last = attr;
}
-
- fprintf (outfile, "\n");
- }
-
- if (die->die_child != NULL)
- {
- print_indent += 4;
- for (c = die->die_child; c != NULL; c = c->die_sib)
- print_die (c, outfile);
-
- print_indent -= 4;
}
}
-/* Print the contents of the source code line number correspondence table.
- This routine is a debugging aid only. */
+/* Add a flag value attribute to a DIE. */
-static void
-print_dwarf_line_table (outfile)
- FILE *outfile;
+static inline void
+add_AT_flag (die, attr_kind, flag)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register unsigned flag;
{
- register unsigned i;
- register dw_line_info_ref line_info;
-
- fprintf (outfile, "\n\nDWARF source line information\n");
- for (i = 1; i < line_info_table_in_use; ++i)
- {
- line_info = &line_info_table[i];
- fprintf (outfile, "%5d: ", i);
- fprintf (outfile, "%-20s", file_table[line_info->dw_file_num]);
- fprintf (outfile, "%6d", line_info->dw_line_num);
- fprintf (outfile, "\n");
- }
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- fprintf (outfile, "\n\n");
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_flag;
+ attr->dw_attr_val.v.val_flag = flag;
+ add_dwarf_attr (die, attr);
}
-/* Print the information collected for a given DIE. */
+/* Add a signed integer attribute value to a DIE. */
-void
-debug_dwarf_die (die)
- dw_die_ref die;
+static inline void
+add_AT_int (die, attr_kind, int_val)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register long int int_val;
{
- print_die (die, stderr);
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_const;
+ attr->dw_attr_val.v.val_int = int_val;
+ add_dwarf_attr (die, attr);
}
-/* Print all DWARF information collected for the compilation unit.
- This routine is a debugging aid only. */
+/* Add an unsigned integer attribute value to a DIE. */
-void
-debug_dwarf ()
+static inline void
+add_AT_unsigned (die, attr_kind, unsigned_val)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register unsigned long unsigned_val;
{
- print_indent = 0;
- print_die (comp_unit_die, stderr);
- print_dwarf_line_table (stderr);
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_unsigned_const;
+ attr->dw_attr_val.v.val_unsigned = unsigned_val;
+ add_dwarf_attr (die, attr);
}
-\f
-/* Traverse the DIE, 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)
+/* Add an unsigned double integer attribute value to a DIE. */
+
+static inline void
+add_AT_long_long (die, attr_kind, val_hi, val_low)
register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register unsigned long val_hi;
+ register unsigned long val_low;
{
- register dw_die_ref c;
- register dw_attr_ref attr;
- if (die != comp_unit_die && die->die_child != NULL)
- {
- attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- attr->dw_attr_next = NULL;
- attr->dw_attr = DW_AT_sibling;
- attr->dw_attr_val.val_class = dw_val_class_die_ref;
- attr->dw_attr_val.v.val_die_ref = die->die_sib;
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- /* Add the sibling link to the front of the attribute list. */
- attr->dw_attr_next = die->die_attr;
- if (die->die_attr == NULL)
- die->die_attr_last = attr;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_long_long;
+ attr->dw_attr_val.v.val_long_long.hi = val_hi;
+ attr->dw_attr_val.v.val_long_long.low = val_low;
+ add_dwarf_attr (die, attr);
+}
- die->die_attr = attr;
- }
+/* Add a floating point attribute value to a DIE and return it. */
- for (c = die->die_child; c != NULL; c = c->die_sib)
- add_sibling_attributes (c);
+static inline void
+add_AT_float (die, attr_kind, length, array)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register unsigned length;
+ register long *array;
+{
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_float;
+ attr->dw_attr_val.v.val_float.length = length;
+ attr->dw_attr_val.v.val_float.array = array;
+ add_dwarf_attr (die, attr);
}
-/* 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. */
+/* Add a string attribute value to a DIE. */
-static void
-build_abbrev_table (die)
+static inline void
+add_AT_string (die, attr_kind, str)
register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register char *str;
{
- 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;
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- while (a_attr != NULL && d_attr != NULL)
- {
- if ((a_attr->dw_attr != d_attr->dw_attr)
- || (value_format (&a_attr->dw_attr_val)
- != value_format (&d_attr->dw_attr_val)))
- break;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_str;
+ attr->dw_attr_val.v.val_str = xstrdup (str);
+ add_dwarf_attr (die, attr);
+}
- a_attr = a_attr->dw_attr_next;
- d_attr = d_attr->dw_attr_next;
- }
+/* Add a DIE reference attribute value to a DIE. */
- if (a_attr == NULL && d_attr == NULL)
- break;
- }
- }
- }
+static inline void
+add_AT_die_ref (die, attr_kind, targ_die)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register dw_die_ref targ_die;
+{
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- 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 *) xmalloc (abbrev_die_table,
- sizeof (dw_die_ref) * n_alloc);
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_die_ref;
+ attr->dw_attr_val.v.val_die_ref = targ_die;
+ add_dwarf_attr (die, attr);
+}
- 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;
- }
+/* Add an FDE reference attribute value to a DIE. */
- ++abbrev_die_table_in_use;
- abbrev_die_table[abbrev_id] = die;
- }
+static inline void
+add_AT_fde_ref (die, attr_kind, targ_fde)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register unsigned targ_fde;
+{
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- die->die_abbrev = abbrev_id;
- for (c = die->die_child; c != NULL; c = c->die_sib)
- build_abbrev_table (c);
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_fde_ref;
+ attr->dw_attr_val.v.val_fde_index = targ_fde;
+ add_dwarf_attr (die, attr);
}
-\f
-/* Return the size of an unsigned LEB128 quantity. */
-static inline unsigned long
-size_of_uleb128 (value)
- register unsigned long value;
-{
- register unsigned long size = 0;
- register unsigned byte;
+/* Add a location description attribute value to a DIE. */
- do
- {
- byte = (value & 0x7f);
- value >>= 7;
- size += 1;
- }
- while (value != 0);
+static inline void
+add_AT_loc (die, attr_kind, loc)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register dw_loc_descr_ref loc;
+{
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- return size;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_loc;
+ attr->dw_attr_val.v.val_loc = loc;
+ add_dwarf_attr (die, attr);
}
-/* Return the size of a signed LEB128 quantity. */
+/* Add an address constant attribute value to a DIE. */
-static inline unsigned long
-size_of_sleb128 (value)
- register long value;
+static inline void
+add_AT_addr (die, attr_kind, addr)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ char *addr;
{
- register unsigned long size = 0;
- register unsigned byte;
-
- do
- {
- byte = (value & 0x7f);
- value >>= 7;
- size += 1;
- }
- while (!(((value == 0) && ((byte & 0x40) == 0))
- || ((value == -1) && ((byte & 0x40) != 0))));
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- return size;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_addr;
+ attr->dw_attr_val.v.val_addr = addr;
+ add_dwarf_attr (die, attr);
}
-/* Return the size of a string, including the null byte. */
+/* Add a label identifier attribute value to a DIE. */
-static unsigned long
-size_of_string (str)
- register char *str;
+static inline void
+add_AT_lbl_id (die, attr_kind, lbl_id)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register char *lbl_id;
{
- register unsigned long size = 0;
- register unsigned long slen = strlen (str);
- register unsigned long i;
- register unsigned c;
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- for (i = 0; i < slen; ++i)
- {
- c = str[i];
- if (c == '\\')
- ++i;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_lbl_id;
+ attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id);
+ add_dwarf_attr (die, attr);
+}
- size += 1;
- }
+/* Add a section offset attribute value to a DIE. */
+
+static inline void
+add_AT_section_offset (die, attr_kind, section)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+ register char *section;
+{
+ register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
- /* Null terminator. */
- size += 1;
- return size;
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = attr_kind;
+ attr->dw_attr_val.val_class = dw_val_class_section_offset;
+ attr->dw_attr_val.v.val_section = section;
+ add_dwarf_attr (die, attr);
+
}
-/* Return the size of a location descriptor. */
+/* Test if die refers to an external subroutine. */
-static unsigned long
-size_of_loc_descr (loc)
- register dw_loc_descr_ref loc;
+static inline int
+is_extern_subr_die (die)
+ register dw_die_ref die;
{
- register unsigned long size = 1;
+ register dw_attr_ref a;
+ register int is_subr = FALSE;
+ register int is_extern = FALSE;
- switch (loc->dw_loc_opc)
+ if (die != NULL && die->die_tag == DW_TAG_subprogram)
{
- case DW_OP_addr:
- size += PTR_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;
+ is_subr = TRUE;
+ for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+ {
+ if (a->dw_attr == DW_AT_external
+ && a->dw_attr_val.val_class == dw_val_class_flag
+ && a->dw_attr_val.v.val_flag != 0)
+ {
+ is_extern = TRUE;
+ break;
+ }
+ }
}
- return size;
+ return is_subr && is_extern;
}
-/* Return the size of a series of location descriptors. */
+/* Get the attribute of type attr_kind. */
-static unsigned long
-size_of_locs (loc)
- register dw_loc_descr_ref loc;
+static inline dw_attr_ref
+get_AT (die, attr_kind)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
{
- register unsigned long size = 0;
+ register dw_attr_ref a;
+ register dw_die_ref spec = NULL;
+
+ if (die != NULL)
+ {
+ for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
+ {
+ if (a->dw_attr == attr_kind)
+ return a;
- for (; loc != NULL; loc = loc->dw_loc_next)
- size += size_of_loc_descr (loc);
+ if (a->dw_attr == DW_AT_specification
+ || a->dw_attr == DW_AT_abstract_origin)
+ spec = a->dw_attr_val.v.val_die_ref;
+ }
- return size;
+ if (spec)
+ return get_AT (spec, attr_kind);
+ }
+
+ return NULL;
}
-/* Return the power-of-two number of bytes necessary to represent VALUE. */
+/* Return the "low pc" attribute value, typically associated with
+ a subprogram DIE. Return null if the "low pc" attribute is
+ either not prsent, or if it cannot be represented as an
+ assembler label identifier. */
-static int
-constant_size (value)
- long unsigned value;
+static inline char *
+get_AT_low_pc (die)
+ register dw_die_ref die;
{
- int log;
-
- if (value == 0)
- log = 0;
- else
- log = floor_log2 (value);
+ register dw_attr_ref a = get_AT (die, DW_AT_low_pc);
- log = log / 8;
- log = 1 << (floor_log2 (log) + 1);
+ if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id)
+ return a->dw_attr_val.v.val_lbl_id;
- return log;
+ return NULL;
}
-/* Return the size of a DIE, as it is represented in the
- .debug_info section. */
+/* Return the "high pc" attribute value, typically associated with
+ a subprogram DIE. Return null if the "high pc" attribute is
+ either not prsent, or if it cannot be represented as an
+ assembler label identifier. */
-static unsigned long
-size_of_die (die)
+static inline char *
+get_AT_hi_pc (die)
register dw_die_ref die;
{
- register unsigned long size = 0;
- register dw_attr_ref a;
+ register dw_attr_ref a = get_AT (die, DW_AT_high_pc);
- size += size_of_uleb128 (die->die_abbrev);
- for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
- {
- switch (a->dw_attr_val.val_class)
- {
- case dw_val_class_addr:
- size += PTR_SIZE;
- break;
- case dw_val_class_loc:
- {
- register unsigned long lsize
- = size_of_locs (a->dw_attr_val.v.val_loc);
+ if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id)
+ return a->dw_attr_val.v.val_lbl_id;
- /* Block length. */
- size += constant_size (lsize);
- size += lsize;
- }
- break;
- case dw_val_class_const:
- size += 4;
- break;
- case dw_val_class_unsigned_const:
- size += constant_size (a->dw_attr_val.v.val_unsigned);
- break;
- case dw_val_class_long_long:
- size += 1 + 8; /* block */
- break;
- case dw_val_class_float:
- size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
- break;
- case dw_val_class_flag:
- size += 1;
- break;
- case dw_val_class_die_ref:
- size += DWARF_OFFSET_SIZE;
- break;
- case dw_val_class_fde_ref:
- size += DWARF_OFFSET_SIZE;
- break;
- case dw_val_class_lbl_id:
- size += PTR_SIZE;
- break;
- case dw_val_class_section_offset:
- size += DWARF_OFFSET_SIZE;
- break;
- case dw_val_class_str:
- size += size_of_string (a->dw_attr_val.v.val_str);
- break;
- default:
- abort ();
- }
- }
+ return NULL;
+}
+
+/* Return the value of the string attribute designated by ATTR_KIND, or
+ NULL if it is not present. */
- return size;
+static inline char *
+get_AT_string (die, attr_kind)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+{
+ register dw_attr_ref a = get_AT (die, attr_kind);
+
+ if (a && a->dw_attr_val.val_class == dw_val_class_str)
+ return a->dw_attr_val.v.val_str;
+
+ return NULL;
}
-/* Size the debgging information associted with a given DIE.
- Visits the DIE's children recursively. Updates the global
- variable next_die_offset, on each time through. Uses the
- current value of next_die_offset to updete the die_offset
- field in each DIE. */
+/* Return the value of the flag attribute designated by ATTR_KIND, or -1
+ if it is not present. */
-static void
-calc_die_sizes (die)
- dw_die_ref die;
+static inline int
+get_AT_flag (die, attr_kind)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
{
- register dw_die_ref c;
- die->die_offset = next_die_offset;
- next_die_offset += size_of_die (die);
+ register dw_attr_ref a = get_AT (die, attr_kind);
- for (c = die->die_child; c != NULL; c = c->die_sib)
- calc_die_sizes (c);
+ if (a && a->dw_attr_val.val_class == dw_val_class_flag)
+ return a->dw_attr_val.v.val_flag;
- if (die->die_child != NULL)
- /* Count the null byte used to terminate sibling lists. */
- next_die_offset += 1;
+ return -1;
}
-/* Return the size of the line information prolog generated for the
- compilation unit. */
+/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0
+ if it is not present. */
-static unsigned long
-size_of_line_prolog ()
+static inline unsigned
+get_AT_unsigned (die, attr_kind)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
{
- register unsigned long size;
- register unsigned long ft_index;
+ register dw_attr_ref a = get_AT (die, attr_kind);
- size = DWARF_LINE_PROLOG_HEADER_SIZE;
+ if (a && a->dw_attr_val.val_class == dw_val_class_unsigned_const)
+ return a->dw_attr_val.v.val_unsigned;
- /* Count the size of the table giving number of args for each
- standard opcode. */
- size += DWARF_LINE_OPCODE_BASE - 1;
+ return 0;
+}
- /* Include directory table is empty (at present). Count only the
- the null byte used to terminate the table. */
- size += 1;
+static inline int
+is_c_family ()
+{
+ register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
- for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
- {
- /* File name entry. */
- size += size_of_string (file_table[ft_index]);
+ return (lang == DW_LANG_C || lang == DW_LANG_C89
+ || lang == DW_LANG_C_plus_plus);
+}
- /* Include directory index. */
- size += size_of_uleb128 (0);
+static inline int
+is_fortran ()
+{
+ register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language);
- /* Modification time. */
- size += size_of_uleb128 (0);
+ return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90);
+}
- /* File length in bytes. */
- size += size_of_uleb128 (0);
- }
+/* Remove the specified attribute if present. */
- /* Count the file table terminator. */
- size += 1;
- return size;
-}
+static inline void
+remove_AT (die, attr_kind)
+ register dw_die_ref die;
+ register enum dwarf_attribute attr_kind;
+{
+ register dw_attr_ref a;
+ register dw_attr_ref removed = NULL;;
-/* Return the size of the line information generated for this
- compilation unit. */
+ if (die != NULL)
+ {
+ if (die->die_attr->dw_attr == attr_kind)
+ {
+ removed = die->die_attr;
+ if (die->die_attr_last == die->die_attr)
+ die->die_attr_last = NULL;
-static unsigned long
-size_of_line_info ()
-{
- register unsigned long size;
- register unsigned long lt_index;
- register unsigned long current_line;
- register long line_offset;
- register long line_delta;
- register unsigned long current_file;
- register unsigned long function;
+ die->die_attr = die->die_attr->dw_attr_next;
+ }
- /* Version number. */
- size = 2;
+ else
+ for (a = die->die_attr; a->dw_attr_next != NULL;
+ a = a->dw_attr_next)
+ if (a->dw_attr_next->dw_attr == attr_kind)
+ {
+ removed = a->dw_attr_next;
+ if (die->die_attr_last == a->dw_attr_next)
+ die->die_attr_last = a;
- /* Prolog length specifier. */
- size += DWARF_OFFSET_SIZE;
+ a->dw_attr_next = a->dw_attr_next->dw_attr_next;
+ break;
+ }
- /* Prolog. */
- size += size_of_line_prolog ();
+ if (removed != 0)
+ free (removed);
+ }
+}
- /* Set address register instruction. */
- size += 1 + size_of_uleb128 (1 + PTR_SIZE) + 1 + PTR_SIZE;
+/* Discard the children of this DIE. */
- current_file = 1;
- current_line = 1;
- for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
+static inline void
+remove_children (die)
+ register dw_die_ref die;
+{
+ register dw_die_ref child_die = die->die_child;
+
+ die->die_child = NULL;
+ die->die_child_last = NULL;
+
+ while (child_die != NULL)
{
- register dw_line_info_ref line_info;
+ register dw_die_ref tmp_die = child_die;
+ register dw_attr_ref a;
- /* Advance pc instruction. */
- size += 1 + 2;
- line_info = &line_info_table[lt_index];
- if (line_info->dw_file_num != current_file)
+ child_die = child_die->die_sib;
+
+ for (a = tmp_die->die_attr; a != NULL; )
{
- /* Set file number instruction. */
- size += 1;
- current_file = line_info->dw_file_num;
- size += size_of_uleb128 (current_file);
- }
+ register dw_attr_ref tmp_a = a;
- if (line_info->dw_line_num != current_line)
- {
- line_offset = line_info->dw_line_num - current_line;
- line_delta = line_offset - DWARF_LINE_BASE;
- current_line = line_info->dw_line_num;
- if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
- /* 1-byte special line number instruction. */
- size += 1;
- else
- {
- /* Advance line instruction. */
- size += 1;
- size += size_of_sleb128 (line_offset);
- /* Generate line entry instruction. */
- size += 1;
- }
+ a = a->dw_attr_next;
+ free (tmp_a);
}
- }
- /* Advance pc instruction. */
- size += 1 + 2;
+ free (tmp_die);
+ }
+}
- /* End of line number info. marker. */
- size += 1 + size_of_uleb128 (1) + 1;
+/* Add a child DIE below its parent. */
- function = 0;
- current_file = 1;
- current_line = 1;
- for (lt_index = 0; lt_index < separate_line_info_table_in_use; )
+static inline void
+add_child_die (die, child_die)
+ register dw_die_ref die;
+ register dw_die_ref child_die;
+{
+ if (die != NULL && child_die != NULL)
{
- register dw_separate_line_info_ref line_info
- = &separate_line_info_table[lt_index];
- if (function != line_info->function)
+ assert (die != child_die);
+ child_die->die_parent = die;
+ child_die->die_sib = NULL;
+
+ if (die->die_child == NULL)
{
- function = line_info->function;
- /* Set address register instruction. */
- size += 1 + size_of_uleb128 (1 + PTR_SIZE) + 1 + PTR_SIZE;
+ die->die_child = child_die;
+ die->die_child_last = child_die;
}
else
- /* Advance pc instruction. */
- size += 1 + 2;
-
- if (line_info->dw_file_num != current_file)
{
- /* Set file number instruction. */
- size += 1;
- current_file = line_info->dw_file_num;
- size += size_of_uleb128 (current_file);
+ die->die_child_last->die_sib = child_die;
+ die->die_child_last = child_die;
}
+ }
+}
+
+/* Return a pointer to a newly created DIE node. */
+
+static inline dw_die_ref
+new_die (tag_value, parent_die)
+ register enum dwarf_tag tag_value;
+ register dw_die_ref parent_die;
+{
+ register dw_die_ref die = (dw_die_ref) xmalloc (sizeof (die_node));
+
+ die->die_tag = tag_value;
+ die->die_abbrev = 0;
+ die->die_offset = 0;
+ die->die_child = NULL;
+ die->die_parent = NULL;
+ die->die_sib = NULL;
+ die->die_child_last = NULL;
+ die->die_attr = NULL;
+ die->die_attr_last = NULL;
+
+ if (parent_die != NULL)
+ add_child_die (parent_die, die);
+ else
+ ++limbo_die_count;
- if (line_info->dw_line_num != current_line)
- {
- line_offset = line_info->dw_line_num - current_line;
- line_delta = line_offset - DWARF_LINE_BASE;
- current_line = line_info->dw_line_num;
- if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
- /* 1-byte special line number instruction. */
- size += 1;
- else
- {
- /* Advance line instruction. */
- size += 1;
- size += size_of_sleb128 (line_offset);
+ return die;
+}
- /* Generate line entry instruction. */
- size += 1;
- }
- }
+/* Return the DIE associated with the given type specifier. */
- ++lt_index;
+static inline dw_die_ref
+lookup_type_die (type)
+ register tree type;
+{
+ return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
+}
- /* If we're done with a function, end its sequence. */
- if (lt_index == separate_line_info_table_in_use
- || separate_line_info_table[lt_index].function != function)
- {
- current_file = 1;
- current_line = 1;
+/* Equate a DIE to a given type specifier. */
- /* Advance pc instruction. */
- size += 1 + 2;
+static void
+equate_type_number_to_die (type, type_die)
+ register tree type;
+ register dw_die_ref type_die;
+{
+ TYPE_SYMTAB_POINTER (type) = (char *) type_die;
+}
- /* End of line number info. marker. */
- size += 1 + size_of_uleb128 (1) + 1;
- }
- }
+/* Return the DIE associated with a given declaration. */
- return size;
+static inline dw_die_ref
+lookup_decl_die (decl)
+ register tree decl;
+{
+ register unsigned decl_id = DECL_UID (decl);
+
+ return (decl_id < decl_die_table_in_use
+ ? decl_die_table[decl_id] : NULL);
}
-/* Return the size of the .debug_pubnames table generated for the
- compilation unit. */
+/* Equate a DIE to a particular declaration. */
-static unsigned long
-size_of_pubnames ()
+static void
+equate_decl_number_to_die (decl, decl_die)
+ register tree decl;
+ register dw_die_ref decl_die;
{
- register unsigned long size;
+ register unsigned decl_id = DECL_UID (decl);
register unsigned i;
+ register unsigned num_allocated;
- size = DWARF_PUBNAMES_HEADER_SIZE;
- for (i = 0; i < pubname_table_in_use; ++i)
+ if (decl_id >= decl_die_table_allocated)
{
- register pubname_ref p = &pubname_table[i];
- size += DWARF_OFFSET_SIZE + size_of_string (p->name);
+ num_allocated
+ = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1)
+ / DECL_DIE_TABLE_INCREMENT)
+ * DECL_DIE_TABLE_INCREMENT;
+
+ decl_die_table
+ = (dw_die_ref *) xrealloc (decl_die_table,
+ sizeof (dw_die_ref) * num_allocated);
+
+ bzero ((char *) &decl_die_table[decl_die_table_allocated],
+ (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref));
+ decl_die_table_allocated = num_allocated;
}
- size += DWARF_OFFSET_SIZE;
- return size;
+ if (decl_id >= decl_die_table_in_use)
+ decl_die_table_in_use = (decl_id + 1);
+
+ decl_die_table[decl_id] = decl_die;
}
-/* Return the size of the information in the .debug_aranges seciton. */
+/* 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 unsigned long
-size_of_aranges ()
+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 unsigned long size;
-
- size = DWARF_ARANGES_HEADER_SIZE;
+ register dw_loc_descr_ref descr
+ = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node));
- /* Count the address/length pair for this compilation unit. */
- size += 2 * PTR_SIZE;
- size += 2 * PTR_SIZE * arange_table_in_use;
+ 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;
- /* Count the two zero words used to terminated the address range table. */
- size += 2 * PTR_SIZE;
- return size;
+ return descr;
}
-\f
-/* Output an unsigned LEB128 quantity. */
-static void
-output_uleb128 (value)
- register unsigned long value;
+/* 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;
{
- unsigned long save_value = value;
+ register dw_loc_descr_ref *d;
- fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP);
- do
- {
- register unsigned byte = (value & 0x7f);
- value >>= 7;
- if (value != 0)
- /* More bytes to follow. */
- byte |= 0x80;
+ /* Find the end of the chain. */
+ for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
+ ;
- fprintf (asm_out_file, "0x%x", byte);
- if (value != 0)
- fprintf (asm_out_file, ",");
- }
- while (value != 0);
+ *d = descr;
+}
+\f
+/* Keep track of the number of spaces used to indent the
+ output of the debugging routines that print the structure of
+ the DIE internal representation. */
+static int print_indent;
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s ULEB128 0x%x", ASM_COMMENT_START, save_value);
+/* Indent the line the number of spaces given by print_indent. */
+
+static inline void
+print_spaces (outfile)
+ FILE *outfile;
+{
+ fprintf (outfile, "%*s", print_indent, "");
}
-/* Output an signed LEB128 quantity. */
+/* Print the information assoaciated with a given DIE, and its children.
+ This routine is a debugging aid only. */
static void
-output_sleb128 (value)
- register long value;
+print_die (die, outfile)
+ dw_die_ref die;
+ FILE *outfile;
{
- register int more;
- register unsigned byte;
- long save_value = value;
+ register dw_attr_ref a;
+ register dw_die_ref c;
- fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP);
- do
+ print_spaces (outfile);
+ fprintf (outfile, "DIE %4u: %s\n",
+ die->die_offset, dwarf_tag_name (die->die_tag));
+ print_spaces (outfile);
+ fprintf (outfile, " abbrev id: %u", die->die_abbrev);
+ fprintf (outfile, " offset: %u\n", die->die_offset);
+
+ for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
{
- byte = (value & 0x7f);
- /* arithmetic shift */
- value >>= 7;
- more = !((((value == 0) && ((byte & 0x40) == 0))
- || ((value == -1) && ((byte & 0x40) != 0))));
- if (more)
- byte |= 0x80;
+ print_spaces (outfile);
+ fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr));
+
+ switch (a->dw_attr_val.val_class)
+ {
+ case dw_val_class_addr:
+ fprintf (outfile, "address");
+ break;
+ case dw_val_class_loc:
+ fprintf (outfile, "location descriptor");
+ break;
+ case dw_val_class_const:
+ fprintf (outfile, "%d", a->dw_attr_val.v.val_int);
+ break;
+ case dw_val_class_unsigned_const:
+ fprintf (outfile, "%u", a->dw_attr_val.v.val_unsigned);
+ break;
+ case dw_val_class_long_long:
+ fprintf (outfile, "constant (%u,%u)",
+ a->dw_attr_val.v.val_long_long.hi,
+ a->dw_attr_val.v.val_long_long.low);
+ break;
+ case dw_val_class_float:
+ fprintf (outfile, "floating-point constant");
+ break;
+ case dw_val_class_flag:
+ fprintf (outfile, "%u", a->dw_attr_val.v.val_flag);
+ break;
+ case dw_val_class_die_ref:
+ if (a->dw_attr_val.v.val_die_ref != NULL)
+ fprintf (outfile, "die -> %u",
+ a->dw_attr_val.v.val_die_ref->die_offset);
+ else
+ fprintf (outfile, "die -> <null>");
+ break;
+ case dw_val_class_lbl_id:
+ fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id);
+ break;
+ case dw_val_class_section_offset:
+ fprintf (outfile, "section: %s", a->dw_attr_val.v.val_section);
+ break;
+ case dw_val_class_str:
+ if (a->dw_attr_val.v.val_str != NULL)
+ fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str);
+ else
+ fprintf (outfile, "<null>");
+ break;
+ }
+
+ fprintf (outfile, "\n");
+ }
+
+ if (die->die_child != NULL)
+ {
+ print_indent += 4;
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ print_die (c, outfile);
- fprintf (asm_out_file, "0x%x", byte);
- if (more)
- fprintf (asm_out_file, ",");
+ print_indent -= 4;
}
-
- while (more);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s SLEB128 %d", ASM_COMMENT_START, save_value);
}
-/* Select the encoding of an attribute value. */
+/* Print the contents of the source code line number correspondence table.
+ This routine is a debugging aid only. */
-static enum dwarf_form
-value_format (v)
- dw_val_ref v;
+static void
+print_dwarf_line_table (outfile)
+ FILE *outfile;
{
- switch (v->val_class)
+ register unsigned i;
+ register dw_line_info_ref line_info;
+
+ fprintf (outfile, "\n\nDWARF source line information\n");
+ for (i = 1; i < line_info_table_in_use; ++i)
{
- case dw_val_class_addr:
- return DW_FORM_addr;
- case dw_val_class_loc:
- switch (constant_size (size_of_locs (v->v.val_loc)))
- {
- case 1:
- return DW_FORM_block1;
- case 2:
- return DW_FORM_block2;
- default:
- abort ();
- }
- case dw_val_class_const:
- return DW_FORM_data4;
- case dw_val_class_unsigned_const:
- switch (constant_size (v->v.val_unsigned))
- {
- case 1:
- return DW_FORM_data1;
- case 2:
- return DW_FORM_data2;
- case 4:
- return DW_FORM_data4;
- case 8:
- return DW_FORM_data8;
- default:
- abort ();
- }
- case dw_val_class_long_long:
- return DW_FORM_block1;
- case dw_val_class_float:
- return DW_FORM_block1;
- case dw_val_class_flag:
- return DW_FORM_flag;
- case dw_val_class_die_ref:
- return DW_FORM_ref;
- case dw_val_class_fde_ref:
- return DW_FORM_data;
- case dw_val_class_lbl_id:
- return DW_FORM_addr;
- case dw_val_class_section_offset:
- return DW_FORM_data;
- case dw_val_class_str:
- return DW_FORM_string;
- default:
- abort ();
+ line_info = &line_info_table[i];
+ fprintf (outfile, "%5d: ", i);
+ fprintf (outfile, "%-20s", file_table[line_info->dw_file_num]);
+ fprintf (outfile, "%6d", line_info->dw_line_num);
+ fprintf (outfile, "\n");
}
+
+ fprintf (outfile, "\n\n");
}
-/* Output the encoding of an attribute value. */
+/* Print the information collected for a given DIE. */
+
+void
+debug_dwarf_die (die)
+ dw_die_ref die;
+{
+ print_die (die, stderr);
+}
+
+/* Print all DWARF information collected for the compilation unit.
+ This routine is a debugging aid only. */
+
+void
+debug_dwarf ()
+{
+ print_indent = 0;
+ print_die (comp_unit_die, stderr);
+ print_dwarf_line_table (stderr);
+}
+\f
+/* Traverse the DIE, 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
-output_value_format (v)
- dw_val_ref v;
+add_sibling_attributes(die)
+ register dw_die_ref die;
{
- enum dwarf_form form = value_format (v);
+ register dw_die_ref c;
+ register dw_attr_ref attr;
+ if (die != comp_unit_die && die->die_child != NULL)
+ {
+ attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
+ attr->dw_attr_next = NULL;
+ attr->dw_attr = DW_AT_sibling;
+ attr->dw_attr_val.val_class = dw_val_class_die_ref;
+ attr->dw_attr_val.v.val_die_ref = die->die_sib;
- output_uleb128 (form);
- if (flag_verbose_asm)
- fprintf (asm_out_file, " (%s)", dwarf_form_name (form));
+ /* Add the sibling link to the front of the attribute list. */
+ attr->dw_attr_next = die->die_attr;
+ if (die->die_attr == NULL)
+ die->die_attr_last = attr;
- fputc ('\n', asm_out_file);
+ die->die_attr = attr;
+ }
+
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ add_sibling_attributes (c);
}
-/* Output the .debug_abbrev section which defines the DIE abbreviation
- table. */
+/* 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
-output_abbrev_section ()
+build_abbrev_table (die)
+ register dw_die_ref die;
{
- unsigned long abbrev_id;
-
- dw_attr_ref a_attr;
+ 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];
- output_uleb128 (abbrev_id);
- if (flag_verbose_asm)
- fprintf (asm_out_file, " (abbrev code)");
-
- fputc ('\n', asm_out_file);
- output_uleb128 (abbrev->die_tag);
- if (flag_verbose_asm)
- fprintf (asm_out_file, " (TAG: %s)",
- dwarf_tag_name (abbrev->die_tag));
+ 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;
- fputc ('\n', asm_out_file);
- fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP,
- abbrev->die_child != NULL ? DW_children_yes : DW_children_no);
+ while (a_attr != NULL && d_attr != NULL)
+ {
+ if ((a_attr->dw_attr != d_attr->dw_attr)
+ || (value_format (&a_attr->dw_attr_val)
+ != value_format (&d_attr->dw_attr_val)))
+ break;
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START,
- (abbrev->die_child != NULL
- ? "DW_children_yes" : "DW_children_no"));
+ a_attr = a_attr->dw_attr_next;
+ d_attr = d_attr->dw_attr_next;
+ }
- fputc ('\n', asm_out_file);
+ if (a_attr == NULL && d_attr == NULL)
+ break;
+ }
+ }
+ }
- for (a_attr = abbrev->die_attr; a_attr != NULL;
- a_attr = a_attr->dw_attr_next)
+ if (abbrev_id >= abbrev_die_table_in_use)
+ {
+ if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
{
- output_uleb128 (a_attr->dw_attr);
- if (flag_verbose_asm)
- fprintf (asm_out_file, " (%s)",
- dwarf_attr_name (a_attr->dw_attr));
+ n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
+ abbrev_die_table
+ = (dw_die_ref *) xmalloc (abbrev_die_table,
+ sizeof (dw_die_ref) * n_alloc);
- fputc ('\n', asm_out_file);
- output_value_format (&a_attr->dw_attr_val);
+ 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;
}
- fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP);
+ ++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. */
-/* Output location description stack opcode's operands (if any). */
+static unsigned long
+size_of_string (str)
+ register char *str;
+{
+ register unsigned long size = 0;
+ register unsigned long slen = strlen (str);
+ register unsigned long i;
+ register unsigned c;
-static void
-output_loc_operands (loc)
+ for (i = 0; i < slen; ++i)
+ {
+ c = str[i];
+ if (c == '\\')
+ ++i;
+
+ size += 1;
+ }
+
+ /* Null terminator. */
+ size += 1;
+ return size;
+}
+
+/* Return the size of a location descriptor. */
+
+static unsigned long
+size_of_loc_descr (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;
+ register unsigned long size = 1;
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);
+ size += PTR_SIZE;
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);
+ size += 1;
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);
+ size += 2;
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);
+ size += 4;
break;
case DW_OP_const8u:
case DW_OP_const8s:
- abort ();
- fputc ('\n', asm_out_file);
+ size += 8;
break;
case DW_OP_constu:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
break;
case DW_OP_consts:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
break;
case DW_OP_pick:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
- fputc ('\n', asm_out_file);
+ size += 1;
break;
case DW_OP_plus_uconst:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
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);
+ size += 2;
break;
case DW_OP_breg0:
case DW_OP_breg1:
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
break;
case DW_OP_regx:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
break;
case DW_OP_fbreg:
- output_sleb128 (val1->v.val_int);
- fputc ('\n', asm_out_file);
+ size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int);
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);
+ 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:
- output_uleb128 (val1->v.val_unsigned);
- fputc ('\n', asm_out_file);
+ size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned);
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);
+ size += 1;
break;
default:
break;
}
+
+ return size;
}
-/* Compute the offset of a sibling. */
+/* Return the size of a series of location descriptors. */
static unsigned long
-sibling_offset (die)
- dw_die_ref die;
+size_of_locs (loc)
+ register dw_loc_descr_ref loc;
{
- unsigned long offset;
+ register unsigned long size = 0;
- if (die->die_child_last == NULL)
- offset = die->die_offset + size_of_die (die);
+ for (; loc != NULL; loc = loc->dw_loc_next)
+ size += size_of_loc_descr (loc);
+
+ return size;
+}
+
+/* Return the power-of-two number of bytes necessary to represent VALUE. */
+
+static int
+constant_size (value)
+ long unsigned value;
+{
+ int log;
+
+ if (value == 0)
+ log = 0;
else
- offset = sibling_offset (die->die_child_last) + 1;
+ log = floor_log2 (value);
- return offset;
+ log = log / 8;
+ log = 1 << (floor_log2 (log) + 1);
+
+ return log;
}
-/* Output the DIE and its attributes. Called recursively to generate
- the definitions of each child DIE. */
+/* Return the size of a DIE, as it is represented in the
+ .debug_info section. */
-static void
-output_die (die)
+static unsigned long
+size_of_die (die)
register dw_die_ref die;
{
+ register unsigned long size = 0;
register dw_attr_ref a;
- register dw_die_ref c;
- register unsigned long ref_offset;
- register unsigned long size;
- register dw_loc_descr_ref loc;
- register int i;
-
- output_uleb128 (die->die_abbrev);
- if (flag_verbose_asm)
- fprintf (asm_out_file, " (DIE (0x%x) %s)",
- die->die_offset, dwarf_tag_name (die->die_tag));
-
- fputc ('\n', asm_out_file);
+ size += size_of_uleb128 (die->die_abbrev);
for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
{
switch (a->dw_attr_val.val_class)
{
case dw_val_class_addr:
- ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file,
- a->dw_attr_val.v.val_addr);
+ size += PTR_SIZE;
break;
-
case dw_val_class_loc:
- size = size_of_locs (a->dw_attr_val.v.val_loc);
-
- /* Output the block length for this list of location operations. */
- switch (constant_size (size))
- {
- case 1:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, size);
- break;
- case 2:
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, size);
- break;
- default:
- abort ();
- }
-
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
- fputc ('\n', asm_out_file);
- for (loc = a->dw_attr_val.v.val_loc; loc != NULL;
- loc = loc->dw_loc_next)
- {
- /* Output the opcode. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
- dwarf_stack_op_name (loc->dw_loc_opc));
-
- fputc ('\n', asm_out_file);
+ {
+ register unsigned long lsize
+ = size_of_locs (a->dw_attr_val.v.val_loc);
- /* Output the operand(s) (if any). */
- output_loc_operands (loc);
- }
+ /* Block length. */
+ size += constant_size (lsize);
+ size += lsize;
+ }
break;
-
case dw_val_class_const:
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, a->dw_attr_val.v.val_int);
+ size += 4;
break;
-
case dw_val_class_unsigned_const:
- switch (constant_size (a->dw_attr_val.v.val_unsigned))
- {
- case 1:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- a->dw_attr_val.v.val_unsigned);
- break;
- case 2:
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file,
- a->dw_attr_val.v.val_unsigned);
- break;
- case 4:
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
- a->dw_attr_val.v.val_unsigned);
- break;
- default:
- abort ();
- }
+ size += constant_size (a->dw_attr_val.v.val_unsigned);
break;
-
case dw_val_class_long_long:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s",
- 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);
-
- if (flag_verbose_asm)
- fprintf (asm_out_file,
- "\t%s long long constant", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
+ size += 1 + 8; /* block */
break;
-
case dw_val_class_float:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- a->dw_attr_val.v.val_float.length * 4);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
- fputc ('\n', asm_out_file);
- for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
- {
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
- a->dw_attr_val.v.val_float.array[i]);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s fp constant word %d",
- ASM_COMMENT_START, i);
-
- fputc ('\n', asm_out_file);
- }
+ size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */
break;
-
case dw_val_class_flag:
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
+ size += 1;
break;
-
case dw_val_class_die_ref:
- if (a->dw_attr_val.v.val_die_ref != NULL)
- ref_offset = a->dw_attr_val.v.val_die_ref->die_offset;
- else if (a->dw_attr == DW_AT_sibling)
- ref_offset = sibling_offset(die);
- else
- abort ();
-
- ASM_OUTPUT_DWARF_DATA (asm_out_file, ref_offset);
+ size += DWARF_OFFSET_SIZE;
break;
-
case dw_val_class_fde_ref:
- ref_offset = fde_table[a->dw_attr_val.v.val_fde_index].dw_fde_offset;
- fprintf (asm_out_file, "\t%s\t%s+0x%x", UNALIGNED_OFFSET_ASM_OP,
- stripattributes (FRAME_SECTION), ref_offset);
+ size += DWARF_OFFSET_SIZE;
break;
-
case dw_val_class_lbl_id:
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id);
- break;
-
- case dw_val_class_section_offset:
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file,
- stripattributes
- (a->dw_attr_val.v.val_section));
- break;
-
- case dw_val_class_str:
- ASM_OUTPUT_DWARF_STRING (asm_out_file, a->dw_attr_val.v.val_str);
- break;
-
- default:
- abort ();
- }
-
- if (a->dw_attr_val.val_class != dw_val_class_loc
- && a->dw_attr_val.val_class != dw_val_class_long_long
- && a->dw_attr_val.val_class != dw_val_class_float)
- {
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s",
- ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
-
- fputc ('\n', asm_out_file);
- }
- }
-
- for (c = die->die_child; c != NULL; c = c->die_sib)
- output_die (c);
-
- if (die->die_child != NULL)
- {
- /* Add null byte to terminate sibling list. */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s end of children of DIE 0x%x",
- ASM_COMMENT_START, die->die_offset);
-
- fputc ('\n', asm_out_file);
+ size += PTR_SIZE;
+ break;
+ case dw_val_class_section_offset:
+ size += DWARF_OFFSET_SIZE;
+ break;
+ case dw_val_class_str:
+ size += size_of_string (a->dw_attr_val.v.val_str);
+ break;
+ default:
+ abort ();
+ }
}
+
+ return size;
}
-/* Output the compilation unit that appears at the beginning of the
- .debug_info section, and precedes the DIE descriptions. */
+/* Size the debgging information associted with a given DIE.
+ Visits the DIE's children recursively. Updates the global
+ variable next_die_offset, on each time through. Uses the
+ current value of next_die_offset to updete the die_offset
+ field in each DIE. */
static void
-output_compilation_unit_header ()
+calc_die_sizes (die)
+ dw_die_ref die;
{
- ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset - DWARF_OFFSET_SIZE);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s Length of Compilation Unit Info.",
- ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (ABBREV_SECTION));
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
- ASM_COMMENT_START);
+ register dw_die_ref c;
+ die->die_offset = next_die_offset;
+ next_die_offset += size_of_die (die);
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s Pointer Size (in bytes)", ASM_COMMENT_START);
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ calc_die_sizes (c);
- fputc ('\n', asm_out_file);
+ if (die->die_child != NULL)
+ /* Count the null byte used to terminate sibling lists. */
+ next_die_offset += 1;
}
-/* Generate a new label for the CFI info to refer to. */
+/* Return the size of the line information prolog generated for the
+ compilation unit. */
-static char *
-dwarf2out_cfi_label ()
+static unsigned long
+size_of_line_prolog ()
{
- static char label[20];
- static unsigned long label_num = 0;
-
- ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++);
- ASM_OUTPUT_LABEL (asm_out_file, label);
-
- return label;
-}
+ register unsigned long size;
+ register unsigned long ft_index;
-/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
- or to the CIE if LABEL is NULL. */
+ size = DWARF_LINE_PROLOG_HEADER_SIZE;
-static void
-add_fde_cfi (label, cfi)
- register char *label;
- register dw_cfi_ref cfi;
-{
- if (label)
- {
- register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
+ /* Count the size of the table giving number of args for each
+ standard opcode. */
+ size += DWARF_LINE_OPCODE_BASE - 1;
- if (*label == 0)
- label = dwarf2out_cfi_label ();
+ /* Include directory table is empty (at present). Count only the
+ the null byte used to terminate the table. */
+ size += 1;
- if (fde->dw_fde_current_label == NULL
- || strcmp (label, fde->dw_fde_current_label) != 0)
- {
- register dw_cfi_ref xcfi;
+ for (ft_index = 1; ft_index < file_table_in_use; ++ft_index)
+ {
+ /* File name entry. */
+ size += size_of_string (file_table[ft_index]);
- fde->dw_fde_current_label = label = xstrdup (label);
+ /* Include directory index. */
+ size += size_of_uleb128 (0);
- /* Set the location counter to the new label. */
- xcfi = new_cfi ();
- xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
- xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
- add_cfi (&fde->dw_fde_cfi, xcfi);
- }
+ /* Modification time. */
+ size += size_of_uleb128 (0);
- add_cfi (&fde->dw_fde_cfi, cfi);
+ /* File length in bytes. */
+ size += size_of_uleb128 (0);
}
- else
- add_cfi (&cie_cfi_head, cfi);
+ /* Count the file table terminator. */
+ size += 1;
+ return size;
}
-/* Subroutine of lookup_cfa. */
+/* Return the size of the line information generated for this
+ compilation unit. */
-static inline void
-lookup_cfa_1 (cfi, regp, offsetp)
- register dw_cfi_ref cfi;
- register unsigned long *regp;
- register long *offsetp;
+static unsigned long
+size_of_line_info ()
{
- switch (cfi->dw_cfi_opc)
- {
- case DW_CFA_def_cfa_offset:
- *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
- break;
- case DW_CFA_def_cfa_register:
- *regp = 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;
- break;
- }
-}
+ register unsigned long size;
+ register unsigned long lt_index;
+ register unsigned long current_line;
+ register long line_offset;
+ register long line_delta;
+ register unsigned long current_file;
+ register unsigned long function;
-/* Find the previous value for the CFA. */
+ /* Version number. */
+ size = 2;
-static void
-lookup_cfa (regp, offsetp)
- register unsigned long *regp;
- register long *offsetp;
-{
- register dw_cfi_ref cfi;
+ /* Prolog length specifier. */
+ size += DWARF_OFFSET_SIZE;
- *regp = (unsigned long) -1;
- *offsetp = 0;
+ /* Prolog. */
+ size += size_of_line_prolog ();
- for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, regp, offsetp);
+ /* Set address register instruction. */
+ size += 1 + size_of_uleb128 (1 + PTR_SIZE) + 1 + PTR_SIZE;
- if (fde_table_in_use)
+ current_file = 1;
+ current_line = 1;
+ for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index)
{
- 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);
+ register dw_line_info_ref line_info;
+
+ /* Advance pc instruction. */
+ size += 1 + 2;
+ line_info = &line_info_table[lt_index];
+ if (line_info->dw_file_num != current_file)
+ {
+ /* Set file number instruction. */
+ size += 1;
+ current_file = line_info->dw_file_num;
+ size += size_of_uleb128 (current_file);
+ }
+
+ if (line_info->dw_line_num != current_line)
+ {
+ line_offset = line_info->dw_line_num - current_line;
+ line_delta = line_offset - DWARF_LINE_BASE;
+ current_line = line_info->dw_line_num;
+ if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ /* 1-byte special line number instruction. */
+ size += 1;
+ else
+ {
+ /* Advance line instruction. */
+ size += 1;
+ size += size_of_sleb128 (line_offset);
+ /* Generate line entry instruction. */
+ size += 1;
+ }
+ }
}
-}
-/* Entry point to update the canonical frame address (CFA).
- LABEL is passed to add_fde_cfi. The value of CFA is now to be
- calculated from REG+OFFSET. */
+ /* Advance pc instruction. */
+ size += 1 + 2;
-void
-dwarf2out_def_cfa (label, reg, offset)
- register char *label;
- register unsigned reg;
- register long offset;
-{
- register dw_cfi_ref cfi;
- unsigned long old_reg;
- long old_offset;
+ /* End of line number info. marker. */
+ size += 1 + size_of_uleb128 (1) + 1;
- reg = DWARF_FRAME_REGNUM (reg);
- lookup_cfa (&old_reg, &old_offset);
+ function = 0;
+ current_file = 1;
+ current_line = 1;
+ for (lt_index = 0; lt_index < separate_line_info_table_in_use; )
+ {
+ register dw_separate_line_info_ref line_info
+ = &separate_line_info_table[lt_index];
+ if (function != line_info->function)
+ {
+ function = line_info->function;
+ /* Set address register instruction. */
+ size += 1 + size_of_uleb128 (1 + PTR_SIZE) + 1 + PTR_SIZE;
+ }
+ else
+ /* Advance pc instruction. */
+ size += 1 + 2;
+
+ if (line_info->dw_file_num != current_file)
+ {
+ /* Set file number instruction. */
+ size += 1;
+ current_file = line_info->dw_file_num;
+ size += size_of_uleb128 (current_file);
+ }
+
+ if (line_info->dw_line_num != current_line)
+ {
+ line_offset = line_info->dw_line_num - current_line;
+ line_delta = line_offset - DWARF_LINE_BASE;
+ current_line = line_info->dw_line_num;
+ if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
+ /* 1-byte special line number instruction. */
+ size += 1;
+ else
+ {
+ /* Advance line instruction. */
+ size += 1;
+ size += size_of_sleb128 (line_offset);
- if (reg == old_reg && offset == old_offset)
- return;
+ /* Generate line entry instruction. */
+ size += 1;
+ }
+ }
- cfi = new_cfi ();
+ ++lt_index;
- if (reg == old_reg)
- {
- cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
- cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
- }
+ /* If we're done with a function, end its sequence. */
+ if (lt_index == separate_line_info_table_in_use
+ || separate_line_info_table[lt_index].function != function)
+ {
+ current_file = 1;
+ current_line = 1;
-#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
- else if (offset == old_offset && old_reg != (unsigned long) -1)
- {
- cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
- }
-#endif
+ /* Advance pc instruction. */
+ size += 1 + 2;
- else
- {
- 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;
+ /* End of line number info. marker. */
+ size += 1 + size_of_uleb128 (1) + 1;
+ }
}
- add_fde_cfi (label, cfi);
+ return size;
}
-/* Add the CFI for saving a register. REG is the CFA column number.
- LABEL is passed to add_fde_cfi.
- If SREG is -1, the register is saved at OFFSET from the CFA;
- otherwise it is saved in SREG. */
+/* Return the size of the .debug_pubnames table generated for the
+ compilation unit. */
-static void
-reg_save (label, reg, sreg, offset)
- register char * label;
- register unsigned reg;
- register unsigned sreg;
- register long offset;
+static unsigned long
+size_of_pubnames ()
{
- register dw_cfi_ref cfi = new_cfi ();
-
- cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
-
- if (sreg == -1)
- {
- if (reg & ~0x3f)
- /* The register number won't fit in 6 bits, so we have to use
- the long form. */
- cfi->dw_cfi_opc = DW_CFA_offset_extended;
- else
- cfi->dw_cfi_opc = DW_CFA_offset;
+ register unsigned long size;
+ register unsigned i;
- offset /= DWARF_CIE_DATA_ALIGNMENT;
- assert (offset >= 0);
- cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
- }
- else
+ size = DWARF_PUBNAMES_HEADER_SIZE;
+ for (i = 0; i < pubname_table_in_use; ++i)
{
- cfi->dw_cfi_opc = DW_CFA_register;
- cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
+ register pubname_ref p = &pubname_table[i];
+ size += DWARF_OFFSET_SIZE + size_of_string (p->name);
}
- add_fde_cfi (label, cfi);
+ size += DWARF_OFFSET_SIZE;
+ return size;
}
-/* Entry point for saving a register. REG is the GCC register number.
- LABEL and OFFSET are passed to reg_save. */
+/* Return the size of the information in the .debug_aranges seciton. */
-void
-dwarf2out_reg_save (label, reg, offset)
- register char * label;
- register unsigned reg;
- register long offset;
+static unsigned long
+size_of_aranges ()
{
- reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset);
-}
+ register unsigned long size;
-/* Record the initial position of the return address. RTL is
- INCOMING_RETURN_ADDR_RTX. */
+ size = DWARF_ARANGES_HEADER_SIZE;
-static void
-initial_return_save (rtl)
- register rtx rtl;
-{
- unsigned reg = -1;
- long offset = 0;
+ /* Count the address/length pair for this compilation unit. */
+ size += 2 * PTR_SIZE;
+ size += 2 * PTR_SIZE * arange_table_in_use;
- switch (GET_CODE (rtl))
+ /* Count the two zero words used to terminated the address range table. */
+ size += 2 * PTR_SIZE;
+ return size;
+}
+\f
+/* Select the encoding of an attribute value. */
+
+static enum dwarf_form
+value_format (v)
+ dw_val_ref v;
+{
+ switch (v->val_class)
{
- case REG:
- /* RA is in a register. */
- reg = reg_number (rtl);
- break;
- case MEM:
- /* RA is on the stack. */
- rtl = XEXP (rtl, 0);
- switch (GET_CODE (rtl))
+ case dw_val_class_addr:
+ return DW_FORM_addr;
+ case dw_val_class_loc:
+ switch (constant_size (size_of_locs (v->v.val_loc)))
{
- case REG:
- assert (REGNO (rtl) == STACK_POINTER_REGNUM);
- offset = 0;
- break;
- case PLUS:
- assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
- offset = INTVAL (XEXP (rtl, 1));
- break;
- case MINUS:
- assert (REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM);
- offset = -INTVAL (XEXP (rtl, 1));
- break;
+ case 1:
+ return DW_FORM_block1;
+ case 2:
+ return DW_FORM_block2;
default:
abort ();
}
- break;
+ case dw_val_class_const:
+ return DW_FORM_data4;
+ case dw_val_class_unsigned_const:
+ switch (constant_size (v->v.val_unsigned))
+ {
+ case 1:
+ return DW_FORM_data1;
+ case 2:
+ return DW_FORM_data2;
+ case 4:
+ return DW_FORM_data4;
+ case 8:
+ return DW_FORM_data8;
+ default:
+ abort ();
+ }
+ case dw_val_class_long_long:
+ return DW_FORM_block1;
+ case dw_val_class_float:
+ return DW_FORM_block1;
+ case dw_val_class_flag:
+ return DW_FORM_flag;
+ case dw_val_class_die_ref:
+ return DW_FORM_ref;
+ case dw_val_class_fde_ref:
+ return DW_FORM_data;
+ case dw_val_class_lbl_id:
+ return DW_FORM_addr;
+ case dw_val_class_section_offset:
+ return DW_FORM_data;
+ case dw_val_class_str:
+ return DW_FORM_string;
default:
abort ();
}
-
- reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset);
}
-/* Record call frame debugging information for INSN, which either
- sets SP or FP (adjusting how we calculate the frame address) or saves a
- register to the stack. If INSN is NULL_RTX, initialize our state. */
+/* Output the encoding of an attribute value. */
-void
-dwarf2out_frame_debug (insn)
- rtx insn;
+static void
+output_value_format (v)
+ dw_val_ref v;
{
- char *label;
- rtx src, dest;
- long offset;
-
- /* The current rule for calculating the DWARF2 canonical frame address. */
- static unsigned cfa_reg;
- static long cfa_offset;
-
- /* 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;
-
- /* A temporary register used in adjusting SP or setting up the store_reg. */
- static unsigned cfa_temp_reg;
- static long cfa_temp_value;
-
- if (insn == NULL_RTX)
- {
- /* Set up state for generating call frame debug info. */
- cfa_reg = STACK_POINTER_REGNUM;
- cfa_offset = 0;
- cfa_store_reg = STACK_POINTER_REGNUM;
- cfa_store_offset = 0;
- cfa_temp_reg = -1;
- cfa_temp_value = 0;
- return;
- }
-
- label = dwarf2out_cfi_label ();
-
- insn = PATTERN (insn);
- assert (GET_CODE (insn) == SET);
-
- src = SET_SRC (insn);
- dest = SET_DEST (insn);
-
- switch (GET_CODE (dest))
- {
- case REG:
- /* Update the CFA rule wrt SP or FP. Make sure src is
- relative to the current CFA register. */
- switch (GET_CODE (src))
- {
- /* Setting FP from SP. */
- case REG:
- assert (cfa_reg == REGNO (src));
- assert (REGNO (dest) == STACK_POINTER_REGNUM
- || (frame_pointer_needed
- && REGNO (dest) == HARD_FRAME_POINTER_REGNUM));
- cfa_reg = REGNO (dest);
- break;
-
- case PLUS:
- case MINUS:
- if (dest == stack_pointer_rtx)
- {
- /* Adjusting SP. */
- switch (GET_CODE (XEXP (src, 1)))
- {
- case CONST_INT:
- offset = INTVAL (XEXP (src, 1));
- break;
- case REG:
- assert (REGNO (XEXP (src, 1)) == cfa_temp_reg);
- offset = cfa_temp_value;
- break;
- default:
- abort ();
- }
+ enum dwarf_form form = value_format (v);
- 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;
- assert (XEXP (src, 0) == stack_pointer_rtx);
- }
- else
- {
- /* Initializing the store base register. */
- assert (GET_CODE (src) == PLUS);
- assert (XEXP (src, 1) == stack_pointer_rtx);
- assert (GET_CODE (XEXP (src, 0)) == REG
- && REGNO (XEXP (src, 0)) == cfa_temp_reg);
- assert (cfa_store_reg == STACK_POINTER_REGNUM);
- cfa_store_reg = REGNO (dest);
- cfa_store_offset -= cfa_temp_value;
- }
- break;
+ output_uleb128 (form);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (%s)", dwarf_form_name (form));
- case CONST_INT:
- cfa_temp_reg = REGNO (dest);
- cfa_temp_value = INTVAL (src);
- break;
+ fputc ('\n', asm_out_file);
+}
- default:
- abort ();
- }
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- break;
+/* Output the .debug_abbrev section which defines the DIE abbreviation
+ table. */
- case MEM:
- /* Saving a register to the stack. Make sure dest is relative to the
- CFA register. */
- assert (GET_CODE (src) == REG);
- switch (GET_CODE (XEXP (dest, 0)))
- {
- /* With a push. */
- case PRE_INC:
- case PRE_DEC:
- offset = GET_MODE_SIZE (GET_MODE (dest));
- if (GET_CODE (src) == PRE_INC)
- offset = -offset;
+static void
+output_abbrev_section ()
+{
+ unsigned long abbrev_id;
- assert (REGNO (XEXP (XEXP (dest, 0), 0)) == STACK_POINTER_REGNUM);
- assert (cfa_store_reg == STACK_POINTER_REGNUM);
- cfa_store_offset += offset;
- if (cfa_reg == STACK_POINTER_REGNUM)
- cfa_offset = cfa_store_offset;
+ dw_attr_ref 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];
- offset = -cfa_store_offset;
- break;
+ output_uleb128 (abbrev_id);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (abbrev code)");
- /* With an offset. */
- case PLUS:
- case MINUS:
- offset = INTVAL (XEXP (XEXP (dest, 0), 1));
- if (GET_CODE (src) == MINUS)
- offset = -offset;
+ fputc ('\n', asm_out_file);
+ output_uleb128 (abbrev->die_tag);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (TAG: %s)",
+ dwarf_tag_name (abbrev->die_tag));
- assert (cfa_store_reg == REGNO (XEXP (XEXP (dest, 0), 0)));
- offset -= cfa_store_offset;
- break;
+ fputc ('\n', asm_out_file);
+ fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP,
+ abbrev->die_child != NULL ? DW_children_yes : DW_children_no);
- default:
- abort ();
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START,
+ (abbrev->die_child != NULL
+ ? "DW_children_yes" : "DW_children_no"));
+
+ fputc ('\n', asm_out_file);
+
+ for (a_attr = abbrev->die_attr; a_attr != NULL;
+ a_attr = a_attr->dw_attr_next)
+ {
+ output_uleb128 (a_attr->dw_attr);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (%s)",
+ dwarf_attr_name (a_attr->dw_attr));
+
+ fputc ('\n', asm_out_file);
+ output_value_format (&a_attr->dw_attr_val);
}
- dwarf2out_def_cfa (label, cfa_reg, cfa_offset);
- dwarf2out_reg_save (label, REGNO (src), offset);
- break;
- default:
- abort ();
+ fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP);
}
}
-/* Return the size of a Call Frame Instruction. */
+/* Output location description stack opcode's operands (if any). */
-static unsigned long
-size_of_cfi (cfi)
- dw_cfi_ref cfi;
+static void
+output_loc_operands (loc)
+ register dw_loc_descr_ref loc;
{
- register unsigned long size;
+ register dw_val_ref val1 = &loc->dw_loc_oprnd1;
+ register dw_val_ref val2 = &loc->dw_loc_oprnd2;
- /* Count the 1-byte opcode */
- size = 1;
- switch (cfi->dw_cfi_opc)
+ switch (loc->dw_loc_opc)
{
- case DW_CFA_offset:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ case DW_OP_addr:
+ ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr);
+ fputc ('\n', asm_out_file);
break;
- case DW_CFA_set_loc:
- size += PTR_SIZE;
+ 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_CFA_advance_loc1:
- size += 1;
+ 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_CFA_advance_loc2:
- size += 2;
+ 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_CFA_advance_loc4:
- size += 4;
+ case DW_OP_const8u:
+ case DW_OP_const8s:
+ abort ();
+ fputc ('\n', asm_out_file);
break;
-#ifdef MIPS_DEBUGGING_INFO
- case DW_CFA_MIPS_advance_loc8:
- size += 8;
+ case DW_OP_constu:
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
break;
-#endif
- case DW_CFA_offset_extended:
- case DW_CFA_def_cfa:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
+ case DW_OP_consts:
+ output_sleb128 (val1->v.val_int);
+ fputc ('\n', asm_out_file);
break;
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ case DW_OP_pick:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int);
+ fputc ('\n', asm_out_file);
break;
- case DW_CFA_same_value:
- case DW_CFA_def_cfa_register:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ case DW_OP_plus_uconst:
+ output_uleb128 (val1->v.val_unsigned);
+ fputc ('\n', asm_out_file);
break;
- case DW_CFA_register:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- size += size_of_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
+ 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_CFA_def_cfa_offset:
- size += size_of_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
+ 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;
}
-
- return size;
}
-/* Return the size of an FDE sans the length word. */
+/* Compute the offset of a sibling. */
-static inline unsigned long
-size_of_fde (fde, npad)
- dw_fde_ref fde;
- unsigned long *npad;
+static unsigned long
+sibling_offset (die)
+ dw_die_ref die;
{
- register dw_cfi_ref cfi;
- register unsigned long aligned_size;
- register unsigned long size;
+ unsigned long offset;
- size = DWARF_FDE_HEADER_SIZE;
- for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
- size += size_of_cfi(cfi);
+ if (die->die_child_last == NULL)
+ offset = die->die_offset + size_of_die (die);
+ else
+ offset = sibling_offset (die->die_child_last) + 1;
- /* Round the size up to a word boundary. */
- aligned_size = DWARF_ROUND (size, PTR_SIZE);
- *npad = aligned_size - size;
- return aligned_size;
+ return offset;
}
-/* Calculate the size of the FDE table, and establish the offset
- of each FDE in the .debug_frame section. */
+/* Output the DIE and its attributes. Called recursively to generate
+ the definitions of each child DIE. */
static void
-calc_fde_sizes ()
+output_die (die)
+ register dw_die_ref die;
{
- register unsigned long i;
- register dw_fde_ref fde;
- register unsigned long fde_size;
- register dw_cfi_ref cfi;
- unsigned long fde_pad;
+ register dw_attr_ref a;
+ register dw_die_ref c;
+ register unsigned long ref_offset;
+ register unsigned long size;
+ register dw_loc_descr_ref loc;
+ register int i;
- cie_size = DWARF_CIE_HEADER_SIZE;
- for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
- cie_size += size_of_cfi (cfi);
+ output_uleb128 (die->die_abbrev);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, " (DIE (0x%x) %s)",
+ die->die_offset, dwarf_tag_name (die->die_tag));
- /* Initialize the beginning FDE offset. */
- next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+ fputc ('\n', asm_out_file);
- for (i = 0; i < fde_table_in_use; ++i)
+ for (a = die->die_attr; a != NULL; a = a->dw_attr_next)
{
- fde = &fde_table[i];
- fde->dw_fde_offset = next_fde_offset;
- fde_size = size_of_fde (fde, &fde_pad);
- next_fde_offset += fde_size;
- }
-}
+ switch (a->dw_attr_val.val_class)
+ {
+ case dw_val_class_addr:
+ ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file,
+ a->dw_attr_val.v.val_addr);
+ break;
-/* Output a Call Frame Information opcode and its operand(s). */
+ case dw_val_class_loc:
+ size = size_of_locs (a->dw_attr_val.v.val_loc);
-static void
-output_cfi (cfi, fde)
- register dw_cfi_ref cfi;
- register dw_fde_ref fde;
-{
- if (cfi->dw_cfi_opc == DW_CFA_advance_loc)
- {
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- cfi->dw_cfi_opc
- | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f));
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%x",
- ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset);
- fputc ('\n', asm_out_file);
- }
+ /* Output the block length for this list of location operations. */
+ switch (constant_size (size))
+ {
+ case 1:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, size);
+ break;
+ case 2:
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file, size);
+ break;
+ default:
+ abort ();
+ }
- else if (cfi->dw_cfi_opc == DW_CFA_offset)
- {
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- cfi->dw_cfi_opc
- | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%x",
- ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
- fputc ('\n', asm_out_file);
- output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- fputc ('\n', asm_out_file);
- }
- else if (cfi->dw_cfi_opc == DW_CFA_restore)
- {
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
- cfi->dw_cfi_opc
- | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f));
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%x",
- ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
+ fputc ('\n', asm_out_file);
+ for (loc = a->dw_attr_val.v.val_loc; loc != NULL;
+ loc = loc->dw_loc_next)
+ {
+ /* Output the opcode. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
+ dwarf_stack_op_name (loc->dw_loc_opc));
- fputc ('\n', asm_out_file);
- }
- else
- {
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, cfi->dw_cfi_opc);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START,
- dwarf_cfi_name (cfi->dw_cfi_opc));
+ fputc ('\n', asm_out_file);
- fputc ('\n', asm_out_file);
- switch (cfi->dw_cfi_opc)
- {
- case DW_CFA_set_loc:
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, cfi->dw_cfi_oprnd1.dw_cfi_addr);
- fputc ('\n', asm_out_file);
- break;
- case DW_CFA_advance_loc1:
- /* TODO: not currently implemented. */
- abort ();
- break;
- case DW_CFA_advance_loc2:
- ASM_OUTPUT_DWARF_DELTA2 (asm_out_file,
- cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label);
- fputc ('\n', asm_out_file);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
- break;
- case DW_CFA_advance_loc4:
- ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
- cfi->dw_cfi_oprnd1.dw_cfi_addr,
- fde->dw_fde_current_label);
- fputc ('\n', asm_out_file);
- fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
+ /* Output the operand(s) (if any). */
+ output_loc_operands (loc);
+ }
break;
-#ifdef MIPS_DEBUGGING_INFO
- case DW_CFA_MIPS_advance_loc8:
- /* TODO: not currently implemented. */
- abort ();
+
+ case dw_val_class_const:
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, a->dw_attr_val.v.val_int);
break;
-#endif
- case DW_CFA_offset_extended:
- case DW_CFA_def_cfa:
- output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- fputc ('\n', asm_out_file);
- output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset);
- fputc ('\n', asm_out_file);
+
+ case dw_val_class_unsigned_const:
+ switch (constant_size (a->dw_attr_val.v.val_unsigned))
+ {
+ case 1:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ a->dw_attr_val.v.val_unsigned);
+ break;
+ case 2:
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file,
+ a->dw_attr_val.v.val_unsigned);
+ break;
+ case 4:
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ a->dw_attr_val.v.val_unsigned);
+ 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);
+ break;
+ default:
+ abort ();
+ }
break;
- case DW_CFA_restore_extended:
- case DW_CFA_undefined:
- output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- fputc ('\n', asm_out_file);
+
+ case dw_val_class_long_long:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ 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);
+
+ if (flag_verbose_asm)
+ fprintf (asm_out_file,
+ "\t%s long long constant", ASM_COMMENT_START);
+
+ fputc ('\n', asm_out_file);
break;
- case DW_CFA_same_value:
- case DW_CFA_def_cfa_register:
- output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- fputc ('\n', asm_out_file);
+
+ case dw_val_class_float:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
+ a->dw_attr_val.v.val_float.length * 4);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
+
+ fputc ('\n', asm_out_file);
+ for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i)
+ {
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ a->dw_attr_val.v.val_float.array[i]);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s fp constant word %d",
+ ASM_COMMENT_START, i);
+
+ fputc ('\n', asm_out_file);
+ }
break;
- case DW_CFA_register:
- output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num);
- fputc ('\n', asm_out_file);
- output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num);
- fputc ('\n', asm_out_file);
+
+ case dw_val_class_flag:
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag);
break;
- case DW_CFA_def_cfa_offset:
- output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset);
- fputc ('\n', asm_out_file);
+
+ case dw_val_class_die_ref:
+ if (a->dw_attr_val.v.val_die_ref != NULL)
+ ref_offset = a->dw_attr_val.v.val_die_ref->die_offset;
+ else if (a->dw_attr == DW_AT_sibling)
+ ref_offset = sibling_offset(die);
+ else
+ abort ();
+
+ ASM_OUTPUT_DWARF_DATA (asm_out_file, ref_offset);
break;
- default:
+
+ case dw_val_class_fde_ref:
+ ref_offset = fde_table[a->dw_attr_val.v.val_fde_index].dw_fde_offset;
+ fprintf (asm_out_file, "\t%s\t%s+0x%x", UNALIGNED_OFFSET_ASM_OP,
+ stripattributes (FRAME_SECTION), ref_offset);
break;
- }
- }
-}
-/* Output the call frame information used to used to record information
- that relates to calculating the frame pointer, and records the
- location of saved registers. */
+ case dw_val_class_lbl_id:
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id);
+ break;
-static void
-output_call_frame_info ()
-{
- register unsigned long i, j;
- register dw_fde_ref fde;
- register unsigned long fde_size;
- register dw_cfi_ref cfi;
- unsigned long fde_pad;
+ case dw_val_class_section_offset:
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file,
+ stripattributes
+ (a->dw_attr_val.v.val_section));
+ break;
- /* Only output the info if it will be interesting. */
- for (i = 0; i < fde_table_in_use; ++i)
- if (fde_table[i].dw_fde_cfi != NULL)
- break;
- if (i == fde_table_in_use)
- return;
+ case dw_val_class_str:
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, a->dw_attr_val.v.val_str);
+ break;
- /* (re-)initialize the beginning FDE offset. */
- next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
+ default:
+ abort ();
+ }
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
+ if (a->dw_attr_val.val_class != dw_val_class_loc
+ && a->dw_attr_val.val_class != dw_val_class_long_long
+ && a->dw_attr_val.val_class != dw_val_class_float)
+ {
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s %s",
+ ASM_COMMENT_START, dwarf_attr_name (a->dw_attr));
- /* Output the CIE. */
- ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s Length of Common Information Entry",
- ASM_COMMENT_START);
+ fputc ('\n', asm_out_file);
+ }
+ }
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE Identifier Tag", ASM_COMMENT_START);
+ for (c = die->die_child; c != NULL; c = c->die_sib)
+ output_die (c);
- fputc ('\n', asm_out_file);
- if (DWARF_OFFSET_SIZE == 8)
+ if (die->die_child != NULL)
{
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID);
+ /* Add null byte to terminate sibling list. */
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\t%s end of children of DIE 0x%x",
+ ASM_COMMENT_START, die->die_offset);
+
fputc ('\n', asm_out_file);
}
+}
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CIE_VERSION);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE Version", ASM_COMMENT_START);
+/* Output the compilation unit that appears at the beginning of the
+ .debug_info section, and precedes the DIE descriptions. */
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0);
+static void
+output_compilation_unit_header ()
+{
+ ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset - DWARF_OFFSET_SIZE);
if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE Augmentation (none)", ASM_COMMENT_START);
+ fprintf (asm_out_file, "\t%s Length of Compilation Unit Info.",
+ ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- output_uleb128 (1);
+ ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION);
if (flag_verbose_asm)
- fprintf (asm_out_file, " (CIE Code Alignment Factor)");
+ fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- output_sleb128 (DWARF_CIE_DATA_ALIGNMENT);
+ ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (ABBREV_SECTION));
if (flag_verbose_asm)
- fprintf (asm_out_file, " (CIE Data Alignment Factor)");
+ fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section",
+ ASM_COMMENT_START);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_FRAME_RETURN_COLUMN);
+ ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE);
if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START);
+ fprintf (asm_out_file, "\t%s Pointer Size (in bytes)", ASM_COMMENT_START);
fputc ('\n', asm_out_file);
-
- for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
- output_cfi (cfi, NULL);
-
- /* Pad the CIE out to an address sized boundary. */
- for (i = next_fde_offset - cie_size; i; --i)
- {
- /* Pad out to a pointer size boundary */
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- }
-
- /* Loop through all of the FDE's. */
- for (i = 0; i < fde_table_in_use; ++i)
- {
- fde = &fde_table[i];
- if (fde->dw_fde_cfi == NULL)
- continue;
-
- fde_size = size_of_fde (fde, &fde_pad);
- ASM_OUTPUT_DWARF_DATA (asm_out_file, fde_size - DWARF_OFFSET_SIZE);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s FDE Length", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION));
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s FDE CIE offset", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, fde->dw_fde_begin);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s FDE initial location", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file,
- fde->dw_fde_end, fde->dw_fde_begin);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s FDE address range", ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
-
- /* Loop through the Call Frame Instructions associated with
- this FDE. */
- fde->dw_fde_current_label = fde->dw_fde_begin;
- for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
- output_cfi (cfi, fde);
-
- /* Pad to a double word boundary. */
- for (j = 0; j < fde_pad; ++j)
- {
- ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
- if (flag_verbose_asm)
- fprintf (asm_out_file, "\t%s CIE DW_CFA_nop (pad)",
- ASM_COMMENT_START);
-
- fputc ('\n', asm_out_file);
- }
- }
}
/* The DWARF2 pubname for a nested thingy looks like "A::f". The output
return TREE_CODE (type) == ENUMERAL_TYPE;
}
-/* Return the register number described by a given RTL node. */
-
-static unsigned
-reg_number (rtl)
- register rtx rtl;
-{
- register unsigned regno = REGNO (rtl);
-
- if (regno >= FIRST_PSEUDO_REGISTER)
- {
- warning_with_decl (dwarf_last_decl, "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
/* Else leave out the attribute. */
break;
+
+ default:
+ abort ();
}
}
/* If we're a function-scope tag, initially use a parent of NULL;
this will be fixed up in decls_for_scope. */
if (decl_function_context (decl))
- return;
+ context_die = NULL;
break;
gen_decl_die (decl, context_die);
output_pending_types_for_scope (comp_unit_die);
-
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL_TREE)
- current_funcdef_number++;
}
/* Output a marker (i.e. a label) for the beginning of the generated code for
}
}
-/* Output a marker (i.e. a label) for the beginning of a function, before
- the prologue. */
-
-void
-dwarf2out_begin_prologue ()
-{
- char label[MAX_ARTIFICIAL_LABEL_BYTES];
- register dw_fde_ref fde;
-
- function_section (current_function_decl);
- ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
- current_funcdef_number);
- ASM_OUTPUT_LABEL (asm_out_file, label);
-
- /* Expand the fde table if necessary. */
- if (fde_table_in_use == fde_table_allocated)
- {
- fde_table_allocated += FDE_TABLE_INCREMENT;
- fde_table
- = (dw_fde_ref) xrealloc (fde_table,
- fde_table_allocated * sizeof (dw_fde_node));
- }
-
- /* Record the FDE associated with this function. */
- current_funcdef_fde = fde_table_in_use;
-
- /* Add the new FDE at the end of the fde_table. */
- fde = &fde_table[fde_table_in_use++];
- fde->dw_fde_begin = xstrdup (label);
- fde->dw_fde_current_label = NULL;
- fde->dw_fde_end = NULL;
- fde->dw_fde_cfi = NULL;
-}
-
-/* Output a marker (i.e. a label) for the absolute end of the generated code
- for a function definition. This gets called *after* the epilogue code has
- been generated. */
-
-void
-dwarf2out_end_epilogue ()
-{
- dw_fde_ref fde;
- char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
- /* Output a label to mark the endpoint of the code generated for this
- function. */
- ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
- ASM_OUTPUT_LABEL (asm_out_file, label);
- fde = &fde_table[fde_table_in_use - 1];
- fde->dw_fde_end = xstrdup (label);
-}
-
/* Lookup a filename (in the list of filenames that we know about here in
dwarf2out.c) and return its "index". The index of each (known) filename is
just a unique number which is associated with only that one filename.
/* Zero-th entry is allocated, but unused */
line_info_table_in_use = 1;
- /* Allocate the initial hunk of the fde_table. */
- fde_table
- = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
- bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node));
- fde_table_allocated = FDE_TABLE_INCREMENT;
- fde_table_in_use = 0;
-
/* Generate the initial DIE for the .debug section. Note that the (string)
value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE
will (typically) be a relative pathname and that this pathname should be
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
- /* Generate the CFA instructions common to all FDE's. Do it now for the
- sake of lookup_cfa. */
-
-#ifdef INCOMING_RETURN_ADDR_RTX
- /* On entry, the Canonical Frame Address is at SP+0. */
- dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, 0);
- initial_return_save (INCOMING_RETURN_ADDR_RTX);
-#endif
+ /* Initialize the frame unwind information. Eventually this should be
+ called from compile_file instead. */
+ dwarf2out_frame_init ();
}
/* Output stuff that dwarf requires at the end of every file,
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0);
#endif
+ /* Output the frame unwind information. Eventually this should be called
+ from compile_file instead. */
+ dwarf2out_frame_finish ();
+
/* Output the source line correspondence table. */
if (line_info_table_in_use > 1 || separate_line_info_table_in_use)
{
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
calc_die_sizes (comp_unit_die);
- /* calculate sizes/offsets for FDEs. */
- calc_fde_sizes ();
-
/* Output debugging information. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_SECTION (asm_out_file, DEBUG_SECTION);
if (fde_table_in_use)
{
- /* Output call frame information. */
- output_call_frame_info ();
-
/* Output the address range information. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);