#include "config.h"
#ifdef DWARF_DEBUGGING_INFO
#include "system.h"
#include "dwarf.h"
#include "tree.h"
#include "flags.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "insn-config.h"
#include "reload.h"
#include "output.h"
#include "defaults.h"
#include "dwarfout.h"
#include "toplev.h"
#if defined(DWARF_TIMESTAMPS)
#if !defined(POSIX)
extern time_t time PROTO ((time_t *));
#endif
#endif
#undef assert
#ifdef NDEBUG
# define assert(e)
#else
# define assert(e) do { if (! (e)) abort (); } while (0)
#endif
extern char *getpwd PROTO((void));
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
#endif
#ifndef PRINT_REG
#define PRINT_REG(RTX, CODE, FILE) \
fprintf ((FILE), "%s", reg_names[REGNO (RTX)])
#endif
#define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
#define TYPE_DECL_IS_STUB(decl) \
(DECL_NAME (decl) == NULL \
|| (DECL_ARTIFICIAL (decl) \
&& is_tagged_type (TREE_TYPE (decl)) \
&& decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
extern int flag_traditional;
extern char *version_string;
extern char *language_string;
#define MAX_ARTIFICIAL_LABEL_BYTES 30
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
#ifndef SHORT_TYPE_SIZE
#define SHORT_TYPE_SIZE (BITS_PER_UNIT * 2)
#endif
#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef LONG_TYPE_SIZE
#define LONG_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef LONG_LONG_TYPE_SIZE
#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#ifndef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
#endif
#ifndef WCHAR_UNSIGNED
#define WCHAR_UNSIGNED 0
#endif
#ifndef FLOAT_TYPE_SIZE
#define FLOAT_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef DOUBLE_TYPE_SIZE
#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#ifndef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
struct filename_entry {
unsigned number;
char * name;
};
typedef struct filename_entry filename_entry;
static filename_entry *filename_table;
static unsigned ft_entries_allocated;
static unsigned ft_entries;
#define FT_ENTRIES_INCREMENT 64
static char *primary_filename;
static char *last_filename;
static unsigned next_block_number = 2;
static unsigned next_unused_dienum = 1;
static unsigned current_dienum;
static int next_pubname_number = 0;
#define NEXT_DIE_NUM pending_sibling_stack[pending_siblings-1]
static unsigned *pending_sibling_stack;
static unsigned pending_siblings;
static unsigned pending_siblings_allocated;
#define PENDING_SIBLINGS_INCREMENT 64
static int finalizing = 0;
static tree *pending_types_list;
static unsigned pending_types_allocated;
static unsigned pending_types;
#define PENDING_TYPES_INCREMENT 64
static tree *incomplete_types_list;
static unsigned incomplete_types_allocated;
static unsigned incomplete_types;
#define INCOMPLETE_TYPES_INCREMENT 64
static tree fake_containing_scope;
static unsigned current_funcdef_number = 1;
static tree dwarf_last_decl;
static int in_class;
static char *dwarf_tag_name PROTO((unsigned));
static char *dwarf_attr_name PROTO((unsigned));
static char *dwarf_stack_op_name PROTO((unsigned));
static char *dwarf_typemod_name PROTO((unsigned));
static char *dwarf_fmt_byte_name PROTO((unsigned));
static char *dwarf_fund_type_name PROTO((unsigned));
static tree decl_ultimate_origin PROTO((tree));
static tree block_ultimate_origin PROTO((tree));
static tree decl_class_context PROTO((tree));
#if 0
static void output_unsigned_leb128 PROTO((unsigned long));
static void output_signed_leb128 PROTO((long));
#endif
static inline int is_body_block PROTO((tree));
static int fundamental_type_code PROTO((tree));
static tree root_type_1 PROTO((tree, int));
static tree root_type PROTO((tree));
static void write_modifier_bytes_1 PROTO((tree, int, int, int));
static void write_modifier_bytes PROTO((tree, int, int));
static inline int type_is_fundamental PROTO((tree));
static void equate_decl_number_to_die_number PROTO((tree));
static inline void equate_type_number_to_die_number PROTO((tree));
static void output_reg_number PROTO((rtx));
static void output_mem_loc_descriptor PROTO((rtx));
static void output_loc_descriptor PROTO((rtx));
static void output_bound_representation PROTO((tree, unsigned, int));
static void output_enumeral_list PROTO((tree));
static inline unsigned ceiling PROTO((unsigned, unsigned));
static inline tree field_type PROTO((tree));
static inline unsigned simple_type_align_in_bits PROTO((tree));
static inline unsigned simple_type_size_in_bits PROTO((tree));
static unsigned field_byte_offset PROTO((tree));
static inline void sibling_attribute PROTO((void));
static void location_attribute PROTO((rtx));
static void data_member_location_attribute PROTO((tree));
static void const_value_attribute PROTO((rtx));
static void location_or_const_value_attribute PROTO((tree));
static inline void name_attribute PROTO((char *));
static inline void fund_type_attribute PROTO((unsigned));
static void mod_fund_type_attribute PROTO((tree, int, int));
static inline void user_def_type_attribute PROTO((tree));
static void mod_u_d_type_attribute PROTO((tree, int, int));
#ifdef USE_ORDERING_ATTRIBUTE
static inline void ordering_attribute PROTO((unsigned));
#endif
static void subscript_data_attribute PROTO((tree));
static void byte_size_attribute PROTO((tree));
static inline void bit_offset_attribute PROTO((tree));
static inline void bit_size_attribute PROTO((tree));
static inline void element_list_attribute PROTO((tree));
static inline void stmt_list_attribute PROTO((char *));
static inline void low_pc_attribute PROTO((char *));
static inline void high_pc_attribute PROTO((char *));
static inline void body_begin_attribute PROTO((char *));
static inline void body_end_attribute PROTO((char *));
static inline void language_attribute PROTO((unsigned));
static inline void member_attribute PROTO((tree));
#if 0
static inline void string_length_attribute PROTO((tree));
#endif
static inline void comp_dir_attribute PROTO((char *));
static inline void sf_names_attribute PROTO((char *));
static inline void src_info_attribute PROTO((char *));
static inline void mac_info_attribute PROTO((char *));
static inline void prototyped_attribute PROTO((tree));
static inline void producer_attribute PROTO((char *));
static inline void inline_attribute PROTO((tree));
static inline void containing_type_attribute PROTO((tree));
static inline void abstract_origin_attribute PROTO((tree));
#ifdef DWARF_DECL_COORDINATES
static inline void src_coords_attribute PROTO((unsigned, unsigned));
#endif
static inline void pure_or_virtual_attribute PROTO((tree));
static void name_and_src_coords_attributes PROTO((tree));
static void type_attribute PROTO((tree, int, int));
static char *type_tag PROTO((tree));
static inline void dienum_push PROTO((void));
static inline void dienum_pop PROTO((void));
static inline tree member_declared_type PROTO((tree));
static char *function_start_label PROTO((tree));
static void output_array_type_die PROTO((void *));
static void output_set_type_die PROTO((void *));
#if 0
static void output_entry_point_die PROTO((void *));
#endif
static void output_inlined_enumeration_type_die PROTO((void *));
static void output_inlined_structure_type_die PROTO((void *));
static void output_inlined_union_type_die PROTO((void *));
static void output_enumeration_type_die PROTO((void *));
static void output_formal_parameter_die PROTO((void *));
static void output_global_subroutine_die PROTO((void *));
static void output_global_variable_die PROTO((void *));
static void output_label_die PROTO((void *));
static void output_lexical_block_die PROTO((void *));
static void output_inlined_subroutine_die PROTO((void *));
static void output_local_variable_die PROTO((void *));
static void output_member_die PROTO((void *));
#if 0
static void output_pointer_type_die PROTO((void *));
static void output_reference_type_die PROTO((void *));
#endif
static void output_ptr_to_mbr_type_die PROTO((void *));
static void output_compile_unit_die PROTO((void *));
static void output_string_type_die PROTO((void *));
static void output_inheritance_die PROTO((void *));
static void output_structure_type_die PROTO((void *));
static void output_local_subroutine_die PROTO((void *));
static void output_subroutine_type_die PROTO((void *));
static void output_typedef_die PROTO((void *));
static void output_union_type_die PROTO((void *));
static void output_unspecified_parameters_die PROTO((void *));
static void output_padded_null_die PROTO((void *));
static void output_die PROTO((void (*) PROTO((void *)), void *));
static void end_sibling_chain PROTO((void));
static void output_formal_types PROTO((tree));
static void pend_type PROTO((tree));
static int type_ok_for_scope PROTO((tree, tree));
static void output_pending_types_for_scope PROTO((tree));
static void output_type PROTO((tree, tree));
static void output_tagged_type_instantiation PROTO((tree));
static void output_block PROTO((tree, int));
static void output_decls_for_scope PROTO((tree, int));
static void output_decl PROTO((tree, tree));
static void shuffle_filename_entry PROTO((filename_entry *));
static void generate_new_sfname_entry PROTO((void));
static unsigned lookup_filename PROTO((char *));
static void generate_srcinfo_entry PROTO((unsigned, unsigned));
static void generate_macinfo_entry PROTO((char *, char *));
static int is_pseudo_reg PROTO((rtx));
static tree type_main_variant PROTO((tree));
static int is_tagged_type PROTO((tree));
static int is_redundant_typedef PROTO((tree));
#ifndef FILE_ASM_OP
#define FILE_ASM_OP ".file"
#endif
#ifndef VERSION_ASM_OP
#define VERSION_ASM_OP ".version"
#endif
#ifndef UNALIGNED_SHORT_ASM_OP
#define UNALIGNED_SHORT_ASM_OP ".2byte"
#endif
#ifndef UNALIGNED_INT_ASM_OP
#define UNALIGNED_INT_ASM_OP ".4byte"
#endif
#ifndef ASM_BYTE_OP
#define ASM_BYTE_OP ".byte"
#endif
#ifndef SET_ASM_OP
#define SET_ASM_OP ".set"
#endif
#ifndef PUSHSECTION_ASM_OP
#define PUSHSECTION_ASM_OP ".section"
#endif
#ifndef POPSECTION_ASM_OP
#define POPSECTION_ASM_OP ".previous"
#endif
#ifndef PUSHSECTION_FORMAT
#define PUSHSECTION_FORMAT "\t%s\t%s\n"
#endif
#ifndef DEBUG_SECTION
#define DEBUG_SECTION ".debug"
#endif
#ifndef LINE_SECTION
#define LINE_SECTION ".line"
#endif
#ifndef SFNAMES_SECTION
#define SFNAMES_SECTION ".debug_sfnames"
#endif
#ifndef SRCINFO_SECTION
#define SRCINFO_SECTION ".debug_srcinfo"
#endif
#ifndef MACINFO_SECTION
#define MACINFO_SECTION ".debug_macinfo"
#endif
#ifndef PUBNAMES_SECTION
#define PUBNAMES_SECTION ".debug_pubnames"
#endif
#ifndef ARANGES_SECTION
#define ARANGES_SECTION ".debug_aranges"
#endif
#ifndef TEXT_SECTION
#define TEXT_SECTION ".text"
#endif
#ifndef DATA_SECTION
#define DATA_SECTION ".data"
#endif
#ifndef DATA1_SECTION
#define DATA1_SECTION ".data1"
#endif
#ifndef RODATA_SECTION
#define RODATA_SECTION ".rodata"
#endif
#ifndef RODATA1_SECTION
#define RODATA1_SECTION ".rodata1"
#endif
#ifndef BSS_SECTION
#define BSS_SECTION ".bss"
#endif
#ifndef TEXT_BEGIN_LABEL
#define TEXT_BEGIN_LABEL "*.L_text_b"
#endif
#ifndef TEXT_END_LABEL
#define TEXT_END_LABEL "*.L_text_e"
#endif
#ifndef DATA_BEGIN_LABEL
#define DATA_BEGIN_LABEL "*.L_data_b"
#endif
#ifndef DATA_END_LABEL
#define DATA_END_LABEL "*.L_data_e"
#endif
#ifndef DATA1_BEGIN_LABEL
#define DATA1_BEGIN_LABEL "*.L_data1_b"
#endif
#ifndef DATA1_END_LABEL
#define DATA1_END_LABEL "*.L_data1_e"
#endif
#ifndef RODATA_BEGIN_LABEL
#define RODATA_BEGIN_LABEL "*.L_rodata_b"
#endif
#ifndef RODATA_END_LABEL
#define RODATA_END_LABEL "*.L_rodata_e"
#endif
#ifndef RODATA1_BEGIN_LABEL
#define RODATA1_BEGIN_LABEL "*.L_rodata1_b"
#endif
#ifndef RODATA1_END_LABEL
#define RODATA1_END_LABEL "*.L_rodata1_e"
#endif
#ifndef BSS_BEGIN_LABEL
#define BSS_BEGIN_LABEL "*.L_bss_b"
#endif
#ifndef BSS_END_LABEL
#define BSS_END_LABEL "*.L_bss_e"
#endif
#ifndef LINE_BEGIN_LABEL
#define LINE_BEGIN_LABEL "*.L_line_b"
#endif
#ifndef LINE_LAST_ENTRY_LABEL
#define LINE_LAST_ENTRY_LABEL "*.L_line_last"
#endif
#ifndef LINE_END_LABEL
#define LINE_END_LABEL "*.L_line_e"
#endif
#ifndef DEBUG_BEGIN_LABEL
#define DEBUG_BEGIN_LABEL "*.L_debug_b"
#endif
#ifndef SFNAMES_BEGIN_LABEL
#define SFNAMES_BEGIN_LABEL "*.L_sfnames_b"
#endif
#ifndef SRCINFO_BEGIN_LABEL
#define SRCINFO_BEGIN_LABEL "*.L_srcinfo_b"
#endif
#ifndef MACINFO_BEGIN_LABEL
#define MACINFO_BEGIN_LABEL "*.L_macinfo_b"
#endif
#ifndef DIE_BEGIN_LABEL_FMT
#define DIE_BEGIN_LABEL_FMT "*.L_D%u"
#endif
#ifndef DIE_END_LABEL_FMT
#define DIE_END_LABEL_FMT "*.L_D%u_e"
#endif
#ifndef PUB_DIE_LABEL_FMT
#define PUB_DIE_LABEL_FMT "*.L_P%u"
#endif
#ifndef INSN_LABEL_FMT
#define INSN_LABEL_FMT "*.L_I%u_%u"
#endif
#ifndef BLOCK_BEGIN_LABEL_FMT
#define BLOCK_BEGIN_LABEL_FMT "*.L_B%u"
#endif
#ifndef BLOCK_END_LABEL_FMT
#define BLOCK_END_LABEL_FMT "*.L_B%u_e"
#endif
#ifndef SS_BEGIN_LABEL_FMT
#define SS_BEGIN_LABEL_FMT "*.L_s%u"
#endif
#ifndef SS_END_LABEL_FMT
#define SS_END_LABEL_FMT "*.L_s%u_e"
#endif
#ifndef EE_BEGIN_LABEL_FMT
#define EE_BEGIN_LABEL_FMT "*.L_e%u"
#endif
#ifndef EE_END_LABEL_FMT
#define EE_END_LABEL_FMT "*.L_e%u_e"
#endif
#ifndef MT_BEGIN_LABEL_FMT
#define MT_BEGIN_LABEL_FMT "*.L_t%u"
#endif
#ifndef MT_END_LABEL_FMT
#define MT_END_LABEL_FMT "*.L_t%u_e"
#endif
#ifndef LOC_BEGIN_LABEL_FMT
#define LOC_BEGIN_LABEL_FMT "*.L_l%u"
#endif
#ifndef LOC_END_LABEL_FMT
#define LOC_END_LABEL_FMT "*.L_l%u_e"
#endif
#ifndef BOUND_BEGIN_LABEL_FMT
#define BOUND_BEGIN_LABEL_FMT "*.L_b%u_%u_%c"
#endif
#ifndef BOUND_END_LABEL_FMT
#define BOUND_END_LABEL_FMT "*.L_b%u_%u_%c_e"
#endif
#ifndef DERIV_BEGIN_LABEL_FMT
#define DERIV_BEGIN_LABEL_FMT "*.L_d%u"
#endif
#ifndef DERIV_END_LABEL_FMT
#define DERIV_END_LABEL_FMT "*.L_d%u_e"
#endif
#ifndef SL_BEGIN_LABEL_FMT
#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
#endif
#ifndef SL_END_LABEL_FMT
#define SL_END_LABEL_FMT "*.L_sl%u_e"
#endif
#ifndef BODY_BEGIN_LABEL_FMT
#define BODY_BEGIN_LABEL_FMT "*.L_b%u"
#endif
#ifndef BODY_END_LABEL_FMT
#define BODY_END_LABEL_FMT "*.L_b%u_e"
#endif
#ifndef FUNC_END_LABEL_FMT
#define FUNC_END_LABEL_FMT "*.L_f%u_e"
#endif
#ifndef TYPE_NAME_FMT
#define TYPE_NAME_FMT "*.L_T%u"
#endif
#ifndef DECL_NAME_FMT
#define DECL_NAME_FMT "*.L_E%u"
#endif
#ifndef LINE_CODE_LABEL_FMT
#define LINE_CODE_LABEL_FMT "*.L_LC%u"
#endif
#ifndef SFNAMES_ENTRY_LABEL_FMT
#define SFNAMES_ENTRY_LABEL_FMT "*.L_F%u"
#endif
#ifndef LINE_ENTRY_LABEL_FMT
#define LINE_ENTRY_LABEL_FMT "*.L_LE%u"
#endif
#ifndef ASM_OUTPUT_PUSH_SECTION
#define ASM_OUTPUT_PUSH_SECTION(FILE, SECTION) \
fprintf ((FILE), PUSHSECTION_FORMAT, PUSHSECTION_ASM_OP, SECTION)
#endif
#ifndef ASM_OUTPUT_POP_SECTION
#define ASM_OUTPUT_POP_SECTION(FILE) \
fprintf ((FILE), "\t%s\n", POPSECTION_ASM_OP)
#endif
#ifndef ASM_OUTPUT_DWARF_DELTA2
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
assemble_name (FILE, LABEL1); \
fprintf (FILE, "-"); \
assemble_name (FILE, LABEL2); \
fprintf (FILE, "\n"); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_DELTA4
#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
assemble_name (FILE, LABEL1); \
fprintf (FILE, "-"); \
assemble_name (FILE, LABEL2); \
fprintf (FILE, "\n"); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_TAG
#define ASM_OUTPUT_DWARF_TAG(FILE,TAG) \
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) TAG); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_tag_name (TAG)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_ATTRIBUTE
#define ASM_OUTPUT_DWARF_ATTRIBUTE(FILE,ATTR) \
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) ATTR); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_attr_name (ATTR)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_STACK_OP
#define ASM_OUTPUT_DWARF_STACK_OP(FILE,OP) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) OP); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_stack_op_name (OP)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_FUND_TYPE
#define ASM_OUTPUT_DWARF_FUND_TYPE(FILE,FT) \
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) FT); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_fund_type_name (FT)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_FMT_BYTE
#define ASM_OUTPUT_DWARF_FMT_BYTE(FILE,FMT) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) FMT); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_fmt_byte_name (FMT)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_TYPE_MODIFIER
#define ASM_OUTPUT_DWARF_TYPE_MODIFIER(FILE,MOD) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) MOD); \
if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_typemod_name (MOD)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_ADDR
#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
assemble_name (FILE, LABEL); \
fprintf (FILE, "\n"); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_ADDR_CONST
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) \
do { \
fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
output_addr_const ((FILE), (RTX)); \
fputc ('\n', (FILE)); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_REF
#define ASM_OUTPUT_DWARF_REF(FILE,LABEL) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \
assemble_name (FILE, LABEL); \
fprintf (FILE, "\n"); \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA1
#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x\n", ASM_BYTE_OP, VALUE)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA2
#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_SHORT_ASM_OP, (unsigned) VALUE)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA4
#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, (unsigned) VALUE)
#endif
#ifndef ASM_OUTPUT_DWARF_DATA8
#define ASM_OUTPUT_DWARF_DATA8(FILE,HIGH_VALUE,LOW_VALUE) \
do { \
if (WORDS_BIG_ENDIAN) \
{ \
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
} \
else \
{ \
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, LOW_VALUE);\
fprintf ((FILE), "\t%s\t0x%x\n", UNALIGNED_INT_ASM_OP, HIGH_VALUE); \
} \
} while (0)
#endif
#ifndef ASM_OUTPUT_DWARF_STRING
#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
#else
#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
#endif
inline static int
is_pseudo_reg (rtl)
register rtx rtl;
{
return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
|| ((GET_CODE (rtl) == SUBREG)
&& (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
}
inline static tree
type_main_variant (type)
register tree type;
{
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == ARRAY_TYPE)
{
while (type != TYPE_MAIN_VARIANT (type))
type = TYPE_MAIN_VARIANT (type);
}
return type;
}
inline static int
is_tagged_type (type)
register tree type;
{
register enum tree_code code = TREE_CODE (type);
return (code == RECORD_TYPE || code == UNION_TYPE
|| code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
}
static char *
dwarf_tag_name (tag)
register unsigned tag;
{
switch (tag)
{
case TAG_padding: return "TAG_padding";
case TAG_array_type: return "TAG_array_type";
case TAG_class_type: return "TAG_class_type";
case TAG_entry_point: return "TAG_entry_point";
case TAG_enumeration_type: return "TAG_enumeration_type";
case TAG_formal_parameter: return "TAG_formal_parameter";
case TAG_global_subroutine: return "TAG_global_subroutine";
case TAG_global_variable: return "TAG_global_variable";
case TAG_label: return "TAG_label";
case TAG_lexical_block: return "TAG_lexical_block";
case TAG_local_variable: return "TAG_local_variable";
case TAG_member: return "TAG_member";
case TAG_pointer_type: return "TAG_pointer_type";
case TAG_reference_type: return "TAG_reference_type";
case TAG_compile_unit: return "TAG_compile_unit";
case TAG_string_type: return "TAG_string_type";
case TAG_structure_type: return "TAG_structure_type";
case TAG_subroutine: return "TAG_subroutine";
case TAG_subroutine_type: return "TAG_subroutine_type";
case TAG_typedef: return "TAG_typedef";
case TAG_union_type: return "TAG_union_type";
case TAG_unspecified_parameters: return "TAG_unspecified_parameters";
case TAG_variant: return "TAG_variant";
case TAG_common_block: return "TAG_common_block";
case TAG_common_inclusion: return "TAG_common_inclusion";
case TAG_inheritance: return "TAG_inheritance";
case TAG_inlined_subroutine: return "TAG_inlined_subroutine";
case TAG_module: return "TAG_module";
case TAG_ptr_to_member_type: return "TAG_ptr_to_member_type";
case TAG_set_type: return "TAG_set_type";
case TAG_subrange_type: return "TAG_subrange_type";
case TAG_with_stmt: return "TAG_with_stmt";
case TAG_format_label: return "TAG_format_label";
case TAG_namelist: return "TAG_namelist";
case TAG_function_template: return "TAG_function_template";
case TAG_class_template: return "TAG_class_template";
default: return "TAG_<unknown>";
}
}
static char *
dwarf_attr_name (attr)
register unsigned attr;
{
switch (attr)
{
case AT_sibling: return "AT_sibling";
case AT_location: return "AT_location";
case AT_name: return "AT_name";
case AT_fund_type: return "AT_fund_type";
case AT_mod_fund_type: return "AT_mod_fund_type";
case AT_user_def_type: return "AT_user_def_type";
case AT_mod_u_d_type: return "AT_mod_u_d_type";
case AT_ordering: return "AT_ordering";
case AT_subscr_data: return "AT_subscr_data";
case AT_byte_size: return "AT_byte_size";
case AT_bit_offset: return "AT_bit_offset";
case AT_bit_size: return "AT_bit_size";
case AT_element_list: return "AT_element_list";
case AT_stmt_list: return "AT_stmt_list";
case AT_low_pc: return "AT_low_pc";
case AT_high_pc: return "AT_high_pc";
case AT_language: return "AT_language";
case AT_member: return "AT_member";
case AT_discr: return "AT_discr";
case AT_discr_value: return "AT_discr_value";
case AT_string_length: return "AT_string_length";
case AT_common_reference: return "AT_common_reference";
case AT_comp_dir: return "AT_comp_dir";
case AT_const_value_string: return "AT_const_value_string";
case AT_const_value_data2: return "AT_const_value_data2";
case AT_const_value_data4: return "AT_const_value_data4";
case AT_const_value_data8: return "AT_const_value_data8";
case AT_const_value_block2: return "AT_const_value_block2";
case AT_const_value_block4: return "AT_const_value_block4";
case AT_containing_type: return "AT_containing_type";
case AT_default_value_addr: return "AT_default_value_addr";
case AT_default_value_data2: return "AT_default_value_data2";
case AT_default_value_data4: return "AT_default_value_data4";
case AT_default_value_data8: return "AT_default_value_data8";
case AT_default_value_string: return "AT_default_value_string";
case AT_friends: return "AT_friends";
case AT_inline: return "AT_inline";
case AT_is_optional: return "AT_is_optional";
case AT_lower_bound_ref: return "AT_lower_bound_ref";
case AT_lower_bound_data2: return "AT_lower_bound_data2";
case AT_lower_bound_data4: return "AT_lower_bound_data4";
case AT_lower_bound_data8: return "AT_lower_bound_data8";
case AT_private: return "AT_private";
case AT_producer: return "AT_producer";
case AT_program: return "AT_program";
case AT_protected: return "AT_protected";
case AT_prototyped: return "AT_prototyped";
case AT_public: return "AT_public";
case AT_pure_virtual: return "AT_pure_virtual";
case AT_return_addr: return "AT_return_addr";
case AT_abstract_origin: return "AT_abstract_origin";
case AT_start_scope: return "AT_start_scope";
case AT_stride_size: return "AT_stride_size";
case AT_upper_bound_ref: return "AT_upper_bound_ref";
case AT_upper_bound_data2: return "AT_upper_bound_data2";
case AT_upper_bound_data4: return "AT_upper_bound_data4";
case AT_upper_bound_data8: return "AT_upper_bound_data8";
case AT_virtual: return "AT_virtual";
case AT_sf_names: return "AT_sf_names";
case AT_src_info: return "AT_src_info";
case AT_mac_info: return "AT_mac_info";
case AT_src_coords: return "AT_src_coords";
case AT_body_begin: return "AT_body_begin";
case AT_body_end: return "AT_body_end";
default: return "AT_<unknown>";
}
}
static char *
dwarf_stack_op_name (op)
register unsigned op;
{
switch (op)
{
case OP_REG: return "OP_REG";
case OP_BASEREG: return "OP_BASEREG";
case OP_ADDR: return "OP_ADDR";
case OP_CONST: return "OP_CONST";
case OP_DEREF2: return "OP_DEREF2";
case OP_DEREF4: return "OP_DEREF4";
case OP_ADD: return "OP_ADD";
default: return "OP_<unknown>";
}
}
static char *
dwarf_typemod_name (mod)
register unsigned mod;
{
switch (mod)
{
case MOD_pointer_to: return "MOD_pointer_to";
case MOD_reference_to: return "MOD_reference_to";
case MOD_const: return "MOD_const";
case MOD_volatile: return "MOD_volatile";
default: return "MOD_<unknown>";
}
}
static char *
dwarf_fmt_byte_name (fmt)
register unsigned fmt;
{
switch (fmt)
{
case FMT_FT_C_C: return "FMT_FT_C_C";
case FMT_FT_C_X: return "FMT_FT_C_X";
case FMT_FT_X_C: return "FMT_FT_X_C";
case FMT_FT_X_X: return "FMT_FT_X_X";
case FMT_UT_C_C: return "FMT_UT_C_C";
case FMT_UT_C_X: return "FMT_UT_C_X";
case FMT_UT_X_C: return "FMT_UT_X_C";
case FMT_UT_X_X: return "FMT_UT_X_X";
case FMT_ET: return "FMT_ET";
default: return "FMT_<unknown>";
}
}
static char *
dwarf_fund_type_name (ft)
register unsigned ft;
{
switch (ft)
{
case FT_char: return "FT_char";
case FT_signed_char: return "FT_signed_char";
case FT_unsigned_char: return "FT_unsigned_char";
case FT_short: return "FT_short";
case FT_signed_short: return "FT_signed_short";
case FT_unsigned_short: return "FT_unsigned_short";
case FT_integer: return "FT_integer";
case FT_signed_integer: return "FT_signed_integer";
case FT_unsigned_integer: return "FT_unsigned_integer";
case FT_long: return "FT_long";
case FT_signed_long: return "FT_signed_long";
case FT_unsigned_long: return "FT_unsigned_long";
case FT_pointer: return "FT_pointer";
case FT_float: return "FT_float";
case FT_dbl_prec_float: return "FT_dbl_prec_float";
case FT_ext_prec_float: return "FT_ext_prec_float";
case FT_complex: return "FT_complex";
case FT_dbl_prec_complex: return "FT_dbl_prec_complex";
case FT_void: return "FT_void";
case FT_boolean: return "FT_boolean";
case FT_ext_prec_complex: return "FT_ext_prec_complex";
case FT_label: return "FT_label";
case FT_long_long: return "FT_long_long";
case FT_signed_long_long: return "FT_signed_long_long";
case FT_unsigned_long_long: return "FT_unsigned_long_long";
case FT_int8: return "FT_int8";
case FT_signed_int8: return "FT_signed_int8";
case FT_unsigned_int8: return "FT_unsigned_int8";
case FT_int16: return "FT_int16";
case FT_signed_int16: return "FT_signed_int16";
case FT_unsigned_int16: return "FT_unsigned_int16";
case FT_int32: return "FT_int32";
case FT_signed_int32: return "FT_signed_int32";
case FT_unsigned_int32: return "FT_unsigned_int32";
case FT_int64: return "FT_int64";
case FT_signed_int64: return "FT_signed_int64";
case FT_unsigned_int64: return "FT_unsigned_int64";
case FT_real32: return "FT_real32";
case FT_real64: return "FT_real64";
case FT_real96: return "FT_real96";
case FT_real128: return "FT_real128";
default: return "FT_<unknown>";
}
}
static tree
decl_ultimate_origin (decl)
register tree decl;
{
#ifdef ENABLE_CHECKING
if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
abort ();
#endif
return DECL_ABSTRACT_ORIGIN (decl);
}
static tree
block_ultimate_origin (block)
register tree block;
{
register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
if (immediate_origin == NULL)
return NULL;
else
{
register tree ret_val;
register tree lookahead = immediate_origin;
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;
}
}
static tree
decl_class_context (decl)
tree decl;
{
tree context = NULL_TREE;
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)))));
if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
context = NULL_TREE;
return context;
}
#if 0
static void
output_unsigned_leb128 (value)
register unsigned long value;
{
register unsigned long orig_value = value;
do
{
register unsigned byte = (value & 0x7f);
value >>= 7;
if (value != 0)
byte |= 0x80;
fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
if (flag_debug_asm && value == 0)
fprintf (asm_out_file, "\t%s ULEB128 number - value = %lu",
ASM_COMMENT_START, orig_value);
fputc ('\n', asm_out_file);
}
while (value != 0);
}
static void
output_signed_leb128 (value)
register long value;
{
register long orig_value = value;
register int negative = (value < 0);
register int more;
do
{
register unsigned byte = (value & 0x7f);
value >>= 7;
if (negative)
value |= 0xfe000000;
if (((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) == 1)))
more = 0;
else
{
byte |= 0x80;
more = 1;
}
fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
if (flag_debug_asm && more == 0)
fprintf (asm_out_file, "\t%s SLEB128 number - value = %ld",
ASM_COMMENT_START, orig_value);
fputc ('\n', asm_out_file);
}
while (more);
}
#endif
static inline int
is_body_block (stmt)
register tree stmt;
{
if (TREE_CODE (stmt) == BLOCK)
{
register tree parent = BLOCK_SUPERCONTEXT (stmt);
if (TREE_CODE (parent) == BLOCK)
{
register tree grandparent = BLOCK_SUPERCONTEXT (parent);
if (TREE_CODE (grandparent) == FUNCTION_DECL)
return 1;
}
}
return 0;
}
static int
fundamental_type_code (type)
register tree type;
{
if (TREE_CODE (type) == ERROR_MARK)
return 0;
switch (TREE_CODE (type))
{
case ERROR_MARK:
return FT_void;
case VOID_TYPE:
return FT_void;
case INTEGER_TYPE:
if (TYPE_NAME (type) != 0
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (type)) != 0
&& TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
{
char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
if (!strcmp (name, "unsigned char"))
return FT_unsigned_char;
if (!strcmp (name, "signed char"))
return FT_signed_char;
if (!strcmp (name, "unsigned int"))
return FT_unsigned_integer;
if (!strcmp (name, "short int"))
return FT_short;
if (!strcmp (name, "short unsigned int"))
return FT_unsigned_short;
if (!strcmp (name, "long int"))
return FT_long;
if (!strcmp (name, "long unsigned int"))
return FT_unsigned_long;
if (!strcmp (name, "long long int"))
return FT_long_long;
if (!strcmp (name, "long long unsigned int"))
return FT_unsigned_long_long;
}
if (TYPE_PRECISION (type) == INT_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_integer : FT_integer);
if (TYPE_PRECISION (type) == LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_long : FT_long);
if (TYPE_PRECISION (type) == LONG_LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_long_long : FT_long_long);
if (TYPE_PRECISION (type) == SHORT_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_short : FT_short);
if (TYPE_PRECISION (type) == CHAR_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? FT_unsigned_char : FT_char);
if (TYPE_PRECISION (type) == 1)
return FT_boolean;
abort ();
case REAL_TYPE:
if (TYPE_NAME (type) != 0
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_NAME (TYPE_NAME (type)) != 0
&& TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
{
char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
if (!strcmp (name, "long double"))
return FT_ext_prec_float;
}
if (TYPE_PRECISION (type) == DOUBLE_TYPE_SIZE)
{
if (DOUBLE_TYPE_SIZE == FLOAT_TYPE_SIZE && FLOAT_TYPE_SIZE == 32)
return FT_float;
return FT_dbl_prec_float;
}
if (TYPE_PRECISION (type) == FLOAT_TYPE_SIZE)
return FT_float;
if (TYPE_PRECISION (type) == LONG_DOUBLE_TYPE_SIZE)
return FT_ext_prec_float;
abort ();
case COMPLEX_TYPE:
return FT_complex;
case CHAR_TYPE:
return FT_char;
case BOOLEAN_TYPE:
return FT_boolean;
default:
abort ();
}
return 0;
}
static tree
root_type_1 (type, count)
register tree type;
register int count;
{
if (count > 1000)
return error_mark_node;
switch (TREE_CODE (type))
{
case ERROR_MARK:
return error_mark_node;
case POINTER_TYPE:
case REFERENCE_TYPE:
return root_type_1 (TREE_TYPE (type), count+1);
default:
return type;
}
}
static tree
root_type (type)
register tree type;
{
type = root_type_1 (type, 0);
if (type != error_mark_node)
type = type_main_variant (type);
return type;
}
static void
write_modifier_bytes_1 (type, decl_const, decl_volatile, count)
register tree type;
register int decl_const;
register int decl_volatile;
register int count;
{
if (TREE_CODE (type) == ERROR_MARK)
return;
if (count > 1000)
return;
if (TYPE_READONLY (type) || decl_const)
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_const);
if (TYPE_VOLATILE (type) || decl_volatile)
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_volatile);
switch (TREE_CODE (type))
{
case POINTER_TYPE:
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_pointer_to);
write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
return;
case REFERENCE_TYPE:
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_reference_to);
write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
return;
case ERROR_MARK:
default:
return;
}
}
static void
write_modifier_bytes (type, decl_const, decl_volatile)
register tree type;
register int decl_const;
register int decl_volatile;
{
write_modifier_bytes_1 (type, decl_const, decl_volatile, 0);
}
static inline int
type_is_fundamental (type)
register tree type;
{
switch (TREE_CODE (type))
{
case ERROR_MARK:
case VOID_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case CHAR_TYPE:
return 1;
case VECTOR_TYPE:
case SET_TYPE:
case ARRAY_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
case ENUMERAL_TYPE:
case FUNCTION_TYPE:
case METHOD_TYPE:
case POINTER_TYPE:
case REFERENCE_TYPE:
case FILE_TYPE:
case OFFSET_TYPE:
case LANG_TYPE:
return 0;
default:
abort ();
}
return 0;
}
static void
equate_decl_number_to_die_number (decl)
register tree decl;
{
char decl_label[MAX_ARTIFICIAL_LABEL_BYTES];
char die_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (decl_label, DECL_NAME_FMT, DECL_UID (decl));
sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);
ASM_OUTPUT_DEF (asm_out_file, decl_label, die_label);
}
static inline void
equate_type_number_to_die_number (type)
register tree type;
{
char type_label[MAX_ARTIFICIAL_LABEL_BYTES];
char die_label[MAX_ARTIFICIAL_LABEL_BYTES];
type = type_main_variant (type);
sprintf (type_label, TYPE_NAME_FMT, TYPE_UID (type));
sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);
ASM_OUTPUT_DEF (asm_out_file, type_label, die_label);
}
static void
output_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;
}
fprintf (asm_out_file, "\t%s\t0x%x",
UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
if (flag_debug_asm)
{
fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
PRINT_REG (rtl, 0, asm_out_file);
}
fputc ('\n', asm_out_file);
}
static void
output_mem_loc_descriptor (rtl)
register rtx rtl;
{
switch (GET_CODE (rtl))
{
case SUBREG:
rtl = XEXP (rtl, 0);
case REG:
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG);
output_reg_number (rtl);
break;
case MEM:
output_mem_loc_descriptor (XEXP (rtl, 0));
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_DEREF4);
break;
case CONST:
case SYMBOL_REF:
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADDR);
ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, rtl);
break;
case PLUS:
output_mem_loc_descriptor (XEXP (rtl, 0));
output_mem_loc_descriptor (XEXP (rtl, 1));
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD);
break;
case CONST_INT:
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, INTVAL (rtl));
break;
case MULT:
output_mem_loc_descriptor (XEXP (rtl, 0));
output_mem_loc_descriptor (XEXP (rtl, 1));
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_MULT);
break;
default:
abort ();
}
}
static void
output_loc_descriptor (rtl)
register rtx rtl;
{
switch (GET_CODE (rtl))
{
case SUBREG:
rtl = XEXP (rtl, 0);
case REG:
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG);
output_reg_number (rtl);
break;
case MEM:
output_mem_loc_descriptor (XEXP (rtl, 0));
break;
default:
abort ();
}
}
static void
output_bound_representation (bound, dim_num, u_or_l)
register tree bound;
register unsigned dim_num;
register char u_or_l;
{
switch (TREE_CODE (bound))
{
case ERROR_MARK:
return;
case INTEGER_CST:
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) TREE_INT_CST_LOW (bound));
break;
default:
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
current_dienum, dim_num, u_or_l);
sprintf (end_label, BOUND_END_LABEL_FMT,
current_dienum, dim_num, u_or_l);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
if (! optimize)
{
while (TREE_CODE (bound) == NOP_EXPR
|| TREE_CODE (bound) == CONVERT_EXPR)
bound = TREE_OPERAND (bound, 0);
if (TREE_CODE (bound) == SAVE_EXPR)
output_loc_descriptor
(eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
}
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
break;
}
}
static void
output_enumeral_list (link)
register tree link;
{
if (link)
{
output_enumeral_list (TREE_CHAIN (link));
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) TREE_INT_CST_LOW (TREE_VALUE (link)));
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (TREE_PURPOSE (link)));
}
}
static inline unsigned
ceiling (value, boundary)
register unsigned value;
register unsigned boundary;
{
return (((value + boundary - 1) / boundary) * boundary);
}
static inline tree
field_type (decl)
register tree decl;
{
register tree type;
if (TREE_CODE (decl) == ERROR_MARK)
return integer_type_node;
type = DECL_BIT_FIELD_TYPE (decl);
if (type == NULL)
type = TREE_TYPE (decl);
return type;
}
static inline unsigned
simple_type_align_in_bits (type)
register tree type;
{
return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD;
}
static inline unsigned
simple_type_size_in_bits (type)
register tree type;
{
if (TREE_CODE (type) == ERROR_MARK)
return BITS_PER_WORD;
else
{
register tree type_size_tree = TYPE_SIZE (type);
if (TREE_CODE (type_size_tree) != INTEGER_CST)
return TYPE_ALIGN (type);
return (unsigned) TREE_INT_CST_LOW (type_size_tree);
}
}
static unsigned
field_byte_offset (decl)
register tree decl;
{
register unsigned type_align_in_bytes;
register unsigned type_align_in_bits;
register unsigned type_size_in_bits;
register unsigned object_offset_in_align_units;
register unsigned object_offset_in_bits;
register unsigned object_offset_in_bytes;
register tree type;
register tree bitpos_tree;
register tree field_size_tree;
register unsigned bitpos_int;
register unsigned deepest_bitpos;
register unsigned field_size_in_bits;
if (TREE_CODE (decl) == ERROR_MARK)
return 0;
if (TREE_CODE (decl) != FIELD_DECL)
abort ();
type = field_type (decl);
bitpos_tree = DECL_FIELD_BITPOS (decl);
field_size_tree = DECL_SIZE (decl);
if (TREE_CODE (bitpos_tree) != INTEGER_CST)
return 0;
bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree);
if (TREE_CODE (field_size_tree) != INTEGER_CST)
return 0;
field_size_in_bits = (unsigned) TREE_INT_CST_LOW (field_size_tree);
type_size_in_bits = simple_type_size_in_bits (type);
type_align_in_bits = simple_type_align_in_bits (type);
type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT;
deepest_bitpos = bitpos_int + field_size_in_bits;
object_offset_in_bits
= ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;
object_offset_in_align_units = object_offset_in_bits / type_align_in_bits;
object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes;
if (BYTES_BIG_ENDIAN
&& object_offset_in_bits > bitpos_int)
{
deepest_bitpos = bitpos_int + 1;
object_offset_in_bits
= ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;
object_offset_in_align_units = (object_offset_in_bits
/ type_align_in_bits);
object_offset_in_bytes = (object_offset_in_align_units
* type_align_in_bytes);
}
return object_offset_in_bytes;
}
static inline void
sibling_attribute ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_sibling);
sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
ASM_OUTPUT_DWARF_REF (asm_out_file, label);
}
static void
location_attribute (rtl)
register rtx rtl;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);
sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
if (! is_pseudo_reg (rtl)
&& (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))
output_loc_descriptor (rtl);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static void
data_member_location_attribute (t)
register tree t;
{
register unsigned object_offset_in_bytes;
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
if (TREE_CODE (t) == TREE_VEC)
object_offset_in_bytes = TREE_INT_CST_LOW (BINFO_OFFSET (t));
else
object_offset_in_bytes = field_byte_offset (t);
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);
sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_CONST);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, object_offset_in_bytes);
ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_ADD);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static void
const_value_attribute (rtl)
register rtx rtl;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_const_value_block4);
sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
switch (GET_CODE (rtl))
{
case CONST_INT:
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, (unsigned) INTVAL (rtl));
break;
case CONST_DOUBLE:
ASM_OUTPUT_DWARF_DATA8 (asm_out_file,
(unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (rtl),
(unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (rtl));
break;
case CONST_STRING:
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, XSTR (rtl, 0));
break;
case SYMBOL_REF:
case LABEL_REF:
case CONST:
ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, rtl);
break;
case PLUS:
break;
default:
abort ();
}
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static void
location_or_const_value_attribute (decl)
register tree decl;
{
register rtx rtl;
if (TREE_CODE (decl) == ERROR_MARK)
return;
if ((TREE_CODE (decl) != VAR_DECL) && (TREE_CODE (decl) != PARM_DECL))
{
abort ();
return;
}
rtl = DECL_RTL (decl);
if (TREE_CODE (decl) == PARM_DECL)
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
register tree declared_type = type_main_variant (TREE_TYPE (decl));
register tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
if (declared_type == passed_type)
rtl = DECL_INCOMING_RTL (decl);
else if (! BYTES_BIG_ENDIAN)
if (TREE_CODE (declared_type) == INTEGER_TYPE)
if (TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
rtl = DECL_INCOMING_RTL (decl);
}
if (rtl == NULL_RTX)
return;
rtl = eliminate_regs (rtl, 0, NULL_RTX);
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
leaf_renumber_regs_insn (rtl);
#endif
switch (GET_CODE (rtl))
{
case ADDRESSOF:
break;
case CONST_INT:
case CONST_DOUBLE:
case CONST_STRING:
case SYMBOL_REF:
case LABEL_REF:
case CONST:
case PLUS:
const_value_attribute (rtl);
break;
case MEM:
case REG:
case SUBREG:
location_attribute (rtl);
break;
case CONCAT:
location_attribute (XEXP (rtl, 0));
break;
default:
abort ();
}
}
static inline void
name_attribute (name_string)
register char *name_string;
{
if (name_string && *name_string)
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_name);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, name_string);
}
}
static inline void
fund_type_attribute (ft_code)
register unsigned ft_code;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_fund_type);
ASM_OUTPUT_DWARF_FUND_TYPE (asm_out_file, ft_code);
}
static void
mod_fund_type_attribute (type, decl_const, decl_volatile)
register tree type;
register int decl_const;
register int decl_volatile;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_mod_fund_type);
sprintf (begin_label, MT_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, MT_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
write_modifier_bytes (type, decl_const, decl_volatile);
ASM_OUTPUT_DWARF_FUND_TYPE (asm_out_file,
fundamental_type_code (root_type (type)));
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static inline void
user_def_type_attribute (type)
register tree type;
{
char ud_type_name[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_user_def_type);
sprintf (ud_type_name, TYPE_NAME_FMT, TYPE_UID (type));
ASM_OUTPUT_DWARF_REF (asm_out_file, ud_type_name);
}
static void
mod_u_d_type_attribute (type, decl_const, decl_volatile)
register tree type;
register int decl_const;
register int decl_volatile;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
char ud_type_name[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_mod_u_d_type);
sprintf (begin_label, MT_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, MT_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
write_modifier_bytes (type, decl_const, decl_volatile);
sprintf (ud_type_name, TYPE_NAME_FMT, TYPE_UID (root_type (type)));
ASM_OUTPUT_DWARF_REF (asm_out_file, ud_type_name);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
#ifdef USE_ORDERING_ATTRIBUTE
static inline void
ordering_attribute (ordering)
register unsigned ordering;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_ordering);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, ordering);
}
#endif
static void
subscript_data_attribute (type)
register tree type;
{
register unsigned dimension_number;
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_subscr_data);
sprintf (begin_label, SS_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, SS_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
for (dimension_number = 0;
TREE_CODE (type) == ARRAY_TYPE;
type = TREE_TYPE (type), dimension_number++)
{
register tree domain = TYPE_DOMAIN (type);
if (domain)
{
register tree lower = TYPE_MIN_VALUE (domain);
register tree upper = TYPE_MAX_VALUE (domain);
if (! type_is_fundamental (domain))
abort ();
ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file,
FMT_CODE (1, TREE_CODE (lower) == INTEGER_CST,
(upper && TREE_CODE (upper) == INTEGER_CST)));
ASM_OUTPUT_DWARF_FUND_TYPE (asm_out_file,
fundamental_type_code (domain));
output_bound_representation (lower, dimension_number, 'l');
output_bound_representation (upper, dimension_number, 'u');
}
else
{
ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file, FMT_FT_C_X);
ASM_OUTPUT_DWARF_FUND_TYPE (asm_out_file, FT_integer);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0);
}
}
ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file, FMT_ET);
type_attribute (type, 0, 0);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static void
byte_size_attribute (tree_node)
register tree tree_node;
{
register unsigned size;
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_byte_size);
switch (TREE_CODE (tree_node))
{
case ERROR_MARK:
size = 0;
break;
case ENUMERAL_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
case ARRAY_TYPE:
size = int_size_in_bytes (tree_node);
break;
case FIELD_DECL:
size = simple_type_size_in_bits (field_type (tree_node))
/ BITS_PER_UNIT;
break;
default:
abort ();
}
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, size);
}
static inline void
bit_offset_attribute (decl)
register tree decl;
{
register unsigned object_offset_in_bytes = field_byte_offset (decl);
register tree type = DECL_BIT_FIELD_TYPE (decl);
register tree bitpos_tree = DECL_FIELD_BITPOS (decl);
register unsigned bitpos_int;
register unsigned highest_order_object_bit_offset;
register unsigned highest_order_field_bit_offset;
register unsigned bit_offset;
if (!type
|| TREE_CODE (decl) != FIELD_DECL)
abort ();
if (TREE_CODE (bitpos_tree) != INTEGER_CST)
return;
bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree);
highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT;
highest_order_field_bit_offset = bitpos_int;
if (! BYTES_BIG_ENDIAN)
{
highest_order_field_bit_offset
+= (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
highest_order_object_bit_offset += simple_type_size_in_bits (type);
}
bit_offset =
(! BYTES_BIG_ENDIAN
? highest_order_object_bit_offset - highest_order_field_bit_offset
: highest_order_field_bit_offset - highest_order_object_bit_offset);
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_offset);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, bit_offset);
}
static inline void
bit_size_attribute (decl)
register tree decl;
{
if (TREE_CODE (decl) != FIELD_DECL
|| ! DECL_BIT_FIELD_TYPE (decl))
abort ();
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_size);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl)));
}
static inline void
element_list_attribute (element)
register tree element;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_element_list);
sprintf (begin_label, EE_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, EE_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
output_enumeral_list (element);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static inline void
stmt_list_attribute (label)
register char *label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_stmt_list);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
}
static inline void
low_pc_attribute (asm_low_label)
register char *asm_low_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_low_pc);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_low_label);
}
static inline void
high_pc_attribute (asm_high_label)
register char *asm_high_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_high_pc);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_high_label);
}
static inline void
body_begin_attribute (asm_begin_label)
register char *asm_begin_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_begin);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_begin_label);
}
static inline void
body_end_attribute (asm_end_label)
register char *asm_end_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_end);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_end_label);
}
static inline void
language_attribute (language_code)
register unsigned language_code;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_language);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, language_code);
}
static inline void
member_attribute (context)
register tree context;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (context != NULL && is_tagged_type (context))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_member);
sprintf (label, TYPE_NAME_FMT, TYPE_UID (context));
ASM_OUTPUT_DWARF_REF (asm_out_file, label);
}
}
#if 0
static inline void
string_length_attribute (upper_bound)
register tree upper_bound;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_string_length);
sprintf (begin_label, SL_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, SL_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
output_bound_representation (upper_bound, 0, 'u');
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
#endif
static inline void
comp_dir_attribute (dirname)
register char *dirname;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_comp_dir);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, dirname);
}
static inline void
sf_names_attribute (sf_names_start_label)
register char *sf_names_start_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_sf_names);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, sf_names_start_label);
}
static inline void
src_info_attribute (src_info_start_label)
register char *src_info_start_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_src_info);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, src_info_start_label);
}
static inline void
mac_info_attribute (mac_info_start_label)
register char *mac_info_start_label;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_mac_info);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, mac_info_start_label);
}
static inline void
prototyped_attribute (func_type)
register tree func_type;
{
if ((strcmp (language_string, "GNU C") == 0)
&& (TYPE_ARG_TYPES (func_type) != NULL))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_prototyped);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
static inline void
producer_attribute (producer)
register char *producer;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_producer);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, producer);
}
static inline void
inline_attribute (decl)
register tree decl;
{
if (DECL_INLINE (decl))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_inline);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
static inline void
containing_type_attribute (containing_type)
register tree containing_type;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_containing_type);
sprintf (label, TYPE_NAME_FMT, TYPE_UID (containing_type));
ASM_OUTPUT_DWARF_REF (asm_out_file, label);
}
static inline void
abstract_origin_attribute (origin)
register tree origin;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_abstract_origin);
switch (TREE_CODE_CLASS (TREE_CODE (origin)))
{
case 'd':
sprintf (label, DECL_NAME_FMT, DECL_UID (origin));
break;
case 't':
sprintf (label, TYPE_NAME_FMT, TYPE_UID (origin));
break;
default:
abort ();
}
ASM_OUTPUT_DWARF_REF (asm_out_file, label);
}
#ifdef DWARF_DECL_COORDINATES
static inline void
src_coords_attribute (src_fileno, src_lineno)
register unsigned src_fileno;
register unsigned src_lineno;
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_src_coords);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, src_fileno);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, src_lineno);
}
#endif
static inline void
pure_or_virtual_attribute (func_decl)
register tree func_decl;
{
if (DECL_VIRTUAL_P (func_decl))
{
#if 0
if (DECL_ABSTRACT_VIRTUAL_P (func_decl))
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
else
#endif
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
static void
name_and_src_coords_attributes (decl)
register tree decl;
{
register tree decl_name = DECL_NAME (decl);
if (decl_name && IDENTIFIER_POINTER (decl_name))
{
name_attribute (IDENTIFIER_POINTER (decl_name));
#ifdef DWARF_DECL_COORDINATES
{
register unsigned file_index;
ASM_OUTPUT_POP_SECTION (asm_out_file);
file_index = lookup_filename (DECL_SOURCE_FILE (decl));
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
}
#endif
}
}
static void
type_attribute (type, decl_const, decl_volatile)
register tree type;
register int decl_const;
register int decl_volatile;
{
register enum tree_code code = TREE_CODE (type);
register int root_type_modified;
if (code == ERROR_MARK)
return;
if (code == VOID_TYPE)
return;
while ((code == INTEGER_TYPE || code == REAL_TYPE)
&& TREE_TYPE (type) != 0)
type = TREE_TYPE (type), code = TREE_CODE (type);
root_type_modified = (code == POINTER_TYPE || code == REFERENCE_TYPE
|| decl_const || decl_volatile
|| TYPE_READONLY (type) || TYPE_VOLATILE (type));
if (type_is_fundamental (root_type (type)))
{
if (root_type_modified)
mod_fund_type_attribute (type, decl_const, decl_volatile);
else
fund_type_attribute (fundamental_type_code (type));
}
else
{
if (root_type_modified)
mod_u_d_type_attribute (type, decl_const, decl_volatile);
else
user_def_type_attribute (type_main_variant (type));
}
}
static char *
type_tag (type)
register tree type;
{
register char *name = 0;
if (TYPE_NAME (type) != 0)
{
register tree t = 0;
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
t = DECL_NAME (TYPE_NAME (type));
if (t != 0)
name = IDENTIFIER_POINTER (t);
}
return (name == 0 || *name == '\0') ? 0 : name;
}
static inline void
dienum_push ()
{
if (pending_siblings == pending_siblings_allocated)
{
pending_siblings_allocated += PENDING_SIBLINGS_INCREMENT;
pending_sibling_stack
= (unsigned *) xrealloc (pending_sibling_stack,
pending_siblings_allocated * sizeof(unsigned));
}
pending_siblings++;
NEXT_DIE_NUM = next_unused_dienum++;
}
static inline void
dienum_pop ()
{
pending_siblings--;
}
static inline tree
member_declared_type (member)
register tree member;
{
return (DECL_BIT_FIELD_TYPE (member))
? DECL_BIT_FIELD_TYPE (member)
: TREE_TYPE (member);
}
static char *
function_start_label (decl)
register tree decl;
{
rtx x;
char *fnname;
x = DECL_RTL (decl);
if (GET_CODE (x) != MEM)
abort ();
x = XEXP (x, 0);
if (GET_CODE (x) != SYMBOL_REF)
abort ();
fnname = XSTR (x, 0);
return fnname;
}
static void
output_array_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_array_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
#ifdef USE_ORDERING_ATTRIBUTE
ordering_attribute (ORD_row_major);
#endif
subscript_data_attribute (type);
}
static void
output_set_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_set_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
type_attribute (TREE_TYPE (type), 0, 0);
}
#if 0
static void
output_entry_point_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_entry_point);
sibling_attribute ();
dienum_push ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
name_and_src_coords_attributes (decl);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (TREE_TYPE (decl)), 0, 0);
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
low_pc_attribute (function_start_label (decl));
}
#endif
static void
output_inlined_enumeration_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_enumeration_type);
sibling_attribute ();
if (!TREE_ASM_WRITTEN (type))
abort ();
abstract_origin_attribute (type);
}
static void
output_inlined_structure_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_structure_type);
sibling_attribute ();
if (!TREE_ASM_WRITTEN (type))
abort ();
abstract_origin_attribute (type);
}
static void
output_inlined_union_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_union_type);
sibling_attribute ();
if (!TREE_ASM_WRITTEN (type))
abort ();
abstract_origin_attribute (type);
}
static void
output_enumeration_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_enumeration_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
name_attribute (type_tag (type));
member_attribute (TYPE_CONTEXT (type));
if (TYPE_SIZE (type))
{
byte_size_attribute (type);
element_list_attribute (TYPE_FIELDS (type));
}
}
static void
output_formal_parameter_die (arg)
register void *arg;
{
register tree node = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_formal_parameter);
sibling_attribute ();
switch (TREE_CODE_CLASS (TREE_CODE (node)))
{
case 'd':
{
register tree origin = decl_ultimate_origin (node);
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
name_and_src_coords_attributes (node);
type_attribute (TREE_TYPE (node),
TREE_READONLY (node), TREE_THIS_VOLATILE (node));
}
if (DECL_ABSTRACT (node))
equate_decl_number_to_die_number (node);
else
location_or_const_value_attribute (node);
}
break;
case 't':
type_attribute (node, 0, 0);
break;
default:
abort ();
}
}
static void
output_global_subroutine_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_subroutine);
sibling_attribute ();
dienum_push ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
register tree type = TREE_TYPE (decl);
name_and_src_coords_attributes (decl);
inline_attribute (decl);
prototyped_attribute (type);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (type), 0, 0);
pure_or_virtual_attribute (decl);
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
{
if (! DECL_EXTERNAL (decl) && ! in_class
&& decl == current_function_decl)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
}
}
}
}
static void
output_global_variable_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_global_variable);
sibling_attribute ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
name_and_src_coords_attributes (decl);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
{
if (! DECL_EXTERNAL (decl) && ! in_class
&& current_function_decl == decl_function_context (decl))
location_or_const_value_attribute (decl);
}
}
static void
output_label_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_label);
sibling_attribute ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
name_and_src_coords_attributes (decl);
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
{
register rtx insn = DECL_RTL (decl);
if (GET_CODE (insn) == CODE_LABEL
|| ((GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (INSN_DELETED_P (insn))
abort ();
sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
(unsigned) INSN_UID (insn));
low_pc_attribute (label);
}
}
}
static void
output_lexical_block_die (arg)
register void *arg;
{
register tree stmt = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_lexical_block);
sibling_attribute ();
dienum_push ();
if (! BLOCK_ABSTRACT (stmt))
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
low_pc_attribute (begin_label);
sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
high_pc_attribute (end_label);
}
}
static void
output_inlined_subroutine_die (arg)
register void *arg;
{
register tree stmt = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inlined_subroutine);
sibling_attribute ();
dienum_push ();
abstract_origin_attribute (block_ultimate_origin (stmt));
if (! BLOCK_ABSTRACT (stmt))
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (begin_label, BLOCK_BEGIN_LABEL_FMT, next_block_number);
low_pc_attribute (begin_label);
sprintf (end_label, BLOCK_END_LABEL_FMT, next_block_number);
high_pc_attribute (end_label);
}
}
static void
output_local_variable_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_local_variable);
sibling_attribute ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
name_and_src_coords_attributes (decl);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
location_or_const_value_attribute (decl);
}
static void
output_member_die (arg)
register void *arg;
{
register tree decl = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_member);
sibling_attribute ();
name_and_src_coords_attributes (decl);
member_attribute (DECL_CONTEXT (decl));
type_attribute (member_declared_type (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
if (DECL_BIT_FIELD_TYPE (decl))
{
byte_size_attribute (decl);
bit_size_attribute (decl);
bit_offset_attribute (decl);
}
data_member_location_attribute (decl);
}
#if 0
static void
output_pointer_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_pointer_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
type_attribute (TREE_TYPE (type), 0, 0);
}
static void
output_reference_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_reference_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
type_attribute (TREE_TYPE (type), 0, 0);
}
#endif
static void
output_ptr_to_mbr_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_ptr_to_member_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
containing_type_attribute (TYPE_OFFSET_BASETYPE (type));
type_attribute (TREE_TYPE (type), 0, 0);
}
static void
output_compile_unit_die (arg)
register void *arg;
{
register char *main_input_filename = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_compile_unit);
sibling_attribute ();
dienum_push ();
name_attribute (main_input_filename);
{
char producer[250];
sprintf (producer, "%s %s", language_string, version_string);
producer_attribute (producer);
}
if (strcmp (language_string, "GNU C++") == 0)
language_attribute (LANG_C_PLUS_PLUS);
else if (strcmp (language_string, "GNU Ada") == 0)
language_attribute (LANG_ADA83);
else if (strcmp (language_string, "GNU F77") == 0)
language_attribute (LANG_FORTRAN77);
else if (strcmp (language_string, "GNU Pascal") == 0)
language_attribute (LANG_PASCAL83);
else if (flag_traditional)
language_attribute (LANG_C);
else
language_attribute (LANG_C89);
low_pc_attribute (TEXT_BEGIN_LABEL);
high_pc_attribute (TEXT_END_LABEL);
if (debug_info_level >= DINFO_LEVEL_NORMAL)
stmt_list_attribute (LINE_BEGIN_LABEL);
last_filename = xstrdup (main_input_filename);
{
char *wd = getpwd ();
if (wd)
comp_dir_attribute (wd);
}
if (debug_info_level >= DINFO_LEVEL_NORMAL && use_gnu_debug_info_extensions)
{
sf_names_attribute (SFNAMES_BEGIN_LABEL);
src_info_attribute (SRCINFO_BEGIN_LABEL);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
mac_info_attribute (MACINFO_BEGIN_LABEL);
}
}
static void
output_string_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_string_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
member_attribute (TYPE_CONTEXT (type));
byte_size_attribute (type);
}
static void
output_inheritance_die (arg)
register void *arg;
{
register tree binfo = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
sibling_attribute ();
type_attribute (BINFO_TYPE (binfo), 0, 0);
data_member_location_attribute (binfo);
if (TREE_VIA_VIRTUAL (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
if (TREE_VIA_PUBLIC (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
else if (TREE_VIA_PROTECTED (binfo))
{
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
static void
output_structure_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_structure_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
name_attribute (type_tag (type));
member_attribute (TYPE_CONTEXT (type));
if (TYPE_SIZE (type))
{
dienum_push ();
byte_size_attribute (type);
}
}
static void
output_local_subroutine_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine);
sibling_attribute ();
dienum_push ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
register tree type = TREE_TYPE (decl);
name_and_src_coords_attributes (decl);
inline_attribute (decl);
prototyped_attribute (type);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (type), 0, 0);
pure_or_virtual_attribute (decl);
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
else
{
if (TREE_ASM_WRITTEN (decl))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
}
}
}
}
static void
output_subroutine_type_die (arg)
register void *arg;
{
register tree type = arg;
register tree return_type = TREE_TYPE (type);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_subroutine_type);
sibling_attribute ();
dienum_push ();
equate_type_number_to_die_number (type);
prototyped_attribute (type);
member_attribute (TYPE_CONTEXT (type));
type_attribute (return_type, 0, 0);
}
static void
output_typedef_die (arg)
register void *arg;
{
register tree decl = arg;
register tree origin = decl_ultimate_origin (decl);
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_typedef);
sibling_attribute ();
if (origin != NULL)
abstract_origin_attribute (origin);
else
{
name_and_src_coords_attributes (decl);
member_attribute (DECL_CONTEXT (decl));
type_attribute (TREE_TYPE (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
}
if (DECL_ABSTRACT (decl))
equate_decl_number_to_die_number (decl);
}
static void
output_union_type_die (arg)
register void *arg;
{
register tree type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_union_type);
sibling_attribute ();
equate_type_number_to_die_number (type);
name_attribute (type_tag (type));
member_attribute (TYPE_CONTEXT (type));
if (TYPE_SIZE (type))
{
dienum_push ();
byte_size_attribute (type);
}
}
static void
output_unspecified_parameters_die (arg)
register void *arg;
{
register tree decl_or_type = arg;
ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_unspecified_parameters);
sibling_attribute ();
if (TREE_CODE (decl_or_type) == FUNCTION_DECL && DECL_INITIAL (decl_or_type))
{
name_attribute ("...");
fund_type_attribute (FT_pointer);
}
}
static void
output_padded_null_die (arg)
register void *arg ATTRIBUTE_UNUSED;
{
ASM_OUTPUT_ALIGN (asm_out_file, 2);
}
static void
output_die (die_specific_output_function, param)
register void (*die_specific_output_function) PROTO ((void *));
register void *param;
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
current_dienum = NEXT_DIE_NUM;
NEXT_DIE_NUM = next_unused_dienum;
sprintf (begin_label, DIE_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, DIE_END_LABEL_FMT, current_dienum);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, end_label, begin_label);
next_unused_dienum++;
die_specific_output_function (param);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
static void
end_sibling_chain ()
{
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
current_dienum = NEXT_DIE_NUM;
NEXT_DIE_NUM = next_unused_dienum;
sprintf (begin_label, DIE_BEGIN_LABEL_FMT, current_dienum);
ASM_OUTPUT_LABEL (asm_out_file, begin_label);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 4);
dienum_pop ();
}
static void
output_formal_types (function_or_method_type)
register tree function_or_method_type;
{
register tree link;
register tree formal_type = NULL;
register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
int save_asm_written = TREE_ASM_WRITTEN (function_or_method_type);
TREE_ASM_WRITTEN (function_or_method_type) = 1;
if (TREE_CODE (function_or_method_type) == METHOD_TYPE)
first_parm_type = TREE_CHAIN (first_parm_type);
for (link = first_parm_type; link; link = TREE_CHAIN (link))
{
formal_type = TREE_VALUE (link);
if (formal_type == void_type_node)
break;
output_die (output_formal_parameter_die, formal_type);
}
if (formal_type != void_type_node)
output_die (output_unspecified_parameters_die, function_or_method_type);
for (link = TYPE_ARG_TYPES (function_or_method_type);
link;
link = TREE_CHAIN (link))
{
formal_type = TREE_VALUE (link);
if (formal_type == void_type_node)
break;
output_type (formal_type, function_or_method_type);
}
TREE_ASM_WRITTEN (function_or_method_type) = save_asm_written;
}
static void
pend_type (type)
register tree type;
{
if (pending_types == pending_types_allocated)
{
pending_types_allocated += PENDING_TYPES_INCREMENT;
pending_types_list
= (tree *) xrealloc (pending_types_list,
sizeof (tree) * pending_types_allocated);
}
pending_types_list[pending_types++] = type;
TREE_ASM_WRITTEN (type) = 1;
}
static inline int
type_ok_for_scope (type, scope)
register tree type;
register tree scope;
{
return is_tagged_type (type)
? (TYPE_CONTEXT (type) == scope
|| (scope == NULL_TREE
&& TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL)
|| (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
&& TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
: (scope == NULL_TREE || ! is_tagged_type (scope));
}
static void
output_pending_types_for_scope (containing_scope)
register tree containing_scope;
{
register unsigned i;
for (i = 0; i < pending_types; )
{
register tree type = pending_types_list[i];
if (type_ok_for_scope (type, containing_scope))
{
register tree *mover;
register tree *limit;
pending_types--;
limit = &pending_types_list[pending_types];
for (mover = &pending_types_list[i]; mover < limit; mover++)
*mover = *(mover+1);
TREE_ASM_WRITTEN (type) = 0;
output_type (type, containing_scope);
}
else
i++;
}
}
static void
add_incomplete_type (type)
tree type;
{
if (incomplete_types == incomplete_types_allocated)
{
incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT;
incomplete_types_list
= (tree *) xrealloc (incomplete_types_list,
sizeof (tree) * incomplete_types_allocated);
}
incomplete_types_list[incomplete_types++] = type;
}
static void
retry_incomplete_types ()
{
register tree type;
finalizing = 1;
while (incomplete_types)
{
--incomplete_types;
type = incomplete_types_list[incomplete_types];
output_type (type, NULL_TREE);
}
}
static void
output_type (type, containing_scope)
register tree type;
register tree containing_scope;
{
if (type == 0 || type == error_mark_node)
return;
type = type_main_variant (type);
if (TREE_ASM_WRITTEN (type))
{
if (finalizing && AGGREGATE_TYPE_P (type))
{
register tree member;
for (member = TYPE_FIELDS (type); member;
member = TREE_CHAIN (member))
if (TREE_CODE (member) == TYPE_DECL
&& ! TREE_ASM_WRITTEN (TREE_TYPE (member)))
output_type (TREE_TYPE (member), containing_scope);
}
return;
}
if (TYPE_CONTEXT (type)
&& TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
{
output_type (TYPE_CONTEXT (type), containing_scope);
return;
}
if (! type_ok_for_scope (type, containing_scope))
{
pend_type (type);
return;
}
switch (TREE_CODE (type))
{
case ERROR_MARK:
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
TREE_ASM_WRITTEN (type) = 1;
output_type (TREE_TYPE (type), containing_scope);
break;
case OFFSET_TYPE:
output_type (TYPE_OFFSET_BASETYPE (type), containing_scope);
output_type (TREE_TYPE (type), containing_scope);
output_die (output_ptr_to_mbr_type_die, type);
break;
case SET_TYPE:
output_type (TYPE_DOMAIN (type), containing_scope);
output_die (output_set_type_die, type);
break;
case FILE_TYPE:
output_type (TREE_TYPE (type), containing_scope);
abort ();
break;
case FUNCTION_TYPE:
output_type (TREE_TYPE (type), containing_scope);
output_die (output_subroutine_type_die, type);
output_formal_types (type);
end_sibling_chain ();
break;
case METHOD_TYPE:
output_type (TREE_TYPE (type), containing_scope);
output_die (output_subroutine_type_die, type);
output_formal_types (type);
end_sibling_chain ();
break;
case ARRAY_TYPE:
if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE)
{
output_type (TREE_TYPE (type), containing_scope);
output_die (output_string_type_die, type);
}
else
{
register tree element_type;
element_type = TREE_TYPE (type);
while (TREE_CODE (element_type) == ARRAY_TYPE)
element_type = TREE_TYPE (element_type);
output_type (element_type, containing_scope);
output_die (output_array_type_die, type);
}
break;
case ENUMERAL_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
if (TYPE_SIZE (type) == 0
&& (TYPE_CONTEXT (type) == NULL
|| (TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
&& TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_TYPE
&& TREE_CODE (TYPE_CONTEXT (type)) != METHOD_TYPE))
&& !finalizing)
{
if (TREE_PERMANENT (type))
add_incomplete_type (type);
return;
}
TREE_ASM_WRITTEN (type) = 1;
switch (TREE_CODE (type))
{
case ENUMERAL_TYPE:
output_die (output_enumeration_type_die, type);
return;
case RECORD_TYPE:
output_die (output_structure_type_die, type);
break;
case UNION_TYPE:
case QUAL_UNION_TYPE:
output_die (output_union_type_die, type);
break;
default:
abort ();
}
if (TYPE_SIZE (type))
{
if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
{
register tree bases = TYPE_BINFO_BASETYPES (type);
register int n_bases = TREE_VEC_LENGTH (bases);
register int i;
for (i = 0; i < n_bases; i++)
{
tree binfo = TREE_VEC_ELT (bases, i);
output_type (BINFO_TYPE (binfo), containing_scope);
output_die (output_inheritance_die, binfo);
}
}
++in_class;
{
register tree normal_member;
for (normal_member = TYPE_FIELDS (type);
normal_member;
normal_member = TREE_CHAIN (normal_member))
output_decl (normal_member, type);
}
{
register tree func_member;
for (func_member = TYPE_METHODS (type);
func_member;
func_member = TREE_CHAIN (func_member))
output_decl (func_member, type);
}
--in_class;
output_pending_types_for_scope (type);
end_sibling_chain ();
}
break;
case VOID_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case CHAR_TYPE:
break;
case LANG_TYPE:
break;
default:
abort ();
}
TREE_ASM_WRITTEN (type) = 1;
}
static void
output_tagged_type_instantiation (type)
register tree type;
{
if (type == 0 || type == error_mark_node)
return;
if (type != type_main_variant (type))
abort ();
if (!TREE_ASM_WRITTEN (type))
abort ();
switch (TREE_CODE (type))
{
case ERROR_MARK:
break;
case ENUMERAL_TYPE:
output_die (output_inlined_enumeration_type_die, type);
break;
case RECORD_TYPE:
output_die (output_inlined_structure_type_die, type);
break;
case UNION_TYPE:
case QUAL_UNION_TYPE:
output_die (output_inlined_union_type_die, type);
break;
default:
abort ();
}
}
static void
output_block (stmt, depth)
register tree stmt;
int depth;
{
register int must_output_die = 0;
register tree origin;
register enum tree_code origin_code;
if (! stmt || ! TREE_USED (stmt))
return;
origin = block_ultimate_origin (stmt);
origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK;
if (origin_code == FUNCTION_DECL)
must_output_die = 1;
else
{
if (! is_body_block (origin ? origin : stmt))
{
if (debug_info_level > DINFO_LEVEL_TERSE)
must_output_die = (BLOCK_VARS (stmt) != NULL);
else
{
register tree decl;
for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
{
must_output_die = 1;
break;
}
}
}
}
if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
;
else if (must_output_die)
{
output_die ((origin_code == FUNCTION_DECL)
? output_inlined_subroutine_die
: output_lexical_block_die,
stmt);
output_decls_for_scope (stmt, depth);
end_sibling_chain ();
}
else
output_decls_for_scope (stmt, depth);
}
static void
output_decls_for_scope (stmt, depth)
register tree stmt;
int depth;
{
if (! stmt || ! TREE_USED (stmt))
return;
if (! BLOCK_ABSTRACT (stmt) && depth > 0)
next_block_number++;
{
register tree decl;
for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
output_decl (decl, stmt);
}
output_pending_types_for_scope (stmt);
{
register tree subblocks;
for (subblocks = BLOCK_SUBBLOCKS (stmt);
subblocks;
subblocks = BLOCK_CHAIN (subblocks))
output_block (subblocks, depth + 1);
}
}
inline static int
is_redundant_typedef (decl)
register tree decl;
{
if (TYPE_DECL_IS_STUB (decl))
return 1;
if (DECL_ARTIFICIAL (decl)
&& DECL_CONTEXT (decl)
&& is_tagged_type (DECL_CONTEXT (decl))
&& TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
&& DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
return 1;
return 0;
}
static void
output_decl (decl, containing_scope)
register tree decl;
register tree containing_scope;
{
dwarf_last_decl = decl;
if (TREE_CODE (decl) == ERROR_MARK)
return;
if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
&& ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0)
|| (TYPE_FIELDS (TREE_TYPE (decl))
&& (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK))))
return;
if (DECL_IGNORED_P (decl) && TREE_CODE (decl) != FUNCTION_DECL)
return;
switch (TREE_CODE (decl))
{
case CONST_DECL:
break;
case FUNCTION_DECL:
if (DECL_INITIAL (decl) == NULL_TREE)
#if (DWARF_VERSION > 1)
if (debug_info_level <= DINFO_LEVEL_TERSE)
#endif
break;
output_type (TREE_TYPE (TREE_TYPE (decl)), containing_scope);
{
register tree origin = decl_class_context (decl);
if (origin)
output_type (origin, containing_scope);
}
if (TREE_PUBLIC (decl))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number++);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
output_die (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)
? output_global_subroutine_die
: output_local_subroutine_die,
decl);
if (decl != current_function_decl || in_class)
output_formal_types (TREE_TYPE (decl));
else
{
register tree arg_decls = DECL_ARGUMENTS (decl);
register tree parm;
for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME(parm) &&
!strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
"__builtin_va_alist") )
output_die (output_unspecified_parameters_die, decl);
else
output_decl (parm, fake_containing_scope);
}
output_pending_types_for_scope (decl);
{
register tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
if (fn_arg_types)
{
if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
output_die (output_unspecified_parameters_die, decl);
}
else
{
if (!DECL_INITIAL (decl))
output_die (output_unspecified_parameters_die, decl);
}
}
{
register tree outer_scope = DECL_INITIAL (decl);
if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
{
output_decls_for_scope (outer_scope, 0);
output_pending_types_for_scope (decl);
}
}
}
end_sibling_chain ();
break;
case TYPE_DECL:
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
return;
if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
{
output_tagged_type_instantiation (TREE_TYPE (decl));
return;
}
output_type (TREE_TYPE (decl), containing_scope);
if (! is_redundant_typedef (decl))
output_die (output_typedef_die, decl);
break;
case LABEL_DECL:
if (debug_info_level >= DINFO_LEVEL_NORMAL)
output_die (output_label_die, decl);
break;
case VAR_DECL:
#if (DWARF_VERSION <= 1)
if (DECL_EXTERNAL (decl) && ! TREE_PUBLIC (decl))
break;
#endif
if (debug_info_level <= DINFO_LEVEL_TERSE)
break;
output_type (TREE_TYPE (decl), containing_scope);
{
register tree origin = decl_class_context (decl);
if (origin)
output_type (origin, containing_scope);
}
if (TREE_PUBLIC (decl) && ! DECL_ABSTRACT (decl))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number++);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
{
register void (*func) PROTO((void *));
register tree origin = decl_ultimate_origin (decl);
if (origin != NULL && TREE_CODE (origin) == PARM_DECL)
func = output_formal_parameter_die;
else
{
if (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
func = output_global_variable_die;
else
func = output_local_variable_die;
}
output_die (func, decl);
}
break;
case FIELD_DECL:
if (DECL_NAME (decl) != 0)
{
output_type (member_declared_type (decl), containing_scope);
output_die (output_member_die, decl);
}
break;
case PARM_DECL:
output_type (TREE_TYPE (decl), containing_scope);
output_die (output_formal_parameter_die, decl);
break;
default:
abort ();
}
}
void
dwarfout_file_scope_decl (decl, set_finalizing)
register tree decl;
register int set_finalizing;
{
if (TREE_CODE (decl) == ERROR_MARK)
return;
if (DECL_IGNORED_P (decl))
{
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL)
abort ();
return;
}
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
return;
if (DECL_INITIAL (decl) == NULL_TREE)
return;
if (TREE_PUBLIC (decl)
&& ! DECL_EXTERNAL (decl)
&& ! DECL_ABSTRACT (decl))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (DECL_NAME (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
break;
case VAR_DECL:
if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
return;
if (TREE_PUBLIC (decl)
&& ! DECL_EXTERNAL (decl)
&& GET_CODE (DECL_RTL (decl)) == MEM
&& ! DECL_ABSTRACT (decl))
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
sprintf (label, PUB_DIE_LABEL_FMT, next_pubname_number);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, label);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
IDENTIFIER_POINTER (DECL_NAME (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (DECL_INITIAL (decl) == NULL)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, ARANGES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) int_size_in_bytes (TREE_TYPE (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
}
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
break;
case TYPE_DECL:
if (DECL_SOURCE_LINE (decl) == 0
&& (type_is_fundamental (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == LANG_TYPE))
return;
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
return;
break;
default:
return;
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
finalizing = set_finalizing;
output_decl (decl, NULL_TREE);
output_pending_types_for_scope (NULL_TREE);
if (! DECL_CONTEXT (decl))
{
if (pending_types != 0)
abort ();
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL)
current_funcdef_number++;
}
void
dwarfout_begin_block (blocknum)
register unsigned blocknum;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
function_section (current_function_decl);
sprintf (label, BLOCK_BEGIN_LABEL_FMT, blocknum);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
void
dwarfout_end_block (blocknum)
register unsigned blocknum;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
function_section (current_function_decl);
sprintf (label, BLOCK_END_LABEL_FMT, blocknum);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
void
dwarfout_label (insn)
register rtx insn;
{
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
function_section (current_function_decl);
sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
(unsigned) INSN_UID (insn));
ASM_OUTPUT_LABEL (asm_out_file, label);
}
}
void
dwarfout_begin_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
void
dwarfout_end_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
void
dwarfout_end_epilogue ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
static void
shuffle_filename_entry (new_zeroth)
register filename_entry *new_zeroth;
{
filename_entry temp_entry;
register filename_entry *limit_p;
register filename_entry *move_p;
if (new_zeroth == &filename_table[0])
return;
temp_entry = *new_zeroth;
limit_p = &filename_table[0];
for (move_p = new_zeroth; move_p > limit_p; move_p--)
*move_p = *(move_p-1);
filename_table[0] = temp_entry;
}
static void
generate_new_sfname_entry ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
filename_table[0].name
? filename_table[0].name
: "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
static unsigned
lookup_filename (file_name)
char *file_name;
{
register filename_entry *search_p;
register filename_entry *limit_p = &filename_table[ft_entries];
for (search_p = filename_table; search_p < limit_p; search_p++)
if (!strcmp (file_name, search_p->name))
{
shuffle_filename_entry (search_p);
return filename_table[0].number;
}
if (ft_entries == ft_entries_allocated)
{
ft_entries_allocated += FT_ENTRIES_INCREMENT;
filename_table
= (filename_entry *)
xrealloc (filename_table,
ft_entries_allocated * sizeof (filename_entry));
}
filename_table[ft_entries].number = ft_entries;
filename_table[ft_entries].name = xstrdup (file_name);
shuffle_filename_entry (&filename_table[ft_entries]);
if (debug_info_level >= DINFO_LEVEL_NORMAL)
generate_new_sfname_entry ();
ft_entries++;
return filename_table[0].number;
}
static void
generate_srcinfo_entry (line_entry_num, files_entry_num)
unsigned line_entry_num;
unsigned files_entry_num;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
sprintf (label, LINE_ENTRY_LABEL_FMT, line_entry_num);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, label, LINE_BEGIN_LABEL);
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, files_entry_num);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, label, SFNAMES_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
void
dwarfout_line (filename, line)
register char *filename;
register unsigned line;
{
if (debug_info_level >= DINFO_LEVEL_NORMAL
&& DECL_SECTION_NAME (current_function_decl) == NULL_TREE)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
static unsigned last_line_entry_num = 0;
static unsigned prev_file_entry_num = (unsigned) -1;
register unsigned this_file_entry_num;
function_section (current_function_decl);
sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
ASM_OUTPUT_LABEL (asm_out_file, label);
fputc ('\n', asm_out_file);
if (use_gnu_debug_info_extensions)
this_file_entry_num = lookup_filename (filename);
else
this_file_entry_num = (unsigned) -1;
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
if (this_file_entry_num != prev_file_entry_num)
{
char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num);
ASM_OUTPUT_LABEL (asm_out_file, line_entry_label);
}
{
register char *tail = rindex (filename, '/');
if (tail != NULL)
filename = tail;
}
fprintf (asm_out_file, "\t%s\t%u\t%s %s:%u\n",
UNALIGNED_INT_ASM_OP, line, ASM_COMMENT_START,
filename, line);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0xffff);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, label, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (this_file_entry_num != prev_file_entry_num)
generate_srcinfo_entry (last_line_entry_num, this_file_entry_num);
prev_file_entry_num = this_file_entry_num;
}
}
static void
generate_macinfo_entry (type_and_offset, string)
register char *type_and_offset;
register char *string;
{
if (! use_gnu_debug_info_extensions)
return;
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, string);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
void
dwarfout_start_new_source_file (filename)
register char *filename;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
char type_and_offset[MAX_ARTIFICIAL_LABEL_BYTES*3];
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, lookup_filename (filename));
sprintf (type_and_offset, "0x%08x+%s-%s",
((unsigned) MACINFO_start << 24),
(*label == '*') + label,
(*SFNAMES_BEGIN_LABEL == '*') + SFNAMES_BEGIN_LABEL);
generate_macinfo_entry (type_and_offset, "");
}
void
dwarfout_resume_previous_source_file (lineno)
register unsigned lineno;
{
char type_and_offset[MAX_ARTIFICIAL_LABEL_BYTES*2];
sprintf (type_and_offset, "0x%08x+%u",
((unsigned) MACINFO_resume << 24), lineno);
generate_macinfo_entry (type_and_offset, "");
}
void
dwarfout_define (lineno, buffer)
register unsigned lineno;
register char *buffer;
{
static int initialized = 0;
char type_and_offset[MAX_ARTIFICIAL_LABEL_BYTES*2];
if (!initialized)
{
dwarfout_start_new_source_file (primary_filename);
initialized = 1;
}
sprintf (type_and_offset, "0x%08x+%u",
((unsigned) MACINFO_define << 24), lineno);
generate_macinfo_entry (type_and_offset, buffer);
}
void
dwarfout_undef (lineno, buffer)
register unsigned lineno;
register char *buffer;
{
char type_and_offset[MAX_ARTIFICIAL_LABEL_BYTES*2];
sprintf (type_and_offset, "0x%08x+%u",
((unsigned) MACINFO_undef << 24), lineno);
generate_macinfo_entry (type_and_offset, buffer);
}
void
dwarfout_init (asm_out_file, main_input_filename)
register FILE *asm_out_file;
register char *main_input_filename;
{
primary_filename = main_input_filename;
pending_sibling_stack
= (unsigned *)
xmalloc (PENDING_SIBLINGS_INCREMENT * sizeof (unsigned));
pending_siblings_allocated = PENDING_SIBLINGS_INCREMENT;
pending_siblings = 1;
filename_table
= (filename_entry *)
xmalloc (FT_ENTRIES_INCREMENT * sizeof (filename_entry));
ft_entries_allocated = FT_ENTRIES_INCREMENT;
ft_entries = 0;
pending_types_list
= (tree *) xmalloc (PENDING_TYPES_INCREMENT * sizeof (tree));
pending_types_allocated = PENDING_TYPES_INCREMENT;
pending_types = 0;
fake_containing_scope = make_node (RECORD_TYPE);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, TEXT_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, DATA_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#if 0
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, DATA1_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#endif
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, RODATA_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#if 0
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, RODATA1_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#endif
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, BSS_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, BSS_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
if (use_gnu_debug_info_extensions)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
{
register char *pwd;
register unsigned len;
register char *dirname;
pwd = getpwd ();
if (!pwd)
pfatal_with_name ("getpwd");
len = strlen (pwd);
dirname = (char *) xmalloc (len + 2);
strcpy (dirname, pwd);
strcpy (dirname + len, "/");
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, dirname);
free (dirname);
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (debug_info_level >= DINFO_LEVEL_VERBOSE
&& use_gnu_debug_info_extensions)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, LINE_END_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (use_gnu_debug_info_extensions)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
#ifdef DWARF_TIMESTAMPS
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
#else
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
#endif
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DEBUG_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, ARANGES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DEBUG_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
NEXT_DIE_NUM = next_unused_dienum++;
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, DEBUG_BEGIN_LABEL);
output_die (output_compile_unit_die, main_input_filename);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
}
void
dwarfout_finish ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
retry_incomplete_types ();
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
output_die (output_padded_null_die, (void *) 0);
dienum_pop ();
sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, TEXT_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, TEXT_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, DATA_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#if 0
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, DATA1_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#endif
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, RODATA_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#if 0
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, RODATA1_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
#endif
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, BSS_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, BSS_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_LAST_ENTRY_LABEL);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 0xffff);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, TEXT_END_LABEL, TEXT_BEGIN_LABEL);
ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (use_gnu_debug_info_extensions)
{
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
dwarfout_resume_previous_source_file (0);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, ARANGES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, TEXT_END_LABEL, TEXT_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA_END_LABEL, DATA_BEGIN_LABEL);
#if 0
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA1_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA1_END_LABEL,
DATA1_BEGIN_LABEL);
#endif
ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA_END_LABEL,
RODATA_BEGIN_LABEL);
#if 0
ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA1_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA1_END_LABEL,
RODATA1_BEGIN_LABEL);
#endif
ASM_OUTPUT_DWARF_ADDR (asm_out_file, BSS_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, BSS_END_LABEL, BSS_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (pending_types != 0)
abort ();
}
#endif