dwarf2out.c revision 96263
150397Sobrien/* Output Dwarf2 format symbol table information from the GNU C compiler. 290075Sobrien Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 390075Sobrien Free Software Foundation, Inc. 450397Sobrien Contributed by Gary Funck (gary@intrepid.com). 550397Sobrien Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). 650397Sobrien Extensively modified by Jason Merrill (jason@cygnus.com). 750397Sobrien 890075SobrienThis file is part of GCC. 950397Sobrien 1090075SobrienGCC is free software; you can redistribute it and/or modify it under 1190075Sobrienthe terms of the GNU General Public License as published by the Free 1290075SobrienSoftware Foundation; either version 2, or (at your option) any later 1390075Sobrienversion. 1450397Sobrien 1590075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1690075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1790075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1890075Sobrienfor more details. 1950397Sobrien 2050397SobrienYou should have received a copy of the GNU General Public License 2190075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 2290075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2390075Sobrien02111-1307, USA. */ 2450397Sobrien 2590075Sobrien/* TODO: Emit .debug_line header even when there are no functions, since 2690075Sobrien the file numbers are used by .debug_info. Alternately, leave 2790075Sobrien out locations for types and decls. 2890075Sobrien Avoid talking about ctors and op= for PODs. 2990075Sobrien Factor out common prologue sequences into multiple CIEs. */ 3090075Sobrien 3150397Sobrien/* The first part of this file deals with the DWARF 2 frame unwind 3250397Sobrien information, which is also used by the GCC efficient exception handling 3350397Sobrien mechanism. The second part, controlled only by an #ifdef 3450397Sobrien DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging 3550397Sobrien information. */ 3650397Sobrien 3750397Sobrien#include "config.h" 3850397Sobrien#include "system.h" 3950397Sobrien#include "tree.h" 4050397Sobrien#include "flags.h" 4150397Sobrien#include "rtl.h" 4250397Sobrien#include "hard-reg-set.h" 4350397Sobrien#include "regs.h" 4450397Sobrien#include "insn-config.h" 4550397Sobrien#include "reload.h" 4690075Sobrien#include "function.h" 4750397Sobrien#include "output.h" 4850397Sobrien#include "expr.h" 4990075Sobrien#include "libfuncs.h" 5050397Sobrien#include "except.h" 5150397Sobrien#include "dwarf2.h" 5250397Sobrien#include "dwarf2out.h" 5390075Sobrien#include "dwarf2asm.h" 5450397Sobrien#include "toplev.h" 5590075Sobrien#include "varray.h" 5690075Sobrien#include "ggc.h" 5790075Sobrien#include "md5.h" 5890075Sobrien#include "tm_p.h" 5990075Sobrien#include "diagnostic.h" 6090075Sobrien#include "debug.h" 6190075Sobrien#include "target.h" 6290075Sobrien#include "langhooks.h" 6390075Sobrien#include "hashtable.h" 6450397Sobrien 6590075Sobrien#ifdef DWARF2_DEBUGGING_INFO 6690075Sobrienstatic void dwarf2out_source_line PARAMS ((unsigned int, const char *)); 6750397Sobrien#endif 6850397Sobrien 6990075Sobrien/* DWARF2 Abbreviation Glossary: 7090075Sobrien CFA = Canonical Frame Address 7190075Sobrien a fixed address on the stack which identifies a call frame. 7290075Sobrien We define it to be the value of SP just before the call insn. 7390075Sobrien The CFA register and offset, which may change during the course 7490075Sobrien of the function, are used to calculate its value at runtime. 7590075Sobrien CFI = Call Frame Instruction 7690075Sobrien an instruction for the DWARF2 abstract machine 7790075Sobrien CIE = Common Information Entry 7890075Sobrien information describing information common to one or more FDEs 7990075Sobrien DIE = Debugging Information Entry 8090075Sobrien FDE = Frame Description Entry 8190075Sobrien information describing the stack call frame, in particular, 8290075Sobrien how to restore registers 8390075Sobrien 8490075Sobrien DW_CFA_... = DWARF2 CFA call frame instruction 8590075Sobrien DW_TAG_... = DWARF2 DIE tag */ 8690075Sobrien 8750397Sobrien/* Decide whether we want to emit frame unwind information for the current 8850397Sobrien translation unit. */ 8950397Sobrien 9050397Sobrienint 9150397Sobriendwarf2out_do_frame () 9250397Sobrien{ 9350397Sobrien return (write_symbols == DWARF2_DEBUG 9490075Sobrien || write_symbols == VMS_AND_DWARF2_DEBUG 9550397Sobrien#ifdef DWARF2_FRAME_INFO 9690075Sobrien || DWARF2_FRAME_INFO 9750397Sobrien#endif 9850397Sobrien#ifdef DWARF2_UNWIND_INFO 9990075Sobrien || flag_unwind_tables 10090075Sobrien || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS) 10150397Sobrien#endif 10250397Sobrien ); 10350397Sobrien} 10450397Sobrien 10590075Sobrien/* The number of the current function definition for which debugging 10690075Sobrien information is being generated. These numbers range from 1 up to the 10790075Sobrien maximum number of function definitions contained within the current 10890075Sobrien compilation unit. These numbers are used to create unique label id's 10990075Sobrien unique to each function definition. */ 11090075Sobrienunsigned current_funcdef_number = 0; 11190075Sobrien 11290075Sobrien/* The size of the target's pointer type. */ 11390075Sobrien#ifndef PTR_SIZE 11490075Sobrien#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT) 11590075Sobrien#endif 11690075Sobrien 11790075Sobrien/* Default version of targetm.eh_frame_section. Note this must appear 11890075Sobrien outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro 11990075Sobrien guards. */ 12090075Sobrien 12190075Sobrienvoid 12290075Sobriendefault_eh_frame_section () 12390075Sobrien{ 12490075Sobrien#ifdef EH_FRAME_SECTION_NAME 12590075Sobrien named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE); 12690075Sobrien#else 12790075Sobrien tree label = get_file_function_name ('F'); 12890075Sobrien 12990075Sobrien data_section (); 13090075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 13190075Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 13290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 13390075Sobrien#endif 13490075Sobrien} 13590075Sobrien 13650397Sobrien#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) 13750397Sobrien 13850397Sobrien/* How to start an assembler comment. */ 13950397Sobrien#ifndef ASM_COMMENT_START 14050397Sobrien#define ASM_COMMENT_START ";#" 14150397Sobrien#endif 14250397Sobrien 14350397Sobrientypedef struct dw_cfi_struct *dw_cfi_ref; 14450397Sobrientypedef struct dw_fde_struct *dw_fde_ref; 14550397Sobrientypedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref; 14650397Sobrien 14750397Sobrien/* Call frames are described using a sequence of Call Frame 14850397Sobrien Information instructions. The register number, offset 14950397Sobrien and address fields are provided as possible operands; 15050397Sobrien their use is selected by the opcode field. */ 15150397Sobrien 15250397Sobrientypedef union dw_cfi_oprnd_struct 15350397Sobrien{ 15450397Sobrien unsigned long dw_cfi_reg_num; 15550397Sobrien long int dw_cfi_offset; 15690075Sobrien const char *dw_cfi_addr; 15790075Sobrien struct dw_loc_descr_struct *dw_cfi_loc; 15850397Sobrien} 15950397Sobriendw_cfi_oprnd; 16050397Sobrien 16150397Sobrientypedef struct dw_cfi_struct 16250397Sobrien{ 16350397Sobrien dw_cfi_ref dw_cfi_next; 16450397Sobrien enum dwarf_call_frame_info dw_cfi_opc; 16550397Sobrien dw_cfi_oprnd dw_cfi_oprnd1; 16650397Sobrien dw_cfi_oprnd dw_cfi_oprnd2; 16750397Sobrien} 16850397Sobriendw_cfi_node; 16950397Sobrien 17090075Sobrien/* This is how we define the location of the CFA. We use to handle it 17190075Sobrien as REG + OFFSET all the time, but now it can be more complex. 17290075Sobrien It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET. 17390075Sobrien Instead of passing around REG and OFFSET, we pass a copy 17490075Sobrien of this structure. */ 17590075Sobrientypedef struct cfa_loc 17690075Sobrien{ 17790075Sobrien unsigned long reg; 17890075Sobrien long offset; 17990075Sobrien long base_offset; 18090075Sobrien int indirect; /* 1 if CFA is accessed via a dereference. */ 18190075Sobrien} dw_cfa_location; 18290075Sobrien 18350397Sobrien/* All call frame descriptions (FDE's) in the GCC generated DWARF 18450397Sobrien refer to a single Common Information Entry (CIE), defined at 18590075Sobrien the beginning of the .debug_frame section. This use of a single 18650397Sobrien CIE obviates the need to keep track of multiple CIE's 18750397Sobrien in the DWARF generation routines below. */ 18850397Sobrien 18950397Sobrientypedef struct dw_fde_struct 19050397Sobrien{ 19190075Sobrien const char *dw_fde_begin; 19290075Sobrien const char *dw_fde_current_label; 19390075Sobrien const char *dw_fde_end; 19450397Sobrien dw_cfi_ref dw_fde_cfi; 19590075Sobrien unsigned funcdef_number; 19690075Sobrien unsigned nothrow : 1; 19790075Sobrien unsigned uses_eh_lsda : 1; 19850397Sobrien} 19950397Sobriendw_fde_node; 20050397Sobrien 20190075Sobrien/* Maximum size (in bytes) of an artificially generated label. */ 20250397Sobrien#define MAX_ARTIFICIAL_LABEL_BYTES 30 20350397Sobrien 20490075Sobrien/* The size of addresses as they appear in the Dwarf 2 data. 20590075Sobrien Some architectures use word addresses to refer to code locations, 20690075Sobrien but Dwarf 2 info always uses byte addresses. On such machines, 20790075Sobrien Dwarf 2 addresses need to be larger than the architecture's 20890075Sobrien pointers. */ 20990075Sobrien#ifndef DWARF2_ADDR_SIZE 21090075Sobrien#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT) 21150397Sobrien#endif 21250397Sobrien 21350397Sobrien/* The size in bytes of a DWARF field indicating an offset or length 21490075Sobrien relative to a debug info section, specified to be 4 bytes in the 21590075Sobrien DWARF-2 specification. The SGI/MIPS ABI defines it to be the same 21690075Sobrien as PTR_SIZE. */ 21750397Sobrien 21850397Sobrien#ifndef DWARF_OFFSET_SIZE 21950397Sobrien#define DWARF_OFFSET_SIZE 4 22050397Sobrien#endif 22150397Sobrien 22250397Sobrien#define DWARF_VERSION 2 22350397Sobrien 22450397Sobrien/* Round SIZE up to the nearest BOUNDARY. */ 22550397Sobrien#define DWARF_ROUND(SIZE,BOUNDARY) \ 22690075Sobrien ((((SIZE) + (BOUNDARY) - 1) / (BOUNDARY)) * (BOUNDARY)) 22750397Sobrien 22850397Sobrien/* Offsets recorded in opcodes are a multiple of this alignment factor. */ 22990075Sobrien#ifndef DWARF_CIE_DATA_ALIGNMENT 23050397Sobrien#ifdef STACK_GROWS_DOWNWARD 23190075Sobrien#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD)) 23250397Sobrien#else 23390075Sobrien#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD) 23450397Sobrien#endif 23590075Sobrien#endif 23650397Sobrien 23750397Sobrien/* A pointer to the base of a table that contains frame description 23850397Sobrien information for each routine. */ 23950397Sobrienstatic dw_fde_ref fde_table; 24050397Sobrien 24150397Sobrien/* Number of elements currently allocated for fde_table. */ 24250397Sobrienstatic unsigned fde_table_allocated; 24350397Sobrien 24450397Sobrien/* Number of elements in fde_table currently in use. */ 24550397Sobrienstatic unsigned fde_table_in_use; 24650397Sobrien 24750397Sobrien/* Size (in elements) of increments by which we may expand the 24850397Sobrien fde_table. */ 24950397Sobrien#define FDE_TABLE_INCREMENT 256 25050397Sobrien 25150397Sobrien/* A list of call frame insns for the CIE. */ 25250397Sobrienstatic dw_cfi_ref cie_cfi_head; 25350397Sobrien 25450397Sobrien/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram 25550397Sobrien attribute that accelerates the lookup of the FDE associated 25690075Sobrien with the subprogram. This variable holds the table index of the FDE 25750397Sobrien associated with the current function (body) definition. */ 25850397Sobrienstatic unsigned current_funcdef_fde; 25950397Sobrien 26090075Sobrienstruct ht *debug_str_hash; 26190075Sobrien 26290075Sobrienstruct indirect_string_node 26390075Sobrien{ 26490075Sobrien struct ht_identifier id; 26590075Sobrien unsigned int refcount; 26690075Sobrien unsigned int form; 26790075Sobrien char *label; 26890075Sobrien}; 26990075Sobrien 27050397Sobrien/* Forward declarations for functions defined in this file. */ 27150397Sobrien 27290075Sobrienstatic char *stripattributes PARAMS ((const char *)); 27390075Sobrienstatic const char *dwarf_cfi_name PARAMS ((unsigned)); 27490075Sobrienstatic dw_cfi_ref new_cfi PARAMS ((void)); 27590075Sobrienstatic void add_cfi PARAMS ((dw_cfi_ref *, dw_cfi_ref)); 27690075Sobrienstatic void add_fde_cfi PARAMS ((const char *, dw_cfi_ref)); 27790075Sobrienstatic void lookup_cfa_1 PARAMS ((dw_cfi_ref, 27890075Sobrien dw_cfa_location *)); 27990075Sobrienstatic void lookup_cfa PARAMS ((dw_cfa_location *)); 28090075Sobrienstatic void reg_save PARAMS ((const char *, unsigned, 28190075Sobrien unsigned, long)); 28290075Sobrienstatic void initial_return_save PARAMS ((rtx)); 28390075Sobrienstatic long stack_adjust_offset PARAMS ((rtx)); 28490075Sobrienstatic void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref, int)); 28590075Sobrienstatic void output_call_frame_info PARAMS ((int)); 28690075Sobrienstatic void dwarf2out_stack_adjust PARAMS ((rtx)); 28790075Sobrienstatic void queue_reg_save PARAMS ((const char *, rtx, long)); 28890075Sobrienstatic void flush_queued_reg_saves PARAMS ((void)); 28990075Sobrienstatic bool clobbers_queued_reg_save PARAMS ((rtx)); 29090075Sobrienstatic void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *)); 29150397Sobrien 29290075Sobrien/* Support for complex CFA locations. */ 29390075Sobrienstatic void output_cfa_loc PARAMS ((dw_cfi_ref)); 29490075Sobrienstatic void get_cfa_from_loc_descr PARAMS ((dw_cfa_location *, 29590075Sobrien struct dw_loc_descr_struct *)); 29690075Sobrienstatic struct dw_loc_descr_struct *build_cfa_loc 29790075Sobrien PARAMS ((dw_cfa_location *)); 29890075Sobrienstatic void def_cfa_1 PARAMS ((const char *, 29990075Sobrien dw_cfa_location *)); 30050397Sobrien 30190075Sobrien/* How to start an assembler comment. */ 30290075Sobrien#ifndef ASM_COMMENT_START 30390075Sobrien#define ASM_COMMENT_START ";#" 30450397Sobrien#endif 30550397Sobrien 30650397Sobrien/* Data and reference forms for relocatable data. */ 30750397Sobrien#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4) 30850397Sobrien#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4) 30950397Sobrien 31050397Sobrien/* Pseudo-op for defining a new section. */ 31150397Sobrien#ifndef SECTION_ASM_OP 31290075Sobrien#define SECTION_ASM_OP "\t.section\t" 31350397Sobrien#endif 31450397Sobrien 31590075Sobrien#ifndef DEBUG_FRAME_SECTION 31690075Sobrien#define DEBUG_FRAME_SECTION ".debug_frame" 31750397Sobrien#endif 31850397Sobrien 31950397Sobrien#ifndef FUNC_BEGIN_LABEL 32050397Sobrien#define FUNC_BEGIN_LABEL "LFB" 32150397Sobrien#endif 32290075Sobrien 32350397Sobrien#ifndef FUNC_END_LABEL 32450397Sobrien#define FUNC_END_LABEL "LFE" 32550397Sobrien#endif 32690075Sobrien 32790075Sobrien#define FRAME_BEGIN_LABEL "Lframe" 32850397Sobrien#define CIE_AFTER_SIZE_LABEL "LSCIE" 32950397Sobrien#define CIE_END_LABEL "LECIE" 33050397Sobrien#define CIE_LENGTH_LABEL "LLCIE" 33190075Sobrien#define FDE_LABEL "LSFDE" 33290075Sobrien#define FDE_AFTER_SIZE_LABEL "LASFDE" 33350397Sobrien#define FDE_END_LABEL "LEFDE" 33450397Sobrien#define FDE_LENGTH_LABEL "LLFDE" 33590075Sobrien#define LINE_NUMBER_BEGIN_LABEL "LSLT" 33690075Sobrien#define LINE_NUMBER_END_LABEL "LELT" 33790075Sobrien#define LN_PROLOG_AS_LABEL "LASLTP" 33890075Sobrien#define LN_PROLOG_END_LABEL "LELTP" 33990075Sobrien#define DIE_LABEL_PREFIX "DW" 34050397Sobrien 34150397Sobrien/* Definitions of defaults for various types of primitive assembly language 34250397Sobrien output operations. These may be overridden from within the tm.h file, 34350397Sobrien but typically, that is unnecessary. */ 34450397Sobrien 34550397Sobrien#ifdef SET_ASM_OP 34650397Sobrien#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 34750397Sobrien#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \ 34850397Sobrien do { \ 34990075Sobrien fprintf (FILE, "%s", SET_ASM_OP); \ 35050397Sobrien assemble_name (FILE, SY); \ 35150397Sobrien fputc (',', FILE); \ 35250397Sobrien assemble_name (FILE, HI); \ 35350397Sobrien fputc ('-', FILE); \ 35450397Sobrien assemble_name (FILE, LO); \ 35550397Sobrien } while (0) 35650397Sobrien#endif 35750397Sobrien#endif 35850397Sobrien 35950397Sobrien/* The DWARF 2 CFA column which tracks the return address. Normally this 36050397Sobrien is the column for PC, or the first column after all of the hard 36150397Sobrien registers. */ 36250397Sobrien#ifndef DWARF_FRAME_RETURN_COLUMN 36350397Sobrien#ifdef PC_REGNUM 36450397Sobrien#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM) 36550397Sobrien#else 36690075Sobrien#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS 36750397Sobrien#endif 36850397Sobrien#endif 36950397Sobrien 37050397Sobrien/* The mapping from gcc register number to DWARF 2 CFA column number. By 37150397Sobrien default, we just provide columns for all registers. */ 37250397Sobrien#ifndef DWARF_FRAME_REGNUM 37350397Sobrien#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) 37450397Sobrien#endif 37550397Sobrien 37690075Sobrien/* The offset from the incoming value of %sp to the top of the stack frame 37790075Sobrien for the current function. */ 37890075Sobrien#ifndef INCOMING_FRAME_SP_OFFSET 37990075Sobrien#define INCOMING_FRAME_SP_OFFSET 0 38090075Sobrien#endif 38190075Sobrien 38250397Sobrien/* Hook used by __throw. */ 38350397Sobrien 38450397Sobrienrtx 38550397Sobrienexpand_builtin_dwarf_fp_regnum () 38650397Sobrien{ 38750397Sobrien return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM)); 38850397Sobrien} 38950397Sobrien 39050397Sobrien/* Return a pointer to a copy of the section string name S with all 39150397Sobrien attributes stripped off, and an asterisk prepended (for assemble_name). */ 39250397Sobrien 39350397Sobrienstatic inline char * 39450397Sobrienstripattributes (s) 39590075Sobrien const char *s; 39650397Sobrien{ 39750397Sobrien char *stripped = xmalloc (strlen (s) + 2); 39850397Sobrien char *p = stripped; 39950397Sobrien 40050397Sobrien *p++ = '*'; 40150397Sobrien 40250397Sobrien while (*s && *s != ',') 40350397Sobrien *p++ = *s++; 40450397Sobrien 40550397Sobrien *p = '\0'; 40650397Sobrien return stripped; 40750397Sobrien} 40850397Sobrien 40990075Sobrien/* Generate code to initialize the register size table. */ 41050397Sobrien 41190075Sobrienvoid 41290075Sobrienexpand_builtin_init_dwarf_reg_sizes (address) 41390075Sobrien tree address; 41450397Sobrien{ 41590075Sobrien int i; 41690075Sobrien enum machine_mode mode = TYPE_MODE (char_type_node); 41790075Sobrien rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0); 41890075Sobrien rtx mem = gen_rtx_MEM (BLKmode, addr); 41950397Sobrien 42090075Sobrien for (i = 0; i < DWARF_FRAME_REGISTERS; i++) 42150397Sobrien { 42290075Sobrien HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode); 42390075Sobrien HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]); 42450397Sobrien 42590075Sobrien if (offset < 0) 42650397Sobrien continue; 42750397Sobrien 42890075Sobrien emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); 42950397Sobrien } 43050397Sobrien} 43150397Sobrien 43250397Sobrien/* Convert a DWARF call frame info. operation to its string name */ 43350397Sobrien 43490075Sobrienstatic const char * 43550397Sobriendwarf_cfi_name (cfi_opc) 43690075Sobrien unsigned cfi_opc; 43750397Sobrien{ 43850397Sobrien switch (cfi_opc) 43950397Sobrien { 44050397Sobrien case DW_CFA_advance_loc: 44150397Sobrien return "DW_CFA_advance_loc"; 44250397Sobrien case DW_CFA_offset: 44350397Sobrien return "DW_CFA_offset"; 44450397Sobrien case DW_CFA_restore: 44550397Sobrien return "DW_CFA_restore"; 44650397Sobrien case DW_CFA_nop: 44750397Sobrien return "DW_CFA_nop"; 44850397Sobrien case DW_CFA_set_loc: 44950397Sobrien return "DW_CFA_set_loc"; 45050397Sobrien case DW_CFA_advance_loc1: 45150397Sobrien return "DW_CFA_advance_loc1"; 45250397Sobrien case DW_CFA_advance_loc2: 45350397Sobrien return "DW_CFA_advance_loc2"; 45450397Sobrien case DW_CFA_advance_loc4: 45550397Sobrien return "DW_CFA_advance_loc4"; 45650397Sobrien case DW_CFA_offset_extended: 45750397Sobrien return "DW_CFA_offset_extended"; 45850397Sobrien case DW_CFA_restore_extended: 45950397Sobrien return "DW_CFA_restore_extended"; 46050397Sobrien case DW_CFA_undefined: 46150397Sobrien return "DW_CFA_undefined"; 46250397Sobrien case DW_CFA_same_value: 46350397Sobrien return "DW_CFA_same_value"; 46450397Sobrien case DW_CFA_register: 46550397Sobrien return "DW_CFA_register"; 46650397Sobrien case DW_CFA_remember_state: 46750397Sobrien return "DW_CFA_remember_state"; 46850397Sobrien case DW_CFA_restore_state: 46950397Sobrien return "DW_CFA_restore_state"; 47050397Sobrien case DW_CFA_def_cfa: 47150397Sobrien return "DW_CFA_def_cfa"; 47250397Sobrien case DW_CFA_def_cfa_register: 47350397Sobrien return "DW_CFA_def_cfa_register"; 47450397Sobrien case DW_CFA_def_cfa_offset: 47550397Sobrien return "DW_CFA_def_cfa_offset"; 47650397Sobrien 47790075Sobrien /* DWARF 3 */ 47890075Sobrien case DW_CFA_def_cfa_expression: 47990075Sobrien return "DW_CFA_def_cfa_expression"; 48090075Sobrien case DW_CFA_expression: 48190075Sobrien return "DW_CFA_expression"; 48290075Sobrien case DW_CFA_offset_extended_sf: 48390075Sobrien return "DW_CFA_offset_extended_sf"; 48490075Sobrien case DW_CFA_def_cfa_sf: 48590075Sobrien return "DW_CFA_def_cfa_sf"; 48690075Sobrien case DW_CFA_def_cfa_offset_sf: 48790075Sobrien return "DW_CFA_def_cfa_offset_sf"; 48890075Sobrien 48950397Sobrien /* SGI/MIPS specific */ 49050397Sobrien case DW_CFA_MIPS_advance_loc8: 49150397Sobrien return "DW_CFA_MIPS_advance_loc8"; 49250397Sobrien 49350397Sobrien /* GNU extensions */ 49450397Sobrien case DW_CFA_GNU_window_save: 49550397Sobrien return "DW_CFA_GNU_window_save"; 49650397Sobrien case DW_CFA_GNU_args_size: 49750397Sobrien return "DW_CFA_GNU_args_size"; 49870635Sobrien case DW_CFA_GNU_negative_offset_extended: 49970635Sobrien return "DW_CFA_GNU_negative_offset_extended"; 50050397Sobrien 50150397Sobrien default: 50250397Sobrien return "DW_CFA_<unknown>"; 50350397Sobrien } 50450397Sobrien} 50550397Sobrien 50650397Sobrien/* Return a pointer to a newly allocated Call Frame Instruction. */ 50750397Sobrien 50850397Sobrienstatic inline dw_cfi_ref 50950397Sobriennew_cfi () 51050397Sobrien{ 51190075Sobrien dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node)); 51250397Sobrien 51350397Sobrien cfi->dw_cfi_next = NULL; 51450397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0; 51550397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0; 51650397Sobrien 51750397Sobrien return cfi; 51850397Sobrien} 51950397Sobrien 52050397Sobrien/* Add a Call Frame Instruction to list of instructions. */ 52150397Sobrien 52250397Sobrienstatic inline void 52350397Sobrienadd_cfi (list_head, cfi) 52490075Sobrien dw_cfi_ref *list_head; 52590075Sobrien dw_cfi_ref cfi; 52650397Sobrien{ 52790075Sobrien dw_cfi_ref *p; 52850397Sobrien 52950397Sobrien /* Find the end of the chain. */ 53050397Sobrien for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next) 53150397Sobrien ; 53250397Sobrien 53350397Sobrien *p = cfi; 53450397Sobrien} 53550397Sobrien 53650397Sobrien/* Generate a new label for the CFI info to refer to. */ 53750397Sobrien 53850397Sobrienchar * 53950397Sobriendwarf2out_cfi_label () 54050397Sobrien{ 54150397Sobrien static char label[20]; 54250397Sobrien static unsigned long label_num = 0; 54390075Sobrien 54450397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++); 54550397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 54650397Sobrien return label; 54750397Sobrien} 54850397Sobrien 54950397Sobrien/* Add CFI to the current fde at the PC value indicated by LABEL if specified, 55050397Sobrien or to the CIE if LABEL is NULL. */ 55150397Sobrien 55250397Sobrienstatic void 55350397Sobrienadd_fde_cfi (label, cfi) 55490075Sobrien const char *label; 55590075Sobrien dw_cfi_ref cfi; 55650397Sobrien{ 55750397Sobrien if (label) 55850397Sobrien { 55990075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 56050397Sobrien 56150397Sobrien if (*label == 0) 56250397Sobrien label = dwarf2out_cfi_label (); 56350397Sobrien 56450397Sobrien if (fde->dw_fde_current_label == NULL 56550397Sobrien || strcmp (label, fde->dw_fde_current_label) != 0) 56650397Sobrien { 56790075Sobrien dw_cfi_ref xcfi; 56850397Sobrien 56950397Sobrien fde->dw_fde_current_label = label = xstrdup (label); 57050397Sobrien 57150397Sobrien /* Set the location counter to the new label. */ 57250397Sobrien xcfi = new_cfi (); 57350397Sobrien xcfi->dw_cfi_opc = DW_CFA_advance_loc4; 57450397Sobrien xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; 57550397Sobrien add_cfi (&fde->dw_fde_cfi, xcfi); 57650397Sobrien } 57750397Sobrien 57850397Sobrien add_cfi (&fde->dw_fde_cfi, cfi); 57950397Sobrien } 58050397Sobrien 58150397Sobrien else 58250397Sobrien add_cfi (&cie_cfi_head, cfi); 58350397Sobrien} 58450397Sobrien 58550397Sobrien/* Subroutine of lookup_cfa. */ 58650397Sobrien 58750397Sobrienstatic inline void 58890075Sobrienlookup_cfa_1 (cfi, loc) 58990075Sobrien dw_cfi_ref cfi; 59090075Sobrien dw_cfa_location *loc; 59150397Sobrien{ 59250397Sobrien switch (cfi->dw_cfi_opc) 59350397Sobrien { 59450397Sobrien case DW_CFA_def_cfa_offset: 59590075Sobrien loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset; 59650397Sobrien break; 59750397Sobrien case DW_CFA_def_cfa_register: 59890075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 59950397Sobrien break; 60050397Sobrien case DW_CFA_def_cfa: 60190075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 60290075Sobrien loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset; 60350397Sobrien break; 60490075Sobrien case DW_CFA_def_cfa_expression: 60590075Sobrien get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc); 60690075Sobrien break; 60750397Sobrien default: 60850397Sobrien break; 60950397Sobrien } 61050397Sobrien} 61150397Sobrien 61250397Sobrien/* Find the previous value for the CFA. */ 61350397Sobrien 61450397Sobrienstatic void 61590075Sobrienlookup_cfa (loc) 61690075Sobrien dw_cfa_location *loc; 61750397Sobrien{ 61890075Sobrien dw_cfi_ref cfi; 61950397Sobrien 62090075Sobrien loc->reg = (unsigned long) -1; 62190075Sobrien loc->offset = 0; 62290075Sobrien loc->indirect = 0; 62390075Sobrien loc->base_offset = 0; 62450397Sobrien 62550397Sobrien for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next) 62690075Sobrien lookup_cfa_1 (cfi, loc); 62750397Sobrien 62850397Sobrien if (fde_table_in_use) 62950397Sobrien { 63090075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 63150397Sobrien for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) 63290075Sobrien lookup_cfa_1 (cfi, loc); 63350397Sobrien } 63450397Sobrien} 63550397Sobrien 63650397Sobrien/* The current rule for calculating the DWARF2 canonical frame address. */ 63790075Sobrienstatic dw_cfa_location cfa; 63850397Sobrien 63950397Sobrien/* The register used for saving registers to the stack, and its offset 64050397Sobrien from the CFA. */ 64190075Sobrienstatic dw_cfa_location cfa_store; 64250397Sobrien 64350397Sobrien/* The running total of the size of arguments pushed onto the stack. */ 64450397Sobrienstatic long args_size; 64550397Sobrien 64650397Sobrien/* The last args_size we actually output. */ 64750397Sobrienstatic long old_args_size; 64850397Sobrien 64950397Sobrien/* Entry point to update the canonical frame address (CFA). 65050397Sobrien LABEL is passed to add_fde_cfi. The value of CFA is now to be 65150397Sobrien calculated from REG+OFFSET. */ 65250397Sobrien 65350397Sobrienvoid 65450397Sobriendwarf2out_def_cfa (label, reg, offset) 65590075Sobrien const char *label; 65690075Sobrien unsigned reg; 65790075Sobrien long offset; 65850397Sobrien{ 65990075Sobrien dw_cfa_location loc; 66090075Sobrien loc.indirect = 0; 66190075Sobrien loc.base_offset = 0; 66290075Sobrien loc.reg = reg; 66390075Sobrien loc.offset = offset; 66490075Sobrien def_cfa_1 (label, &loc); 66590075Sobrien} 66650397Sobrien 66790075Sobrien/* This routine does the actual work. The CFA is now calculated from 66890075Sobrien the dw_cfa_location structure. */ 66950397Sobrien 67090075Sobrienstatic void 67190075Sobriendef_cfa_1 (label, loc_p) 67290075Sobrien const char *label; 67390075Sobrien dw_cfa_location *loc_p; 67490075Sobrien{ 67590075Sobrien dw_cfi_ref cfi; 67690075Sobrien dw_cfa_location old_cfa, loc; 67750397Sobrien 67890075Sobrien cfa = *loc_p; 67990075Sobrien loc = *loc_p; 68090075Sobrien 68190075Sobrien if (cfa_store.reg == loc.reg && loc.indirect == 0) 68290075Sobrien cfa_store.offset = loc.offset; 68390075Sobrien 68490075Sobrien loc.reg = DWARF_FRAME_REGNUM (loc.reg); 68590075Sobrien lookup_cfa (&old_cfa); 68690075Sobrien 68790075Sobrien /* If nothing changed, no need to issue any call frame instructions. */ 68890075Sobrien if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset 68990075Sobrien && loc.indirect == old_cfa.indirect 69090075Sobrien && (loc.indirect == 0 || loc.base_offset == old_cfa.base_offset)) 69150397Sobrien return; 69250397Sobrien 69350397Sobrien cfi = new_cfi (); 69450397Sobrien 69590075Sobrien if (loc.reg == old_cfa.reg && !loc.indirect) 69650397Sobrien { 69790075Sobrien /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, 69890075Sobrien indicating the CFA register did not change but the offset 69990075Sobrien did. */ 70050397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; 70190075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset; 70250397Sobrien } 70350397Sobrien 70450397Sobrien#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ 70590075Sobrien else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1 70690075Sobrien && !loc.indirect) 70750397Sobrien { 70890075Sobrien /* Construct a "DW_CFA_def_cfa_register <register>" instruction, 70990075Sobrien indicating the CFA register has changed to <register> but the 71090075Sobrien offset has not changed. */ 71150397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_register; 71290075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 71350397Sobrien } 71450397Sobrien#endif 71550397Sobrien 71690075Sobrien else if (loc.indirect == 0) 71750397Sobrien { 71890075Sobrien /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction, 71990075Sobrien indicating the CFA register has changed to <register> with 72090075Sobrien the specified offset. */ 72150397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa; 72290075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 72390075Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset; 72450397Sobrien } 72590075Sobrien else 72690075Sobrien { 72790075Sobrien /* Construct a DW_CFA_def_cfa_expression instruction to 72890075Sobrien calculate the CFA using a full location expression since no 72990075Sobrien register-offset pair is available. */ 73090075Sobrien struct dw_loc_descr_struct *loc_list; 73150397Sobrien 73290075Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_expression; 73390075Sobrien loc_list = build_cfa_loc (&loc); 73490075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list; 73590075Sobrien } 73690075Sobrien 73750397Sobrien add_fde_cfi (label, cfi); 73850397Sobrien} 73950397Sobrien 74050397Sobrien/* Add the CFI for saving a register. REG is the CFA column number. 74150397Sobrien LABEL is passed to add_fde_cfi. 74250397Sobrien If SREG is -1, the register is saved at OFFSET from the CFA; 74350397Sobrien otherwise it is saved in SREG. */ 74450397Sobrien 74550397Sobrienstatic void 74650397Sobrienreg_save (label, reg, sreg, offset) 74790075Sobrien const char *label; 74890075Sobrien unsigned reg; 74990075Sobrien unsigned sreg; 75090075Sobrien long offset; 75150397Sobrien{ 75290075Sobrien dw_cfi_ref cfi = new_cfi (); 75350397Sobrien 75450397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 75550397Sobrien 75650397Sobrien /* The following comparison is correct. -1 is used to indicate that 75750397Sobrien the value isn't a register number. */ 75850397Sobrien if (sreg == (unsigned int) -1) 75950397Sobrien { 76050397Sobrien if (reg & ~0x3f) 76150397Sobrien /* The register number won't fit in 6 bits, so we have to use 76250397Sobrien the long form. */ 76350397Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended; 76450397Sobrien else 76550397Sobrien cfi->dw_cfi_opc = DW_CFA_offset; 76650397Sobrien 76790075Sobrien#ifdef ENABLE_CHECKING 76890075Sobrien { 76990075Sobrien /* If we get an offset that is not a multiple of 77090075Sobrien DWARF_CIE_DATA_ALIGNMENT, there is either a bug in the 77190075Sobrien definition of DWARF_CIE_DATA_ALIGNMENT, or a bug in the machine 77290075Sobrien description. */ 77390075Sobrien long check_offset = offset / DWARF_CIE_DATA_ALIGNMENT; 77490075Sobrien 77590075Sobrien if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset) 77690075Sobrien abort (); 77790075Sobrien } 77890075Sobrien#endif 77950397Sobrien offset /= DWARF_CIE_DATA_ALIGNMENT; 78050397Sobrien if (offset < 0) 78190075Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended_sf; 78290075Sobrien 78350397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; 78450397Sobrien } 78590075Sobrien else if (sreg == reg) 78690075Sobrien /* We could emit a DW_CFA_same_value in this case, but don't bother. */ 78790075Sobrien return; 78850397Sobrien else 78950397Sobrien { 79050397Sobrien cfi->dw_cfi_opc = DW_CFA_register; 79150397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg; 79250397Sobrien } 79350397Sobrien 79450397Sobrien add_fde_cfi (label, cfi); 79550397Sobrien} 79650397Sobrien 79750397Sobrien/* Add the CFI for saving a register window. LABEL is passed to reg_save. 79850397Sobrien This CFI tells the unwinder that it needs to restore the window registers 79950397Sobrien from the previous frame's window save area. 80090075Sobrien 80150397Sobrien ??? Perhaps we should note in the CIE where windows are saved (instead of 80250397Sobrien assuming 0(cfa)) and what registers are in the window. */ 80350397Sobrien 80450397Sobrienvoid 80550397Sobriendwarf2out_window_save (label) 80690075Sobrien const char *label; 80750397Sobrien{ 80890075Sobrien dw_cfi_ref cfi = new_cfi (); 80990075Sobrien 81050397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_window_save; 81150397Sobrien add_fde_cfi (label, cfi); 81250397Sobrien} 81350397Sobrien 81450397Sobrien/* Add a CFI to update the running total of the size of arguments 81550397Sobrien pushed onto the stack. */ 81650397Sobrien 81750397Sobrienvoid 81850397Sobriendwarf2out_args_size (label, size) 81990075Sobrien const char *label; 82050397Sobrien long size; 82150397Sobrien{ 82290075Sobrien dw_cfi_ref cfi; 82350397Sobrien 82450397Sobrien if (size == old_args_size) 82550397Sobrien return; 82690075Sobrien 82750397Sobrien old_args_size = size; 82850397Sobrien 82950397Sobrien cfi = new_cfi (); 83050397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_args_size; 83150397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = size; 83250397Sobrien add_fde_cfi (label, cfi); 83350397Sobrien} 83450397Sobrien 83550397Sobrien/* Entry point for saving a register to the stack. REG is the GCC register 83650397Sobrien number. LABEL and OFFSET are passed to reg_save. */ 83750397Sobrien 83850397Sobrienvoid 83950397Sobriendwarf2out_reg_save (label, reg, offset) 84090075Sobrien const char *label; 84190075Sobrien unsigned reg; 84290075Sobrien long offset; 84350397Sobrien{ 84450397Sobrien reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset); 84550397Sobrien} 84650397Sobrien 84750397Sobrien/* Entry point for saving the return address in the stack. 84850397Sobrien LABEL and OFFSET are passed to reg_save. */ 84950397Sobrien 85050397Sobrienvoid 85150397Sobriendwarf2out_return_save (label, offset) 85290075Sobrien const char *label; 85390075Sobrien long offset; 85450397Sobrien{ 85550397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset); 85650397Sobrien} 85750397Sobrien 85850397Sobrien/* Entry point for saving the return address in a register. 85950397Sobrien LABEL and SREG are passed to reg_save. */ 86050397Sobrien 86150397Sobrienvoid 86250397Sobriendwarf2out_return_reg (label, sreg) 86390075Sobrien const char *label; 86490075Sobrien unsigned sreg; 86550397Sobrien{ 86650397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0); 86750397Sobrien} 86850397Sobrien 86950397Sobrien/* Record the initial position of the return address. RTL is 87050397Sobrien INCOMING_RETURN_ADDR_RTX. */ 87150397Sobrien 87250397Sobrienstatic void 87350397Sobrieninitial_return_save (rtl) 87490075Sobrien rtx rtl; 87550397Sobrien{ 87652284Sobrien unsigned int reg = (unsigned int) -1; 87790075Sobrien HOST_WIDE_INT offset = 0; 87850397Sobrien 87950397Sobrien switch (GET_CODE (rtl)) 88050397Sobrien { 88150397Sobrien case REG: 88250397Sobrien /* RA is in a register. */ 88390075Sobrien reg = DWARF_FRAME_REGNUM (REGNO (rtl)); 88450397Sobrien break; 88590075Sobrien 88650397Sobrien case MEM: 88750397Sobrien /* RA is on the stack. */ 88850397Sobrien rtl = XEXP (rtl, 0); 88950397Sobrien switch (GET_CODE (rtl)) 89050397Sobrien { 89150397Sobrien case REG: 89250397Sobrien if (REGNO (rtl) != STACK_POINTER_REGNUM) 89350397Sobrien abort (); 89450397Sobrien offset = 0; 89550397Sobrien break; 89690075Sobrien 89750397Sobrien case PLUS: 89850397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 89950397Sobrien abort (); 90050397Sobrien offset = INTVAL (XEXP (rtl, 1)); 90150397Sobrien break; 90290075Sobrien 90350397Sobrien case MINUS: 90450397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 90550397Sobrien abort (); 90650397Sobrien offset = -INTVAL (XEXP (rtl, 1)); 90750397Sobrien break; 90890075Sobrien 90950397Sobrien default: 91050397Sobrien abort (); 91150397Sobrien } 91290075Sobrien 91350397Sobrien break; 91490075Sobrien 91550397Sobrien case PLUS: 91650397Sobrien /* The return address is at some offset from any value we can 91750397Sobrien actually load. For instance, on the SPARC it is in %i7+8. Just 91850397Sobrien ignore the offset for now; it doesn't matter for unwinding frames. */ 91950397Sobrien if (GET_CODE (XEXP (rtl, 1)) != CONST_INT) 92050397Sobrien abort (); 92150397Sobrien initial_return_save (XEXP (rtl, 0)); 92250397Sobrien return; 92390075Sobrien 92450397Sobrien default: 92550397Sobrien abort (); 92650397Sobrien } 92750397Sobrien 92890075Sobrien reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset); 92950397Sobrien} 93050397Sobrien 93190075Sobrien/* Given a SET, calculate the amount of stack adjustment it 93290075Sobrien contains. */ 93390075Sobrien 93490075Sobrienstatic long 93590075Sobrienstack_adjust_offset (pattern) 93690075Sobrien rtx pattern; 93790075Sobrien{ 93890075Sobrien rtx src = SET_SRC (pattern); 93990075Sobrien rtx dest = SET_DEST (pattern); 94090075Sobrien HOST_WIDE_INT offset = 0; 94190075Sobrien enum rtx_code code; 94290075Sobrien 94390075Sobrien if (dest == stack_pointer_rtx) 94490075Sobrien { 94590075Sobrien /* (set (reg sp) (plus (reg sp) (const_int))) */ 94690075Sobrien code = GET_CODE (src); 94790075Sobrien if (! (code == PLUS || code == MINUS) 94890075Sobrien || XEXP (src, 0) != stack_pointer_rtx 94990075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 95090075Sobrien return 0; 95190075Sobrien 95290075Sobrien offset = INTVAL (XEXP (src, 1)); 95390075Sobrien } 95490075Sobrien else if (GET_CODE (dest) == MEM) 95590075Sobrien { 95690075Sobrien /* (set (mem (pre_dec (reg sp))) (foo)) */ 95790075Sobrien src = XEXP (dest, 0); 95890075Sobrien code = GET_CODE (src); 95990075Sobrien 96090075Sobrien if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY) 96190075Sobrien || XEXP (src, 0) != stack_pointer_rtx) 96290075Sobrien return 0; 96390075Sobrien 96490075Sobrien if (code == PRE_MODIFY) 96590075Sobrien { 96690075Sobrien rtx val = XEXP (XEXP (src, 1), 1); 96790075Sobrien 96890075Sobrien /* We handle only adjustments by constant amount. */ 96990075Sobrien if (GET_CODE (XEXP (src, 1)) != PLUS || 97090075Sobrien GET_CODE (val) != CONST_INT) 97190075Sobrien abort (); 97290075Sobrien 97390075Sobrien offset = -INTVAL (val); 97490075Sobrien } 97590075Sobrien else 97690075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 97790075Sobrien } 97890075Sobrien else 97990075Sobrien return 0; 98090075Sobrien 98190075Sobrien if (code == PLUS || code == PRE_INC) 98290075Sobrien offset = -offset; 98390075Sobrien 98490075Sobrien return offset; 98590075Sobrien} 98690075Sobrien 98750397Sobrien/* Check INSN to see if it looks like a push or a stack adjustment, and 98850397Sobrien make a note of it if it does. EH uses this information to find out how 98950397Sobrien much extra space it needs to pop off the stack. */ 99050397Sobrien 99150397Sobrienstatic void 99250397Sobriendwarf2out_stack_adjust (insn) 99350397Sobrien rtx insn; 99450397Sobrien{ 99590075Sobrien HOST_WIDE_INT offset; 99690075Sobrien const char *label; 99790075Sobrien int i; 99850397Sobrien 99990075Sobrien if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN) 100050397Sobrien { 100150397Sobrien /* Extract the size of the args from the CALL rtx itself. */ 100250397Sobrien insn = PATTERN (insn); 100350397Sobrien if (GET_CODE (insn) == PARALLEL) 100450397Sobrien insn = XVECEXP (insn, 0, 0); 100550397Sobrien if (GET_CODE (insn) == SET) 100650397Sobrien insn = SET_SRC (insn); 100790075Sobrien if (GET_CODE (insn) != CALL) 100890075Sobrien abort (); 100990075Sobrien 101050397Sobrien dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); 101150397Sobrien return; 101250397Sobrien } 101350397Sobrien 101450397Sobrien /* If only calls can throw, and we have a frame pointer, 101550397Sobrien save up adjustments until we see the CALL_INSN. */ 101690075Sobrien else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM) 101750397Sobrien return; 101850397Sobrien 101950397Sobrien if (GET_CODE (insn) == BARRIER) 102050397Sobrien { 102150397Sobrien /* When we see a BARRIER, we know to reset args_size to 0. Usually 102250397Sobrien the compiler will have already emitted a stack adjustment, but 102350397Sobrien doesn't bother for calls to noreturn functions. */ 102450397Sobrien#ifdef STACK_GROWS_DOWNWARD 102550397Sobrien offset = -args_size; 102650397Sobrien#else 102750397Sobrien offset = args_size; 102850397Sobrien#endif 102950397Sobrien } 103050397Sobrien else if (GET_CODE (PATTERN (insn)) == SET) 103190075Sobrien offset = stack_adjust_offset (PATTERN (insn)); 103290075Sobrien else if (GET_CODE (PATTERN (insn)) == PARALLEL 103390075Sobrien || GET_CODE (PATTERN (insn)) == SEQUENCE) 103450397Sobrien { 103590075Sobrien /* There may be stack adjustments inside compound insns. Search 103690075Sobrien for them. */ 103790075Sobrien for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) 103890075Sobrien if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 103990075Sobrien offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i)); 104050397Sobrien } 104150397Sobrien else 104250397Sobrien return; 104350397Sobrien 104450397Sobrien if (offset == 0) 104550397Sobrien return; 104650397Sobrien 104790075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 104890075Sobrien cfa.offset += offset; 104950397Sobrien 105050397Sobrien#ifndef STACK_GROWS_DOWNWARD 105150397Sobrien offset = -offset; 105250397Sobrien#endif 105390075Sobrien 105450397Sobrien args_size += offset; 105550397Sobrien if (args_size < 0) 105650397Sobrien args_size = 0; 105750397Sobrien 105850397Sobrien label = dwarf2out_cfi_label (); 105990075Sobrien def_cfa_1 (label, &cfa); 106050397Sobrien dwarf2out_args_size (label, args_size); 106150397Sobrien} 106250397Sobrien 106390075Sobrien/* We delay emitting a register save until either (a) we reach the end 106490075Sobrien of the prologue or (b) the register is clobbered. This clusters 106590075Sobrien register saves so that there are fewer pc advances. */ 106652284Sobrien 106790075Sobrienstruct queued_reg_save 106890075Sobrien{ 106990075Sobrien struct queued_reg_save *next; 107090075Sobrien rtx reg; 107190075Sobrien long cfa_offset; 107290075Sobrien}; 107352284Sobrien 107490075Sobrienstatic struct queued_reg_save *queued_reg_saves; 107590075Sobrienstatic const char *last_reg_save_label; 107650397Sobrien 107752284Sobrienstatic void 107890075Sobrienqueue_reg_save (label, reg, offset) 107990075Sobrien const char *label; 108090075Sobrien rtx reg; 108190075Sobrien long offset; 108290075Sobrien{ 108390075Sobrien struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q)); 108490075Sobrien 108590075Sobrien q->next = queued_reg_saves; 108690075Sobrien q->reg = reg; 108790075Sobrien q->cfa_offset = offset; 108890075Sobrien queued_reg_saves = q; 108990075Sobrien 109090075Sobrien last_reg_save_label = label; 109190075Sobrien} 109290075Sobrien 109390075Sobrienstatic void 109490075Sobrienflush_queued_reg_saves () 109590075Sobrien{ 109690075Sobrien struct queued_reg_save *q, *next; 109790075Sobrien 109890075Sobrien for (q = queued_reg_saves; q ; q = next) 109990075Sobrien { 110090075Sobrien dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset); 110190075Sobrien next = q->next; 110290075Sobrien free (q); 110390075Sobrien } 110490075Sobrien 110590075Sobrien queued_reg_saves = NULL; 110690075Sobrien last_reg_save_label = NULL; 110790075Sobrien} 110890075Sobrien 110990075Sobrienstatic bool 111090075Sobrienclobbers_queued_reg_save (insn) 111190075Sobrien rtx insn; 111290075Sobrien{ 111390075Sobrien struct queued_reg_save *q; 111490075Sobrien 111590075Sobrien for (q = queued_reg_saves; q ; q = q->next) 111690075Sobrien if (modified_in_p (q->reg, insn)) 111790075Sobrien return true; 111890075Sobrien 111990075Sobrien return false; 112090075Sobrien} 112190075Sobrien 112290075Sobrien 112390075Sobrien/* A temporary register holding an integral value used in adjusting SP 112490075Sobrien or setting up the store_reg. The "offset" field holds the integer 112590075Sobrien value, not an offset. */ 112690075Sobrienstatic dw_cfa_location cfa_temp; 112790075Sobrien 112890075Sobrien/* Record call frame debugging information for an expression EXPR, 112990075Sobrien which either sets SP or FP (adjusting how we calculate the frame 113090075Sobrien address) or saves a register to the stack. LABEL indicates the 113190075Sobrien address of EXPR. 113290075Sobrien 113390075Sobrien This function encodes a state machine mapping rtxes to actions on 113490075Sobrien cfa, cfa_store, and cfa_temp.reg. We describe these rules so 113590075Sobrien users need not read the source code. 113690075Sobrien 113790075Sobrien The High-Level Picture 113890075Sobrien 113990075Sobrien Changes in the register we use to calculate the CFA: Currently we 114090075Sobrien assume that if you copy the CFA register into another register, we 114190075Sobrien should take the other one as the new CFA register; this seems to 114290075Sobrien work pretty well. If it's wrong for some target, it's simple 114390075Sobrien enough not to set RTX_FRAME_RELATED_P on the insn in question. 114490075Sobrien 114590075Sobrien Changes in the register we use for saving registers to the stack: 114690075Sobrien This is usually SP, but not always. Again, we deduce that if you 114790075Sobrien copy SP into another register (and SP is not the CFA register), 114890075Sobrien then the new register is the one we will be using for register 114990075Sobrien saves. This also seems to work. 115090075Sobrien 115190075Sobrien Register saves: There's not much guesswork about this one; if 115290075Sobrien RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a 115390075Sobrien register save, and the register used to calculate the destination 115490075Sobrien had better be the one we think we're using for this purpose. 115590075Sobrien 115690075Sobrien Except: If the register being saved is the CFA register, and the 115790075Sobrien offset is non-zero, we are saving the CFA, so we assume we have to 115890075Sobrien use DW_CFA_def_cfa_expression. If the offset is 0, we assume that 115990075Sobrien the intent is to save the value of SP from the previous frame. 116090075Sobrien 116190075Sobrien Invariants / Summaries of Rules 116290075Sobrien 116390075Sobrien cfa current rule for calculating the CFA. It usually 116490075Sobrien consists of a register and an offset. 116590075Sobrien cfa_store register used by prologue code to save things to the stack 116690075Sobrien cfa_store.offset is the offset from the value of 116790075Sobrien cfa_store.reg to the actual CFA 116890075Sobrien cfa_temp register holding an integral value. cfa_temp.offset 116990075Sobrien stores the value, which will be used to adjust the 117090075Sobrien stack pointer. cfa_temp is also used like cfa_store, 117190075Sobrien to track stores to the stack via fp or a temp reg. 117290075Sobrien 117390075Sobrien Rules 1- 4: Setting a register's value to cfa.reg or an expression 117490075Sobrien with cfa.reg as the first operand changes the cfa.reg and its 117590075Sobrien cfa.offset. Rule 1 and 4 also set cfa_temp.reg and 117690075Sobrien cfa_temp.offset. 117790075Sobrien 117890075Sobrien Rules 6- 9: Set a non-cfa.reg register value to a constant or an 117990075Sobrien expression yielding a constant. This sets cfa_temp.reg 118090075Sobrien and cfa_temp.offset. 118190075Sobrien 118290075Sobrien Rule 5: Create a new register cfa_store used to save items to the 118390075Sobrien stack. 118490075Sobrien 118590075Sobrien Rules 10-14: Save a register to the stack. Define offset as the 118690075Sobrien difference of the original location and cfa_store's 118790075Sobrien location (or cfa_temp's location if cfa_temp is used). 118890075Sobrien 118990075Sobrien The Rules 119090075Sobrien 119190075Sobrien "{a,b}" indicates a choice of a xor b. 119290075Sobrien "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg. 119390075Sobrien 119490075Sobrien Rule 1: 119590075Sobrien (set <reg1> <reg2>:cfa.reg) 119690075Sobrien effects: cfa.reg = <reg1> 119790075Sobrien cfa.offset unchanged 119890075Sobrien cfa_temp.reg = <reg1> 119990075Sobrien cfa_temp.offset = cfa.offset 120090075Sobrien 120190075Sobrien Rule 2: 120290075Sobrien (set sp ({minus,plus,losum} {sp,fp}:cfa.reg 120390075Sobrien {<const_int>,<reg>:cfa_temp.reg})) 120490075Sobrien effects: cfa.reg = sp if fp used 120590075Sobrien cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp 120690075Sobrien cfa_store.offset += {+/- <const_int>, cfa_temp.offset} 120790075Sobrien if cfa_store.reg==sp 120890075Sobrien 120990075Sobrien Rule 3: 121090075Sobrien (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>)) 121190075Sobrien effects: cfa.reg = fp 121290075Sobrien cfa_offset += +/- <const_int> 121390075Sobrien 121490075Sobrien Rule 4: 121590075Sobrien (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>)) 121690075Sobrien constraints: <reg1> != fp 121790075Sobrien <reg1> != sp 121890075Sobrien effects: cfa.reg = <reg1> 121990075Sobrien cfa_temp.reg = <reg1> 122090075Sobrien cfa_temp.offset = cfa.offset 122190075Sobrien 122290075Sobrien Rule 5: 122390075Sobrien (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg)) 122490075Sobrien constraints: <reg1> != fp 122590075Sobrien <reg1> != sp 122690075Sobrien effects: cfa_store.reg = <reg1> 122790075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset 122890075Sobrien 122990075Sobrien Rule 6: 123090075Sobrien (set <reg> <const_int>) 123190075Sobrien effects: cfa_temp.reg = <reg> 123290075Sobrien cfa_temp.offset = <const_int> 123390075Sobrien 123490075Sobrien Rule 7: 123590075Sobrien (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>)) 123690075Sobrien effects: cfa_temp.reg = <reg1> 123790075Sobrien cfa_temp.offset |= <const_int> 123890075Sobrien 123990075Sobrien Rule 8: 124090075Sobrien (set <reg> (high <exp>)) 124190075Sobrien effects: none 124290075Sobrien 124390075Sobrien Rule 9: 124490075Sobrien (set <reg> (lo_sum <exp> <const_int>)) 124590075Sobrien effects: cfa_temp.reg = <reg> 124690075Sobrien cfa_temp.offset = <const_int> 124790075Sobrien 124890075Sobrien Rule 10: 124990075Sobrien (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>) 125090075Sobrien effects: cfa_store.offset -= <const_int> 125190075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 125290075Sobrien cfa.reg = sp 125390075Sobrien cfa.base_offset = -cfa_store.offset 125490075Sobrien 125590075Sobrien Rule 11: 125690075Sobrien (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>) 125790075Sobrien effects: cfa_store.offset += -/+ mode_size(mem) 125890075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 125990075Sobrien cfa.reg = sp 126090075Sobrien cfa.base_offset = -cfa_store.offset 126190075Sobrien 126290075Sobrien Rule 12: 126390075Sobrien (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) 126490075Sobrien 126590075Sobrien <reg2>) 126690075Sobrien effects: cfa.reg = <reg1> 126790075Sobrien cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset 126890075Sobrien 126990075Sobrien Rule 13: 127090075Sobrien (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>) 127190075Sobrien effects: cfa.reg = <reg1> 127290075Sobrien cfa.base_offset = -{cfa_store,cfa_temp}.offset 127390075Sobrien 127490075Sobrien Rule 14: 127590075Sobrien (set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>) 127690075Sobrien effects: cfa.reg = <reg1> 127790075Sobrien cfa.base_offset = -cfa_temp.offset 127890075Sobrien cfa_temp.offset -= mode_size(mem) */ 127990075Sobrien 128090075Sobrienstatic void 128152284Sobriendwarf2out_frame_debug_expr (expr, label) 128252284Sobrien rtx expr; 128390075Sobrien const char *label; 128450397Sobrien{ 128550397Sobrien rtx src, dest; 128690075Sobrien HOST_WIDE_INT offset; 128750397Sobrien 128890075Sobrien /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of 128990075Sobrien the PARALLEL independently. The first element is always processed if 129090075Sobrien it is a SET. This is for backward compatibility. Other elements 129190075Sobrien are processed only if they are SETs and the RTX_FRAME_RELATED_P 129290075Sobrien flag is set in them. */ 129390075Sobrien if (GET_CODE (expr) == PARALLEL || GET_CODE (expr) == SEQUENCE) 129490075Sobrien { 129552284Sobrien int par_index; 129652284Sobrien int limit = XVECLEN (expr, 0); 129750397Sobrien 129852284Sobrien for (par_index = 0; par_index < limit; par_index++) 129990075Sobrien if (GET_CODE (XVECEXP (expr, 0, par_index)) == SET 130090075Sobrien && (RTX_FRAME_RELATED_P (XVECEXP (expr, 0, par_index)) 130190075Sobrien || par_index == 0)) 130290075Sobrien dwarf2out_frame_debug_expr (XVECEXP (expr, 0, par_index), label); 130390075Sobrien 130450397Sobrien return; 130550397Sobrien } 130690075Sobrien 130752284Sobrien if (GET_CODE (expr) != SET) 130850397Sobrien abort (); 130950397Sobrien 131052284Sobrien src = SET_SRC (expr); 131152284Sobrien dest = SET_DEST (expr); 131250397Sobrien 131350397Sobrien switch (GET_CODE (dest)) 131450397Sobrien { 131550397Sobrien case REG: 131690075Sobrien /* Rule 1 */ 131750397Sobrien /* Update the CFA rule wrt SP or FP. Make sure src is 131852284Sobrien relative to the current CFA register. */ 131950397Sobrien switch (GET_CODE (src)) 132090075Sobrien { 132190075Sobrien /* Setting FP from SP. */ 132290075Sobrien case REG: 132390075Sobrien if (cfa.reg == (unsigned) REGNO (src)) 132490075Sobrien /* OK. */ 132590075Sobrien ; 132690075Sobrien else 132790075Sobrien abort (); 132850397Sobrien 132990075Sobrien /* We used to require that dest be either SP or FP, but the 133090075Sobrien ARM copies SP to a temporary register, and from there to 133190075Sobrien FP. So we just rely on the backends to only set 133290075Sobrien RTX_FRAME_RELATED_P on appropriate insns. */ 133390075Sobrien cfa.reg = REGNO (dest); 133490075Sobrien cfa_temp.reg = cfa.reg; 133590075Sobrien cfa_temp.offset = cfa.offset; 133690075Sobrien break; 133750397Sobrien 133890075Sobrien case PLUS: 133990075Sobrien case MINUS: 134090075Sobrien case LO_SUM: 134190075Sobrien if (dest == stack_pointer_rtx) 134290075Sobrien { 134390075Sobrien /* Rule 2 */ 134490075Sobrien /* Adjusting SP. */ 134590075Sobrien switch (GET_CODE (XEXP (src, 1))) 134690075Sobrien { 134790075Sobrien case CONST_INT: 134890075Sobrien offset = INTVAL (XEXP (src, 1)); 134990075Sobrien break; 135090075Sobrien case REG: 135190075Sobrien if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg) 135290075Sobrien abort (); 135390075Sobrien offset = cfa_temp.offset; 135490075Sobrien break; 135590075Sobrien default: 135690075Sobrien abort (); 135790075Sobrien } 135850397Sobrien 135990075Sobrien if (XEXP (src, 0) == hard_frame_pointer_rtx) 136090075Sobrien { 136190075Sobrien /* Restoring SP from FP in the epilogue. */ 136290075Sobrien if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM) 136390075Sobrien abort (); 136490075Sobrien cfa.reg = STACK_POINTER_REGNUM; 136590075Sobrien } 136690075Sobrien else if (GET_CODE (src) == LO_SUM) 136790075Sobrien /* Assume we've set the source reg of the LO_SUM from sp. */ 136890075Sobrien ; 136990075Sobrien else if (XEXP (src, 0) != stack_pointer_rtx) 137090075Sobrien abort (); 137150397Sobrien 137290075Sobrien if (GET_CODE (src) != MINUS) 137390075Sobrien offset = -offset; 137490075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 137590075Sobrien cfa.offset += offset; 137690075Sobrien if (cfa_store.reg == STACK_POINTER_REGNUM) 137790075Sobrien cfa_store.offset += offset; 137890075Sobrien } 137990075Sobrien else if (dest == hard_frame_pointer_rtx) 138090075Sobrien { 138190075Sobrien /* Rule 3 */ 138290075Sobrien /* Either setting the FP from an offset of the SP, 138390075Sobrien or adjusting the FP */ 138490075Sobrien if (! frame_pointer_needed) 138590075Sobrien abort (); 138650397Sobrien 138790075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 138890075Sobrien && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg 138990075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 139090075Sobrien { 139190075Sobrien offset = INTVAL (XEXP (src, 1)); 139290075Sobrien if (GET_CODE (src) != MINUS) 139390075Sobrien offset = -offset; 139490075Sobrien cfa.offset += offset; 139590075Sobrien cfa.reg = HARD_FRAME_POINTER_REGNUM; 139690075Sobrien } 139790075Sobrien else 139890075Sobrien abort (); 139990075Sobrien } 140090075Sobrien else 140190075Sobrien { 140290075Sobrien if (GET_CODE (src) == MINUS) 140390075Sobrien abort (); 140450397Sobrien 140590075Sobrien /* Rule 4 */ 140690075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 140790075Sobrien && REGNO (XEXP (src, 0)) == cfa.reg 140890075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 140990075Sobrien { 141090075Sobrien /* Setting a temporary CFA register that will be copied 141190075Sobrien into the FP later on. */ 141290075Sobrien offset = - INTVAL (XEXP (src, 1)); 141390075Sobrien cfa.offset += offset; 141490075Sobrien cfa.reg = REGNO (dest); 141590075Sobrien /* Or used to save regs to the stack. */ 141690075Sobrien cfa_temp.reg = cfa.reg; 141790075Sobrien cfa_temp.offset = cfa.offset; 141890075Sobrien } 141950397Sobrien 142090075Sobrien /* Rule 5 */ 142190075Sobrien else if (GET_CODE (XEXP (src, 0)) == REG 142290075Sobrien && REGNO (XEXP (src, 0)) == cfa_temp.reg 142390075Sobrien && XEXP (src, 1) == stack_pointer_rtx) 142490075Sobrien { 142590075Sobrien /* Setting a scratch register that we will use instead 142690075Sobrien of SP for saving registers to the stack. */ 142790075Sobrien if (cfa.reg != STACK_POINTER_REGNUM) 142890075Sobrien abort (); 142990075Sobrien cfa_store.reg = REGNO (dest); 143090075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset; 143190075Sobrien } 143250397Sobrien 143390075Sobrien /* Rule 9 */ 143490075Sobrien else if (GET_CODE (src) == LO_SUM 143590075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 143690075Sobrien { 143790075Sobrien cfa_temp.reg = REGNO (dest); 143890075Sobrien cfa_temp.offset = INTVAL (XEXP (src, 1)); 143990075Sobrien } 144090075Sobrien else 144190075Sobrien abort (); 144290075Sobrien } 144390075Sobrien break; 144450397Sobrien 144590075Sobrien /* Rule 6 */ 144690075Sobrien case CONST_INT: 144790075Sobrien cfa_temp.reg = REGNO (dest); 144890075Sobrien cfa_temp.offset = INTVAL (src); 144990075Sobrien break; 145050397Sobrien 145190075Sobrien /* Rule 7 */ 145290075Sobrien case IOR: 145390075Sobrien if (GET_CODE (XEXP (src, 0)) != REG 145490075Sobrien || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg 145590075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 145690075Sobrien abort (); 145750397Sobrien 145890075Sobrien if ((unsigned) REGNO (dest) != cfa_temp.reg) 145990075Sobrien cfa_temp.reg = REGNO (dest); 146090075Sobrien cfa_temp.offset |= INTVAL (XEXP (src, 1)); 146190075Sobrien break; 146250397Sobrien 146390075Sobrien /* Skip over HIGH, assuming it will be followed by a LO_SUM, 146490075Sobrien which will fill in all of the bits. */ 146590075Sobrien /* Rule 8 */ 146690075Sobrien case HIGH: 146790075Sobrien break; 146850397Sobrien 146990075Sobrien default: 147090075Sobrien abort (); 147190075Sobrien } 147250397Sobrien 147390075Sobrien def_cfa_1 (label, &cfa); 147490075Sobrien break; 147550397Sobrien 147690075Sobrien case MEM: 147790075Sobrien if (GET_CODE (src) != REG) 147890075Sobrien abort (); 147952284Sobrien 148090075Sobrien /* Saving a register to the stack. Make sure dest is relative to the 148190075Sobrien CFA register. */ 148290075Sobrien switch (GET_CODE (XEXP (dest, 0))) 148390075Sobrien { 148490075Sobrien /* Rule 10 */ 148590075Sobrien /* With a push. */ 148690075Sobrien case PRE_MODIFY: 148790075Sobrien /* We can't handle variable size modifications. */ 148890075Sobrien if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT) 148990075Sobrien abort (); 149090075Sobrien offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)); 149190075Sobrien 149290075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 149390075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 149490075Sobrien abort (); 149590075Sobrien 149690075Sobrien cfa_store.offset += offset; 149790075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 149890075Sobrien cfa.offset = cfa_store.offset; 149990075Sobrien 150090075Sobrien offset = -cfa_store.offset; 150190075Sobrien break; 150290075Sobrien 150390075Sobrien /* Rule 11 */ 150490075Sobrien case PRE_INC: 150590075Sobrien case PRE_DEC: 150690075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 150790075Sobrien if (GET_CODE (XEXP (dest, 0)) == PRE_INC) 150890075Sobrien offset = -offset; 150990075Sobrien 151090075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 151190075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 151290075Sobrien abort (); 151390075Sobrien 151490075Sobrien cfa_store.offset += offset; 151590075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 151690075Sobrien cfa.offset = cfa_store.offset; 151790075Sobrien 151890075Sobrien offset = -cfa_store.offset; 151990075Sobrien break; 152090075Sobrien 152190075Sobrien /* Rule 12 */ 152290075Sobrien /* With an offset. */ 152390075Sobrien case PLUS: 152490075Sobrien case MINUS: 152590075Sobrien case LO_SUM: 152690075Sobrien if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT) 152790075Sobrien abort (); 152890075Sobrien offset = INTVAL (XEXP (XEXP (dest, 0), 1)); 152990075Sobrien if (GET_CODE (XEXP (dest, 0)) == MINUS) 153090075Sobrien offset = -offset; 153190075Sobrien 153290075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153390075Sobrien offset -= cfa_store.offset; 153490075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153590075Sobrien offset -= cfa_temp.offset; 153690075Sobrien else 153790075Sobrien abort (); 153890075Sobrien break; 153990075Sobrien 154090075Sobrien /* Rule 13 */ 154190075Sobrien /* Without an offset. */ 154290075Sobrien case REG: 154390075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0))) 154490075Sobrien offset = -cfa_store.offset; 154590075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0))) 154690075Sobrien offset = -cfa_temp.offset; 154790075Sobrien else 154890075Sobrien abort (); 154990075Sobrien break; 155090075Sobrien 155190075Sobrien /* Rule 14 */ 155290075Sobrien case POST_INC: 155390075Sobrien if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 155490075Sobrien abort (); 155590075Sobrien offset = -cfa_temp.offset; 155690075Sobrien cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest)); 155790075Sobrien break; 155890075Sobrien 155990075Sobrien default: 156090075Sobrien abort (); 156190075Sobrien } 156290075Sobrien 156390075Sobrien if (REGNO (src) != STACK_POINTER_REGNUM 156490075Sobrien && REGNO (src) != HARD_FRAME_POINTER_REGNUM 156590075Sobrien && (unsigned) REGNO (src) == cfa.reg) 156690075Sobrien { 156790075Sobrien /* We're storing the current CFA reg into the stack. */ 156890075Sobrien 156990075Sobrien if (cfa.offset == 0) 157090075Sobrien { 157190075Sobrien /* If the source register is exactly the CFA, assume 157290075Sobrien we're saving SP like any other register; this happens 157390075Sobrien on the ARM. */ 157490075Sobrien def_cfa_1 (label, &cfa); 157590075Sobrien queue_reg_save (label, stack_pointer_rtx, offset); 157690075Sobrien break; 157790075Sobrien } 157890075Sobrien else 157990075Sobrien { 158090075Sobrien /* Otherwise, we'll need to look in the stack to 158190075Sobrien calculate the CFA. */ 158290075Sobrien rtx x = XEXP (dest, 0); 158390075Sobrien 158490075Sobrien if (GET_CODE (x) != REG) 158590075Sobrien x = XEXP (x, 0); 158690075Sobrien if (GET_CODE (x) != REG) 158790075Sobrien abort (); 158890075Sobrien 158990075Sobrien cfa.reg = REGNO (x); 159090075Sobrien cfa.base_offset = offset; 159190075Sobrien cfa.indirect = 1; 159290075Sobrien def_cfa_1 (label, &cfa); 159390075Sobrien break; 159490075Sobrien } 159590075Sobrien } 159690075Sobrien 159790075Sobrien def_cfa_1 (label, &cfa); 159890075Sobrien queue_reg_save (label, src, offset); 159990075Sobrien break; 160090075Sobrien 160190075Sobrien default: 160290075Sobrien abort (); 160390075Sobrien } 160452284Sobrien} 160552284Sobrien 160652284Sobrien/* Record call frame debugging information for INSN, which either 160752284Sobrien sets SP or FP (adjusting how we calculate the frame address) or saves a 160852284Sobrien register to the stack. If INSN is NULL_RTX, initialize our state. */ 160952284Sobrien 161052284Sobrienvoid 161152284Sobriendwarf2out_frame_debug (insn) 161252284Sobrien rtx insn; 161352284Sobrien{ 161490075Sobrien const char *label; 161552284Sobrien rtx src; 161652284Sobrien 161752284Sobrien if (insn == NULL_RTX) 161852284Sobrien { 161990075Sobrien /* Flush any queued register saves. */ 162090075Sobrien flush_queued_reg_saves (); 162190075Sobrien 162252284Sobrien /* Set up state for generating call frame debug info. */ 162390075Sobrien lookup_cfa (&cfa); 162490075Sobrien if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)) 162552284Sobrien abort (); 162690075Sobrien 162790075Sobrien cfa.reg = STACK_POINTER_REGNUM; 162890075Sobrien cfa_store = cfa; 162990075Sobrien cfa_temp.reg = -1; 163090075Sobrien cfa_temp.offset = 0; 163152284Sobrien return; 163250397Sobrien } 163352284Sobrien 163490075Sobrien if (GET_CODE (insn) != INSN || clobbers_queued_reg_save (insn)) 163590075Sobrien flush_queued_reg_saves (); 163690075Sobrien 163752284Sobrien if (! RTX_FRAME_RELATED_P (insn)) 163852284Sobrien { 163990075Sobrien if (!ACCUMULATE_OUTGOING_ARGS) 164090075Sobrien dwarf2out_stack_adjust (insn); 164190075Sobrien 164252284Sobrien return; 164352284Sobrien } 164452284Sobrien 164552284Sobrien label = dwarf2out_cfi_label (); 164652284Sobrien src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 164752284Sobrien if (src) 164852284Sobrien insn = XEXP (src, 0); 164990075Sobrien else 165052284Sobrien insn = PATTERN (insn); 165152284Sobrien 165252284Sobrien dwarf2out_frame_debug_expr (insn, label); 165350397Sobrien} 165450397Sobrien 165550397Sobrien/* Output a Call Frame Information opcode and its operand(s). */ 165650397Sobrien 165750397Sobrienstatic void 165890075Sobrienoutput_cfi (cfi, fde, for_eh) 165990075Sobrien dw_cfi_ref cfi; 166090075Sobrien dw_fde_ref fde; 166190075Sobrien int for_eh; 166250397Sobrien{ 166350397Sobrien if (cfi->dw_cfi_opc == DW_CFA_advance_loc) 166490075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 166590075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)), 166690075Sobrien "DW_CFA_advance_loc 0x%lx", 166790075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset); 166850397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_offset) 166950397Sobrien { 167090075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167190075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 167290075Sobrien "DW_CFA_offset, column 0x%lx", 167390075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 167490075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 167550397Sobrien } 167650397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_restore) 167790075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167890075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 167990075Sobrien "DW_CFA_restore, column 0x%lx", 168090075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 168150397Sobrien else 168250397Sobrien { 168390075Sobrien dw2_asm_output_data (1, cfi->dw_cfi_opc, 168490075Sobrien "%s", dwarf_cfi_name (cfi->dw_cfi_opc)); 168550397Sobrien 168650397Sobrien switch (cfi->dw_cfi_opc) 168750397Sobrien { 168850397Sobrien case DW_CFA_set_loc: 168990075Sobrien if (for_eh) 169090075Sobrien dw2_asm_output_encoded_addr_rtx ( 169190075Sobrien ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0), 169290075Sobrien gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr), 169390075Sobrien NULL); 169490075Sobrien else 169590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, 169690075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL); 169750397Sobrien break; 169890075Sobrien 169950397Sobrien case DW_CFA_advance_loc1: 170090075Sobrien dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170190075Sobrien fde->dw_fde_current_label, NULL); 170250397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 170350397Sobrien break; 170490075Sobrien 170550397Sobrien case DW_CFA_advance_loc2: 170690075Sobrien dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170790075Sobrien fde->dw_fde_current_label, NULL); 170850397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 170950397Sobrien break; 171090075Sobrien 171150397Sobrien case DW_CFA_advance_loc4: 171290075Sobrien dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr, 171390075Sobrien fde->dw_fde_current_label, NULL); 171450397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 171550397Sobrien break; 171690075Sobrien 171750397Sobrien case DW_CFA_MIPS_advance_loc8: 171890075Sobrien dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr, 171990075Sobrien fde->dw_fde_current_label, NULL); 172090075Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 172150397Sobrien break; 172290075Sobrien 172350397Sobrien case DW_CFA_offset_extended: 172450397Sobrien case DW_CFA_def_cfa: 172590075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 172690075Sobrien NULL); 172790075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 172850397Sobrien break; 172990075Sobrien 173090075Sobrien case DW_CFA_offset_extended_sf: 173190075Sobrien case DW_CFA_def_cfa_sf: 173290075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 173390075Sobrien NULL); 173490075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 173590075Sobrien break; 173690075Sobrien 173750397Sobrien case DW_CFA_restore_extended: 173850397Sobrien case DW_CFA_undefined: 173950397Sobrien case DW_CFA_same_value: 174050397Sobrien case DW_CFA_def_cfa_register: 174190075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174290075Sobrien NULL); 174350397Sobrien break; 174490075Sobrien 174550397Sobrien case DW_CFA_register: 174690075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174790075Sobrien NULL); 174890075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 174990075Sobrien NULL); 175050397Sobrien break; 175190075Sobrien 175250397Sobrien case DW_CFA_def_cfa_offset: 175390075Sobrien case DW_CFA_GNU_args_size: 175490075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 175550397Sobrien break; 175690075Sobrien 175790075Sobrien case DW_CFA_def_cfa_offset_sf: 175890075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 175990075Sobrien break; 176090075Sobrien 176150397Sobrien case DW_CFA_GNU_window_save: 176250397Sobrien break; 176390075Sobrien 176490075Sobrien case DW_CFA_def_cfa_expression: 176590075Sobrien case DW_CFA_expression: 176690075Sobrien output_cfa_loc (cfi); 176750397Sobrien break; 176890075Sobrien 176990075Sobrien case DW_CFA_GNU_negative_offset_extended: 177090075Sobrien /* Obsoleted by DW_CFA_offset_extended_sf. */ 177190075Sobrien abort (); 177290075Sobrien 177350397Sobrien default: 177450397Sobrien break; 177550397Sobrien } 177690075Sobrien } 177750397Sobrien} 177850397Sobrien 177950397Sobrien/* Output the call frame information used to used to record information 178050397Sobrien that relates to calculating the frame pointer, and records the 178150397Sobrien location of saved registers. */ 178250397Sobrien 178350397Sobrienstatic void 178450397Sobrienoutput_call_frame_info (for_eh) 178550397Sobrien int for_eh; 178650397Sobrien{ 178790075Sobrien unsigned int i; 178890075Sobrien dw_fde_ref fde; 178990075Sobrien dw_cfi_ref cfi; 179090075Sobrien char l1[20], l2[20], section_start_label[20]; 179190075Sobrien int any_lsda_needed = 0; 179290075Sobrien char augmentation[6]; 179390075Sobrien int augmentation_size; 179490075Sobrien int fde_encoding = DW_EH_PE_absptr; 179590075Sobrien int per_encoding = DW_EH_PE_absptr; 179690075Sobrien int lsda_encoding = DW_EH_PE_absptr; 179750397Sobrien 179890075Sobrien /* If we don't have any functions we'll want to unwind out of, don't emit any 179990075Sobrien EH unwind information. */ 180090075Sobrien if (for_eh) 180190075Sobrien { 180290075Sobrien int any_eh_needed = flag_asynchronous_unwind_tables; 180350397Sobrien 180490075Sobrien for (i = 0; i < fde_table_in_use; i++) 180590075Sobrien if (fde_table[i].uses_eh_lsda) 180690075Sobrien any_eh_needed = any_lsda_needed = 1; 180790075Sobrien else if (! fde_table[i].nothrow) 180890075Sobrien any_eh_needed = 1; 180950397Sobrien 181090075Sobrien if (! any_eh_needed) 181190075Sobrien return; 181290075Sobrien } 181390075Sobrien 181450397Sobrien /* We're going to be generating comments, so turn on app. */ 181550397Sobrien if (flag_debug_asm) 181650397Sobrien app_enable (); 181750397Sobrien 181850397Sobrien if (for_eh) 181990075Sobrien (*targetm.asm_out.eh_frame_section) (); 182050397Sobrien else 182190075Sobrien named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG); 182250397Sobrien 182390075Sobrien ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh); 182490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, section_start_label); 182590075Sobrien 182690075Sobrien /* Output the CIE. */ 182750397Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); 182850397Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); 182990075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 183090075Sobrien "Length of Common Information Entry"); 183150397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 183250397Sobrien 183390075Sobrien /* Now that the CIE pointer is PC-relative for EH, 183490075Sobrien use 0 to identify the CIE. */ 183590075Sobrien dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE), 183690075Sobrien (for_eh ? 0 : DW_CIE_ID), 183790075Sobrien "CIE Identifier Tag"); 183850397Sobrien 183990075Sobrien dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version"); 184050397Sobrien 184190075Sobrien augmentation[0] = 0; 184290075Sobrien augmentation_size = 0; 184390075Sobrien if (for_eh) 184450397Sobrien { 184590075Sobrien char *p; 184650397Sobrien 184790075Sobrien /* Augmentation: 184890075Sobrien z Indicates that a uleb128 is present to size the 184990075Sobrien augmentation section. 185090075Sobrien L Indicates the encoding (and thus presence) of 185190075Sobrien an LSDA pointer in the FDE augmentation. 185290075Sobrien R Indicates a non-default pointer encoding for 185390075Sobrien FDE code pointers. 185490075Sobrien P Indicates the presence of an encoding + language 185590075Sobrien personality routine in the CIE augmentation. */ 185650397Sobrien 185790075Sobrien fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0); 185890075Sobrien per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); 185990075Sobrien lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); 186090075Sobrien 186190075Sobrien p = augmentation + 1; 186290075Sobrien if (eh_personality_libfunc) 186350397Sobrien { 186490075Sobrien *p++ = 'P'; 186590075Sobrien augmentation_size += 1 + size_of_encoded_value (per_encoding); 186650397Sobrien } 186790075Sobrien if (any_lsda_needed) 186850397Sobrien { 186990075Sobrien *p++ = 'L'; 187090075Sobrien augmentation_size += 1; 187150397Sobrien } 187290075Sobrien if (fde_encoding != DW_EH_PE_absptr) 187390075Sobrien { 187490075Sobrien *p++ = 'R'; 187590075Sobrien augmentation_size += 1; 187690075Sobrien } 187790075Sobrien if (p > augmentation + 1) 187890075Sobrien { 187990075Sobrien augmentation[0] = 'z'; 188090075Sobrien *p = '\0'; 188190075Sobrien } 188250397Sobrien 188390075Sobrien /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ 188490075Sobrien if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) 188590075Sobrien { 188690075Sobrien int offset = ( 4 /* Length */ 188790075Sobrien + 4 /* CIE Id */ 188890075Sobrien + 1 /* CIE version */ 188990075Sobrien + strlen (augmentation) + 1 /* Augmentation */ 189090075Sobrien + size_of_uleb128 (1) /* Code alignment */ 189190075Sobrien + size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT) 189290075Sobrien + 1 /* RA column */ 189390075Sobrien + 1 /* Augmentation size */ 189490075Sobrien + 1 /* Personality encoding */ ); 189590075Sobrien int pad = -offset & (PTR_SIZE - 1); 189690075Sobrien 189790075Sobrien augmentation_size += pad; 189890075Sobrien 189990075Sobrien /* Augmentations should be small, so there's scarce need to 190090075Sobrien iterate for a solution. Die if we exceed one uleb128 byte. */ 190190075Sobrien if (size_of_uleb128 (augmentation_size) != 1) 190290075Sobrien abort (); 190390075Sobrien } 190450397Sobrien } 190550397Sobrien 190690075Sobrien dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); 190790075Sobrien dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); 190890075Sobrien dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT, 190990075Sobrien "CIE Data Alignment Factor"); 191090075Sobrien dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column"); 191150397Sobrien 191290075Sobrien if (augmentation[0]) 191390075Sobrien { 191490075Sobrien dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); 191590075Sobrien if (eh_personality_libfunc) 191690075Sobrien { 191790075Sobrien dw2_asm_output_data (1, per_encoding, "Personality (%s)", 191890075Sobrien eh_data_format_name (per_encoding)); 191990075Sobrien dw2_asm_output_encoded_addr_rtx (per_encoding, 192090075Sobrien eh_personality_libfunc, NULL); 192190075Sobrien } 192250397Sobrien 192390075Sobrien if (any_lsda_needed) 192490075Sobrien dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)", 192590075Sobrien eh_data_format_name (lsda_encoding)); 192650397Sobrien 192790075Sobrien if (fde_encoding != DW_EH_PE_absptr) 192890075Sobrien dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)", 192990075Sobrien eh_data_format_name (fde_encoding)); 193090075Sobrien } 193150397Sobrien 193250397Sobrien for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next) 193390075Sobrien output_cfi (cfi, NULL, for_eh); 193450397Sobrien 193550397Sobrien /* Pad the CIE out to an address sized boundary. */ 193690075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 193790075Sobrien floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)); 193850397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 193950397Sobrien 194050397Sobrien /* Loop through all of the FDE's. */ 194190075Sobrien for (i = 0; i < fde_table_in_use; i++) 194250397Sobrien { 194350397Sobrien fde = &fde_table[i]; 194450397Sobrien 194590075Sobrien /* Don't emit EH unwind info for leaf functions that don't need it. */ 194690075Sobrien if (for_eh && fde->nothrow && ! fde->uses_eh_lsda) 194790075Sobrien continue; 194890075Sobrien 194990075Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2); 195090075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2); 195190075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2); 195290075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 195390075Sobrien "FDE Length"); 195490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 195590075Sobrien 195650397Sobrien if (for_eh) 195790075Sobrien dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset"); 195850397Sobrien else 195990075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label, 196090075Sobrien "FDE CIE offset"); 196150397Sobrien 196250397Sobrien if (for_eh) 196390075Sobrien { 196490075Sobrien dw2_asm_output_encoded_addr_rtx (fde_encoding, 196590075Sobrien gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin), 196690075Sobrien "FDE initial location"); 196790075Sobrien dw2_asm_output_delta (size_of_encoded_value (fde_encoding), 196890075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 196990075Sobrien "FDE address range"); 197090075Sobrien } 197150397Sobrien else 197290075Sobrien { 197390075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, 197490075Sobrien "FDE initial location"); 197590075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, 197690075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 197790075Sobrien "FDE address range"); 197890075Sobrien } 197950397Sobrien 198090075Sobrien if (augmentation[0]) 198190075Sobrien { 198290075Sobrien if (any_lsda_needed) 198390075Sobrien { 198490075Sobrien int size = size_of_encoded_value (lsda_encoding); 198550397Sobrien 198690075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 198790075Sobrien { 198890075Sobrien int offset = ( 4 /* Length */ 198990075Sobrien + 4 /* CIE offset */ 199090075Sobrien + 2 * size_of_encoded_value (fde_encoding) 199190075Sobrien + 1 /* Augmentation size */ ); 199290075Sobrien int pad = -offset & (PTR_SIZE - 1); 199350397Sobrien 199490075Sobrien size += pad; 199590075Sobrien if (size_of_uleb128 (size) != 1) 199690075Sobrien abort (); 199790075Sobrien } 199850397Sobrien 199990075Sobrien dw2_asm_output_data_uleb128 (size, "Augmentation size"); 200090075Sobrien 200190075Sobrien if (fde->uses_eh_lsda) 200290075Sobrien { 200390075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", 200490075Sobrien fde->funcdef_number); 200590075Sobrien dw2_asm_output_encoded_addr_rtx ( 200690075Sobrien lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1), 200790075Sobrien "Language Specific Data Area"); 200890075Sobrien } 200990075Sobrien else 201090075Sobrien { 201190075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 201290075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 201390075Sobrien dw2_asm_output_data 201490075Sobrien (size_of_encoded_value (lsda_encoding), 0, 201590075Sobrien "Language Specific Data Area (none)"); 201690075Sobrien } 201790075Sobrien } 201890075Sobrien else 201990075Sobrien dw2_asm_output_data_uleb128 (0, "Augmentation size"); 202090075Sobrien } 202190075Sobrien 202250397Sobrien /* Loop through the Call Frame Instructions associated with 202350397Sobrien this FDE. */ 202450397Sobrien fde->dw_fde_current_label = fde->dw_fde_begin; 202550397Sobrien for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) 202690075Sobrien output_cfi (cfi, fde, for_eh); 202750397Sobrien 202850397Sobrien /* Pad the FDE out to an address sized boundary. */ 202990075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 203090075Sobrien floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); 203150397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 203250397Sobrien } 203390075Sobrien 203490075Sobrien#ifndef EH_FRAME_SECTION_NAME 203550397Sobrien if (for_eh) 203690075Sobrien dw2_asm_output_data (4, 0, "End of Table"); 203750397Sobrien#endif 203850397Sobrien#ifdef MIPS_DEBUGGING_INFO 203950397Sobrien /* Work around Irix 6 assembler bug whereby labels at the end of a section 204050397Sobrien get a value of 0. Putting .align 0 after the label fixes it. */ 204150397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 0); 204250397Sobrien#endif 204350397Sobrien 204450397Sobrien /* Turn off app to make assembly quicker. */ 204550397Sobrien if (flag_debug_asm) 204650397Sobrien app_disable (); 204750397Sobrien} 204850397Sobrien 204950397Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before 205050397Sobrien the prologue. */ 205150397Sobrien 205250397Sobrienvoid 205390075Sobriendwarf2out_begin_prologue (line, file) 205490075Sobrien unsigned int line ATTRIBUTE_UNUSED; 205590075Sobrien const char *file ATTRIBUTE_UNUSED; 205650397Sobrien{ 205750397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 205890075Sobrien dw_fde_ref fde; 205950397Sobrien 206090075Sobrien current_function_func_begin_label = 0; 206150397Sobrien 206290075Sobrien#ifdef IA64_UNWIND_INFO 206390075Sobrien /* ??? current_function_func_begin_label is also used by except.c 206490075Sobrien for call-site information. We must emit this label if it might 206590075Sobrien be used. */ 206690075Sobrien if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS) 206790075Sobrien && ! dwarf2out_do_frame ()) 206890075Sobrien return; 206990075Sobrien#else 207090075Sobrien if (! dwarf2out_do_frame ()) 207190075Sobrien return; 207290075Sobrien#endif 207390075Sobrien 207490075Sobrien current_funcdef_number++; 207550397Sobrien function_section (current_function_decl); 207650397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 207750397Sobrien current_funcdef_number); 207890075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL, 207990075Sobrien current_funcdef_number); 208090075Sobrien current_function_func_begin_label = get_identifier (label); 208150397Sobrien 208290075Sobrien#ifdef IA64_UNWIND_INFO 208390075Sobrien /* We can elide the fde allocation if we're not emitting debug info. */ 208490075Sobrien if (! dwarf2out_do_frame ()) 208590075Sobrien return; 208690075Sobrien#endif 208790075Sobrien 208850397Sobrien /* Expand the fde table if necessary. */ 208950397Sobrien if (fde_table_in_use == fde_table_allocated) 209050397Sobrien { 209150397Sobrien fde_table_allocated += FDE_TABLE_INCREMENT; 209250397Sobrien fde_table 209350397Sobrien = (dw_fde_ref) xrealloc (fde_table, 209450397Sobrien fde_table_allocated * sizeof (dw_fde_node)); 209550397Sobrien } 209650397Sobrien 209750397Sobrien /* Record the FDE associated with this function. */ 209850397Sobrien current_funcdef_fde = fde_table_in_use; 209950397Sobrien 210050397Sobrien /* Add the new FDE at the end of the fde_table. */ 210150397Sobrien fde = &fde_table[fde_table_in_use++]; 210250397Sobrien fde->dw_fde_begin = xstrdup (label); 210350397Sobrien fde->dw_fde_current_label = NULL; 210450397Sobrien fde->dw_fde_end = NULL; 210550397Sobrien fde->dw_fde_cfi = NULL; 210690075Sobrien fde->funcdef_number = current_funcdef_number; 210790075Sobrien fde->nothrow = current_function_nothrow; 210890075Sobrien fde->uses_eh_lsda = cfun->uses_eh_lsda; 210950397Sobrien 211050397Sobrien args_size = old_args_size = 0; 211190075Sobrien 211290075Sobrien /* We only want to output line number information for the genuine dwarf2 211390075Sobrien prologue case, not the eh frame case. */ 211490075Sobrien#ifdef DWARF2_DEBUGGING_INFO 211590075Sobrien if (file) 211690075Sobrien dwarf2out_source_line (line, file); 211790075Sobrien#endif 211850397Sobrien} 211950397Sobrien 212050397Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code 212150397Sobrien for a function definition. This gets called *after* the epilogue code has 212250397Sobrien been generated. */ 212350397Sobrien 212450397Sobrienvoid 212550397Sobriendwarf2out_end_epilogue () 212650397Sobrien{ 212750397Sobrien dw_fde_ref fde; 212850397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 212950397Sobrien 213050397Sobrien /* Output a label to mark the endpoint of the code generated for this 213190075Sobrien function. */ 213250397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number); 213350397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 213450397Sobrien fde = &fde_table[fde_table_in_use - 1]; 213550397Sobrien fde->dw_fde_end = xstrdup (label); 213650397Sobrien} 213750397Sobrien 213850397Sobrienvoid 213950397Sobriendwarf2out_frame_init () 214050397Sobrien{ 214150397Sobrien /* Allocate the initial hunk of the fde_table. */ 214290075Sobrien fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node)); 214350397Sobrien fde_table_allocated = FDE_TABLE_INCREMENT; 214450397Sobrien fde_table_in_use = 0; 214550397Sobrien 214650397Sobrien /* Generate the CFA instructions common to all FDE's. Do it now for the 214750397Sobrien sake of lookup_cfa. */ 214850397Sobrien 214950397Sobrien#ifdef DWARF2_UNWIND_INFO 215050397Sobrien /* On entry, the Canonical Frame Address is at SP. */ 215150397Sobrien dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); 215250397Sobrien initial_return_save (INCOMING_RETURN_ADDR_RTX); 215350397Sobrien#endif 215450397Sobrien} 215550397Sobrien 215650397Sobrienvoid 215750397Sobriendwarf2out_frame_finish () 215850397Sobrien{ 215950397Sobrien /* Output call frame information. */ 216090075Sobrien if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) 216150397Sobrien output_call_frame_info (0); 216290075Sobrien 216390075Sobrien if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions)) 216450397Sobrien output_call_frame_info (1); 216590075Sobrien} 216690075Sobrien 216790075Sobrien/* And now, the subset of the debugging information support code necessary 216890075Sobrien for emitting location expressions. */ 216950397Sobrien 217090075Sobrientypedef struct dw_val_struct *dw_val_ref; 217190075Sobrientypedef struct die_struct *dw_die_ref; 217290075Sobrientypedef struct dw_loc_descr_struct *dw_loc_descr_ref; 217390075Sobrientypedef struct dw_loc_list_struct *dw_loc_list_ref; 217450397Sobrien 217550397Sobrien/* Each DIE may have a series of attribute/value pairs. Values 217650397Sobrien can take on several forms. The forms that are used in this 217750397Sobrien implementation are listed below. */ 217850397Sobrien 217950397Sobrientypedef enum 218050397Sobrien{ 218150397Sobrien dw_val_class_addr, 218290075Sobrien dw_val_class_offset, 218350397Sobrien dw_val_class_loc, 218490075Sobrien dw_val_class_loc_list, 218590075Sobrien dw_val_class_range_list, 218650397Sobrien dw_val_class_const, 218750397Sobrien dw_val_class_unsigned_const, 218850397Sobrien dw_val_class_long_long, 218950397Sobrien dw_val_class_float, 219050397Sobrien dw_val_class_flag, 219150397Sobrien dw_val_class_die_ref, 219250397Sobrien dw_val_class_fde_ref, 219350397Sobrien dw_val_class_lbl_id, 219452284Sobrien dw_val_class_lbl_offset, 219550397Sobrien dw_val_class_str 219650397Sobrien} 219750397Sobriendw_val_class; 219850397Sobrien 219950397Sobrien/* Describe a double word constant value. */ 220090075Sobrien/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */ 220150397Sobrien 220250397Sobrientypedef struct dw_long_long_struct 220350397Sobrien{ 220450397Sobrien unsigned long hi; 220550397Sobrien unsigned long low; 220650397Sobrien} 220750397Sobriendw_long_long_const; 220850397Sobrien 220950397Sobrien/* Describe a floating point constant value. */ 221050397Sobrien 221150397Sobrientypedef struct dw_fp_struct 221250397Sobrien{ 221350397Sobrien long *array; 221450397Sobrien unsigned length; 221550397Sobrien} 221650397Sobriendw_float_const; 221750397Sobrien 221850397Sobrien/* The dw_val_node describes an attribute's value, as it is 221950397Sobrien represented internally. */ 222050397Sobrien 222150397Sobrientypedef struct dw_val_struct 222250397Sobrien{ 222350397Sobrien dw_val_class val_class; 222450397Sobrien union 222550397Sobrien { 222690075Sobrien rtx val_addr; 222790075Sobrien long unsigned val_offset; 222890075Sobrien dw_loc_list_ref val_loc_list; 222950397Sobrien dw_loc_descr_ref val_loc; 223050397Sobrien long int val_int; 223150397Sobrien long unsigned val_unsigned; 223250397Sobrien dw_long_long_const val_long_long; 223350397Sobrien dw_float_const val_float; 223490075Sobrien struct 223590075Sobrien { 223690075Sobrien dw_die_ref die; 223790075Sobrien int external; 223890075Sobrien } val_die_ref; 223950397Sobrien unsigned val_fde_index; 224090075Sobrien struct indirect_string_node *val_str; 224150397Sobrien char *val_lbl_id; 224250397Sobrien unsigned char val_flag; 224350397Sobrien } 224450397Sobrien v; 224550397Sobrien} 224650397Sobriendw_val_node; 224750397Sobrien 224850397Sobrien/* Locations in memory are described using a sequence of stack machine 224950397Sobrien operations. */ 225050397Sobrien 225150397Sobrientypedef struct dw_loc_descr_struct 225250397Sobrien{ 225350397Sobrien dw_loc_descr_ref dw_loc_next; 225450397Sobrien enum dwarf_location_atom dw_loc_opc; 225550397Sobrien dw_val_node dw_loc_oprnd1; 225650397Sobrien dw_val_node dw_loc_oprnd2; 225790075Sobrien int dw_loc_addr; 225850397Sobrien} 225950397Sobriendw_loc_descr_node; 226050397Sobrien 226190075Sobrien/* Location lists are ranges + location descriptions for that range, 226290075Sobrien so you can track variables that are in different places over 226390075Sobrien their entire life. */ 226490075Sobrientypedef struct dw_loc_list_struct 226590075Sobrien{ 226690075Sobrien dw_loc_list_ref dw_loc_next; 226790075Sobrien const char *begin; /* Label for begin address of range */ 226890075Sobrien const char *end; /* Label for end address of range */ 226990075Sobrien char *ll_symbol; /* Label for beginning of location list. 227090075Sobrien Only on head of list */ 227190075Sobrien const char *section; /* Section this loclist is relative to */ 227290075Sobrien dw_loc_descr_ref expr; 227390075Sobrien} dw_loc_list_node; 227490075Sobrien 227590075Sobrienstatic const char *dwarf_stack_op_name PARAMS ((unsigned)); 227690075Sobrienstatic dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom, 227790075Sobrien unsigned long, 227890075Sobrien unsigned long)); 227990075Sobrienstatic void add_loc_descr PARAMS ((dw_loc_descr_ref *, 228090075Sobrien dw_loc_descr_ref)); 228190075Sobrienstatic unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref)); 228290075Sobrienstatic unsigned long size_of_locs PARAMS ((dw_loc_descr_ref)); 228390075Sobrienstatic void output_loc_operands PARAMS ((dw_loc_descr_ref)); 228490075Sobrienstatic void output_loc_sequence PARAMS ((dw_loc_descr_ref)); 228590075Sobrien 228690075Sobrien/* Convert a DWARF stack opcode into its string name. */ 228790075Sobrien 228890075Sobrienstatic const char * 228990075Sobriendwarf_stack_op_name (op) 229090075Sobrien unsigned op; 229190075Sobrien{ 229290075Sobrien switch (op) 229390075Sobrien { 229490075Sobrien case DW_OP_addr: 229590075Sobrien return "DW_OP_addr"; 229690075Sobrien case DW_OP_deref: 229790075Sobrien return "DW_OP_deref"; 229890075Sobrien case DW_OP_const1u: 229990075Sobrien return "DW_OP_const1u"; 230090075Sobrien case DW_OP_const1s: 230190075Sobrien return "DW_OP_const1s"; 230290075Sobrien case DW_OP_const2u: 230390075Sobrien return "DW_OP_const2u"; 230490075Sobrien case DW_OP_const2s: 230590075Sobrien return "DW_OP_const2s"; 230690075Sobrien case DW_OP_const4u: 230790075Sobrien return "DW_OP_const4u"; 230890075Sobrien case DW_OP_const4s: 230990075Sobrien return "DW_OP_const4s"; 231090075Sobrien case DW_OP_const8u: 231190075Sobrien return "DW_OP_const8u"; 231290075Sobrien case DW_OP_const8s: 231390075Sobrien return "DW_OP_const8s"; 231490075Sobrien case DW_OP_constu: 231590075Sobrien return "DW_OP_constu"; 231690075Sobrien case DW_OP_consts: 231790075Sobrien return "DW_OP_consts"; 231890075Sobrien case DW_OP_dup: 231990075Sobrien return "DW_OP_dup"; 232090075Sobrien case DW_OP_drop: 232190075Sobrien return "DW_OP_drop"; 232290075Sobrien case DW_OP_over: 232390075Sobrien return "DW_OP_over"; 232490075Sobrien case DW_OP_pick: 232590075Sobrien return "DW_OP_pick"; 232690075Sobrien case DW_OP_swap: 232790075Sobrien return "DW_OP_swap"; 232890075Sobrien case DW_OP_rot: 232990075Sobrien return "DW_OP_rot"; 233090075Sobrien case DW_OP_xderef: 233190075Sobrien return "DW_OP_xderef"; 233290075Sobrien case DW_OP_abs: 233390075Sobrien return "DW_OP_abs"; 233490075Sobrien case DW_OP_and: 233590075Sobrien return "DW_OP_and"; 233690075Sobrien case DW_OP_div: 233790075Sobrien return "DW_OP_div"; 233890075Sobrien case DW_OP_minus: 233990075Sobrien return "DW_OP_minus"; 234090075Sobrien case DW_OP_mod: 234190075Sobrien return "DW_OP_mod"; 234290075Sobrien case DW_OP_mul: 234390075Sobrien return "DW_OP_mul"; 234490075Sobrien case DW_OP_neg: 234590075Sobrien return "DW_OP_neg"; 234690075Sobrien case DW_OP_not: 234790075Sobrien return "DW_OP_not"; 234890075Sobrien case DW_OP_or: 234990075Sobrien return "DW_OP_or"; 235090075Sobrien case DW_OP_plus: 235190075Sobrien return "DW_OP_plus"; 235290075Sobrien case DW_OP_plus_uconst: 235390075Sobrien return "DW_OP_plus_uconst"; 235490075Sobrien case DW_OP_shl: 235590075Sobrien return "DW_OP_shl"; 235690075Sobrien case DW_OP_shr: 235790075Sobrien return "DW_OP_shr"; 235890075Sobrien case DW_OP_shra: 235990075Sobrien return "DW_OP_shra"; 236090075Sobrien case DW_OP_xor: 236190075Sobrien return "DW_OP_xor"; 236290075Sobrien case DW_OP_bra: 236390075Sobrien return "DW_OP_bra"; 236490075Sobrien case DW_OP_eq: 236590075Sobrien return "DW_OP_eq"; 236690075Sobrien case DW_OP_ge: 236790075Sobrien return "DW_OP_ge"; 236890075Sobrien case DW_OP_gt: 236990075Sobrien return "DW_OP_gt"; 237090075Sobrien case DW_OP_le: 237190075Sobrien return "DW_OP_le"; 237290075Sobrien case DW_OP_lt: 237390075Sobrien return "DW_OP_lt"; 237490075Sobrien case DW_OP_ne: 237590075Sobrien return "DW_OP_ne"; 237690075Sobrien case DW_OP_skip: 237790075Sobrien return "DW_OP_skip"; 237890075Sobrien case DW_OP_lit0: 237990075Sobrien return "DW_OP_lit0"; 238090075Sobrien case DW_OP_lit1: 238190075Sobrien return "DW_OP_lit1"; 238290075Sobrien case DW_OP_lit2: 238390075Sobrien return "DW_OP_lit2"; 238490075Sobrien case DW_OP_lit3: 238590075Sobrien return "DW_OP_lit3"; 238690075Sobrien case DW_OP_lit4: 238790075Sobrien return "DW_OP_lit4"; 238890075Sobrien case DW_OP_lit5: 238990075Sobrien return "DW_OP_lit5"; 239090075Sobrien case DW_OP_lit6: 239190075Sobrien return "DW_OP_lit6"; 239290075Sobrien case DW_OP_lit7: 239390075Sobrien return "DW_OP_lit7"; 239490075Sobrien case DW_OP_lit8: 239590075Sobrien return "DW_OP_lit8"; 239690075Sobrien case DW_OP_lit9: 239790075Sobrien return "DW_OP_lit9"; 239890075Sobrien case DW_OP_lit10: 239990075Sobrien return "DW_OP_lit10"; 240090075Sobrien case DW_OP_lit11: 240190075Sobrien return "DW_OP_lit11"; 240290075Sobrien case DW_OP_lit12: 240390075Sobrien return "DW_OP_lit12"; 240490075Sobrien case DW_OP_lit13: 240590075Sobrien return "DW_OP_lit13"; 240690075Sobrien case DW_OP_lit14: 240790075Sobrien return "DW_OP_lit14"; 240890075Sobrien case DW_OP_lit15: 240990075Sobrien return "DW_OP_lit15"; 241090075Sobrien case DW_OP_lit16: 241190075Sobrien return "DW_OP_lit16"; 241290075Sobrien case DW_OP_lit17: 241390075Sobrien return "DW_OP_lit17"; 241490075Sobrien case DW_OP_lit18: 241590075Sobrien return "DW_OP_lit18"; 241690075Sobrien case DW_OP_lit19: 241790075Sobrien return "DW_OP_lit19"; 241890075Sobrien case DW_OP_lit20: 241990075Sobrien return "DW_OP_lit20"; 242090075Sobrien case DW_OP_lit21: 242190075Sobrien return "DW_OP_lit21"; 242290075Sobrien case DW_OP_lit22: 242390075Sobrien return "DW_OP_lit22"; 242490075Sobrien case DW_OP_lit23: 242590075Sobrien return "DW_OP_lit23"; 242690075Sobrien case DW_OP_lit24: 242790075Sobrien return "DW_OP_lit24"; 242890075Sobrien case DW_OP_lit25: 242990075Sobrien return "DW_OP_lit25"; 243090075Sobrien case DW_OP_lit26: 243190075Sobrien return "DW_OP_lit26"; 243290075Sobrien case DW_OP_lit27: 243390075Sobrien return "DW_OP_lit27"; 243490075Sobrien case DW_OP_lit28: 243590075Sobrien return "DW_OP_lit28"; 243690075Sobrien case DW_OP_lit29: 243790075Sobrien return "DW_OP_lit29"; 243890075Sobrien case DW_OP_lit30: 243990075Sobrien return "DW_OP_lit30"; 244090075Sobrien case DW_OP_lit31: 244190075Sobrien return "DW_OP_lit31"; 244290075Sobrien case DW_OP_reg0: 244390075Sobrien return "DW_OP_reg0"; 244490075Sobrien case DW_OP_reg1: 244590075Sobrien return "DW_OP_reg1"; 244690075Sobrien case DW_OP_reg2: 244790075Sobrien return "DW_OP_reg2"; 244890075Sobrien case DW_OP_reg3: 244990075Sobrien return "DW_OP_reg3"; 245090075Sobrien case DW_OP_reg4: 245190075Sobrien return "DW_OP_reg4"; 245290075Sobrien case DW_OP_reg5: 245390075Sobrien return "DW_OP_reg5"; 245490075Sobrien case DW_OP_reg6: 245590075Sobrien return "DW_OP_reg6"; 245690075Sobrien case DW_OP_reg7: 245790075Sobrien return "DW_OP_reg7"; 245890075Sobrien case DW_OP_reg8: 245990075Sobrien return "DW_OP_reg8"; 246090075Sobrien case DW_OP_reg9: 246190075Sobrien return "DW_OP_reg9"; 246290075Sobrien case DW_OP_reg10: 246390075Sobrien return "DW_OP_reg10"; 246490075Sobrien case DW_OP_reg11: 246590075Sobrien return "DW_OP_reg11"; 246690075Sobrien case DW_OP_reg12: 246790075Sobrien return "DW_OP_reg12"; 246890075Sobrien case DW_OP_reg13: 246990075Sobrien return "DW_OP_reg13"; 247090075Sobrien case DW_OP_reg14: 247190075Sobrien return "DW_OP_reg14"; 247290075Sobrien case DW_OP_reg15: 247390075Sobrien return "DW_OP_reg15"; 247490075Sobrien case DW_OP_reg16: 247590075Sobrien return "DW_OP_reg16"; 247690075Sobrien case DW_OP_reg17: 247790075Sobrien return "DW_OP_reg17"; 247890075Sobrien case DW_OP_reg18: 247990075Sobrien return "DW_OP_reg18"; 248090075Sobrien case DW_OP_reg19: 248190075Sobrien return "DW_OP_reg19"; 248290075Sobrien case DW_OP_reg20: 248390075Sobrien return "DW_OP_reg20"; 248490075Sobrien case DW_OP_reg21: 248590075Sobrien return "DW_OP_reg21"; 248690075Sobrien case DW_OP_reg22: 248790075Sobrien return "DW_OP_reg22"; 248890075Sobrien case DW_OP_reg23: 248990075Sobrien return "DW_OP_reg23"; 249090075Sobrien case DW_OP_reg24: 249190075Sobrien return "DW_OP_reg24"; 249290075Sobrien case DW_OP_reg25: 249390075Sobrien return "DW_OP_reg25"; 249490075Sobrien case DW_OP_reg26: 249590075Sobrien return "DW_OP_reg26"; 249690075Sobrien case DW_OP_reg27: 249790075Sobrien return "DW_OP_reg27"; 249890075Sobrien case DW_OP_reg28: 249990075Sobrien return "DW_OP_reg28"; 250090075Sobrien case DW_OP_reg29: 250190075Sobrien return "DW_OP_reg29"; 250290075Sobrien case DW_OP_reg30: 250390075Sobrien return "DW_OP_reg30"; 250490075Sobrien case DW_OP_reg31: 250590075Sobrien return "DW_OP_reg31"; 250690075Sobrien case DW_OP_breg0: 250790075Sobrien return "DW_OP_breg0"; 250890075Sobrien case DW_OP_breg1: 250990075Sobrien return "DW_OP_breg1"; 251090075Sobrien case DW_OP_breg2: 251190075Sobrien return "DW_OP_breg2"; 251290075Sobrien case DW_OP_breg3: 251390075Sobrien return "DW_OP_breg3"; 251490075Sobrien case DW_OP_breg4: 251590075Sobrien return "DW_OP_breg4"; 251690075Sobrien case DW_OP_breg5: 251790075Sobrien return "DW_OP_breg5"; 251890075Sobrien case DW_OP_breg6: 251990075Sobrien return "DW_OP_breg6"; 252090075Sobrien case DW_OP_breg7: 252190075Sobrien return "DW_OP_breg7"; 252290075Sobrien case DW_OP_breg8: 252390075Sobrien return "DW_OP_breg8"; 252490075Sobrien case DW_OP_breg9: 252590075Sobrien return "DW_OP_breg9"; 252690075Sobrien case DW_OP_breg10: 252790075Sobrien return "DW_OP_breg10"; 252890075Sobrien case DW_OP_breg11: 252990075Sobrien return "DW_OP_breg11"; 253090075Sobrien case DW_OP_breg12: 253190075Sobrien return "DW_OP_breg12"; 253290075Sobrien case DW_OP_breg13: 253390075Sobrien return "DW_OP_breg13"; 253490075Sobrien case DW_OP_breg14: 253590075Sobrien return "DW_OP_breg14"; 253690075Sobrien case DW_OP_breg15: 253790075Sobrien return "DW_OP_breg15"; 253890075Sobrien case DW_OP_breg16: 253990075Sobrien return "DW_OP_breg16"; 254090075Sobrien case DW_OP_breg17: 254190075Sobrien return "DW_OP_breg17"; 254290075Sobrien case DW_OP_breg18: 254390075Sobrien return "DW_OP_breg18"; 254490075Sobrien case DW_OP_breg19: 254590075Sobrien return "DW_OP_breg19"; 254690075Sobrien case DW_OP_breg20: 254790075Sobrien return "DW_OP_breg20"; 254890075Sobrien case DW_OP_breg21: 254990075Sobrien return "DW_OP_breg21"; 255090075Sobrien case DW_OP_breg22: 255190075Sobrien return "DW_OP_breg22"; 255290075Sobrien case DW_OP_breg23: 255390075Sobrien return "DW_OP_breg23"; 255490075Sobrien case DW_OP_breg24: 255590075Sobrien return "DW_OP_breg24"; 255690075Sobrien case DW_OP_breg25: 255790075Sobrien return "DW_OP_breg25"; 255890075Sobrien case DW_OP_breg26: 255990075Sobrien return "DW_OP_breg26"; 256090075Sobrien case DW_OP_breg27: 256190075Sobrien return "DW_OP_breg27"; 256290075Sobrien case DW_OP_breg28: 256390075Sobrien return "DW_OP_breg28"; 256490075Sobrien case DW_OP_breg29: 256590075Sobrien return "DW_OP_breg29"; 256690075Sobrien case DW_OP_breg30: 256790075Sobrien return "DW_OP_breg30"; 256890075Sobrien case DW_OP_breg31: 256990075Sobrien return "DW_OP_breg31"; 257090075Sobrien case DW_OP_regx: 257190075Sobrien return "DW_OP_regx"; 257290075Sobrien case DW_OP_fbreg: 257390075Sobrien return "DW_OP_fbreg"; 257490075Sobrien case DW_OP_bregx: 257590075Sobrien return "DW_OP_bregx"; 257690075Sobrien case DW_OP_piece: 257790075Sobrien return "DW_OP_piece"; 257890075Sobrien case DW_OP_deref_size: 257990075Sobrien return "DW_OP_deref_size"; 258090075Sobrien case DW_OP_xderef_size: 258190075Sobrien return "DW_OP_xderef_size"; 258290075Sobrien case DW_OP_nop: 258390075Sobrien return "DW_OP_nop"; 258490075Sobrien default: 258590075Sobrien return "OP_<unknown>"; 258690075Sobrien } 258790075Sobrien} 258890075Sobrien 258990075Sobrien/* Return a pointer to a newly allocated location description. Location 259090075Sobrien descriptions are simple expression terms that can be strung 259190075Sobrien together to form more complicated location (address) descriptions. */ 259290075Sobrien 259390075Sobrienstatic inline dw_loc_descr_ref 259490075Sobriennew_loc_descr (op, oprnd1, oprnd2) 259590075Sobrien enum dwarf_location_atom op; 259690075Sobrien unsigned long oprnd1; 259790075Sobrien unsigned long oprnd2; 259890075Sobrien{ 259990075Sobrien /* Use xcalloc here so we clear out all of the long_long constant in 260090075Sobrien the union. */ 260190075Sobrien dw_loc_descr_ref descr 260290075Sobrien = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node)); 260390075Sobrien 260490075Sobrien descr->dw_loc_opc = op; 260590075Sobrien descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const; 260690075Sobrien descr->dw_loc_oprnd1.v.val_unsigned = oprnd1; 260790075Sobrien descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const; 260890075Sobrien descr->dw_loc_oprnd2.v.val_unsigned = oprnd2; 260990075Sobrien 261090075Sobrien return descr; 261190075Sobrien} 261290075Sobrien 261390075Sobrien 261490075Sobrien/* Add a location description term to a location description expression. */ 261590075Sobrien 261690075Sobrienstatic inline void 261790075Sobrienadd_loc_descr (list_head, descr) 261890075Sobrien dw_loc_descr_ref *list_head; 261990075Sobrien dw_loc_descr_ref descr; 262090075Sobrien{ 262190075Sobrien dw_loc_descr_ref *d; 262290075Sobrien 262390075Sobrien /* Find the end of the chain. */ 262490075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 262590075Sobrien ; 262690075Sobrien 262790075Sobrien *d = descr; 262890075Sobrien} 262990075Sobrien 263090075Sobrien/* Return the size of a location descriptor. */ 263190075Sobrien 263290075Sobrienstatic unsigned long 263390075Sobriensize_of_loc_descr (loc) 263490075Sobrien dw_loc_descr_ref loc; 263590075Sobrien{ 263690075Sobrien unsigned long size = 1; 263790075Sobrien 263890075Sobrien switch (loc->dw_loc_opc) 263990075Sobrien { 264090075Sobrien case DW_OP_addr: 264190075Sobrien size += DWARF2_ADDR_SIZE; 264290075Sobrien break; 264390075Sobrien case DW_OP_const1u: 264490075Sobrien case DW_OP_const1s: 264590075Sobrien size += 1; 264690075Sobrien break; 264790075Sobrien case DW_OP_const2u: 264890075Sobrien case DW_OP_const2s: 264990075Sobrien size += 2; 265090075Sobrien break; 265190075Sobrien case DW_OP_const4u: 265290075Sobrien case DW_OP_const4s: 265390075Sobrien size += 4; 265490075Sobrien break; 265590075Sobrien case DW_OP_const8u: 265690075Sobrien case DW_OP_const8s: 265790075Sobrien size += 8; 265890075Sobrien break; 265990075Sobrien case DW_OP_constu: 266090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 266190075Sobrien break; 266290075Sobrien case DW_OP_consts: 266390075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 266490075Sobrien break; 266590075Sobrien case DW_OP_pick: 266690075Sobrien size += 1; 266790075Sobrien break; 266890075Sobrien case DW_OP_plus_uconst: 266990075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 267090075Sobrien break; 267190075Sobrien case DW_OP_skip: 267290075Sobrien case DW_OP_bra: 267390075Sobrien size += 2; 267490075Sobrien break; 267590075Sobrien case DW_OP_breg0: 267690075Sobrien case DW_OP_breg1: 267790075Sobrien case DW_OP_breg2: 267890075Sobrien case DW_OP_breg3: 267990075Sobrien case DW_OP_breg4: 268090075Sobrien case DW_OP_breg5: 268190075Sobrien case DW_OP_breg6: 268290075Sobrien case DW_OP_breg7: 268390075Sobrien case DW_OP_breg8: 268490075Sobrien case DW_OP_breg9: 268590075Sobrien case DW_OP_breg10: 268690075Sobrien case DW_OP_breg11: 268790075Sobrien case DW_OP_breg12: 268890075Sobrien case DW_OP_breg13: 268990075Sobrien case DW_OP_breg14: 269090075Sobrien case DW_OP_breg15: 269190075Sobrien case DW_OP_breg16: 269290075Sobrien case DW_OP_breg17: 269390075Sobrien case DW_OP_breg18: 269490075Sobrien case DW_OP_breg19: 269590075Sobrien case DW_OP_breg20: 269690075Sobrien case DW_OP_breg21: 269790075Sobrien case DW_OP_breg22: 269890075Sobrien case DW_OP_breg23: 269990075Sobrien case DW_OP_breg24: 270090075Sobrien case DW_OP_breg25: 270190075Sobrien case DW_OP_breg26: 270290075Sobrien case DW_OP_breg27: 270390075Sobrien case DW_OP_breg28: 270490075Sobrien case DW_OP_breg29: 270590075Sobrien case DW_OP_breg30: 270690075Sobrien case DW_OP_breg31: 270790075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 270890075Sobrien break; 270990075Sobrien case DW_OP_regx: 271090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271190075Sobrien break; 271290075Sobrien case DW_OP_fbreg: 271390075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 271490075Sobrien break; 271590075Sobrien case DW_OP_bregx: 271690075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271790075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); 271890075Sobrien break; 271990075Sobrien case DW_OP_piece: 272090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 272190075Sobrien break; 272290075Sobrien case DW_OP_deref_size: 272390075Sobrien case DW_OP_xderef_size: 272490075Sobrien size += 1; 272590075Sobrien break; 272690075Sobrien default: 272790075Sobrien break; 272890075Sobrien } 272990075Sobrien 273090075Sobrien return size; 273190075Sobrien} 273290075Sobrien 273390075Sobrien/* Return the size of a series of location descriptors. */ 273490075Sobrien 273590075Sobrienstatic unsigned long 273690075Sobriensize_of_locs (loc) 273790075Sobrien dw_loc_descr_ref loc; 273890075Sobrien{ 273990075Sobrien unsigned long size; 274090075Sobrien 274190075Sobrien for (size = 0; loc != NULL; loc = loc->dw_loc_next) 274290075Sobrien { 274390075Sobrien loc->dw_loc_addr = size; 274490075Sobrien size += size_of_loc_descr (loc); 274590075Sobrien } 274690075Sobrien 274790075Sobrien return size; 274890075Sobrien} 274990075Sobrien 275090075Sobrien/* Output location description stack opcode's operands (if any). */ 275190075Sobrien 275290075Sobrienstatic void 275390075Sobrienoutput_loc_operands (loc) 275490075Sobrien dw_loc_descr_ref loc; 275590075Sobrien{ 275690075Sobrien dw_val_ref val1 = &loc->dw_loc_oprnd1; 275790075Sobrien dw_val_ref val2 = &loc->dw_loc_oprnd2; 275890075Sobrien 275990075Sobrien switch (loc->dw_loc_opc) 276090075Sobrien { 276190075Sobrien#ifdef DWARF2_DEBUGGING_INFO 276290075Sobrien case DW_OP_addr: 276390075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val1->v.val_addr, NULL); 276490075Sobrien break; 276590075Sobrien case DW_OP_const2u: 276690075Sobrien case DW_OP_const2s: 276790075Sobrien dw2_asm_output_data (2, val1->v.val_int, NULL); 276890075Sobrien break; 276990075Sobrien case DW_OP_const4u: 277090075Sobrien case DW_OP_const4s: 277190075Sobrien dw2_asm_output_data (4, val1->v.val_int, NULL); 277290075Sobrien break; 277390075Sobrien case DW_OP_const8u: 277490075Sobrien case DW_OP_const8s: 277590075Sobrien if (HOST_BITS_PER_LONG < 64) 277690075Sobrien abort (); 277790075Sobrien dw2_asm_output_data (8, val1->v.val_int, NULL); 277890075Sobrien break; 277990075Sobrien case DW_OP_skip: 278090075Sobrien case DW_OP_bra: 278190075Sobrien { 278290075Sobrien int offset; 278390075Sobrien 278490075Sobrien if (val1->val_class == dw_val_class_loc) 278590075Sobrien offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3); 278690075Sobrien else 278790075Sobrien abort (); 278890075Sobrien 278990075Sobrien dw2_asm_output_data (2, offset, NULL); 279090075Sobrien } 279190075Sobrien break; 279290075Sobrien#else 279390075Sobrien case DW_OP_addr: 279490075Sobrien case DW_OP_const2u: 279590075Sobrien case DW_OP_const2s: 279690075Sobrien case DW_OP_const4u: 279790075Sobrien case DW_OP_const4s: 279890075Sobrien case DW_OP_const8u: 279990075Sobrien case DW_OP_const8s: 280090075Sobrien case DW_OP_skip: 280190075Sobrien case DW_OP_bra: 280290075Sobrien /* We currently don't make any attempt to make sure these are 280390075Sobrien aligned properly like we do for the main unwind info, so 280490075Sobrien don't support emitting things larger than a byte if we're 280590075Sobrien only doing unwinding. */ 280690075Sobrien abort (); 280790075Sobrien#endif 280890075Sobrien case DW_OP_const1u: 280990075Sobrien case DW_OP_const1s: 281090075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 281190075Sobrien break; 281290075Sobrien case DW_OP_constu: 281390075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 281490075Sobrien break; 281590075Sobrien case DW_OP_consts: 281690075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 281790075Sobrien break; 281890075Sobrien case DW_OP_pick: 281990075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 282090075Sobrien break; 282190075Sobrien case DW_OP_plus_uconst: 282290075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 282390075Sobrien break; 282490075Sobrien case DW_OP_breg0: 282590075Sobrien case DW_OP_breg1: 282690075Sobrien case DW_OP_breg2: 282790075Sobrien case DW_OP_breg3: 282890075Sobrien case DW_OP_breg4: 282990075Sobrien case DW_OP_breg5: 283090075Sobrien case DW_OP_breg6: 283190075Sobrien case DW_OP_breg7: 283290075Sobrien case DW_OP_breg8: 283390075Sobrien case DW_OP_breg9: 283490075Sobrien case DW_OP_breg10: 283590075Sobrien case DW_OP_breg11: 283690075Sobrien case DW_OP_breg12: 283790075Sobrien case DW_OP_breg13: 283890075Sobrien case DW_OP_breg14: 283990075Sobrien case DW_OP_breg15: 284090075Sobrien case DW_OP_breg16: 284190075Sobrien case DW_OP_breg17: 284290075Sobrien case DW_OP_breg18: 284390075Sobrien case DW_OP_breg19: 284490075Sobrien case DW_OP_breg20: 284590075Sobrien case DW_OP_breg21: 284690075Sobrien case DW_OP_breg22: 284790075Sobrien case DW_OP_breg23: 284890075Sobrien case DW_OP_breg24: 284990075Sobrien case DW_OP_breg25: 285090075Sobrien case DW_OP_breg26: 285190075Sobrien case DW_OP_breg27: 285290075Sobrien case DW_OP_breg28: 285390075Sobrien case DW_OP_breg29: 285490075Sobrien case DW_OP_breg30: 285590075Sobrien case DW_OP_breg31: 285690075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 285790075Sobrien break; 285890075Sobrien case DW_OP_regx: 285990075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286090075Sobrien break; 286190075Sobrien case DW_OP_fbreg: 286290075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 286390075Sobrien break; 286490075Sobrien case DW_OP_bregx: 286590075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286690075Sobrien dw2_asm_output_data_sleb128 (val2->v.val_int, NULL); 286790075Sobrien break; 286890075Sobrien case DW_OP_piece: 286990075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 287090075Sobrien break; 287190075Sobrien case DW_OP_deref_size: 287290075Sobrien case DW_OP_xderef_size: 287390075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 287490075Sobrien break; 287590075Sobrien default: 287690075Sobrien /* Other codes have no operands. */ 287790075Sobrien break; 287890075Sobrien } 287990075Sobrien} 288090075Sobrien 288190075Sobrien/* Output a sequence of location operations. */ 288290075Sobrien 288390075Sobrienstatic void 288490075Sobrienoutput_loc_sequence (loc) 288590075Sobrien dw_loc_descr_ref loc; 288690075Sobrien{ 288790075Sobrien for (; loc != NULL; loc = loc->dw_loc_next) 288890075Sobrien { 288990075Sobrien /* Output the opcode. */ 289090075Sobrien dw2_asm_output_data (1, loc->dw_loc_opc, 289190075Sobrien "%s", dwarf_stack_op_name (loc->dw_loc_opc)); 289290075Sobrien 289390075Sobrien /* Output the operand(s) (if any). */ 289490075Sobrien output_loc_operands (loc); 289590075Sobrien } 289690075Sobrien} 289790075Sobrien 289890075Sobrien/* This routine will generate the correct assembly data for a location 289990075Sobrien description based on a cfi entry with a complex address. */ 290090075Sobrien 290190075Sobrienstatic void 290290075Sobrienoutput_cfa_loc (cfi) 290390075Sobrien dw_cfi_ref cfi; 290490075Sobrien{ 290590075Sobrien dw_loc_descr_ref loc; 290690075Sobrien unsigned long size; 290790075Sobrien 290890075Sobrien /* Output the size of the block. */ 290990075Sobrien loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; 291090075Sobrien size = size_of_locs (loc); 291190075Sobrien dw2_asm_output_data_uleb128 (size, NULL); 291290075Sobrien 291390075Sobrien /* Now output the operations themselves. */ 291490075Sobrien output_loc_sequence (loc); 291590075Sobrien} 291690075Sobrien 291790075Sobrien/* This function builds a dwarf location descriptor sequence from 291890075Sobrien a dw_cfa_location. */ 291990075Sobrien 292090075Sobrienstatic struct dw_loc_descr_struct * 292190075Sobrienbuild_cfa_loc (cfa) 292290075Sobrien dw_cfa_location *cfa; 292390075Sobrien{ 292490075Sobrien struct dw_loc_descr_struct *head, *tmp; 292590075Sobrien 292690075Sobrien if (cfa->indirect == 0) 292790075Sobrien abort (); 292890075Sobrien 292990075Sobrien if (cfa->base_offset) 293090075Sobrien { 293190075Sobrien if (cfa->reg <= 31) 293290075Sobrien head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0); 293390075Sobrien else 293490075Sobrien head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset); 293590075Sobrien } 293690075Sobrien else if (cfa->reg <= 31) 293790075Sobrien head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); 293890075Sobrien else 293990075Sobrien head = new_loc_descr (DW_OP_regx, cfa->reg, 0); 294090075Sobrien 294190075Sobrien head->dw_loc_oprnd1.val_class = dw_val_class_const; 294290075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 294390075Sobrien add_loc_descr (&head, tmp); 294490075Sobrien if (cfa->offset != 0) 294590075Sobrien { 294690075Sobrien tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0); 294790075Sobrien add_loc_descr (&head, tmp); 294890075Sobrien } 294990075Sobrien 295090075Sobrien return head; 295190075Sobrien} 295290075Sobrien 295390075Sobrien/* This function fills in aa dw_cfa_location structure from a dwarf location 295490075Sobrien descriptor sequence. */ 295590075Sobrien 295690075Sobrienstatic void 295790075Sobrienget_cfa_from_loc_descr (cfa, loc) 295890075Sobrien dw_cfa_location *cfa; 295990075Sobrien struct dw_loc_descr_struct *loc; 296090075Sobrien{ 296190075Sobrien struct dw_loc_descr_struct *ptr; 296290075Sobrien cfa->offset = 0; 296390075Sobrien cfa->base_offset = 0; 296490075Sobrien cfa->indirect = 0; 296590075Sobrien cfa->reg = -1; 296690075Sobrien 296790075Sobrien for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next) 296890075Sobrien { 296990075Sobrien enum dwarf_location_atom op = ptr->dw_loc_opc; 297090075Sobrien 297190075Sobrien switch (op) 297290075Sobrien { 297390075Sobrien case DW_OP_reg0: 297490075Sobrien case DW_OP_reg1: 297590075Sobrien case DW_OP_reg2: 297690075Sobrien case DW_OP_reg3: 297790075Sobrien case DW_OP_reg4: 297890075Sobrien case DW_OP_reg5: 297990075Sobrien case DW_OP_reg6: 298090075Sobrien case DW_OP_reg7: 298190075Sobrien case DW_OP_reg8: 298290075Sobrien case DW_OP_reg9: 298390075Sobrien case DW_OP_reg10: 298490075Sobrien case DW_OP_reg11: 298590075Sobrien case DW_OP_reg12: 298690075Sobrien case DW_OP_reg13: 298790075Sobrien case DW_OP_reg14: 298890075Sobrien case DW_OP_reg15: 298990075Sobrien case DW_OP_reg16: 299090075Sobrien case DW_OP_reg17: 299190075Sobrien case DW_OP_reg18: 299290075Sobrien case DW_OP_reg19: 299390075Sobrien case DW_OP_reg20: 299490075Sobrien case DW_OP_reg21: 299590075Sobrien case DW_OP_reg22: 299690075Sobrien case DW_OP_reg23: 299790075Sobrien case DW_OP_reg24: 299890075Sobrien case DW_OP_reg25: 299990075Sobrien case DW_OP_reg26: 300090075Sobrien case DW_OP_reg27: 300190075Sobrien case DW_OP_reg28: 300290075Sobrien case DW_OP_reg29: 300390075Sobrien case DW_OP_reg30: 300490075Sobrien case DW_OP_reg31: 300590075Sobrien cfa->reg = op - DW_OP_reg0; 300690075Sobrien break; 300790075Sobrien case DW_OP_regx: 300890075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 300990075Sobrien break; 301090075Sobrien case DW_OP_breg0: 301190075Sobrien case DW_OP_breg1: 301290075Sobrien case DW_OP_breg2: 301390075Sobrien case DW_OP_breg3: 301490075Sobrien case DW_OP_breg4: 301590075Sobrien case DW_OP_breg5: 301690075Sobrien case DW_OP_breg6: 301790075Sobrien case DW_OP_breg7: 301890075Sobrien case DW_OP_breg8: 301990075Sobrien case DW_OP_breg9: 302090075Sobrien case DW_OP_breg10: 302190075Sobrien case DW_OP_breg11: 302290075Sobrien case DW_OP_breg12: 302390075Sobrien case DW_OP_breg13: 302490075Sobrien case DW_OP_breg14: 302590075Sobrien case DW_OP_breg15: 302690075Sobrien case DW_OP_breg16: 302790075Sobrien case DW_OP_breg17: 302890075Sobrien case DW_OP_breg18: 302990075Sobrien case DW_OP_breg19: 303090075Sobrien case DW_OP_breg20: 303190075Sobrien case DW_OP_breg21: 303290075Sobrien case DW_OP_breg22: 303390075Sobrien case DW_OP_breg23: 303490075Sobrien case DW_OP_breg24: 303590075Sobrien case DW_OP_breg25: 303690075Sobrien case DW_OP_breg26: 303790075Sobrien case DW_OP_breg27: 303890075Sobrien case DW_OP_breg28: 303990075Sobrien case DW_OP_breg29: 304090075Sobrien case DW_OP_breg30: 304190075Sobrien case DW_OP_breg31: 304290075Sobrien cfa->reg = op - DW_OP_breg0; 304390075Sobrien cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int; 304490075Sobrien break; 304590075Sobrien case DW_OP_bregx: 304690075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 304790075Sobrien cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int; 304890075Sobrien break; 304990075Sobrien case DW_OP_deref: 305090075Sobrien cfa->indirect = 1; 305190075Sobrien break; 305290075Sobrien case DW_OP_plus_uconst: 305390075Sobrien cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned; 305490075Sobrien break; 305590075Sobrien default: 305690075Sobrien internal_error ("DW_LOC_OP %s not implemented\n", 305790075Sobrien dwarf_stack_op_name (ptr->dw_loc_opc)); 305890075Sobrien } 305990075Sobrien } 306090075Sobrien} 306190075Sobrien#endif /* .debug_frame support */ 306290075Sobrien 306390075Sobrien/* And now, the support for symbolic debugging information. */ 306490075Sobrien#ifdef DWARF2_DEBUGGING_INFO 306590075Sobrien 306690075Sobrien/* .debug_str support. */ 306790075Sobrienstatic hashnode indirect_string_alloc PARAMS ((hash_table *)); 306890075Sobrienstatic int output_indirect_string PARAMS ((struct cpp_reader *, 306990075Sobrien hashnode, const PTR)); 307090075Sobrien 307190075Sobrien 307290075Sobrienstatic void dwarf2out_init PARAMS ((const char *)); 307390075Sobrienstatic void dwarf2out_finish PARAMS ((const char *)); 307490075Sobrienstatic void dwarf2out_define PARAMS ((unsigned int, const char *)); 307590075Sobrienstatic void dwarf2out_undef PARAMS ((unsigned int, const char *)); 307690075Sobrienstatic void dwarf2out_start_source_file PARAMS ((unsigned, const char *)); 307790075Sobrienstatic void dwarf2out_end_source_file PARAMS ((unsigned)); 307890075Sobrienstatic void dwarf2out_begin_block PARAMS ((unsigned, unsigned)); 307990075Sobrienstatic void dwarf2out_end_block PARAMS ((unsigned, unsigned)); 308090075Sobrienstatic bool dwarf2out_ignore_block PARAMS ((tree)); 308190075Sobrienstatic void dwarf2out_global_decl PARAMS ((tree)); 308290075Sobrienstatic void dwarf2out_abstract_function PARAMS ((tree)); 308390075Sobrien 308490075Sobrien/* The debug hooks structure. */ 308590075Sobrien 308690075Sobrienstruct gcc_debug_hooks dwarf2_debug_hooks = 308790075Sobrien{ 308890075Sobrien dwarf2out_init, 308990075Sobrien dwarf2out_finish, 309090075Sobrien dwarf2out_define, 309190075Sobrien dwarf2out_undef, 309290075Sobrien dwarf2out_start_source_file, 309390075Sobrien dwarf2out_end_source_file, 309490075Sobrien dwarf2out_begin_block, 309590075Sobrien dwarf2out_end_block, 309690075Sobrien dwarf2out_ignore_block, 309790075Sobrien dwarf2out_source_line, 309890075Sobrien dwarf2out_begin_prologue, 309990075Sobrien debug_nothing_int, /* end_prologue */ 310090075Sobrien dwarf2out_end_epilogue, 310190075Sobrien debug_nothing_tree, /* begin_function */ 310290075Sobrien debug_nothing_int, /* end_function */ 310390075Sobrien dwarf2out_decl, /* function_decl */ 310490075Sobrien dwarf2out_global_decl, 310590075Sobrien debug_nothing_tree, /* deferred_inline_function */ 310690075Sobrien /* The DWARF 2 backend tries to reduce debugging bloat by not 310790075Sobrien emitting the abstract description of inline functions until 310890075Sobrien something tries to reference them. */ 310990075Sobrien dwarf2out_abstract_function, /* outlining_inline_function */ 311090075Sobrien debug_nothing_rtx /* label */ 311190075Sobrien}; 311290075Sobrien 311390075Sobrien/* NOTE: In the comments in this file, many references are made to 311490075Sobrien "Debugging Information Entries". This term is abbreviated as `DIE' 311590075Sobrien throughout the remainder of this file. */ 311690075Sobrien 311790075Sobrien/* An internal representation of the DWARF output is built, and then 311890075Sobrien walked to generate the DWARF debugging info. The walk of the internal 311990075Sobrien representation is done after the entire program has been compiled. 312090075Sobrien The types below are used to describe the internal representation. */ 312190075Sobrien 312290075Sobrien/* Various DIE's use offsets relative to the beginning of the 312390075Sobrien .debug_info section to refer to each other. */ 312490075Sobrien 312590075Sobrientypedef long int dw_offset; 312690075Sobrien 312790075Sobrien/* Define typedefs here to avoid circular dependencies. */ 312890075Sobrien 312990075Sobrientypedef struct dw_attr_struct *dw_attr_ref; 313090075Sobrientypedef struct dw_line_info_struct *dw_line_info_ref; 313190075Sobrientypedef struct dw_separate_line_info_struct *dw_separate_line_info_ref; 313290075Sobrientypedef struct pubname_struct *pubname_ref; 313390075Sobrientypedef struct dw_ranges_struct *dw_ranges_ref; 313490075Sobrien 313590075Sobrien/* Each entry in the line_info_table maintains the file and 313690075Sobrien line number associated with the label generated for that 313790075Sobrien entry. The label gives the PC value associated with 313890075Sobrien the line number entry. */ 313990075Sobrien 314090075Sobrientypedef struct dw_line_info_struct 314190075Sobrien{ 314290075Sobrien unsigned long dw_file_num; 314390075Sobrien unsigned long dw_line_num; 314490075Sobrien} 314590075Sobriendw_line_info_entry; 314690075Sobrien 314790075Sobrien/* Line information for functions in separate sections; each one gets its 314890075Sobrien own sequence. */ 314990075Sobrientypedef struct dw_separate_line_info_struct 315090075Sobrien{ 315190075Sobrien unsigned long dw_file_num; 315290075Sobrien unsigned long dw_line_num; 315390075Sobrien unsigned long function; 315490075Sobrien} 315590075Sobriendw_separate_line_info_entry; 315690075Sobrien 315750397Sobrien/* Each DIE attribute has a field specifying the attribute kind, 315850397Sobrien a link to the next attribute in the chain, and an attribute value. 315950397Sobrien Attributes are typically linked below the DIE they modify. */ 316050397Sobrien 316150397Sobrientypedef struct dw_attr_struct 316250397Sobrien{ 316350397Sobrien enum dwarf_attribute dw_attr; 316450397Sobrien dw_attr_ref dw_attr_next; 316550397Sobrien dw_val_node dw_attr_val; 316650397Sobrien} 316750397Sobriendw_attr_node; 316850397Sobrien 316950397Sobrien/* The Debugging Information Entry (DIE) structure */ 317050397Sobrien 317150397Sobrientypedef struct die_struct 317250397Sobrien{ 317350397Sobrien enum dwarf_tag die_tag; 317490075Sobrien char *die_symbol; 317550397Sobrien dw_attr_ref die_attr; 317650397Sobrien dw_die_ref die_parent; 317750397Sobrien dw_die_ref die_child; 317850397Sobrien dw_die_ref die_sib; 317950397Sobrien dw_offset die_offset; 318050397Sobrien unsigned long die_abbrev; 318190075Sobrien int die_mark; 318250397Sobrien} 318350397Sobriendie_node; 318450397Sobrien 318550397Sobrien/* The pubname structure */ 318650397Sobrien 318750397Sobrientypedef struct pubname_struct 318850397Sobrien{ 318950397Sobrien dw_die_ref die; 319090075Sobrien char *name; 319150397Sobrien} 319250397Sobrienpubname_entry; 319350397Sobrien 319490075Sobrienstruct dw_ranges_struct 319590075Sobrien{ 319690075Sobrien int block_num; 319790075Sobrien}; 319890075Sobrien 319950397Sobrien/* The limbo die list structure. */ 320050397Sobrientypedef struct limbo_die_struct 320150397Sobrien{ 320250397Sobrien dw_die_ref die; 320390075Sobrien tree created_for; 320450397Sobrien struct limbo_die_struct *next; 320550397Sobrien} 320650397Sobrienlimbo_die_node; 320750397Sobrien 320850397Sobrien/* How to start an assembler comment. */ 320950397Sobrien#ifndef ASM_COMMENT_START 321050397Sobrien#define ASM_COMMENT_START ";#" 321150397Sobrien#endif 321250397Sobrien 321350397Sobrien/* Define a macro which returns non-zero for a TYPE_DECL which was 321450397Sobrien implicitly generated for a tagged type. 321550397Sobrien 321650397Sobrien Note that unlike the gcc front end (which generates a NULL named 321750397Sobrien TYPE_DECL node for each complete tagged type, each array type, and 321850397Sobrien each function type node created) the g++ front end generates a 321950397Sobrien _named_ TYPE_DECL node for each tagged type node created. 322050397Sobrien These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to 322150397Sobrien generate a DW_TAG_typedef DIE for them. */ 322250397Sobrien 322350397Sobrien#define TYPE_DECL_IS_STUB(decl) \ 322450397Sobrien (DECL_NAME (decl) == NULL_TREE \ 322550397Sobrien || (DECL_ARTIFICIAL (decl) \ 322650397Sobrien && is_tagged_type (TREE_TYPE (decl)) \ 322750397Sobrien && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \ 322850397Sobrien /* This is necessary for stub decls that \ 322950397Sobrien appear in nested inline functions. */ \ 323050397Sobrien || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \ 323150397Sobrien && (decl_ultimate_origin (decl) \ 323250397Sobrien == TYPE_STUB_DECL (TREE_TYPE (decl))))))) 323350397Sobrien 323450397Sobrien/* Information concerning the compilation unit's programming 323550397Sobrien language, and compiler version. */ 323650397Sobrien 323750397Sobrienextern int flag_traditional; 323850397Sobrien 323950397Sobrien/* Fixed size portion of the DWARF compilation unit header. */ 324050397Sobrien#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3) 324150397Sobrien 324250397Sobrien/* Fixed size portion of debugging line information prolog. */ 324350397Sobrien#define DWARF_LINE_PROLOG_HEADER_SIZE 5 324450397Sobrien 324550397Sobrien/* Fixed size portion of public names info. */ 324650397Sobrien#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2) 324750397Sobrien 324850397Sobrien/* Fixed size portion of the address range info. */ 324990075Sobrien#define DWARF_ARANGES_HEADER_SIZE \ 325090075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325190075Sobrien - DWARF_OFFSET_SIZE) 325250397Sobrien 325390075Sobrien/* Size of padding portion in the address range info. It must be 325490075Sobrien aligned to twice the pointer size. */ 325590075Sobrien#define DWARF_ARANGES_PAD_SIZE \ 325690075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325790075Sobrien - (2 * DWARF_OFFSET_SIZE + 4)) 325890075Sobrien 325990075Sobrien/* Use assembler line directives if available. */ 326090075Sobrien#ifndef DWARF2_ASM_LINE_DEBUG_INFO 326190075Sobrien#ifdef HAVE_AS_DWARF2_DEBUG_LINE 326290075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 1 326390075Sobrien#else 326490075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 0 326590075Sobrien#endif 326690075Sobrien#endif 326790075Sobrien 326850397Sobrien/* Minimum line offset in a special line info. opcode. 326950397Sobrien This value was chosen to give a reasonable range of values. */ 327050397Sobrien#define DWARF_LINE_BASE -10 327150397Sobrien 327290075Sobrien/* First special line opcode - leave room for the standard opcodes. */ 327350397Sobrien#define DWARF_LINE_OPCODE_BASE 10 327450397Sobrien 327550397Sobrien/* Range of line offsets in a special line info. opcode. */ 327650397Sobrien#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1) 327750397Sobrien 327850397Sobrien/* Flag that indicates the initial value of the is_stmt_start flag. 327950397Sobrien In the present implementation, we do not mark any lines as 328050397Sobrien the beginning of a source statement, because that information 328150397Sobrien is not made available by the GCC front-end. */ 328250397Sobrien#define DWARF_LINE_DEFAULT_IS_STMT_START 1 328350397Sobrien 328450397Sobrien/* This location is used by calc_die_sizes() to keep track 328550397Sobrien the offset of each DIE within the .debug_info section. */ 328650397Sobrienstatic unsigned long next_die_offset; 328750397Sobrien 328850397Sobrien/* Record the root of the DIE's built for the current compilation unit. */ 328950397Sobrienstatic dw_die_ref comp_unit_die; 329050397Sobrien 329150397Sobrien/* A list of DIEs with a NULL parent waiting to be relocated. */ 329250397Sobrienstatic limbo_die_node *limbo_die_list = 0; 329350397Sobrien 329490075Sobrien/* Structure used by lookup_filename to manage sets of filenames. */ 329590075Sobrienstruct file_table 329690075Sobrien{ 329790075Sobrien char **table; 329890075Sobrien unsigned allocated; 329990075Sobrien unsigned in_use; 330090075Sobrien unsigned last_lookup_index; 330190075Sobrien}; 330250397Sobrien 330350397Sobrien/* Size (in elements) of increments by which we may expand the filename 330450397Sobrien table. */ 330550397Sobrien#define FILE_TABLE_INCREMENT 64 330650397Sobrien 330790075Sobrien/* Filenames referenced by this compilation unit. */ 330890075Sobrienstatic struct file_table file_table; 330990075Sobrien 331050397Sobrien/* Local pointer to the name of the main input file. Initialized in 331150397Sobrien dwarf2out_init. */ 331290075Sobrienstatic const char *primary_filename; 331350397Sobrien 331450397Sobrien/* A pointer to the base of a table of references to DIE's that describe 331550397Sobrien declarations. The table is indexed by DECL_UID() which is a unique 331650397Sobrien number identifying each decl. */ 331750397Sobrienstatic dw_die_ref *decl_die_table; 331850397Sobrien 331950397Sobrien/* Number of elements currently allocated for the decl_die_table. */ 332050397Sobrienstatic unsigned decl_die_table_allocated; 332150397Sobrien 332250397Sobrien/* Number of elements in decl_die_table currently in use. */ 332350397Sobrienstatic unsigned decl_die_table_in_use; 332450397Sobrien 332550397Sobrien/* Size (in elements) of increments by which we may expand the 332650397Sobrien decl_die_table. */ 332750397Sobrien#define DECL_DIE_TABLE_INCREMENT 256 332850397Sobrien 332950397Sobrien/* A pointer to the base of a table of references to declaration 333050397Sobrien scopes. This table is a display which tracks the nesting 333150397Sobrien of declaration scopes at the current scope and containing 333250397Sobrien scopes. This table is used to find the proper place to 333350397Sobrien define type declaration DIE's. */ 333490075Sobrienvarray_type decl_scope_table; 333550397Sobrien 333650397Sobrien/* A pointer to the base of a list of references to DIE's that 333750397Sobrien are uniquely identified by their tag, presence/absence of 333850397Sobrien children DIE's, and list of attribute/value pairs. */ 333950397Sobrienstatic dw_die_ref *abbrev_die_table; 334050397Sobrien 334150397Sobrien/* Number of elements currently allocated for abbrev_die_table. */ 334250397Sobrienstatic unsigned abbrev_die_table_allocated; 334350397Sobrien 334450397Sobrien/* Number of elements in type_die_table currently in use. */ 334550397Sobrienstatic unsigned abbrev_die_table_in_use; 334650397Sobrien 334750397Sobrien/* Size (in elements) of increments by which we may expand the 334850397Sobrien abbrev_die_table. */ 334950397Sobrien#define ABBREV_DIE_TABLE_INCREMENT 256 335050397Sobrien 335150397Sobrien/* A pointer to the base of a table that contains line information 335250397Sobrien for each source code line in .text in the compilation unit. */ 335350397Sobrienstatic dw_line_info_ref line_info_table; 335450397Sobrien 335550397Sobrien/* Number of elements currently allocated for line_info_table. */ 335650397Sobrienstatic unsigned line_info_table_allocated; 335750397Sobrien 335850397Sobrien/* Number of elements in separate_line_info_table currently in use. */ 335950397Sobrienstatic unsigned separate_line_info_table_in_use; 336050397Sobrien 336150397Sobrien/* A pointer to the base of a table that contains line information 336250397Sobrien for each source code line outside of .text in the compilation unit. */ 336350397Sobrienstatic dw_separate_line_info_ref separate_line_info_table; 336450397Sobrien 336550397Sobrien/* Number of elements currently allocated for separate_line_info_table. */ 336650397Sobrienstatic unsigned separate_line_info_table_allocated; 336750397Sobrien 336850397Sobrien/* Number of elements in line_info_table currently in use. */ 336950397Sobrienstatic unsigned line_info_table_in_use; 337050397Sobrien 337150397Sobrien/* Size (in elements) of increments by which we may expand the 337250397Sobrien line_info_table. */ 337350397Sobrien#define LINE_INFO_TABLE_INCREMENT 1024 337450397Sobrien 337550397Sobrien/* A pointer to the base of a table that contains a list of publicly 337650397Sobrien accessible names. */ 337750397Sobrienstatic pubname_ref pubname_table; 337850397Sobrien 337950397Sobrien/* Number of elements currently allocated for pubname_table. */ 338050397Sobrienstatic unsigned pubname_table_allocated; 338150397Sobrien 338250397Sobrien/* Number of elements in pubname_table currently in use. */ 338350397Sobrienstatic unsigned pubname_table_in_use; 338450397Sobrien 338550397Sobrien/* Size (in elements) of increments by which we may expand the 338650397Sobrien pubname_table. */ 338750397Sobrien#define PUBNAME_TABLE_INCREMENT 64 338850397Sobrien 338990075Sobrien/* Array of dies for which we should generate .debug_arange info. */ 339090075Sobrienstatic dw_die_ref *arange_table; 339150397Sobrien 339250397Sobrien/* Number of elements currently allocated for arange_table. */ 339350397Sobrienstatic unsigned arange_table_allocated; 339450397Sobrien 339550397Sobrien/* Number of elements in arange_table currently in use. */ 339650397Sobrienstatic unsigned arange_table_in_use; 339750397Sobrien 339850397Sobrien/* Size (in elements) of increments by which we may expand the 339950397Sobrien arange_table. */ 340050397Sobrien#define ARANGE_TABLE_INCREMENT 64 340150397Sobrien 340290075Sobrien/* Array of dies for which we should generate .debug_ranges info. */ 340390075Sobrienstatic dw_ranges_ref ranges_table; 340450397Sobrien 340590075Sobrien/* Number of elements currently allocated for ranges_table. */ 340690075Sobrienstatic unsigned ranges_table_allocated; 340750397Sobrien 340890075Sobrien/* Number of elements in ranges_table currently in use. */ 340990075Sobrienstatic unsigned ranges_table_in_use; 341050397Sobrien 341190075Sobrien/* Size (in elements) of increments by which we may expand the 341290075Sobrien ranges_table. */ 341390075Sobrien#define RANGES_TABLE_INCREMENT 64 341450397Sobrien 341590075Sobrien/* Whether we have location lists that need outputting */ 341690075Sobrienstatic unsigned have_location_lists; 341750397Sobrien 341852284Sobrien/* A pointer to the base of a list of incomplete types which might be 341990075Sobrien completed at some later time. incomplete_types_list needs to be a VARRAY 342090075Sobrien because we want to tell the garbage collector about it. */ 342190075Sobrienvarray_type incomplete_types; 342252284Sobrien 342350397Sobrien/* Record whether the function being analyzed contains inlined functions. */ 342450397Sobrienstatic int current_function_has_inlines; 342550397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 342650397Sobrienstatic int comp_unit_has_inlines; 342750397Sobrien#endif 342850397Sobrien 342990075Sobrien/* Array of RTXes referenced by the debugging information, which therefore 343090075Sobrien must be kept around forever. This is a GC root. */ 343190075Sobrienstatic varray_type used_rtx_varray; 343250397Sobrien 343350397Sobrien/* Forward declarations for functions defined in this file. */ 343450397Sobrien 343590075Sobrienstatic int is_pseudo_reg PARAMS ((rtx)); 343690075Sobrienstatic tree type_main_variant PARAMS ((tree)); 343790075Sobrienstatic int is_tagged_type PARAMS ((tree)); 343890075Sobrienstatic const char *dwarf_tag_name PARAMS ((unsigned)); 343990075Sobrienstatic const char *dwarf_attr_name PARAMS ((unsigned)); 344090075Sobrienstatic const char *dwarf_form_name PARAMS ((unsigned)); 344150397Sobrien#if 0 344290075Sobrienstatic const char *dwarf_type_encoding_name PARAMS ((unsigned)); 344350397Sobrien#endif 344490075Sobrienstatic tree decl_ultimate_origin PARAMS ((tree)); 344590075Sobrienstatic tree block_ultimate_origin PARAMS ((tree)); 344690075Sobrienstatic tree decl_class_context PARAMS ((tree)); 344790075Sobrienstatic void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref)); 344890075Sobrienstatic inline dw_val_class AT_class PARAMS ((dw_attr_ref)); 344990075Sobrienstatic void add_AT_flag PARAMS ((dw_die_ref, 345090075Sobrien enum dwarf_attribute, 345190075Sobrien unsigned)); 345290075Sobrienstatic inline unsigned AT_flag PARAMS ((dw_attr_ref)); 345390075Sobrienstatic void add_AT_int PARAMS ((dw_die_ref, 345490075Sobrien enum dwarf_attribute, long)); 345590075Sobrienstatic inline long int AT_int PARAMS ((dw_attr_ref)); 345690075Sobrienstatic void add_AT_unsigned PARAMS ((dw_die_ref, 345790075Sobrien enum dwarf_attribute, 345890075Sobrien unsigned long)); 345990075Sobrienstatic inline unsigned long AT_unsigned PARAMS ((dw_attr_ref)); 346090075Sobrienstatic void add_AT_long_long PARAMS ((dw_die_ref, 346190075Sobrien enum dwarf_attribute, 346290075Sobrien unsigned long, 346390075Sobrien unsigned long)); 346490075Sobrienstatic void add_AT_float PARAMS ((dw_die_ref, 346590075Sobrien enum dwarf_attribute, 346690075Sobrien unsigned, long *)); 346790075Sobrienstatic void add_AT_string PARAMS ((dw_die_ref, 346890075Sobrien enum dwarf_attribute, 346990075Sobrien const char *)); 347090075Sobrienstatic inline const char *AT_string PARAMS ((dw_attr_ref)); 347190075Sobrienstatic int AT_string_form PARAMS ((dw_attr_ref)); 347290075Sobrienstatic void add_AT_die_ref PARAMS ((dw_die_ref, 347390075Sobrien enum dwarf_attribute, 347490075Sobrien dw_die_ref)); 347590075Sobrienstatic inline dw_die_ref AT_ref PARAMS ((dw_attr_ref)); 347690075Sobrienstatic inline int AT_ref_external PARAMS ((dw_attr_ref)); 347790075Sobrienstatic inline void set_AT_ref_external PARAMS ((dw_attr_ref, int)); 347890075Sobrienstatic void add_AT_fde_ref PARAMS ((dw_die_ref, 347990075Sobrien enum dwarf_attribute, 348090075Sobrien unsigned)); 348190075Sobrienstatic void add_AT_loc PARAMS ((dw_die_ref, 348290075Sobrien enum dwarf_attribute, 348390075Sobrien dw_loc_descr_ref)); 348490075Sobrienstatic inline dw_loc_descr_ref AT_loc PARAMS ((dw_attr_ref)); 348590075Sobrienstatic void add_AT_loc_list PARAMS ((dw_die_ref, 348690075Sobrien enum dwarf_attribute, 348790075Sobrien dw_loc_list_ref)); 348890075Sobrienstatic inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref)); 348990075Sobrienstatic void add_AT_addr PARAMS ((dw_die_ref, 349090075Sobrien enum dwarf_attribute, 349190075Sobrien rtx)); 349290075Sobrienstatic inline rtx AT_addr PARAMS ((dw_attr_ref)); 349390075Sobrienstatic void add_AT_lbl_id PARAMS ((dw_die_ref, 349490075Sobrien enum dwarf_attribute, 349590075Sobrien const char *)); 349690075Sobrienstatic void add_AT_lbl_offset PARAMS ((dw_die_ref, 349790075Sobrien enum dwarf_attribute, 349890075Sobrien const char *)); 349990075Sobrienstatic void add_AT_offset PARAMS ((dw_die_ref, 350090075Sobrien enum dwarf_attribute, 350190075Sobrien unsigned long)); 350290075Sobrienstatic void add_AT_range_list PARAMS ((dw_die_ref, 350390075Sobrien enum dwarf_attribute, 350490075Sobrien unsigned long)); 350590075Sobrienstatic inline const char *AT_lbl PARAMS ((dw_attr_ref)); 350690075Sobrienstatic dw_attr_ref get_AT PARAMS ((dw_die_ref, 350790075Sobrien enum dwarf_attribute)); 350890075Sobrienstatic const char *get_AT_low_pc PARAMS ((dw_die_ref)); 350990075Sobrienstatic const char *get_AT_hi_pc PARAMS ((dw_die_ref)); 351090075Sobrienstatic const char *get_AT_string PARAMS ((dw_die_ref, 351190075Sobrien enum dwarf_attribute)); 351290075Sobrienstatic int get_AT_flag PARAMS ((dw_die_ref, 351390075Sobrien enum dwarf_attribute)); 351490075Sobrienstatic unsigned get_AT_unsigned PARAMS ((dw_die_ref, 351590075Sobrien enum dwarf_attribute)); 351690075Sobrienstatic inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref, 351790075Sobrien enum dwarf_attribute)); 351890075Sobrienstatic int is_c_family PARAMS ((void)); 351990075Sobrienstatic int is_cxx PARAMS ((void)); 352090075Sobrienstatic int is_java PARAMS ((void)); 352190075Sobrienstatic int is_fortran PARAMS ((void)); 352290075Sobrienstatic void remove_AT PARAMS ((dw_die_ref, 352390075Sobrien enum dwarf_attribute)); 352490075Sobrienstatic inline void free_die PARAMS ((dw_die_ref)); 352590075Sobrienstatic void remove_children PARAMS ((dw_die_ref)); 352690075Sobrienstatic void add_child_die PARAMS ((dw_die_ref, dw_die_ref)); 352790075Sobrienstatic dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref, 352890075Sobrien tree)); 352990075Sobrienstatic dw_die_ref lookup_type_die PARAMS ((tree)); 353090075Sobrienstatic void equate_type_number_to_die PARAMS ((tree, dw_die_ref)); 353190075Sobrienstatic dw_die_ref lookup_decl_die PARAMS ((tree)); 353290075Sobrienstatic void equate_decl_number_to_die PARAMS ((tree, dw_die_ref)); 353390075Sobrienstatic void print_spaces PARAMS ((FILE *)); 353490075Sobrienstatic void print_die PARAMS ((dw_die_ref, FILE *)); 353590075Sobrienstatic void print_dwarf_line_table PARAMS ((FILE *)); 353690075Sobrienstatic void reverse_die_lists PARAMS ((dw_die_ref)); 353790075Sobrienstatic void reverse_all_dies PARAMS ((dw_die_ref)); 353890075Sobrienstatic dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref)); 353990075Sobrienstatic dw_die_ref pop_compile_unit PARAMS ((dw_die_ref)); 354090075Sobrienstatic void loc_checksum PARAMS ((dw_loc_descr_ref, 354190075Sobrien struct md5_ctx *)); 354290075Sobrienstatic void attr_checksum PARAMS ((dw_attr_ref, 354390075Sobrien struct md5_ctx *)); 354490075Sobrienstatic void die_checksum PARAMS ((dw_die_ref, 354590075Sobrien struct md5_ctx *)); 354690075Sobrienstatic void compute_section_prefix PARAMS ((dw_die_ref)); 354790075Sobrienstatic int is_type_die PARAMS ((dw_die_ref)); 354890075Sobrienstatic int is_comdat_die PARAMS ((dw_die_ref)); 354990075Sobrienstatic int is_symbol_die PARAMS ((dw_die_ref)); 355090075Sobrienstatic void assign_symbol_names PARAMS ((dw_die_ref)); 355190075Sobrienstatic void break_out_includes PARAMS ((dw_die_ref)); 355290075Sobrienstatic void add_sibling_attributes PARAMS ((dw_die_ref)); 355390075Sobrienstatic void build_abbrev_table PARAMS ((dw_die_ref)); 355490075Sobrienstatic void output_location_lists PARAMS ((dw_die_ref)); 355590075Sobrienstatic int constant_size PARAMS ((long unsigned)); 355690075Sobrienstatic unsigned long size_of_die PARAMS ((dw_die_ref)); 355790075Sobrienstatic void calc_die_sizes PARAMS ((dw_die_ref)); 355890075Sobrienstatic void mark_dies PARAMS ((dw_die_ref)); 355990075Sobrienstatic void unmark_dies PARAMS ((dw_die_ref)); 356090075Sobrienstatic unsigned long size_of_pubnames PARAMS ((void)); 356190075Sobrienstatic unsigned long size_of_aranges PARAMS ((void)); 356290075Sobrienstatic enum dwarf_form value_format PARAMS ((dw_attr_ref)); 356390075Sobrienstatic void output_value_format PARAMS ((dw_attr_ref)); 356490075Sobrienstatic void output_abbrev_section PARAMS ((void)); 356590075Sobrienstatic void output_die_symbol PARAMS ((dw_die_ref)); 356690075Sobrienstatic void output_die PARAMS ((dw_die_ref)); 356790075Sobrienstatic void output_compilation_unit_header PARAMS ((void)); 356890075Sobrienstatic void output_comp_unit PARAMS ((dw_die_ref)); 356990075Sobrienstatic const char *dwarf2_name PARAMS ((tree, int)); 357090075Sobrienstatic void add_pubname PARAMS ((tree, dw_die_ref)); 357190075Sobrienstatic void output_pubnames PARAMS ((void)); 357290075Sobrienstatic void add_arange PARAMS ((tree, dw_die_ref)); 357390075Sobrienstatic void output_aranges PARAMS ((void)); 357490075Sobrienstatic unsigned int add_ranges PARAMS ((tree)); 357590075Sobrienstatic void output_ranges PARAMS ((void)); 357690075Sobrienstatic void output_line_info PARAMS ((void)); 357790075Sobrienstatic void output_file_names PARAMS ((void)); 357890075Sobrienstatic dw_die_ref base_type_die PARAMS ((tree)); 357990075Sobrienstatic tree root_type PARAMS ((tree)); 358090075Sobrienstatic int is_base_type PARAMS ((tree)); 358190075Sobrienstatic dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref)); 358290075Sobrienstatic int type_is_enum PARAMS ((tree)); 358390075Sobrienstatic unsigned int reg_number PARAMS ((rtx)); 358490075Sobrienstatic dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx)); 358590075Sobrienstatic dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT)); 358690075Sobrienstatic dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long)); 358790075Sobrienstatic int is_based_loc PARAMS ((rtx)); 358890075Sobrienstatic dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode)); 358990075Sobrienstatic dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx)); 359090075Sobrienstatic dw_loc_descr_ref loc_descriptor PARAMS ((rtx)); 359190075Sobrienstatic dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int)); 359290075Sobrienstatic HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int)); 359390075Sobrienstatic tree field_type PARAMS ((tree)); 359490075Sobrienstatic unsigned int simple_type_align_in_bits PARAMS ((tree)); 359596263Sobrienstatic unsigned int simple_field_decl_align_in_bits PARAMS ((tree)); 359690075Sobrienstatic unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree)); 359790075Sobrienstatic HOST_WIDE_INT field_byte_offset PARAMS ((tree)); 359890075Sobrienstatic void add_AT_location_description PARAMS ((dw_die_ref, 359990075Sobrien enum dwarf_attribute, rtx)); 360090075Sobrienstatic void add_data_member_location_attribute PARAMS ((dw_die_ref, tree)); 360190075Sobrienstatic void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); 360290075Sobrienstatic rtx rtl_for_decl_location PARAMS ((tree)); 360390075Sobrienstatic void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree)); 360490075Sobrienstatic void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree)); 360590075Sobrienstatic void add_name_attribute PARAMS ((dw_die_ref, const char *)); 360690075Sobrienstatic void add_bound_info PARAMS ((dw_die_ref, 360790075Sobrien enum dwarf_attribute, tree)); 360890075Sobrienstatic void add_subscript_info PARAMS ((dw_die_ref, tree)); 360990075Sobrienstatic void add_byte_size_attribute PARAMS ((dw_die_ref, tree)); 361090075Sobrienstatic void add_bit_offset_attribute PARAMS ((dw_die_ref, tree)); 361190075Sobrienstatic void add_bit_size_attribute PARAMS ((dw_die_ref, tree)); 361290075Sobrienstatic void add_prototyped_attribute PARAMS ((dw_die_ref, tree)); 361390075Sobrienstatic void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree)); 361490075Sobrienstatic void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree)); 361590075Sobrienstatic void add_src_coords_attributes PARAMS ((dw_die_ref, tree)); 361690075Sobrienstatic void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree)); 361790075Sobrienstatic void push_decl_scope PARAMS ((tree)); 361890075Sobrienstatic void pop_decl_scope PARAMS ((void)); 361990075Sobrienstatic dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref)); 362090075Sobrienstatic inline int local_scope_p PARAMS ((dw_die_ref)); 362190075Sobrienstatic inline int class_scope_p PARAMS ((dw_die_ref)); 362290075Sobrienstatic void add_type_attribute PARAMS ((dw_die_ref, tree, int, int, 362390075Sobrien dw_die_ref)); 362490075Sobrienstatic const char *type_tag PARAMS ((tree)); 362590075Sobrienstatic tree member_declared_type PARAMS ((tree)); 362650397Sobrien#if 0 362790075Sobrienstatic const char *decl_start_label PARAMS ((tree)); 362850397Sobrien#endif 362990075Sobrienstatic void gen_array_type_die PARAMS ((tree, dw_die_ref)); 363090075Sobrienstatic void gen_set_type_die PARAMS ((tree, dw_die_ref)); 363150397Sobrien#if 0 363290075Sobrienstatic void gen_entry_point_die PARAMS ((tree, dw_die_ref)); 363350397Sobrien#endif 363490075Sobrienstatic void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref)); 363590075Sobrienstatic void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref)); 363690075Sobrienstatic void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref)); 363790075Sobrienstatic void gen_enumeration_type_die PARAMS ((tree, dw_die_ref)); 363890075Sobrienstatic dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref)); 363990075Sobrienstatic void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref)); 364090075Sobrienstatic void gen_formal_types_die PARAMS ((tree, dw_die_ref)); 364190075Sobrienstatic void gen_subprogram_die PARAMS ((tree, dw_die_ref)); 364290075Sobrienstatic void gen_variable_die PARAMS ((tree, dw_die_ref)); 364390075Sobrienstatic void gen_label_die PARAMS ((tree, dw_die_ref)); 364490075Sobrienstatic void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int)); 364590075Sobrienstatic void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int)); 364690075Sobrienstatic void gen_field_die PARAMS ((tree, dw_die_ref)); 364790075Sobrienstatic void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref)); 364890075Sobrienstatic dw_die_ref gen_compile_unit_die PARAMS ((const char *)); 364990075Sobrienstatic void gen_string_type_die PARAMS ((tree, dw_die_ref)); 365090075Sobrienstatic void gen_inheritance_die PARAMS ((tree, dw_die_ref)); 365190075Sobrienstatic void gen_member_die PARAMS ((tree, dw_die_ref)); 365290075Sobrienstatic void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref)); 365390075Sobrienstatic void gen_subroutine_type_die PARAMS ((tree, dw_die_ref)); 365490075Sobrienstatic void gen_typedef_die PARAMS ((tree, dw_die_ref)); 365590075Sobrienstatic void gen_type_die PARAMS ((tree, dw_die_ref)); 365690075Sobrienstatic void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref)); 365790075Sobrienstatic void gen_block_die PARAMS ((tree, dw_die_ref, int)); 365890075Sobrienstatic void decls_for_scope PARAMS ((tree, dw_die_ref, int)); 365990075Sobrienstatic int is_redundant_typedef PARAMS ((tree)); 366090075Sobrienstatic void gen_decl_die PARAMS ((tree, dw_die_ref)); 366190075Sobrienstatic unsigned lookup_filename PARAMS ((const char *)); 366290075Sobrienstatic void init_file_table PARAMS ((void)); 366390075Sobrienstatic void retry_incomplete_types PARAMS ((void)); 366490075Sobrienstatic void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); 366590075Sobrienstatic void splice_child_die PARAMS ((dw_die_ref, dw_die_ref)); 366690075Sobrienstatic int file_info_cmp PARAMS ((const void *, const void *)); 366790075Sobrienstatic dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref, 366890075Sobrien const char *, const char *, 366990075Sobrien const char *, unsigned)); 367090075Sobrienstatic void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *, 367190075Sobrien dw_loc_descr_ref, 367290075Sobrien const char *, const char *, const char *)); 367390075Sobrienstatic void output_loc_list PARAMS ((dw_loc_list_ref)); 367490075Sobrienstatic char *gen_internal_sym PARAMS ((const char *)); 367590075Sobrienstatic void mark_limbo_die_list PARAMS ((void *)); 367650397Sobrien 367750397Sobrien/* Section names used to hold DWARF debugging information. */ 367850397Sobrien#ifndef DEBUG_INFO_SECTION 367950397Sobrien#define DEBUG_INFO_SECTION ".debug_info" 368050397Sobrien#endif 368190075Sobrien#ifndef DEBUG_ABBREV_SECTION 368290075Sobrien#define DEBUG_ABBREV_SECTION ".debug_abbrev" 368350397Sobrien#endif 368490075Sobrien#ifndef DEBUG_ARANGES_SECTION 368590075Sobrien#define DEBUG_ARANGES_SECTION ".debug_aranges" 368650397Sobrien#endif 368790075Sobrien#ifndef DEBUG_MACINFO_SECTION 368890075Sobrien#define DEBUG_MACINFO_SECTION ".debug_macinfo" 368950397Sobrien#endif 369050397Sobrien#ifndef DEBUG_LINE_SECTION 369150397Sobrien#define DEBUG_LINE_SECTION ".debug_line" 369250397Sobrien#endif 369390075Sobrien#ifndef DEBUG_LOC_SECTION 369490075Sobrien#define DEBUG_LOC_SECTION ".debug_loc" 369550397Sobrien#endif 369690075Sobrien#ifndef DEBUG_PUBNAMES_SECTION 369790075Sobrien#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" 369850397Sobrien#endif 369990075Sobrien#ifndef DEBUG_STR_SECTION 370090075Sobrien#define DEBUG_STR_SECTION ".debug_str" 370150397Sobrien#endif 370290075Sobrien#ifndef DEBUG_RANGES_SECTION 370390075Sobrien#define DEBUG_RANGES_SECTION ".debug_ranges" 370490075Sobrien#endif 370550397Sobrien 370650397Sobrien/* Standard ELF section names for compiled code and data. */ 370790075Sobrien#ifndef TEXT_SECTION_NAME 370890075Sobrien#define TEXT_SECTION_NAME ".text" 370950397Sobrien#endif 371090075Sobrien 371190075Sobrien/* Section flags for .debug_str section. */ 371290075Sobrien#ifdef HAVE_GAS_SHF_MERGE 371390075Sobrien#define DEBUG_STR_SECTION_FLAGS \ 371490075Sobrien (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1) 371590075Sobrien#else 371690075Sobrien#define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG 371750397Sobrien#endif 371850397Sobrien 371952284Sobrien/* Labels we insert at beginning sections we can reference instead of 372090075Sobrien the section names themselves. */ 372150397Sobrien 372252284Sobrien#ifndef TEXT_SECTION_LABEL 372390075Sobrien#define TEXT_SECTION_LABEL "Ltext" 372452284Sobrien#endif 372552284Sobrien#ifndef DEBUG_LINE_SECTION_LABEL 372690075Sobrien#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" 372752284Sobrien#endif 372852284Sobrien#ifndef DEBUG_INFO_SECTION_LABEL 372990075Sobrien#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" 373052284Sobrien#endif 373190075Sobrien#ifndef DEBUG_ABBREV_SECTION_LABEL 373290075Sobrien#define DEBUG_ABBREV_SECTION_LABEL "Ldebug_abbrev" 373352284Sobrien#endif 373490075Sobrien#ifndef DEBUG_LOC_SECTION_LABEL 373590075Sobrien#define DEBUG_LOC_SECTION_LABEL "Ldebug_loc" 373690075Sobrien#endif 373790075Sobrien#ifndef DEBUG_RANGES_SECTION_LABEL 373890075Sobrien#define DEBUG_RANGES_SECTION_LABEL "Ldebug_ranges" 373990075Sobrien#endif 374090075Sobrien#ifndef DEBUG_MACINFO_SECTION_LABEL 374190075Sobrien#define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo" 374290075Sobrien#endif 374352284Sobrien 374450397Sobrien/* Definitions of defaults for formats and names of various special 374550397Sobrien (artificial) labels which may be generated within this file (when the -g 374650397Sobrien options is used and DWARF_DEBUGGING_INFO is in effect. 374750397Sobrien If necessary, these may be overridden from within the tm.h file, but 374850397Sobrien typically, overriding these defaults is unnecessary. */ 374950397Sobrien 375050397Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375152284Sobrienstatic char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375252284Sobrienstatic char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375352284Sobrienstatic char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375452284Sobrienstatic char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375590075Sobrienstatic char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375690075Sobrienstatic char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375790075Sobrienstatic char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; 375850397Sobrien 375950397Sobrien#ifndef TEXT_END_LABEL 376050397Sobrien#define TEXT_END_LABEL "Letext" 376150397Sobrien#endif 376250397Sobrien#ifndef DATA_END_LABEL 376350397Sobrien#define DATA_END_LABEL "Ledata" 376450397Sobrien#endif 376550397Sobrien#ifndef BSS_END_LABEL 376650397Sobrien#define BSS_END_LABEL "Lebss" 376750397Sobrien#endif 376850397Sobrien#ifndef BLOCK_BEGIN_LABEL 376950397Sobrien#define BLOCK_BEGIN_LABEL "LBB" 377050397Sobrien#endif 377150397Sobrien#ifndef BLOCK_END_LABEL 377250397Sobrien#define BLOCK_END_LABEL "LBE" 377350397Sobrien#endif 377450397Sobrien#ifndef BODY_BEGIN_LABEL 377550397Sobrien#define BODY_BEGIN_LABEL "Lbb" 377650397Sobrien#endif 377750397Sobrien#ifndef BODY_END_LABEL 377850397Sobrien#define BODY_END_LABEL "Lbe" 377950397Sobrien#endif 378050397Sobrien#ifndef LINE_CODE_LABEL 378150397Sobrien#define LINE_CODE_LABEL "LM" 378250397Sobrien#endif 378350397Sobrien#ifndef SEPARATE_LINE_CODE_LABEL 378450397Sobrien#define SEPARATE_LINE_CODE_LABEL "LSM" 378550397Sobrien#endif 378650397Sobrien 378790075Sobrien/* We allow a language front-end to designate a function that is to be 378890075Sobrien called to "demangle" any name before it it put into a DIE. */ 378950397Sobrien 379090075Sobrienstatic const char *(*demangle_name_func) PARAMS ((const char *)); 379150397Sobrien 379290075Sobrienvoid 379390075Sobriendwarf2out_set_demangle_name_func (func) 379490075Sobrien const char *(*func) PARAMS ((const char *)); 379550397Sobrien{ 379690075Sobrien demangle_name_func = func; 379750397Sobrien} 379850397Sobrien 379950397Sobrien/* Test if rtl node points to a pseudo register. */ 380050397Sobrien 380150397Sobrienstatic inline int 380250397Sobrienis_pseudo_reg (rtl) 380390075Sobrien rtx rtl; 380450397Sobrien{ 380590075Sobrien return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 380690075Sobrien || (GET_CODE (rtl) == SUBREG 380790075Sobrien && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)); 380850397Sobrien} 380950397Sobrien 381050397Sobrien/* Return a reference to a type, with its const and volatile qualifiers 381150397Sobrien removed. */ 381250397Sobrien 381350397Sobrienstatic inline tree 381450397Sobrientype_main_variant (type) 381590075Sobrien tree type; 381650397Sobrien{ 381750397Sobrien type = TYPE_MAIN_VARIANT (type); 381850397Sobrien 381990075Sobrien /* ??? There really should be only one main variant among any group of 382090075Sobrien variants of a given type (and all of the MAIN_VARIANT values for all 382190075Sobrien members of the group should point to that one type) but sometimes the C 382290075Sobrien front-end messes this up for array types, so we work around that bug 382390075Sobrien here. */ 382450397Sobrien if (TREE_CODE (type) == ARRAY_TYPE) 382550397Sobrien while (type != TYPE_MAIN_VARIANT (type)) 382650397Sobrien type = TYPE_MAIN_VARIANT (type); 382750397Sobrien 382850397Sobrien return type; 382950397Sobrien} 383050397Sobrien 383150397Sobrien/* Return non-zero if the given type node represents a tagged type. */ 383250397Sobrien 383350397Sobrienstatic inline int 383450397Sobrienis_tagged_type (type) 383590075Sobrien tree type; 383650397Sobrien{ 383790075Sobrien enum tree_code code = TREE_CODE (type); 383850397Sobrien 383950397Sobrien return (code == RECORD_TYPE || code == UNION_TYPE 384050397Sobrien || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE); 384150397Sobrien} 384250397Sobrien 384350397Sobrien/* Convert a DIE tag into its string name. */ 384450397Sobrien 384590075Sobrienstatic const char * 384650397Sobriendwarf_tag_name (tag) 384790075Sobrien unsigned tag; 384850397Sobrien{ 384950397Sobrien switch (tag) 385050397Sobrien { 385150397Sobrien case DW_TAG_padding: 385250397Sobrien return "DW_TAG_padding"; 385350397Sobrien case DW_TAG_array_type: 385450397Sobrien return "DW_TAG_array_type"; 385550397Sobrien case DW_TAG_class_type: 385650397Sobrien return "DW_TAG_class_type"; 385750397Sobrien case DW_TAG_entry_point: 385850397Sobrien return "DW_TAG_entry_point"; 385950397Sobrien case DW_TAG_enumeration_type: 386050397Sobrien return "DW_TAG_enumeration_type"; 386150397Sobrien case DW_TAG_formal_parameter: 386250397Sobrien return "DW_TAG_formal_parameter"; 386350397Sobrien case DW_TAG_imported_declaration: 386450397Sobrien return "DW_TAG_imported_declaration"; 386550397Sobrien case DW_TAG_label: 386650397Sobrien return "DW_TAG_label"; 386750397Sobrien case DW_TAG_lexical_block: 386850397Sobrien return "DW_TAG_lexical_block"; 386950397Sobrien case DW_TAG_member: 387050397Sobrien return "DW_TAG_member"; 387150397Sobrien case DW_TAG_pointer_type: 387250397Sobrien return "DW_TAG_pointer_type"; 387350397Sobrien case DW_TAG_reference_type: 387450397Sobrien return "DW_TAG_reference_type"; 387550397Sobrien case DW_TAG_compile_unit: 387650397Sobrien return "DW_TAG_compile_unit"; 387750397Sobrien case DW_TAG_string_type: 387850397Sobrien return "DW_TAG_string_type"; 387950397Sobrien case DW_TAG_structure_type: 388050397Sobrien return "DW_TAG_structure_type"; 388150397Sobrien case DW_TAG_subroutine_type: 388250397Sobrien return "DW_TAG_subroutine_type"; 388350397Sobrien case DW_TAG_typedef: 388450397Sobrien return "DW_TAG_typedef"; 388550397Sobrien case DW_TAG_union_type: 388650397Sobrien return "DW_TAG_union_type"; 388750397Sobrien case DW_TAG_unspecified_parameters: 388850397Sobrien return "DW_TAG_unspecified_parameters"; 388950397Sobrien case DW_TAG_variant: 389050397Sobrien return "DW_TAG_variant"; 389150397Sobrien case DW_TAG_common_block: 389250397Sobrien return "DW_TAG_common_block"; 389350397Sobrien case DW_TAG_common_inclusion: 389450397Sobrien return "DW_TAG_common_inclusion"; 389550397Sobrien case DW_TAG_inheritance: 389650397Sobrien return "DW_TAG_inheritance"; 389750397Sobrien case DW_TAG_inlined_subroutine: 389850397Sobrien return "DW_TAG_inlined_subroutine"; 389950397Sobrien case DW_TAG_module: 390050397Sobrien return "DW_TAG_module"; 390150397Sobrien case DW_TAG_ptr_to_member_type: 390250397Sobrien return "DW_TAG_ptr_to_member_type"; 390350397Sobrien case DW_TAG_set_type: 390450397Sobrien return "DW_TAG_set_type"; 390550397Sobrien case DW_TAG_subrange_type: 390650397Sobrien return "DW_TAG_subrange_type"; 390750397Sobrien case DW_TAG_with_stmt: 390850397Sobrien return "DW_TAG_with_stmt"; 390950397Sobrien case DW_TAG_access_declaration: 391050397Sobrien return "DW_TAG_access_declaration"; 391150397Sobrien case DW_TAG_base_type: 391250397Sobrien return "DW_TAG_base_type"; 391350397Sobrien case DW_TAG_catch_block: 391450397Sobrien return "DW_TAG_catch_block"; 391550397Sobrien case DW_TAG_const_type: 391650397Sobrien return "DW_TAG_const_type"; 391750397Sobrien case DW_TAG_constant: 391850397Sobrien return "DW_TAG_constant"; 391950397Sobrien case DW_TAG_enumerator: 392050397Sobrien return "DW_TAG_enumerator"; 392150397Sobrien case DW_TAG_file_type: 392250397Sobrien return "DW_TAG_file_type"; 392350397Sobrien case DW_TAG_friend: 392450397Sobrien return "DW_TAG_friend"; 392550397Sobrien case DW_TAG_namelist: 392650397Sobrien return "DW_TAG_namelist"; 392750397Sobrien case DW_TAG_namelist_item: 392850397Sobrien return "DW_TAG_namelist_item"; 392950397Sobrien case DW_TAG_packed_type: 393050397Sobrien return "DW_TAG_packed_type"; 393150397Sobrien case DW_TAG_subprogram: 393250397Sobrien return "DW_TAG_subprogram"; 393350397Sobrien case DW_TAG_template_type_param: 393450397Sobrien return "DW_TAG_template_type_param"; 393550397Sobrien case DW_TAG_template_value_param: 393650397Sobrien return "DW_TAG_template_value_param"; 393750397Sobrien case DW_TAG_thrown_type: 393850397Sobrien return "DW_TAG_thrown_type"; 393950397Sobrien case DW_TAG_try_block: 394050397Sobrien return "DW_TAG_try_block"; 394150397Sobrien case DW_TAG_variant_part: 394250397Sobrien return "DW_TAG_variant_part"; 394350397Sobrien case DW_TAG_variable: 394450397Sobrien return "DW_TAG_variable"; 394550397Sobrien case DW_TAG_volatile_type: 394650397Sobrien return "DW_TAG_volatile_type"; 394750397Sobrien case DW_TAG_MIPS_loop: 394850397Sobrien return "DW_TAG_MIPS_loop"; 394950397Sobrien case DW_TAG_format_label: 395050397Sobrien return "DW_TAG_format_label"; 395150397Sobrien case DW_TAG_function_template: 395250397Sobrien return "DW_TAG_function_template"; 395350397Sobrien case DW_TAG_class_template: 395450397Sobrien return "DW_TAG_class_template"; 395590075Sobrien case DW_TAG_GNU_BINCL: 395690075Sobrien return "DW_TAG_GNU_BINCL"; 395790075Sobrien case DW_TAG_GNU_EINCL: 395890075Sobrien return "DW_TAG_GNU_EINCL"; 395950397Sobrien default: 396050397Sobrien return "DW_TAG_<unknown>"; 396150397Sobrien } 396250397Sobrien} 396350397Sobrien 396450397Sobrien/* Convert a DWARF attribute code into its string name. */ 396550397Sobrien 396690075Sobrienstatic const char * 396750397Sobriendwarf_attr_name (attr) 396890075Sobrien unsigned attr; 396950397Sobrien{ 397050397Sobrien switch (attr) 397150397Sobrien { 397250397Sobrien case DW_AT_sibling: 397350397Sobrien return "DW_AT_sibling"; 397450397Sobrien case DW_AT_location: 397550397Sobrien return "DW_AT_location"; 397650397Sobrien case DW_AT_name: 397750397Sobrien return "DW_AT_name"; 397850397Sobrien case DW_AT_ordering: 397950397Sobrien return "DW_AT_ordering"; 398050397Sobrien case DW_AT_subscr_data: 398150397Sobrien return "DW_AT_subscr_data"; 398250397Sobrien case DW_AT_byte_size: 398350397Sobrien return "DW_AT_byte_size"; 398450397Sobrien case DW_AT_bit_offset: 398550397Sobrien return "DW_AT_bit_offset"; 398650397Sobrien case DW_AT_bit_size: 398750397Sobrien return "DW_AT_bit_size"; 398850397Sobrien case DW_AT_element_list: 398950397Sobrien return "DW_AT_element_list"; 399050397Sobrien case DW_AT_stmt_list: 399150397Sobrien return "DW_AT_stmt_list"; 399250397Sobrien case DW_AT_low_pc: 399350397Sobrien return "DW_AT_low_pc"; 399450397Sobrien case DW_AT_high_pc: 399550397Sobrien return "DW_AT_high_pc"; 399650397Sobrien case DW_AT_language: 399750397Sobrien return "DW_AT_language"; 399850397Sobrien case DW_AT_member: 399950397Sobrien return "DW_AT_member"; 400050397Sobrien case DW_AT_discr: 400150397Sobrien return "DW_AT_discr"; 400250397Sobrien case DW_AT_discr_value: 400350397Sobrien return "DW_AT_discr_value"; 400450397Sobrien case DW_AT_visibility: 400550397Sobrien return "DW_AT_visibility"; 400650397Sobrien case DW_AT_import: 400750397Sobrien return "DW_AT_import"; 400850397Sobrien case DW_AT_string_length: 400950397Sobrien return "DW_AT_string_length"; 401050397Sobrien case DW_AT_common_reference: 401150397Sobrien return "DW_AT_common_reference"; 401250397Sobrien case DW_AT_comp_dir: 401350397Sobrien return "DW_AT_comp_dir"; 401450397Sobrien case DW_AT_const_value: 401550397Sobrien return "DW_AT_const_value"; 401650397Sobrien case DW_AT_containing_type: 401750397Sobrien return "DW_AT_containing_type"; 401850397Sobrien case DW_AT_default_value: 401950397Sobrien return "DW_AT_default_value"; 402050397Sobrien case DW_AT_inline: 402150397Sobrien return "DW_AT_inline"; 402250397Sobrien case DW_AT_is_optional: 402350397Sobrien return "DW_AT_is_optional"; 402450397Sobrien case DW_AT_lower_bound: 402550397Sobrien return "DW_AT_lower_bound"; 402650397Sobrien case DW_AT_producer: 402750397Sobrien return "DW_AT_producer"; 402850397Sobrien case DW_AT_prototyped: 402950397Sobrien return "DW_AT_prototyped"; 403050397Sobrien case DW_AT_return_addr: 403150397Sobrien return "DW_AT_return_addr"; 403250397Sobrien case DW_AT_start_scope: 403350397Sobrien return "DW_AT_start_scope"; 403450397Sobrien case DW_AT_stride_size: 403550397Sobrien return "DW_AT_stride_size"; 403650397Sobrien case DW_AT_upper_bound: 403750397Sobrien return "DW_AT_upper_bound"; 403850397Sobrien case DW_AT_abstract_origin: 403950397Sobrien return "DW_AT_abstract_origin"; 404050397Sobrien case DW_AT_accessibility: 404150397Sobrien return "DW_AT_accessibility"; 404250397Sobrien case DW_AT_address_class: 404350397Sobrien return "DW_AT_address_class"; 404450397Sobrien case DW_AT_artificial: 404550397Sobrien return "DW_AT_artificial"; 404650397Sobrien case DW_AT_base_types: 404750397Sobrien return "DW_AT_base_types"; 404850397Sobrien case DW_AT_calling_convention: 404950397Sobrien return "DW_AT_calling_convention"; 405050397Sobrien case DW_AT_count: 405150397Sobrien return "DW_AT_count"; 405250397Sobrien case DW_AT_data_member_location: 405350397Sobrien return "DW_AT_data_member_location"; 405450397Sobrien case DW_AT_decl_column: 405550397Sobrien return "DW_AT_decl_column"; 405650397Sobrien case DW_AT_decl_file: 405750397Sobrien return "DW_AT_decl_file"; 405850397Sobrien case DW_AT_decl_line: 405950397Sobrien return "DW_AT_decl_line"; 406050397Sobrien case DW_AT_declaration: 406150397Sobrien return "DW_AT_declaration"; 406250397Sobrien case DW_AT_discr_list: 406350397Sobrien return "DW_AT_discr_list"; 406450397Sobrien case DW_AT_encoding: 406550397Sobrien return "DW_AT_encoding"; 406650397Sobrien case DW_AT_external: 406750397Sobrien return "DW_AT_external"; 406850397Sobrien case DW_AT_frame_base: 406950397Sobrien return "DW_AT_frame_base"; 407050397Sobrien case DW_AT_friend: 407150397Sobrien return "DW_AT_friend"; 407250397Sobrien case DW_AT_identifier_case: 407350397Sobrien return "DW_AT_identifier_case"; 407450397Sobrien case DW_AT_macro_info: 407550397Sobrien return "DW_AT_macro_info"; 407650397Sobrien case DW_AT_namelist_items: 407750397Sobrien return "DW_AT_namelist_items"; 407850397Sobrien case DW_AT_priority: 407950397Sobrien return "DW_AT_priority"; 408050397Sobrien case DW_AT_segment: 408150397Sobrien return "DW_AT_segment"; 408250397Sobrien case DW_AT_specification: 408350397Sobrien return "DW_AT_specification"; 408450397Sobrien case DW_AT_static_link: 408550397Sobrien return "DW_AT_static_link"; 408650397Sobrien case DW_AT_type: 408750397Sobrien return "DW_AT_type"; 408850397Sobrien case DW_AT_use_location: 408950397Sobrien return "DW_AT_use_location"; 409050397Sobrien case DW_AT_variable_parameter: 409150397Sobrien return "DW_AT_variable_parameter"; 409250397Sobrien case DW_AT_virtuality: 409350397Sobrien return "DW_AT_virtuality"; 409450397Sobrien case DW_AT_vtable_elem_location: 409550397Sobrien return "DW_AT_vtable_elem_location"; 409650397Sobrien 409790075Sobrien case DW_AT_allocated: 409890075Sobrien return "DW_AT_allocated"; 409990075Sobrien case DW_AT_associated: 410090075Sobrien return "DW_AT_associated"; 410190075Sobrien case DW_AT_data_location: 410290075Sobrien return "DW_AT_data_location"; 410390075Sobrien case DW_AT_stride: 410490075Sobrien return "DW_AT_stride"; 410590075Sobrien case DW_AT_entry_pc: 410690075Sobrien return "DW_AT_entry_pc"; 410790075Sobrien case DW_AT_use_UTF8: 410890075Sobrien return "DW_AT_use_UTF8"; 410990075Sobrien case DW_AT_extension: 411090075Sobrien return "DW_AT_extension"; 411190075Sobrien case DW_AT_ranges: 411290075Sobrien return "DW_AT_ranges"; 411390075Sobrien case DW_AT_trampoline: 411490075Sobrien return "DW_AT_trampoline"; 411590075Sobrien case DW_AT_call_column: 411690075Sobrien return "DW_AT_call_column"; 411790075Sobrien case DW_AT_call_file: 411890075Sobrien return "DW_AT_call_file"; 411990075Sobrien case DW_AT_call_line: 412090075Sobrien return "DW_AT_call_line"; 412190075Sobrien 412250397Sobrien case DW_AT_MIPS_fde: 412350397Sobrien return "DW_AT_MIPS_fde"; 412450397Sobrien case DW_AT_MIPS_loop_begin: 412550397Sobrien return "DW_AT_MIPS_loop_begin"; 412650397Sobrien case DW_AT_MIPS_tail_loop_begin: 412750397Sobrien return "DW_AT_MIPS_tail_loop_begin"; 412850397Sobrien case DW_AT_MIPS_epilog_begin: 412950397Sobrien return "DW_AT_MIPS_epilog_begin"; 413050397Sobrien case DW_AT_MIPS_loop_unroll_factor: 413150397Sobrien return "DW_AT_MIPS_loop_unroll_factor"; 413250397Sobrien case DW_AT_MIPS_software_pipeline_depth: 413350397Sobrien return "DW_AT_MIPS_software_pipeline_depth"; 413450397Sobrien case DW_AT_MIPS_linkage_name: 413550397Sobrien return "DW_AT_MIPS_linkage_name"; 413650397Sobrien case DW_AT_MIPS_stride: 413750397Sobrien return "DW_AT_MIPS_stride"; 413850397Sobrien case DW_AT_MIPS_abstract_name: 413950397Sobrien return "DW_AT_MIPS_abstract_name"; 414050397Sobrien case DW_AT_MIPS_clone_origin: 414150397Sobrien return "DW_AT_MIPS_clone_origin"; 414250397Sobrien case DW_AT_MIPS_has_inlines: 414350397Sobrien return "DW_AT_MIPS_has_inlines"; 414450397Sobrien 414550397Sobrien case DW_AT_sf_names: 414650397Sobrien return "DW_AT_sf_names"; 414750397Sobrien case DW_AT_src_info: 414850397Sobrien return "DW_AT_src_info"; 414950397Sobrien case DW_AT_mac_info: 415050397Sobrien return "DW_AT_mac_info"; 415150397Sobrien case DW_AT_src_coords: 415250397Sobrien return "DW_AT_src_coords"; 415350397Sobrien case DW_AT_body_begin: 415450397Sobrien return "DW_AT_body_begin"; 415550397Sobrien case DW_AT_body_end: 415650397Sobrien return "DW_AT_body_end"; 415796263Sobrien case DW_AT_GNU_vector: 415896263Sobrien return "DW_AT_GNU_vector"; 415996263Sobrien 416090075Sobrien case DW_AT_VMS_rtnbeg_pd_address: 416190075Sobrien return "DW_AT_VMS_rtnbeg_pd_address"; 416290075Sobrien 416350397Sobrien default: 416450397Sobrien return "DW_AT_<unknown>"; 416550397Sobrien } 416650397Sobrien} 416750397Sobrien 416850397Sobrien/* Convert a DWARF value form code into its string name. */ 416950397Sobrien 417090075Sobrienstatic const char * 417150397Sobriendwarf_form_name (form) 417290075Sobrien unsigned form; 417350397Sobrien{ 417450397Sobrien switch (form) 417550397Sobrien { 417650397Sobrien case DW_FORM_addr: 417750397Sobrien return "DW_FORM_addr"; 417850397Sobrien case DW_FORM_block2: 417950397Sobrien return "DW_FORM_block2"; 418050397Sobrien case DW_FORM_block4: 418150397Sobrien return "DW_FORM_block4"; 418250397Sobrien case DW_FORM_data2: 418350397Sobrien return "DW_FORM_data2"; 418450397Sobrien case DW_FORM_data4: 418550397Sobrien return "DW_FORM_data4"; 418650397Sobrien case DW_FORM_data8: 418750397Sobrien return "DW_FORM_data8"; 418850397Sobrien case DW_FORM_string: 418950397Sobrien return "DW_FORM_string"; 419050397Sobrien case DW_FORM_block: 419150397Sobrien return "DW_FORM_block"; 419250397Sobrien case DW_FORM_block1: 419350397Sobrien return "DW_FORM_block1"; 419450397Sobrien case DW_FORM_data1: 419550397Sobrien return "DW_FORM_data1"; 419650397Sobrien case DW_FORM_flag: 419750397Sobrien return "DW_FORM_flag"; 419850397Sobrien case DW_FORM_sdata: 419950397Sobrien return "DW_FORM_sdata"; 420050397Sobrien case DW_FORM_strp: 420150397Sobrien return "DW_FORM_strp"; 420250397Sobrien case DW_FORM_udata: 420350397Sobrien return "DW_FORM_udata"; 420450397Sobrien case DW_FORM_ref_addr: 420550397Sobrien return "DW_FORM_ref_addr"; 420650397Sobrien case DW_FORM_ref1: 420750397Sobrien return "DW_FORM_ref1"; 420850397Sobrien case DW_FORM_ref2: 420950397Sobrien return "DW_FORM_ref2"; 421050397Sobrien case DW_FORM_ref4: 421150397Sobrien return "DW_FORM_ref4"; 421250397Sobrien case DW_FORM_ref8: 421350397Sobrien return "DW_FORM_ref8"; 421450397Sobrien case DW_FORM_ref_udata: 421550397Sobrien return "DW_FORM_ref_udata"; 421650397Sobrien case DW_FORM_indirect: 421750397Sobrien return "DW_FORM_indirect"; 421850397Sobrien default: 421950397Sobrien return "DW_FORM_<unknown>"; 422050397Sobrien } 422150397Sobrien} 422250397Sobrien 422350397Sobrien/* Convert a DWARF type code into its string name. */ 422450397Sobrien 422550397Sobrien#if 0 422690075Sobrienstatic const char * 422750397Sobriendwarf_type_encoding_name (enc) 422890075Sobrien unsigned enc; 422950397Sobrien{ 423050397Sobrien switch (enc) 423150397Sobrien { 423250397Sobrien case DW_ATE_address: 423350397Sobrien return "DW_ATE_address"; 423450397Sobrien case DW_ATE_boolean: 423550397Sobrien return "DW_ATE_boolean"; 423650397Sobrien case DW_ATE_complex_float: 423750397Sobrien return "DW_ATE_complex_float"; 423850397Sobrien case DW_ATE_float: 423950397Sobrien return "DW_ATE_float"; 424050397Sobrien case DW_ATE_signed: 424150397Sobrien return "DW_ATE_signed"; 424250397Sobrien case DW_ATE_signed_char: 424350397Sobrien return "DW_ATE_signed_char"; 424450397Sobrien case DW_ATE_unsigned: 424550397Sobrien return "DW_ATE_unsigned"; 424650397Sobrien case DW_ATE_unsigned_char: 424750397Sobrien return "DW_ATE_unsigned_char"; 424850397Sobrien default: 424950397Sobrien return "DW_ATE_<unknown>"; 425050397Sobrien } 425150397Sobrien} 425250397Sobrien#endif 425350397Sobrien 425450397Sobrien/* Determine the "ultimate origin" of a decl. The decl may be an inlined 425550397Sobrien instance of an inlined instance of a decl which is local to an inline 425650397Sobrien function, so we have to trace all of the way back through the origin chain 425750397Sobrien to find out what sort of node actually served as the original seed for the 425850397Sobrien given block. */ 425950397Sobrien 426050397Sobrienstatic tree 426150397Sobriendecl_ultimate_origin (decl) 426290075Sobrien tree decl; 426350397Sobrien{ 426490075Sobrien /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the 426590075Sobrien nodes in the function to point to themselves; ignore that if 426690075Sobrien we're trying to output the abstract instance of this function. */ 426790075Sobrien if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl) 426890075Sobrien return NULL_TREE; 426990075Sobrien 427090075Sobrien#ifdef ENABLE_CHECKING 427152284Sobrien if (DECL_FROM_INLINE (DECL_ORIGIN (decl))) 427252284Sobrien /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the 427352284Sobrien most distant ancestor, this should never happen. */ 427452284Sobrien abort (); 427552284Sobrien#endif 427650397Sobrien 427752284Sobrien return DECL_ABSTRACT_ORIGIN (decl); 427850397Sobrien} 427950397Sobrien 428050397Sobrien/* Determine the "ultimate origin" of a block. The block may be an inlined 428150397Sobrien instance of an inlined instance of a block which is local to an inline 428250397Sobrien function, so we have to trace all of the way back through the origin chain 428350397Sobrien to find out what sort of node actually served as the original seed for the 428450397Sobrien given block. */ 428550397Sobrien 428650397Sobrienstatic tree 428750397Sobrienblock_ultimate_origin (block) 428890075Sobrien tree block; 428950397Sobrien{ 429090075Sobrien tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); 429150397Sobrien 429290075Sobrien /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the 429390075Sobrien nodes in the function to point to themselves; ignore that if 429490075Sobrien we're trying to output the abstract instance of this function. */ 429590075Sobrien if (BLOCK_ABSTRACT (block) && immediate_origin == block) 429690075Sobrien return NULL_TREE; 429790075Sobrien 429850397Sobrien if (immediate_origin == NULL_TREE) 429950397Sobrien return NULL_TREE; 430050397Sobrien else 430150397Sobrien { 430290075Sobrien tree ret_val; 430390075Sobrien tree lookahead = immediate_origin; 430450397Sobrien 430550397Sobrien do 430650397Sobrien { 430750397Sobrien ret_val = lookahead; 430890075Sobrien lookahead = (TREE_CODE (ret_val) == BLOCK 430990075Sobrien ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL); 431050397Sobrien } 431150397Sobrien while (lookahead != NULL && lookahead != ret_val); 431250397Sobrien 431350397Sobrien return ret_val; 431450397Sobrien } 431550397Sobrien} 431650397Sobrien 431750397Sobrien/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT 431850397Sobrien of a virtual function may refer to a base class, so we check the 'this' 431950397Sobrien parameter. */ 432050397Sobrien 432150397Sobrienstatic tree 432250397Sobriendecl_class_context (decl) 432350397Sobrien tree decl; 432450397Sobrien{ 432550397Sobrien tree context = NULL_TREE; 432650397Sobrien 432750397Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl)) 432850397Sobrien context = DECL_CONTEXT (decl); 432950397Sobrien else 433050397Sobrien context = TYPE_MAIN_VARIANT 433150397Sobrien (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); 433250397Sobrien 433390075Sobrien if (context && !TYPE_P (context)) 433450397Sobrien context = NULL_TREE; 433550397Sobrien 433650397Sobrien return context; 433750397Sobrien} 433850397Sobrien 433990075Sobrien/* Add an attribute/value pair to a DIE. We build the lists up in reverse 434090075Sobrien addition order, and correct that in reverse_all_dies. */ 434150397Sobrien 434250397Sobrienstatic inline void 434350397Sobrienadd_dwarf_attr (die, attr) 434490075Sobrien dw_die_ref die; 434590075Sobrien dw_attr_ref attr; 434650397Sobrien{ 434750397Sobrien if (die != NULL && attr != NULL) 434850397Sobrien { 434990075Sobrien attr->dw_attr_next = die->die_attr; 435090075Sobrien die->die_attr = attr; 435150397Sobrien } 435250397Sobrien} 435350397Sobrien 435490075Sobrienstatic inline dw_val_class 435590075SobrienAT_class (a) 435690075Sobrien dw_attr_ref a; 435790075Sobrien{ 435890075Sobrien return a->dw_attr_val.val_class; 435990075Sobrien} 436090075Sobrien 436150397Sobrien/* Add a flag value attribute to a DIE. */ 436250397Sobrien 436350397Sobrienstatic inline void 436450397Sobrienadd_AT_flag (die, attr_kind, flag) 436590075Sobrien dw_die_ref die; 436690075Sobrien enum dwarf_attribute attr_kind; 436790075Sobrien unsigned flag; 436850397Sobrien{ 436990075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 437050397Sobrien 437150397Sobrien attr->dw_attr_next = NULL; 437250397Sobrien attr->dw_attr = attr_kind; 437350397Sobrien attr->dw_attr_val.val_class = dw_val_class_flag; 437450397Sobrien attr->dw_attr_val.v.val_flag = flag; 437550397Sobrien add_dwarf_attr (die, attr); 437650397Sobrien} 437750397Sobrien 437890075Sobrienstatic inline unsigned 437990075SobrienAT_flag (a) 438090075Sobrien dw_attr_ref a; 438190075Sobrien{ 438290075Sobrien if (a && AT_class (a) == dw_val_class_flag) 438390075Sobrien return a->dw_attr_val.v.val_flag; 438490075Sobrien 438590075Sobrien abort (); 438690075Sobrien} 438790075Sobrien 438850397Sobrien/* Add a signed integer attribute value to a DIE. */ 438950397Sobrien 439050397Sobrienstatic inline void 439150397Sobrienadd_AT_int (die, attr_kind, int_val) 439290075Sobrien dw_die_ref die; 439390075Sobrien enum dwarf_attribute attr_kind; 439490075Sobrien long int int_val; 439550397Sobrien{ 439690075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 439750397Sobrien 439850397Sobrien attr->dw_attr_next = NULL; 439950397Sobrien attr->dw_attr = attr_kind; 440050397Sobrien attr->dw_attr_val.val_class = dw_val_class_const; 440150397Sobrien attr->dw_attr_val.v.val_int = int_val; 440250397Sobrien add_dwarf_attr (die, attr); 440350397Sobrien} 440450397Sobrien 440590075Sobrienstatic inline long int 440690075SobrienAT_int (a) 440790075Sobrien dw_attr_ref a; 440890075Sobrien{ 440990075Sobrien if (a && AT_class (a) == dw_val_class_const) 441090075Sobrien return a->dw_attr_val.v.val_int; 441190075Sobrien 441290075Sobrien abort (); 441390075Sobrien} 441490075Sobrien 441550397Sobrien/* Add an unsigned integer attribute value to a DIE. */ 441650397Sobrien 441750397Sobrienstatic inline void 441850397Sobrienadd_AT_unsigned (die, attr_kind, unsigned_val) 441990075Sobrien dw_die_ref die; 442090075Sobrien enum dwarf_attribute attr_kind; 442190075Sobrien unsigned long unsigned_val; 442250397Sobrien{ 442390075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 442450397Sobrien 442550397Sobrien attr->dw_attr_next = NULL; 442650397Sobrien attr->dw_attr = attr_kind; 442750397Sobrien attr->dw_attr_val.val_class = dw_val_class_unsigned_const; 442850397Sobrien attr->dw_attr_val.v.val_unsigned = unsigned_val; 442950397Sobrien add_dwarf_attr (die, attr); 443050397Sobrien} 443150397Sobrien 443290075Sobrienstatic inline unsigned long 443390075SobrienAT_unsigned (a) 443490075Sobrien dw_attr_ref a; 443590075Sobrien{ 443690075Sobrien if (a && AT_class (a) == dw_val_class_unsigned_const) 443790075Sobrien return a->dw_attr_val.v.val_unsigned; 443890075Sobrien 443990075Sobrien abort (); 444090075Sobrien} 444190075Sobrien 444250397Sobrien/* Add an unsigned double integer attribute value to a DIE. */ 444350397Sobrien 444450397Sobrienstatic inline void 444550397Sobrienadd_AT_long_long (die, attr_kind, val_hi, val_low) 444690075Sobrien dw_die_ref die; 444790075Sobrien enum dwarf_attribute attr_kind; 444890075Sobrien unsigned long val_hi; 444990075Sobrien unsigned long val_low; 445050397Sobrien{ 445190075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 445250397Sobrien 445350397Sobrien attr->dw_attr_next = NULL; 445450397Sobrien attr->dw_attr = attr_kind; 445550397Sobrien attr->dw_attr_val.val_class = dw_val_class_long_long; 445650397Sobrien attr->dw_attr_val.v.val_long_long.hi = val_hi; 445750397Sobrien attr->dw_attr_val.v.val_long_long.low = val_low; 445850397Sobrien add_dwarf_attr (die, attr); 445950397Sobrien} 446050397Sobrien 446150397Sobrien/* Add a floating point attribute value to a DIE and return it. */ 446250397Sobrien 446350397Sobrienstatic inline void 446450397Sobrienadd_AT_float (die, attr_kind, length, array) 446590075Sobrien dw_die_ref die; 446690075Sobrien enum dwarf_attribute attr_kind; 446790075Sobrien unsigned length; 446890075Sobrien long *array; 446950397Sobrien{ 447090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 447150397Sobrien 447250397Sobrien attr->dw_attr_next = NULL; 447350397Sobrien attr->dw_attr = attr_kind; 447450397Sobrien attr->dw_attr_val.val_class = dw_val_class_float; 447550397Sobrien attr->dw_attr_val.v.val_float.length = length; 447650397Sobrien attr->dw_attr_val.v.val_float.array = array; 447750397Sobrien add_dwarf_attr (die, attr); 447850397Sobrien} 447950397Sobrien 448050397Sobrien/* Add a string attribute value to a DIE. */ 448150397Sobrien 448250397Sobrienstatic inline void 448350397Sobrienadd_AT_string (die, attr_kind, str) 448490075Sobrien dw_die_ref die; 448590075Sobrien enum dwarf_attribute attr_kind; 448690075Sobrien const char *str; 448750397Sobrien{ 448890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 448990075Sobrien struct indirect_string_node *node; 449090075Sobrien 449190075Sobrien if (! debug_str_hash) 449290075Sobrien { 449390075Sobrien debug_str_hash = ht_create (10); 449490075Sobrien debug_str_hash->alloc_node = indirect_string_alloc; 449590075Sobrien } 449650397Sobrien 449790075Sobrien node = (struct indirect_string_node *) 449890075Sobrien ht_lookup (debug_str_hash, (const unsigned char *) str, 449990075Sobrien strlen (str), HT_ALLOC); 450090075Sobrien node->refcount++; 450190075Sobrien 450250397Sobrien attr->dw_attr_next = NULL; 450350397Sobrien attr->dw_attr = attr_kind; 450450397Sobrien attr->dw_attr_val.val_class = dw_val_class_str; 450590075Sobrien attr->dw_attr_val.v.val_str = node; 450650397Sobrien add_dwarf_attr (die, attr); 450750397Sobrien} 450850397Sobrien 450990075Sobrienstatic inline const char * 451090075SobrienAT_string (a) 451190075Sobrien dw_attr_ref a; 451290075Sobrien{ 451390075Sobrien if (a && AT_class (a) == dw_val_class_str) 451490075Sobrien return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id); 451590075Sobrien 451690075Sobrien abort (); 451790075Sobrien} 451890075Sobrien 451990075Sobrien/* Find out whether a string should be output inline in DIE 452090075Sobrien or out-of-line in .debug_str section. */ 452190075Sobrien 452290075Sobrienstatic int 452390075SobrienAT_string_form (a) 452490075Sobrien dw_attr_ref a; 452590075Sobrien{ 452690075Sobrien if (a && AT_class (a) == dw_val_class_str) 452790075Sobrien { 452890075Sobrien struct indirect_string_node *node; 452990075Sobrien unsigned int len; 453090075Sobrien extern int const_labelno; 453190075Sobrien char label[32]; 453290075Sobrien 453390075Sobrien node = a->dw_attr_val.v.val_str; 453490075Sobrien if (node->form) 453590075Sobrien return node->form; 453690075Sobrien 453790075Sobrien len = HT_LEN (&node->id) + 1; 453890075Sobrien 453990075Sobrien /* If the string is shorter or equal to the size of the reference, it is 454090075Sobrien always better to put it inline. */ 454190075Sobrien if (len <= DWARF_OFFSET_SIZE || node->refcount == 0) 454290075Sobrien return node->form = DW_FORM_string; 454390075Sobrien 454490075Sobrien /* If we cannot expect the linker to merge strings in .debug_str 454590075Sobrien section, only put it into .debug_str if it is worth even in this 454690075Sobrien single module. */ 454790075Sobrien if ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0 454890075Sobrien && (len - DWARF_OFFSET_SIZE) * node->refcount <= len) 454990075Sobrien return node->form = DW_FORM_string; 455090075Sobrien 455190075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); 455290075Sobrien ++const_labelno; 455390075Sobrien node->label = xstrdup (label); 455490075Sobrien 455590075Sobrien return node->form = DW_FORM_strp; 455690075Sobrien } 455790075Sobrien 455890075Sobrien abort (); 455990075Sobrien} 456090075Sobrien 456150397Sobrien/* Add a DIE reference attribute value to a DIE. */ 456250397Sobrien 456350397Sobrienstatic inline void 456450397Sobrienadd_AT_die_ref (die, attr_kind, targ_die) 456590075Sobrien dw_die_ref die; 456690075Sobrien enum dwarf_attribute attr_kind; 456790075Sobrien dw_die_ref targ_die; 456850397Sobrien{ 456990075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 457050397Sobrien 457150397Sobrien attr->dw_attr_next = NULL; 457250397Sobrien attr->dw_attr = attr_kind; 457350397Sobrien attr->dw_attr_val.val_class = dw_val_class_die_ref; 457490075Sobrien attr->dw_attr_val.v.val_die_ref.die = targ_die; 457590075Sobrien attr->dw_attr_val.v.val_die_ref.external = 0; 457650397Sobrien add_dwarf_attr (die, attr); 457750397Sobrien} 457850397Sobrien 457990075Sobrienstatic inline dw_die_ref 458090075SobrienAT_ref (a) 458190075Sobrien dw_attr_ref a; 458290075Sobrien{ 458390075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 458490075Sobrien return a->dw_attr_val.v.val_die_ref.die; 458590075Sobrien 458690075Sobrien abort (); 458790075Sobrien} 458890075Sobrien 458990075Sobrienstatic inline int 459090075SobrienAT_ref_external (a) 459190075Sobrien dw_attr_ref a; 459290075Sobrien{ 459390075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 459490075Sobrien return a->dw_attr_val.v.val_die_ref.external; 459590075Sobrien 459690075Sobrien return 0; 459790075Sobrien} 459890075Sobrien 459990075Sobrienstatic inline void 460090075Sobrienset_AT_ref_external (a, i) 460190075Sobrien dw_attr_ref a; 460290075Sobrien int i; 460390075Sobrien{ 460490075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 460590075Sobrien a->dw_attr_val.v.val_die_ref.external = i; 460690075Sobrien else 460790075Sobrien abort (); 460890075Sobrien} 460990075Sobrien 461050397Sobrien/* Add an FDE reference attribute value to a DIE. */ 461150397Sobrien 461250397Sobrienstatic inline void 461350397Sobrienadd_AT_fde_ref (die, attr_kind, targ_fde) 461490075Sobrien dw_die_ref die; 461590075Sobrien enum dwarf_attribute attr_kind; 461690075Sobrien unsigned targ_fde; 461750397Sobrien{ 461890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 461950397Sobrien 462050397Sobrien attr->dw_attr_next = NULL; 462150397Sobrien attr->dw_attr = attr_kind; 462250397Sobrien attr->dw_attr_val.val_class = dw_val_class_fde_ref; 462350397Sobrien attr->dw_attr_val.v.val_fde_index = targ_fde; 462450397Sobrien add_dwarf_attr (die, attr); 462550397Sobrien} 462650397Sobrien 462750397Sobrien/* Add a location description attribute value to a DIE. */ 462850397Sobrien 462950397Sobrienstatic inline void 463050397Sobrienadd_AT_loc (die, attr_kind, loc) 463190075Sobrien dw_die_ref die; 463290075Sobrien enum dwarf_attribute attr_kind; 463390075Sobrien dw_loc_descr_ref loc; 463450397Sobrien{ 463590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 463650397Sobrien 463750397Sobrien attr->dw_attr_next = NULL; 463850397Sobrien attr->dw_attr = attr_kind; 463950397Sobrien attr->dw_attr_val.val_class = dw_val_class_loc; 464050397Sobrien attr->dw_attr_val.v.val_loc = loc; 464150397Sobrien add_dwarf_attr (die, attr); 464250397Sobrien} 464350397Sobrien 464490075Sobrienstatic inline dw_loc_descr_ref 464590075SobrienAT_loc (a) 464690075Sobrien dw_attr_ref a; 464790075Sobrien{ 464890075Sobrien if (a && AT_class (a) == dw_val_class_loc) 464990075Sobrien return a->dw_attr_val.v.val_loc; 465090075Sobrien 465190075Sobrien abort (); 465290075Sobrien} 465390075Sobrien 465490075Sobrienstatic inline void 465590075Sobrienadd_AT_loc_list (die, attr_kind, loc_list) 465690075Sobrien dw_die_ref die; 465790075Sobrien enum dwarf_attribute attr_kind; 465890075Sobrien dw_loc_list_ref loc_list; 465990075Sobrien{ 466090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 466190075Sobrien 466290075Sobrien attr->dw_attr_next = NULL; 466390075Sobrien attr->dw_attr = attr_kind; 466490075Sobrien attr->dw_attr_val.val_class = dw_val_class_loc_list; 466590075Sobrien attr->dw_attr_val.v.val_loc_list = loc_list; 466690075Sobrien add_dwarf_attr (die, attr); 466790075Sobrien have_location_lists = 1; 466890075Sobrien} 466990075Sobrien 467090075Sobrienstatic inline dw_loc_list_ref 467190075SobrienAT_loc_list (a) 467290075Sobrien dw_attr_ref a; 467390075Sobrien{ 467490075Sobrien if (a && AT_class (a) == dw_val_class_loc_list) 467590075Sobrien return a->dw_attr_val.v.val_loc_list; 467690075Sobrien 467790075Sobrien abort (); 467890075Sobrien} 467990075Sobrien 468050397Sobrien/* Add an address constant attribute value to a DIE. */ 468150397Sobrien 468250397Sobrienstatic inline void 468350397Sobrienadd_AT_addr (die, attr_kind, addr) 468490075Sobrien dw_die_ref die; 468590075Sobrien enum dwarf_attribute attr_kind; 468690075Sobrien rtx addr; 468750397Sobrien{ 468890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 468950397Sobrien 469050397Sobrien attr->dw_attr_next = NULL; 469150397Sobrien attr->dw_attr = attr_kind; 469250397Sobrien attr->dw_attr_val.val_class = dw_val_class_addr; 469350397Sobrien attr->dw_attr_val.v.val_addr = addr; 469450397Sobrien add_dwarf_attr (die, attr); 469550397Sobrien} 469650397Sobrien 469790075Sobrienstatic inline rtx 469890075SobrienAT_addr (a) 469990075Sobrien dw_attr_ref a; 470090075Sobrien{ 470190075Sobrien if (a && AT_class (a) == dw_val_class_addr) 470290075Sobrien return a->dw_attr_val.v.val_addr; 470390075Sobrien 470490075Sobrien abort (); 470590075Sobrien} 470690075Sobrien 470750397Sobrien/* Add a label identifier attribute value to a DIE. */ 470850397Sobrien 470950397Sobrienstatic inline void 471050397Sobrienadd_AT_lbl_id (die, attr_kind, lbl_id) 471190075Sobrien dw_die_ref die; 471290075Sobrien enum dwarf_attribute attr_kind; 471390075Sobrien const char *lbl_id; 471450397Sobrien{ 471590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 471650397Sobrien 471750397Sobrien attr->dw_attr_next = NULL; 471850397Sobrien attr->dw_attr = attr_kind; 471950397Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_id; 472050397Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); 472150397Sobrien add_dwarf_attr (die, attr); 472250397Sobrien} 472350397Sobrien 472450397Sobrien/* Add a section offset attribute value to a DIE. */ 472550397Sobrien 472650397Sobrienstatic inline void 472752284Sobrienadd_AT_lbl_offset (die, attr_kind, label) 472890075Sobrien dw_die_ref die; 472990075Sobrien enum dwarf_attribute attr_kind; 473090075Sobrien const char *label; 473150397Sobrien{ 473290075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 473350397Sobrien 473450397Sobrien attr->dw_attr_next = NULL; 473550397Sobrien attr->dw_attr = attr_kind; 473652284Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_offset; 473790075Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (label); 473850397Sobrien add_dwarf_attr (die, attr); 473950397Sobrien} 474050397Sobrien 474190075Sobrien/* Add an offset attribute value to a DIE. */ 474250397Sobrien 474390075Sobrienstatic inline void 474490075Sobrienadd_AT_offset (die, attr_kind, offset) 474590075Sobrien dw_die_ref die; 474690075Sobrien enum dwarf_attribute attr_kind; 474790075Sobrien unsigned long offset; 474850397Sobrien{ 474990075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 475050397Sobrien 475190075Sobrien attr->dw_attr_next = NULL; 475290075Sobrien attr->dw_attr = attr_kind; 475390075Sobrien attr->dw_attr_val.val_class = dw_val_class_offset; 475490075Sobrien attr->dw_attr_val.v.val_offset = offset; 475590075Sobrien add_dwarf_attr (die, attr); 475690075Sobrien} 475750397Sobrien 475890075Sobrien/* Add an range_list attribute value to a DIE. */ 475990075Sobrien 476090075Sobrienstatic void 476190075Sobrienadd_AT_range_list (die, attr_kind, offset) 476290075Sobrien dw_die_ref die; 476390075Sobrien enum dwarf_attribute attr_kind; 476490075Sobrien unsigned long offset; 476590075Sobrien{ 476690075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 476790075Sobrien 476890075Sobrien attr->dw_attr_next = NULL; 476990075Sobrien attr->dw_attr = attr_kind; 477090075Sobrien attr->dw_attr_val.val_class = dw_val_class_range_list; 477190075Sobrien attr->dw_attr_val.v.val_offset = offset; 477290075Sobrien add_dwarf_attr (die, attr); 477350397Sobrien} 477450397Sobrien 477590075Sobrienstatic inline const char * 477690075SobrienAT_lbl (a) 477790075Sobrien dw_attr_ref a; 477890075Sobrien{ 477990075Sobrien if (a && (AT_class (a) == dw_val_class_lbl_id 478090075Sobrien || AT_class (a) == dw_val_class_lbl_offset)) 478190075Sobrien return a->dw_attr_val.v.val_lbl_id; 478290075Sobrien 478390075Sobrien abort (); 478490075Sobrien} 478590075Sobrien 478650397Sobrien/* Get the attribute of type attr_kind. */ 478750397Sobrien 478850397Sobrienstatic inline dw_attr_ref 478950397Sobrienget_AT (die, attr_kind) 479090075Sobrien dw_die_ref die; 479190075Sobrien enum dwarf_attribute attr_kind; 479250397Sobrien{ 479390075Sobrien dw_attr_ref a; 479490075Sobrien dw_die_ref spec = NULL; 479590075Sobrien 479650397Sobrien if (die != NULL) 479750397Sobrien { 479850397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 479990075Sobrien if (a->dw_attr == attr_kind) 480090075Sobrien return a; 480190075Sobrien else if (a->dw_attr == DW_AT_specification 480290075Sobrien || a->dw_attr == DW_AT_abstract_origin) 480390075Sobrien spec = AT_ref (a); 480450397Sobrien 480550397Sobrien if (spec) 480650397Sobrien return get_AT (spec, attr_kind); 480750397Sobrien } 480850397Sobrien 480950397Sobrien return NULL; 481050397Sobrien} 481150397Sobrien 481290075Sobrien/* Return the "low pc" attribute value, typically associated with a subprogram 481390075Sobrien DIE. Return null if the "low pc" attribute is either not present, or if it 481490075Sobrien cannot be represented as an assembler label identifier. */ 481550397Sobrien 481690075Sobrienstatic inline const char * 481750397Sobrienget_AT_low_pc (die) 481890075Sobrien dw_die_ref die; 481950397Sobrien{ 482090075Sobrien dw_attr_ref a = get_AT (die, DW_AT_low_pc); 482150397Sobrien 482290075Sobrien return a ? AT_lbl (a) : NULL; 482350397Sobrien} 482450397Sobrien 482590075Sobrien/* Return the "high pc" attribute value, typically associated with a subprogram 482690075Sobrien DIE. Return null if the "high pc" attribute is either not present, or if it 482790075Sobrien cannot be represented as an assembler label identifier. */ 482850397Sobrien 482990075Sobrienstatic inline const char * 483050397Sobrienget_AT_hi_pc (die) 483190075Sobrien dw_die_ref die; 483250397Sobrien{ 483390075Sobrien dw_attr_ref a = get_AT (die, DW_AT_high_pc); 483450397Sobrien 483590075Sobrien return a ? AT_lbl (a) : NULL; 483650397Sobrien} 483750397Sobrien 483850397Sobrien/* Return the value of the string attribute designated by ATTR_KIND, or 483950397Sobrien NULL if it is not present. */ 484050397Sobrien 484190075Sobrienstatic inline const char * 484250397Sobrienget_AT_string (die, attr_kind) 484390075Sobrien dw_die_ref die; 484490075Sobrien enum dwarf_attribute attr_kind; 484550397Sobrien{ 484690075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 484750397Sobrien 484890075Sobrien return a ? AT_string (a) : NULL; 484950397Sobrien} 485050397Sobrien 485150397Sobrien/* Return the value of the flag attribute designated by ATTR_KIND, or -1 485250397Sobrien if it is not present. */ 485350397Sobrien 485450397Sobrienstatic inline int 485550397Sobrienget_AT_flag (die, attr_kind) 485690075Sobrien dw_die_ref die; 485790075Sobrien enum dwarf_attribute attr_kind; 485850397Sobrien{ 485990075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 486050397Sobrien 486190075Sobrien return a ? AT_flag (a) : 0; 486250397Sobrien} 486350397Sobrien 486450397Sobrien/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0 486550397Sobrien if it is not present. */ 486650397Sobrien 486750397Sobrienstatic inline unsigned 486850397Sobrienget_AT_unsigned (die, attr_kind) 486990075Sobrien dw_die_ref die; 487090075Sobrien enum dwarf_attribute attr_kind; 487150397Sobrien{ 487290075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 487350397Sobrien 487490075Sobrien return a ? AT_unsigned (a) : 0; 487590075Sobrien} 487650397Sobrien 487790075Sobrienstatic inline dw_die_ref 487890075Sobrienget_AT_ref (die, attr_kind) 487990075Sobrien dw_die_ref die; 488090075Sobrien enum dwarf_attribute attr_kind; 488190075Sobrien{ 488290075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 488390075Sobrien 488490075Sobrien return a ? AT_ref (a) : NULL; 488550397Sobrien} 488650397Sobrien 488750397Sobrienstatic inline int 488850397Sobrienis_c_family () 488950397Sobrien{ 489090075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 489150397Sobrien 489250397Sobrien return (lang == DW_LANG_C || lang == DW_LANG_C89 489350397Sobrien || lang == DW_LANG_C_plus_plus); 489490075Sobrien} 489550397Sobrien 489650397Sobrienstatic inline int 489790075Sobrienis_cxx () 489890075Sobrien{ 489990075Sobrien return (get_AT_unsigned (comp_unit_die, DW_AT_language) 490090075Sobrien == DW_LANG_C_plus_plus); 490190075Sobrien} 490290075Sobrien 490390075Sobrienstatic inline int 490450397Sobrienis_fortran () 490550397Sobrien{ 490690075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 490750397Sobrien 490850397Sobrien return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90); 490990075Sobrien} 491050397Sobrien 491190075Sobrienstatic inline int 491290075Sobrienis_java () 491390075Sobrien{ 491490075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 491590075Sobrien 491690075Sobrien return (lang == DW_LANG_Java); 491790075Sobrien} 491890075Sobrien 491990075Sobrien/* Free up the memory used by A. */ 492090075Sobrien 492190075Sobrienstatic inline void free_AT PARAMS ((dw_attr_ref)); 492290075Sobrienstatic inline void 492390075Sobrienfree_AT (a) 492490075Sobrien dw_attr_ref a; 492590075Sobrien{ 492690075Sobrien switch (AT_class (a)) 492790075Sobrien { 492890075Sobrien case dw_val_class_str: 492990075Sobrien if (a->dw_attr_val.v.val_str->refcount) 493090075Sobrien a->dw_attr_val.v.val_str->refcount--; 493190075Sobrien break; 493290075Sobrien 493390075Sobrien case dw_val_class_lbl_id: 493490075Sobrien case dw_val_class_lbl_offset: 493590075Sobrien free (a->dw_attr_val.v.val_lbl_id); 493690075Sobrien break; 493790075Sobrien 493890075Sobrien case dw_val_class_float: 493990075Sobrien free (a->dw_attr_val.v.val_float.array); 494090075Sobrien break; 494190075Sobrien 494290075Sobrien default: 494390075Sobrien break; 494490075Sobrien } 494590075Sobrien 494690075Sobrien free (a); 494790075Sobrien} 494890075Sobrien 494950397Sobrien/* Remove the specified attribute if present. */ 495050397Sobrien 495190075Sobrienstatic void 495250397Sobrienremove_AT (die, attr_kind) 495390075Sobrien dw_die_ref die; 495490075Sobrien enum dwarf_attribute attr_kind; 495550397Sobrien{ 495690075Sobrien dw_attr_ref *p; 495790075Sobrien dw_attr_ref removed = NULL; 495850397Sobrien 495950397Sobrien if (die != NULL) 496050397Sobrien { 496190075Sobrien for (p = &(die->die_attr); *p; p = &((*p)->dw_attr_next)) 496290075Sobrien if ((*p)->dw_attr == attr_kind) 496390075Sobrien { 496490075Sobrien removed = *p; 496590075Sobrien *p = (*p)->dw_attr_next; 496690075Sobrien break; 496790075Sobrien } 496850397Sobrien 496950397Sobrien if (removed != 0) 497090075Sobrien free_AT (removed); 497150397Sobrien } 497250397Sobrien} 497350397Sobrien 497490075Sobrien/* Free up the memory used by DIE. */ 497590075Sobrien 497690075Sobrienstatic inline void 497790075Sobrienfree_die (die) 497890075Sobrien dw_die_ref die; 497990075Sobrien{ 498090075Sobrien remove_children (die); 498190075Sobrien free (die); 498290075Sobrien} 498390075Sobrien 498450397Sobrien/* Discard the children of this DIE. */ 498550397Sobrien 498690075Sobrienstatic void 498750397Sobrienremove_children (die) 498890075Sobrien dw_die_ref die; 498950397Sobrien{ 499090075Sobrien dw_die_ref child_die = die->die_child; 499150397Sobrien 499250397Sobrien die->die_child = NULL; 499350397Sobrien 499450397Sobrien while (child_die != NULL) 499550397Sobrien { 499690075Sobrien dw_die_ref tmp_die = child_die; 499790075Sobrien dw_attr_ref a; 499850397Sobrien 499950397Sobrien child_die = child_die->die_sib; 500090075Sobrien 500190075Sobrien for (a = tmp_die->die_attr; a != NULL;) 500250397Sobrien { 500390075Sobrien dw_attr_ref tmp_a = a; 500450397Sobrien 500550397Sobrien a = a->dw_attr_next; 500690075Sobrien free_AT (tmp_a); 500750397Sobrien } 500850397Sobrien 500990075Sobrien free_die (tmp_die); 501050397Sobrien } 501150397Sobrien} 501250397Sobrien 501390075Sobrien/* Add a child DIE below its parent. We build the lists up in reverse 501490075Sobrien addition order, and correct that in reverse_all_dies. */ 501550397Sobrien 501650397Sobrienstatic inline void 501750397Sobrienadd_child_die (die, child_die) 501890075Sobrien dw_die_ref die; 501990075Sobrien dw_die_ref child_die; 502050397Sobrien{ 502150397Sobrien if (die != NULL && child_die != NULL) 502250397Sobrien { 502350397Sobrien if (die == child_die) 502450397Sobrien abort (); 502590075Sobrien 502650397Sobrien child_die->die_parent = die; 502790075Sobrien child_die->die_sib = die->die_child; 502890075Sobrien die->die_child = child_die; 502990075Sobrien } 503090075Sobrien} 503150397Sobrien 503290075Sobrien/* Move CHILD, which must be a child of PARENT or the DIE for which PARENT 503390075Sobrien is the specification, to the front of PARENT's list of children. */ 503490075Sobrien 503590075Sobrienstatic void 503690075Sobriensplice_child_die (parent, child) 503790075Sobrien dw_die_ref parent, child; 503890075Sobrien{ 503990075Sobrien dw_die_ref *p; 504090075Sobrien 504190075Sobrien /* We want the declaration DIE from inside the class, not the 504290075Sobrien specification DIE at toplevel. */ 504390075Sobrien if (child->die_parent != parent) 504490075Sobrien { 504590075Sobrien dw_die_ref tmp = get_AT_ref (child, DW_AT_specification); 504690075Sobrien 504790075Sobrien if (tmp) 504890075Sobrien child = tmp; 504950397Sobrien } 505090075Sobrien 505190075Sobrien if (child->die_parent != parent 505290075Sobrien && child->die_parent != get_AT_ref (parent, DW_AT_specification)) 505390075Sobrien abort (); 505490075Sobrien 505590075Sobrien for (p = &(child->die_parent->die_child); *p; p = &((*p)->die_sib)) 505690075Sobrien if (*p == child) 505790075Sobrien { 505890075Sobrien *p = child->die_sib; 505990075Sobrien break; 506090075Sobrien } 506190075Sobrien 506290075Sobrien child->die_sib = parent->die_child; 506390075Sobrien parent->die_child = child; 506450397Sobrien} 506550397Sobrien 506650397Sobrien/* Return a pointer to a newly created DIE node. */ 506750397Sobrien 506850397Sobrienstatic inline dw_die_ref 506990075Sobriennew_die (tag_value, parent_die, t) 507090075Sobrien enum dwarf_tag tag_value; 507190075Sobrien dw_die_ref parent_die; 507290075Sobrien tree t; 507350397Sobrien{ 507490075Sobrien dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node)); 507550397Sobrien 507650397Sobrien die->die_tag = tag_value; 507750397Sobrien 507850397Sobrien if (parent_die != NULL) 507950397Sobrien add_child_die (parent_die, die); 508050397Sobrien else 508150397Sobrien { 508250397Sobrien limbo_die_node *limbo_node; 508350397Sobrien 508450397Sobrien limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node)); 508550397Sobrien limbo_node->die = die; 508690075Sobrien limbo_node->created_for = t; 508750397Sobrien limbo_node->next = limbo_die_list; 508850397Sobrien limbo_die_list = limbo_node; 508950397Sobrien } 509050397Sobrien 509150397Sobrien return die; 509250397Sobrien} 509350397Sobrien 509450397Sobrien/* Return the DIE associated with the given type specifier. */ 509550397Sobrien 509650397Sobrienstatic inline dw_die_ref 509750397Sobrienlookup_type_die (type) 509890075Sobrien tree type; 509950397Sobrien{ 510050397Sobrien return (dw_die_ref) TYPE_SYMTAB_POINTER (type); 510150397Sobrien} 510250397Sobrien 510350397Sobrien/* Equate a DIE to a given type specifier. */ 510450397Sobrien 510590075Sobrienstatic inline void 510650397Sobrienequate_type_number_to_die (type, type_die) 510790075Sobrien tree type; 510890075Sobrien dw_die_ref type_die; 510950397Sobrien{ 511050397Sobrien TYPE_SYMTAB_POINTER (type) = (char *) type_die; 511150397Sobrien} 511250397Sobrien 511350397Sobrien/* Return the DIE associated with a given declaration. */ 511450397Sobrien 511550397Sobrienstatic inline dw_die_ref 511650397Sobrienlookup_decl_die (decl) 511790075Sobrien tree decl; 511850397Sobrien{ 511990075Sobrien unsigned decl_id = DECL_UID (decl); 512050397Sobrien 512190075Sobrien return (decl_id < decl_die_table_in_use ? decl_die_table[decl_id] : NULL); 512250397Sobrien} 512350397Sobrien 512450397Sobrien/* Equate a DIE to a particular declaration. */ 512550397Sobrien 512650397Sobrienstatic void 512750397Sobrienequate_decl_number_to_die (decl, decl_die) 512890075Sobrien tree decl; 512990075Sobrien dw_die_ref decl_die; 513050397Sobrien{ 513190075Sobrien unsigned int decl_id = DECL_UID (decl); 513290075Sobrien unsigned int num_allocated; 513350397Sobrien 513450397Sobrien if (decl_id >= decl_die_table_allocated) 513550397Sobrien { 513650397Sobrien num_allocated 513750397Sobrien = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1) 513850397Sobrien / DECL_DIE_TABLE_INCREMENT) 513950397Sobrien * DECL_DIE_TABLE_INCREMENT; 514050397Sobrien 514150397Sobrien decl_die_table 514250397Sobrien = (dw_die_ref *) xrealloc (decl_die_table, 514350397Sobrien sizeof (dw_die_ref) * num_allocated); 514450397Sobrien 514590075Sobrien memset ((char *) &decl_die_table[decl_die_table_allocated], 0, 514650397Sobrien (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref)); 514750397Sobrien decl_die_table_allocated = num_allocated; 514850397Sobrien } 514950397Sobrien 515050397Sobrien if (decl_id >= decl_die_table_in_use) 515150397Sobrien decl_die_table_in_use = (decl_id + 1); 515250397Sobrien 515350397Sobrien decl_die_table[decl_id] = decl_die; 515450397Sobrien} 515550397Sobrien 515650397Sobrien/* Keep track of the number of spaces used to indent the 515750397Sobrien output of the debugging routines that print the structure of 515850397Sobrien the DIE internal representation. */ 515950397Sobrienstatic int print_indent; 516050397Sobrien 516150397Sobrien/* Indent the line the number of spaces given by print_indent. */ 516250397Sobrien 516350397Sobrienstatic inline void 516450397Sobrienprint_spaces (outfile) 516550397Sobrien FILE *outfile; 516650397Sobrien{ 516750397Sobrien fprintf (outfile, "%*s", print_indent, ""); 516850397Sobrien} 516950397Sobrien 517050397Sobrien/* Print the information associated with a given DIE, and its children. 517150397Sobrien This routine is a debugging aid only. */ 517250397Sobrien 517350397Sobrienstatic void 517450397Sobrienprint_die (die, outfile) 517550397Sobrien dw_die_ref die; 517650397Sobrien FILE *outfile; 517750397Sobrien{ 517890075Sobrien dw_attr_ref a; 517990075Sobrien dw_die_ref c; 518050397Sobrien 518150397Sobrien print_spaces (outfile); 518250397Sobrien fprintf (outfile, "DIE %4lu: %s\n", 518350397Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 518450397Sobrien print_spaces (outfile); 518550397Sobrien fprintf (outfile, " abbrev id: %lu", die->die_abbrev); 518650397Sobrien fprintf (outfile, " offset: %lu\n", die->die_offset); 518750397Sobrien 518850397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 518950397Sobrien { 519050397Sobrien print_spaces (outfile); 519150397Sobrien fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr)); 519250397Sobrien 519390075Sobrien switch (AT_class (a)) 519450397Sobrien { 519550397Sobrien case dw_val_class_addr: 519650397Sobrien fprintf (outfile, "address"); 519750397Sobrien break; 519890075Sobrien case dw_val_class_offset: 519990075Sobrien fprintf (outfile, "offset"); 520090075Sobrien break; 520150397Sobrien case dw_val_class_loc: 520250397Sobrien fprintf (outfile, "location descriptor"); 520350397Sobrien break; 520490075Sobrien case dw_val_class_loc_list: 520590075Sobrien fprintf (outfile, "location list -> label:%s", 520690075Sobrien AT_loc_list (a)->ll_symbol); 520790075Sobrien break; 520890075Sobrien case dw_val_class_range_list: 520990075Sobrien fprintf (outfile, "range list"); 521090075Sobrien break; 521150397Sobrien case dw_val_class_const: 521290075Sobrien fprintf (outfile, "%ld", AT_int (a)); 521350397Sobrien break; 521450397Sobrien case dw_val_class_unsigned_const: 521590075Sobrien fprintf (outfile, "%lu", AT_unsigned (a)); 521650397Sobrien break; 521750397Sobrien case dw_val_class_long_long: 521850397Sobrien fprintf (outfile, "constant (%lu,%lu)", 521990075Sobrien a->dw_attr_val.v.val_long_long.hi, 522090075Sobrien a->dw_attr_val.v.val_long_long.low); 522150397Sobrien break; 522250397Sobrien case dw_val_class_float: 522350397Sobrien fprintf (outfile, "floating-point constant"); 522450397Sobrien break; 522550397Sobrien case dw_val_class_flag: 522690075Sobrien fprintf (outfile, "%u", AT_flag (a)); 522750397Sobrien break; 522850397Sobrien case dw_val_class_die_ref: 522990075Sobrien if (AT_ref (a) != NULL) 523090075Sobrien { 523190075Sobrien if (AT_ref (a)->die_symbol) 523290075Sobrien fprintf (outfile, "die -> label: %s", AT_ref (a)->die_symbol); 523390075Sobrien else 523490075Sobrien fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset); 523590075Sobrien } 523650397Sobrien else 523750397Sobrien fprintf (outfile, "die -> <null>"); 523850397Sobrien break; 523950397Sobrien case dw_val_class_lbl_id: 524052284Sobrien case dw_val_class_lbl_offset: 524190075Sobrien fprintf (outfile, "label: %s", AT_lbl (a)); 524250397Sobrien break; 524350397Sobrien case dw_val_class_str: 524490075Sobrien if (AT_string (a) != NULL) 524590075Sobrien fprintf (outfile, "\"%s\"", AT_string (a)); 524650397Sobrien else 524750397Sobrien fprintf (outfile, "<null>"); 524850397Sobrien break; 524950397Sobrien default: 525050397Sobrien break; 525150397Sobrien } 525250397Sobrien 525350397Sobrien fprintf (outfile, "\n"); 525450397Sobrien } 525550397Sobrien 525650397Sobrien if (die->die_child != NULL) 525750397Sobrien { 525850397Sobrien print_indent += 4; 525950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 526050397Sobrien print_die (c, outfile); 526150397Sobrien 526250397Sobrien print_indent -= 4; 526350397Sobrien } 526490075Sobrien if (print_indent == 0) 526590075Sobrien fprintf (outfile, "\n"); 526650397Sobrien} 526750397Sobrien 526850397Sobrien/* Print the contents of the source code line number correspondence table. 526950397Sobrien This routine is a debugging aid only. */ 527050397Sobrien 527150397Sobrienstatic void 527250397Sobrienprint_dwarf_line_table (outfile) 527350397Sobrien FILE *outfile; 527450397Sobrien{ 527590075Sobrien unsigned i; 527690075Sobrien dw_line_info_ref line_info; 527750397Sobrien 527850397Sobrien fprintf (outfile, "\n\nDWARF source line information\n"); 527990075Sobrien for (i = 1; i < line_info_table_in_use; i++) 528050397Sobrien { 528150397Sobrien line_info = &line_info_table[i]; 528250397Sobrien fprintf (outfile, "%5d: ", i); 528390075Sobrien fprintf (outfile, "%-20s", file_table.table[line_info->dw_file_num]); 528450397Sobrien fprintf (outfile, "%6ld", line_info->dw_line_num); 528550397Sobrien fprintf (outfile, "\n"); 528650397Sobrien } 528750397Sobrien 528850397Sobrien fprintf (outfile, "\n\n"); 528950397Sobrien} 529050397Sobrien 529150397Sobrien/* Print the information collected for a given DIE. */ 529250397Sobrien 529350397Sobrienvoid 529450397Sobriendebug_dwarf_die (die) 529550397Sobrien dw_die_ref die; 529650397Sobrien{ 529750397Sobrien print_die (die, stderr); 529850397Sobrien} 529950397Sobrien 530050397Sobrien/* Print all DWARF information collected for the compilation unit. 530150397Sobrien This routine is a debugging aid only. */ 530250397Sobrien 530350397Sobrienvoid 530450397Sobriendebug_dwarf () 530550397Sobrien{ 530650397Sobrien print_indent = 0; 530750397Sobrien print_die (comp_unit_die, stderr); 530890075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 530990075Sobrien print_dwarf_line_table (stderr); 531050397Sobrien} 531150397Sobrien 531290075Sobrien/* We build up the lists of children and attributes by pushing new ones 531390075Sobrien onto the beginning of the list. Reverse the lists for DIE so that 531490075Sobrien they are in order of addition. */ 531550397Sobrien 531650397Sobrienstatic void 531790075Sobrienreverse_die_lists (die) 531890075Sobrien dw_die_ref die; 531950397Sobrien{ 532090075Sobrien dw_die_ref c, cp, cn; 532190075Sobrien dw_attr_ref a, ap, an; 532290075Sobrien 532390075Sobrien for (a = die->die_attr, ap = 0; a; a = an) 532450397Sobrien { 532590075Sobrien an = a->dw_attr_next; 532690075Sobrien a->dw_attr_next = ap; 532790075Sobrien ap = a; 532890075Sobrien } 532950397Sobrien 533090075Sobrien die->die_attr = ap; 533150397Sobrien 533290075Sobrien for (c = die->die_child, cp = 0; c; c = cn) 533390075Sobrien { 533490075Sobrien cn = c->die_sib; 533590075Sobrien c->die_sib = cp; 533690075Sobrien cp = c; 533750397Sobrien } 533850397Sobrien 533990075Sobrien die->die_child = cp; 534090075Sobrien} 534190075Sobrien 534290075Sobrien/* reverse_die_lists only reverses the single die you pass it. Since we used to 534390075Sobrien reverse all dies in add_sibling_attributes, which runs through all the dies, 534490075Sobrien it would reverse all the dies. Now, however, since we don't call 534590075Sobrien reverse_die_lists in add_sibling_attributes, we need a routine to 534690075Sobrien recursively reverse all the dies. This is that routine. */ 534790075Sobrien 534890075Sobrienstatic void 534990075Sobrienreverse_all_dies (die) 535090075Sobrien dw_die_ref die; 535190075Sobrien{ 535290075Sobrien dw_die_ref c; 535390075Sobrien 535490075Sobrien reverse_die_lists (die); 535590075Sobrien 535690075Sobrien for (c = die->die_child; c; c = c->die_sib) 535790075Sobrien reverse_all_dies (c); 535890075Sobrien} 535990075Sobrien 536090075Sobrien/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU 536190075Sobrien for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL 536290075Sobrien DIE that marks the start of the DIEs for this include file. */ 536390075Sobrien 536490075Sobrienstatic dw_die_ref 536590075Sobrienpush_new_compile_unit (old_unit, bincl_die) 536690075Sobrien dw_die_ref old_unit, bincl_die; 536790075Sobrien{ 536890075Sobrien const char *filename = get_AT_string (bincl_die, DW_AT_name); 536990075Sobrien dw_die_ref new_unit = gen_compile_unit_die (filename); 537090075Sobrien 537190075Sobrien new_unit->die_sib = old_unit; 537290075Sobrien return new_unit; 537390075Sobrien} 537490075Sobrien 537590075Sobrien/* Close an include-file CU and reopen the enclosing one. */ 537690075Sobrien 537790075Sobrienstatic dw_die_ref 537890075Sobrienpop_compile_unit (old_unit) 537990075Sobrien dw_die_ref old_unit; 538090075Sobrien{ 538190075Sobrien dw_die_ref new_unit = old_unit->die_sib; 538290075Sobrien 538390075Sobrien old_unit->die_sib = NULL; 538490075Sobrien return new_unit; 538590075Sobrien} 538690075Sobrien 538790075Sobrien#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx) 538890075Sobrien#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO), ctx) 538990075Sobrien 539090075Sobrien/* Calculate the checksum of a location expression. */ 539190075Sobrien 539290075Sobrienstatic inline void 539390075Sobrienloc_checksum (loc, ctx) 539490075Sobrien dw_loc_descr_ref loc; 539590075Sobrien struct md5_ctx *ctx; 539690075Sobrien{ 539790075Sobrien CHECKSUM (loc->dw_loc_opc); 539890075Sobrien CHECKSUM (loc->dw_loc_oprnd1); 539990075Sobrien CHECKSUM (loc->dw_loc_oprnd2); 540090075Sobrien} 540190075Sobrien 540290075Sobrien/* Calculate the checksum of an attribute. */ 540390075Sobrien 540490075Sobrienstatic void 540590075Sobrienattr_checksum (at, ctx) 540690075Sobrien dw_attr_ref at; 540790075Sobrien struct md5_ctx *ctx; 540890075Sobrien{ 540990075Sobrien dw_loc_descr_ref loc; 541090075Sobrien rtx r; 541190075Sobrien 541290075Sobrien CHECKSUM (at->dw_attr); 541390075Sobrien 541490075Sobrien /* We don't care about differences in file numbering. */ 541590075Sobrien if (at->dw_attr == DW_AT_decl_file 541690075Sobrien /* Or that this was compiled with a different compiler snapshot; if 541790075Sobrien the output is the same, that's what matters. */ 541890075Sobrien || at->dw_attr == DW_AT_producer) 541990075Sobrien return; 542090075Sobrien 542190075Sobrien switch (AT_class (at)) 542290075Sobrien { 542390075Sobrien case dw_val_class_const: 542490075Sobrien CHECKSUM (at->dw_attr_val.v.val_int); 542590075Sobrien break; 542690075Sobrien case dw_val_class_unsigned_const: 542790075Sobrien CHECKSUM (at->dw_attr_val.v.val_unsigned); 542890075Sobrien break; 542990075Sobrien case dw_val_class_long_long: 543090075Sobrien CHECKSUM (at->dw_attr_val.v.val_long_long); 543190075Sobrien break; 543290075Sobrien case dw_val_class_float: 543390075Sobrien CHECKSUM (at->dw_attr_val.v.val_float); 543490075Sobrien break; 543590075Sobrien case dw_val_class_flag: 543690075Sobrien CHECKSUM (at->dw_attr_val.v.val_flag); 543790075Sobrien break; 543890075Sobrien case dw_val_class_str: 543990075Sobrien CHECKSUM_STRING (AT_string (at)); 544090075Sobrien break; 544190075Sobrien 544290075Sobrien case dw_val_class_addr: 544390075Sobrien r = AT_addr (at); 544490075Sobrien switch (GET_CODE (r)) 544590075Sobrien { 544690075Sobrien case SYMBOL_REF: 544790075Sobrien CHECKSUM_STRING (XSTR (r, 0)); 544890075Sobrien break; 544990075Sobrien 545090075Sobrien default: 545190075Sobrien abort (); 545290075Sobrien } 545390075Sobrien break; 545490075Sobrien 545590075Sobrien case dw_val_class_offset: 545690075Sobrien CHECKSUM (at->dw_attr_val.v.val_offset); 545790075Sobrien break; 545890075Sobrien 545990075Sobrien case dw_val_class_loc: 546090075Sobrien for (loc = AT_loc (at); loc; loc = loc->dw_loc_next) 546190075Sobrien loc_checksum (loc, ctx); 546290075Sobrien break; 546390075Sobrien 546490075Sobrien case dw_val_class_die_ref: 546590075Sobrien if (AT_ref (at)->die_offset) 546690075Sobrien CHECKSUM (AT_ref (at)->die_offset); 546790075Sobrien /* FIXME else use target die name or something. */ 546890075Sobrien 546990075Sobrien case dw_val_class_fde_ref: 547090075Sobrien case dw_val_class_lbl_id: 547190075Sobrien case dw_val_class_lbl_offset: 547290075Sobrien break; 547390075Sobrien 547490075Sobrien default: 547590075Sobrien break; 547690075Sobrien } 547790075Sobrien} 547890075Sobrien 547990075Sobrien/* Calculate the checksum of a DIE. */ 548090075Sobrien 548190075Sobrienstatic void 548290075Sobriendie_checksum (die, ctx) 548390075Sobrien dw_die_ref die; 548490075Sobrien struct md5_ctx *ctx; 548590075Sobrien{ 548690075Sobrien dw_die_ref c; 548790075Sobrien dw_attr_ref a; 548890075Sobrien 548990075Sobrien CHECKSUM (die->die_tag); 549090075Sobrien 549190075Sobrien for (a = die->die_attr; a; a = a->dw_attr_next) 549290075Sobrien attr_checksum (a, ctx); 549390075Sobrien 549490075Sobrien for (c = die->die_child; c; c = c->die_sib) 549590075Sobrien die_checksum (c, ctx); 549690075Sobrien} 549790075Sobrien 549890075Sobrien#undef CHECKSUM 549990075Sobrien#undef CHECKSUM_STRING 550090075Sobrien 550190075Sobrien/* The prefix to attach to symbols on DIEs in the current comdat debug 550290075Sobrien info section. */ 550390075Sobrienstatic char *comdat_symbol_id; 550490075Sobrien 550590075Sobrien/* The index of the current symbol within the current comdat CU. */ 550690075Sobrienstatic unsigned int comdat_symbol_number; 550790075Sobrien 550890075Sobrien/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its 550990075Sobrien children, and set comdat_symbol_id accordingly. */ 551090075Sobrien 551190075Sobrienstatic void 551290075Sobriencompute_section_prefix (unit_die) 551390075Sobrien dw_die_ref unit_die; 551490075Sobrien{ 551590075Sobrien const char *base = lbasename (get_AT_string (unit_die, DW_AT_name)); 551690075Sobrien char *name = (char *) alloca (strlen (base) + 64); 551790075Sobrien char *p; 551890075Sobrien int i; 551990075Sobrien unsigned char checksum[16]; 552090075Sobrien struct md5_ctx ctx; 552190075Sobrien 552290075Sobrien /* Compute the checksum of the DIE, then append part of it as hex digits to 552390075Sobrien the name filename of the unit. */ 552490075Sobrien 552590075Sobrien md5_init_ctx (&ctx); 552690075Sobrien die_checksum (unit_die, &ctx); 552790075Sobrien md5_finish_ctx (&ctx, checksum); 552890075Sobrien 552990075Sobrien sprintf (name, "%s.", base); 553090075Sobrien clean_symbol_name (name); 553190075Sobrien 553290075Sobrien p = name + strlen (name); 553390075Sobrien for (i = 0; i < 4; i++) 553490075Sobrien { 553590075Sobrien sprintf (p, "%.2x", checksum[i]); 553690075Sobrien p += 2; 553790075Sobrien } 553890075Sobrien 553990075Sobrien comdat_symbol_id = unit_die->die_symbol = xstrdup (name); 554090075Sobrien comdat_symbol_number = 0; 554190075Sobrien} 554290075Sobrien 554390075Sobrien/* Returns nonzero if DIE represents a type, in the sense of TYPE_P. */ 554490075Sobrien 554590075Sobrienstatic int 554690075Sobrienis_type_die (die) 554790075Sobrien dw_die_ref die; 554890075Sobrien{ 554990075Sobrien switch (die->die_tag) 555090075Sobrien { 555190075Sobrien case DW_TAG_array_type: 555290075Sobrien case DW_TAG_class_type: 555390075Sobrien case DW_TAG_enumeration_type: 555490075Sobrien case DW_TAG_pointer_type: 555590075Sobrien case DW_TAG_reference_type: 555690075Sobrien case DW_TAG_string_type: 555790075Sobrien case DW_TAG_structure_type: 555890075Sobrien case DW_TAG_subroutine_type: 555990075Sobrien case DW_TAG_union_type: 556090075Sobrien case DW_TAG_ptr_to_member_type: 556190075Sobrien case DW_TAG_set_type: 556290075Sobrien case DW_TAG_subrange_type: 556390075Sobrien case DW_TAG_base_type: 556490075Sobrien case DW_TAG_const_type: 556590075Sobrien case DW_TAG_file_type: 556690075Sobrien case DW_TAG_packed_type: 556790075Sobrien case DW_TAG_volatile_type: 556890075Sobrien return 1; 556990075Sobrien default: 557090075Sobrien return 0; 557190075Sobrien } 557290075Sobrien} 557390075Sobrien 557490075Sobrien/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU. 557590075Sobrien Basically, we want to choose the bits that are likely to be shared between 557690075Sobrien compilations (types) and leave out the bits that are specific to individual 557790075Sobrien compilations (functions). */ 557890075Sobrien 557990075Sobrienstatic int 558090075Sobrienis_comdat_die (c) 558190075Sobrien dw_die_ref c; 558290075Sobrien{ 558390075Sobrien /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as 558490075Sobrien we do for stabs. The advantage is a greater likelihood of sharing between 558590075Sobrien objects that don't include headers in the same order (and therefore would 558690075Sobrien put the base types in a different comdat). jason 8/28/00 */ 558790075Sobrien 558890075Sobrien if (c->die_tag == DW_TAG_base_type) 558990075Sobrien return 0; 559090075Sobrien 559190075Sobrien if (c->die_tag == DW_TAG_pointer_type 559290075Sobrien || c->die_tag == DW_TAG_reference_type 559390075Sobrien || c->die_tag == DW_TAG_const_type 559490075Sobrien || c->die_tag == DW_TAG_volatile_type) 559590075Sobrien { 559690075Sobrien dw_die_ref t = get_AT_ref (c, DW_AT_type); 559790075Sobrien 559890075Sobrien return t ? is_comdat_die (t) : 0; 559990075Sobrien } 560090075Sobrien 560190075Sobrien return is_type_die (c); 560290075Sobrien} 560390075Sobrien 560490075Sobrien/* Returns 1 iff C is the sort of DIE that might be referred to from another 560590075Sobrien compilation unit. */ 560690075Sobrien 560790075Sobrienstatic int 560890075Sobrienis_symbol_die (c) 560990075Sobrien dw_die_ref c; 561090075Sobrien{ 561190075Sobrien return (is_type_die (c) 561290075Sobrien || (get_AT (c, DW_AT_declaration) 561390075Sobrien && !get_AT (c, DW_AT_specification))); 561490075Sobrien} 561590075Sobrien 561690075Sobrienstatic char * 561790075Sobriengen_internal_sym (prefix) 561890075Sobrien const char *prefix; 561990075Sobrien{ 562090075Sobrien char buf[256]; 562190075Sobrien static int label_num; 562290075Sobrien 562390075Sobrien ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++); 562490075Sobrien return xstrdup (buf); 562590075Sobrien} 562690075Sobrien 562790075Sobrien/* Assign symbols to all worthy DIEs under DIE. */ 562890075Sobrien 562990075Sobrienstatic void 563090075Sobrienassign_symbol_names (die) 563190075Sobrien dw_die_ref die; 563290075Sobrien{ 563390075Sobrien dw_die_ref c; 563490075Sobrien 563590075Sobrien if (is_symbol_die (die)) 563690075Sobrien { 563790075Sobrien if (comdat_symbol_id) 563890075Sobrien { 563990075Sobrien char *p = alloca (strlen (comdat_symbol_id) + 64); 564090075Sobrien 564190075Sobrien sprintf (p, "%s.%s.%x", DIE_LABEL_PREFIX, 564290075Sobrien comdat_symbol_id, comdat_symbol_number++); 564390075Sobrien die->die_symbol = xstrdup (p); 564490075Sobrien } 564590075Sobrien else 564690075Sobrien die->die_symbol = gen_internal_sym ("LDIE"); 564790075Sobrien } 564890075Sobrien 564950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 565090075Sobrien assign_symbol_names (c); 565190075Sobrien} 565290075Sobrien 565390075Sobrien/* Traverse the DIE (which is always comp_unit_die), and set up 565490075Sobrien additional compilation units for each of the include files we see 565590075Sobrien bracketed by BINCL/EINCL. */ 565690075Sobrien 565790075Sobrienstatic void 565890075Sobrienbreak_out_includes (die) 565990075Sobrien dw_die_ref die; 566090075Sobrien{ 566190075Sobrien dw_die_ref *ptr; 566290075Sobrien dw_die_ref unit = NULL; 566390075Sobrien limbo_die_node *node; 566490075Sobrien 566590075Sobrien for (ptr = &(die->die_child); *ptr; ) 566690075Sobrien { 566790075Sobrien dw_die_ref c = *ptr; 566890075Sobrien 566990075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL 567090075Sobrien || (unit && is_comdat_die (c))) 567190075Sobrien { 567290075Sobrien /* This DIE is for a secondary CU; remove it from the main one. */ 567390075Sobrien *ptr = c->die_sib; 567490075Sobrien 567590075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL) 567690075Sobrien { 567790075Sobrien unit = push_new_compile_unit (unit, c); 567890075Sobrien free_die (c); 567990075Sobrien } 568090075Sobrien else if (c->die_tag == DW_TAG_GNU_EINCL) 568190075Sobrien { 568290075Sobrien unit = pop_compile_unit (unit); 568390075Sobrien free_die (c); 568490075Sobrien } 568590075Sobrien else 568690075Sobrien add_child_die (unit, c); 568790075Sobrien } 568890075Sobrien else 568990075Sobrien { 569090075Sobrien /* Leave this DIE in the main CU. */ 569190075Sobrien ptr = &(c->die_sib); 569290075Sobrien continue; 569390075Sobrien } 569490075Sobrien } 569590075Sobrien 569690075Sobrien#if 0 569790075Sobrien /* We can only use this in debugging, since the frontend doesn't check 569890075Sobrien to make sure that we leave every include file we enter. */ 569990075Sobrien if (unit != NULL) 570090075Sobrien abort (); 570190075Sobrien#endif 570290075Sobrien 570390075Sobrien assign_symbol_names (die); 570490075Sobrien for (node = limbo_die_list; node; node = node->next) 570590075Sobrien { 570690075Sobrien compute_section_prefix (node->die); 570790075Sobrien assign_symbol_names (node->die); 570890075Sobrien } 570990075Sobrien} 571090075Sobrien 571190075Sobrien/* Traverse the DIE and add a sibling attribute if it may have the 571290075Sobrien effect of speeding up access to siblings. To save some space, 571390075Sobrien avoid generating sibling attributes for DIE's without children. */ 571490075Sobrien 571590075Sobrienstatic void 571690075Sobrienadd_sibling_attributes (die) 571790075Sobrien dw_die_ref die; 571890075Sobrien{ 571990075Sobrien dw_die_ref c; 572090075Sobrien 572190075Sobrien if (die->die_tag != DW_TAG_compile_unit 572290075Sobrien && die->die_sib && die->die_child != NULL) 572390075Sobrien /* Add the sibling link to the front of the attribute list. */ 572490075Sobrien add_AT_die_ref (die, DW_AT_sibling, die->die_sib); 572590075Sobrien 572690075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 572750397Sobrien add_sibling_attributes (c); 572850397Sobrien} 572950397Sobrien 573090075Sobrien/* Output all location lists for the DIE and its children. */ 573150397Sobrien 573250397Sobrienstatic void 573390075Sobrienoutput_location_lists (die) 573490075Sobrien dw_die_ref die; 573590075Sobrien{ 573690075Sobrien dw_die_ref c; 573790075Sobrien dw_attr_ref d_attr; 573890075Sobrien 573990075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 574090075Sobrien if (AT_class (d_attr) == dw_val_class_loc_list) 574190075Sobrien output_loc_list (AT_loc_list (d_attr)); 574290075Sobrien 574390075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 574490075Sobrien output_location_lists (c); 574590075Sobrien 574690075Sobrien} 574790075Sobrien/* The format of each DIE (and its attribute value pairs) is encoded in an 574890075Sobrien abbreviation table. This routine builds the abbreviation table and assigns 574990075Sobrien a unique abbreviation id for each abbreviation entry. The children of each 575090075Sobrien die are visited recursively. */ 575190075Sobrien 575290075Sobrienstatic void 575350397Sobrienbuild_abbrev_table (die) 575490075Sobrien dw_die_ref die; 575550397Sobrien{ 575690075Sobrien unsigned long abbrev_id; 575790075Sobrien unsigned int n_alloc; 575890075Sobrien dw_die_ref c; 575990075Sobrien dw_attr_ref d_attr, a_attr; 576090075Sobrien 576190075Sobrien /* Scan the DIE references, and mark as external any that refer to 576290075Sobrien DIEs from other CUs (i.e. those which are not marked). */ 576390075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 576490075Sobrien if (AT_class (d_attr) == dw_val_class_die_ref 576590075Sobrien && AT_ref (d_attr)->die_mark == 0) 576690075Sobrien { 576790075Sobrien if (AT_ref (d_attr)->die_symbol == 0) 576890075Sobrien abort (); 576990075Sobrien 577090075Sobrien set_AT_ref_external (d_attr, 1); 577190075Sobrien } 577290075Sobrien 577350397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 577450397Sobrien { 577590075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 577650397Sobrien 577750397Sobrien if (abbrev->die_tag == die->die_tag) 577850397Sobrien { 577950397Sobrien if ((abbrev->die_child != NULL) == (die->die_child != NULL)) 578050397Sobrien { 578150397Sobrien a_attr = abbrev->die_attr; 578250397Sobrien d_attr = die->die_attr; 578350397Sobrien 578450397Sobrien while (a_attr != NULL && d_attr != NULL) 578550397Sobrien { 578650397Sobrien if ((a_attr->dw_attr != d_attr->dw_attr) 578790075Sobrien || (value_format (a_attr) != value_format (d_attr))) 578850397Sobrien break; 578950397Sobrien 579050397Sobrien a_attr = a_attr->dw_attr_next; 579150397Sobrien d_attr = d_attr->dw_attr_next; 579250397Sobrien } 579350397Sobrien 579450397Sobrien if (a_attr == NULL && d_attr == NULL) 579550397Sobrien break; 579650397Sobrien } 579750397Sobrien } 579850397Sobrien } 579950397Sobrien 580050397Sobrien if (abbrev_id >= abbrev_die_table_in_use) 580150397Sobrien { 580250397Sobrien if (abbrev_die_table_in_use >= abbrev_die_table_allocated) 580350397Sobrien { 580450397Sobrien n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; 580590075Sobrien abbrev_die_table 580650397Sobrien = (dw_die_ref *) xrealloc (abbrev_die_table, 580750397Sobrien sizeof (dw_die_ref) * n_alloc); 580850397Sobrien 580990075Sobrien memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0, 581050397Sobrien (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); 581150397Sobrien abbrev_die_table_allocated = n_alloc; 581250397Sobrien } 581350397Sobrien 581450397Sobrien ++abbrev_die_table_in_use; 581550397Sobrien abbrev_die_table[abbrev_id] = die; 581650397Sobrien } 581750397Sobrien 581850397Sobrien die->die_abbrev = abbrev_id; 581950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 582050397Sobrien build_abbrev_table (c); 582150397Sobrien} 582250397Sobrien 582350397Sobrien/* Return the power-of-two number of bytes necessary to represent VALUE. */ 582450397Sobrien 582550397Sobrienstatic int 582650397Sobrienconstant_size (value) 582750397Sobrien long unsigned value; 582850397Sobrien{ 582950397Sobrien int log; 583050397Sobrien 583150397Sobrien if (value == 0) 583250397Sobrien log = 0; 583350397Sobrien else 583450397Sobrien log = floor_log2 (value); 583550397Sobrien 583650397Sobrien log = log / 8; 583750397Sobrien log = 1 << (floor_log2 (log) + 1); 583850397Sobrien 583950397Sobrien return log; 584050397Sobrien} 584150397Sobrien 584290075Sobrien/* Return the size of a DIE as it is represented in the 584350397Sobrien .debug_info section. */ 584450397Sobrien 584550397Sobrienstatic unsigned long 584650397Sobriensize_of_die (die) 584790075Sobrien dw_die_ref die; 584850397Sobrien{ 584990075Sobrien unsigned long size = 0; 585090075Sobrien dw_attr_ref a; 585150397Sobrien 585250397Sobrien size += size_of_uleb128 (die->die_abbrev); 585350397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 585450397Sobrien { 585590075Sobrien switch (AT_class (a)) 585650397Sobrien { 585750397Sobrien case dw_val_class_addr: 585890075Sobrien size += DWARF2_ADDR_SIZE; 585950397Sobrien break; 586090075Sobrien case dw_val_class_offset: 586190075Sobrien size += DWARF_OFFSET_SIZE; 586290075Sobrien break; 586350397Sobrien case dw_val_class_loc: 586450397Sobrien { 586590075Sobrien unsigned long lsize = size_of_locs (AT_loc (a)); 586650397Sobrien 586750397Sobrien /* Block length. */ 586850397Sobrien size += constant_size (lsize); 586950397Sobrien size += lsize; 587050397Sobrien } 587150397Sobrien break; 587290075Sobrien case dw_val_class_loc_list: 587390075Sobrien size += DWARF_OFFSET_SIZE; 587490075Sobrien break; 587590075Sobrien case dw_val_class_range_list: 587690075Sobrien size += DWARF_OFFSET_SIZE; 587790075Sobrien break; 587850397Sobrien case dw_val_class_const: 587990075Sobrien size += size_of_sleb128 (AT_int (a)); 588050397Sobrien break; 588150397Sobrien case dw_val_class_unsigned_const: 588290075Sobrien size += constant_size (AT_unsigned (a)); 588350397Sobrien break; 588450397Sobrien case dw_val_class_long_long: 588590075Sobrien size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */ 588650397Sobrien break; 588750397Sobrien case dw_val_class_float: 588850397Sobrien size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ 588950397Sobrien break; 589050397Sobrien case dw_val_class_flag: 589150397Sobrien size += 1; 589250397Sobrien break; 589350397Sobrien case dw_val_class_die_ref: 589450397Sobrien size += DWARF_OFFSET_SIZE; 589550397Sobrien break; 589650397Sobrien case dw_val_class_fde_ref: 589750397Sobrien size += DWARF_OFFSET_SIZE; 589850397Sobrien break; 589950397Sobrien case dw_val_class_lbl_id: 590090075Sobrien size += DWARF2_ADDR_SIZE; 590150397Sobrien break; 590252284Sobrien case dw_val_class_lbl_offset: 590350397Sobrien size += DWARF_OFFSET_SIZE; 590450397Sobrien break; 590550397Sobrien case dw_val_class_str: 590690075Sobrien if (AT_string_form (a) == DW_FORM_strp) 590790075Sobrien size += DWARF_OFFSET_SIZE; 590890075Sobrien else 590990075Sobrien size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1; 591050397Sobrien break; 591150397Sobrien default: 591250397Sobrien abort (); 591350397Sobrien } 591450397Sobrien } 591550397Sobrien 591650397Sobrien return size; 591750397Sobrien} 591850397Sobrien 591990075Sobrien/* Size the debugging information associated with a given DIE. Visits the 592090075Sobrien DIE's children recursively. Updates the global variable next_die_offset, on 592190075Sobrien each time through. Uses the current value of next_die_offset to update the 592290075Sobrien die_offset field in each DIE. */ 592350397Sobrien 592450397Sobrienstatic void 592550397Sobriencalc_die_sizes (die) 592650397Sobrien dw_die_ref die; 592750397Sobrien{ 592890075Sobrien dw_die_ref c; 592990075Sobrien 593050397Sobrien die->die_offset = next_die_offset; 593150397Sobrien next_die_offset += size_of_die (die); 593250397Sobrien 593350397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 593450397Sobrien calc_die_sizes (c); 593550397Sobrien 593650397Sobrien if (die->die_child != NULL) 593750397Sobrien /* Count the null byte used to terminate sibling lists. */ 593850397Sobrien next_die_offset += 1; 593950397Sobrien} 594050397Sobrien 594190075Sobrien/* Set the marks for a die and its children. We do this so 594290075Sobrien that we know whether or not a reference needs to use FORM_ref_addr; only 594390075Sobrien DIEs in the same CU will be marked. We used to clear out the offset 594490075Sobrien and use that as the flag, but ran into ordering problems. */ 594550397Sobrien 594690075Sobrienstatic void 594790075Sobrienmark_dies (die) 594890075Sobrien dw_die_ref die; 594950397Sobrien{ 595090075Sobrien dw_die_ref c; 595150397Sobrien 595290075Sobrien die->die_mark = 1; 595390075Sobrien for (c = die->die_child; c; c = c->die_sib) 595490075Sobrien mark_dies (c); 595550397Sobrien} 595650397Sobrien 595790075Sobrien/* Clear the marks for a die and its children. */ 595850397Sobrien 595990075Sobrienstatic void 596090075Sobrienunmark_dies (die) 596190075Sobrien dw_die_ref die; 596250397Sobrien{ 596390075Sobrien dw_die_ref c; 596450397Sobrien 596590075Sobrien die->die_mark = 0; 596690075Sobrien for (c = die->die_child; c; c = c->die_sib) 596790075Sobrien unmark_dies (c); 596850397Sobrien} 596950397Sobrien 597050397Sobrien/* Return the size of the .debug_pubnames table generated for the 597150397Sobrien compilation unit. */ 597250397Sobrien 597350397Sobrienstatic unsigned long 597450397Sobriensize_of_pubnames () 597550397Sobrien{ 597690075Sobrien unsigned long size; 597790075Sobrien unsigned i; 597850397Sobrien 597950397Sobrien size = DWARF_PUBNAMES_HEADER_SIZE; 598090075Sobrien for (i = 0; i < pubname_table_in_use; i++) 598150397Sobrien { 598290075Sobrien pubname_ref p = &pubname_table[i]; 598390075Sobrien size += DWARF_OFFSET_SIZE + strlen (p->name) + 1; 598450397Sobrien } 598550397Sobrien 598650397Sobrien size += DWARF_OFFSET_SIZE; 598750397Sobrien return size; 598850397Sobrien} 598950397Sobrien 599050397Sobrien/* Return the size of the information in the .debug_aranges section. */ 599150397Sobrien 599250397Sobrienstatic unsigned long 599350397Sobriensize_of_aranges () 599450397Sobrien{ 599590075Sobrien unsigned long size; 599650397Sobrien 599750397Sobrien size = DWARF_ARANGES_HEADER_SIZE; 599850397Sobrien 599950397Sobrien /* Count the address/length pair for this compilation unit. */ 600090075Sobrien size += 2 * DWARF2_ADDR_SIZE; 600190075Sobrien size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use; 600250397Sobrien 600350397Sobrien /* Count the two zero words used to terminated the address range table. */ 600490075Sobrien size += 2 * DWARF2_ADDR_SIZE; 600550397Sobrien return size; 600650397Sobrien} 600750397Sobrien 600850397Sobrien/* Select the encoding of an attribute value. */ 600950397Sobrien 601050397Sobrienstatic enum dwarf_form 601190075Sobrienvalue_format (a) 601290075Sobrien dw_attr_ref a; 601350397Sobrien{ 601490075Sobrien switch (a->dw_attr_val.val_class) 601550397Sobrien { 601650397Sobrien case dw_val_class_addr: 601750397Sobrien return DW_FORM_addr; 601890075Sobrien case dw_val_class_range_list: 601990075Sobrien case dw_val_class_offset: 602090075Sobrien if (DWARF_OFFSET_SIZE == 4) 602190075Sobrien return DW_FORM_data4; 602290075Sobrien if (DWARF_OFFSET_SIZE == 8) 602390075Sobrien return DW_FORM_data8; 602490075Sobrien abort (); 602590075Sobrien case dw_val_class_loc_list: 602690075Sobrien /* FIXME: Could be DW_FORM_data8, with a > 32 bit size 602790075Sobrien .debug_loc section */ 602890075Sobrien return DW_FORM_data4; 602950397Sobrien case dw_val_class_loc: 603090075Sobrien switch (constant_size (size_of_locs (AT_loc (a)))) 603150397Sobrien { 603250397Sobrien case 1: 603350397Sobrien return DW_FORM_block1; 603450397Sobrien case 2: 603550397Sobrien return DW_FORM_block2; 603650397Sobrien default: 603750397Sobrien abort (); 603850397Sobrien } 603950397Sobrien case dw_val_class_const: 604090075Sobrien return DW_FORM_sdata; 604150397Sobrien case dw_val_class_unsigned_const: 604290075Sobrien switch (constant_size (AT_unsigned (a))) 604350397Sobrien { 604450397Sobrien case 1: 604550397Sobrien return DW_FORM_data1; 604650397Sobrien case 2: 604750397Sobrien return DW_FORM_data2; 604850397Sobrien case 4: 604950397Sobrien return DW_FORM_data4; 605050397Sobrien case 8: 605150397Sobrien return DW_FORM_data8; 605250397Sobrien default: 605350397Sobrien abort (); 605450397Sobrien } 605550397Sobrien case dw_val_class_long_long: 605650397Sobrien return DW_FORM_block1; 605750397Sobrien case dw_val_class_float: 605850397Sobrien return DW_FORM_block1; 605950397Sobrien case dw_val_class_flag: 606050397Sobrien return DW_FORM_flag; 606150397Sobrien case dw_val_class_die_ref: 606290075Sobrien if (AT_ref_external (a)) 606390075Sobrien return DW_FORM_ref_addr; 606490075Sobrien else 606590075Sobrien return DW_FORM_ref; 606650397Sobrien case dw_val_class_fde_ref: 606750397Sobrien return DW_FORM_data; 606850397Sobrien case dw_val_class_lbl_id: 606950397Sobrien return DW_FORM_addr; 607052284Sobrien case dw_val_class_lbl_offset: 607150397Sobrien return DW_FORM_data; 607250397Sobrien case dw_val_class_str: 607390075Sobrien return AT_string_form (a); 607490075Sobrien 607550397Sobrien default: 607650397Sobrien abort (); 607750397Sobrien } 607850397Sobrien} 607950397Sobrien 608050397Sobrien/* Output the encoding of an attribute value. */ 608150397Sobrien 608250397Sobrienstatic void 608390075Sobrienoutput_value_format (a) 608490075Sobrien dw_attr_ref a; 608550397Sobrien{ 608690075Sobrien enum dwarf_form form = value_format (a); 608750397Sobrien 608890075Sobrien dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form)); 608950397Sobrien} 609050397Sobrien 609150397Sobrien/* Output the .debug_abbrev section which defines the DIE abbreviation 609250397Sobrien table. */ 609350397Sobrien 609450397Sobrienstatic void 609550397Sobrienoutput_abbrev_section () 609650397Sobrien{ 609750397Sobrien unsigned long abbrev_id; 609850397Sobrien 609950397Sobrien dw_attr_ref a_attr; 610090075Sobrien 610150397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 610250397Sobrien { 610390075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 610450397Sobrien 610590075Sobrien dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)"); 610690075Sobrien dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)", 610790075Sobrien dwarf_tag_name (abbrev->die_tag)); 610850397Sobrien 610990075Sobrien if (abbrev->die_child != NULL) 611090075Sobrien dw2_asm_output_data (1, DW_children_yes, "DW_children_yes"); 611190075Sobrien else 611290075Sobrien dw2_asm_output_data (1, DW_children_no, "DW_children_no"); 611350397Sobrien 611450397Sobrien for (a_attr = abbrev->die_attr; a_attr != NULL; 611550397Sobrien a_attr = a_attr->dw_attr_next) 611650397Sobrien { 611790075Sobrien dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", 611890075Sobrien dwarf_attr_name (a_attr->dw_attr)); 611990075Sobrien output_value_format (a_attr); 612050397Sobrien } 612150397Sobrien 612290075Sobrien dw2_asm_output_data (1, 0, NULL); 612390075Sobrien dw2_asm_output_data (1, 0, NULL); 612450397Sobrien } 612552284Sobrien 612690075Sobrien /* Terminate the table. */ 612790075Sobrien dw2_asm_output_data (1, 0, NULL); 612850397Sobrien} 612950397Sobrien 613090075Sobrien/* Output a symbol we can use to refer to this DIE from another CU. */ 613150397Sobrien 613290075Sobrienstatic inline void 613390075Sobrienoutput_die_symbol (die) 613490075Sobrien dw_die_ref die; 613590075Sobrien{ 613690075Sobrien char *sym = die->die_symbol; 613790075Sobrien 613890075Sobrien if (sym == 0) 613990075Sobrien return; 614090075Sobrien 614190075Sobrien if (strncmp (sym, DIE_LABEL_PREFIX, sizeof (DIE_LABEL_PREFIX) - 1) == 0) 614290075Sobrien /* We make these global, not weak; if the target doesn't support 614390075Sobrien .linkonce, it doesn't support combining the sections, so debugging 614490075Sobrien will break. */ 614590075Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, sym); 614690075Sobrien 614790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, sym); 614890075Sobrien} 614990075Sobrien 615090075Sobrien/* Return a new location list, given the begin and end range, and the 615190075Sobrien expression. gensym tells us whether to generate a new internal symbol for 615290075Sobrien this location list node, which is done for the head of the list only. */ 615390075Sobrien 615490075Sobrienstatic inline dw_loc_list_ref 615590075Sobriennew_loc_list (expr, begin, end, section, gensym) 615690075Sobrien dw_loc_descr_ref expr; 615790075Sobrien const char *begin; 615890075Sobrien const char *end; 615990075Sobrien const char *section; 616090075Sobrien unsigned gensym; 616190075Sobrien{ 616290075Sobrien dw_loc_list_ref retlist 616390075Sobrien = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node)); 616490075Sobrien 616590075Sobrien retlist->begin = begin; 616690075Sobrien retlist->end = end; 616790075Sobrien retlist->expr = expr; 616890075Sobrien retlist->section = section; 616990075Sobrien if (gensym) 617090075Sobrien retlist->ll_symbol = gen_internal_sym ("LLST"); 617190075Sobrien 617290075Sobrien return retlist; 617390075Sobrien} 617490075Sobrien 617590075Sobrien/* Add a location description expression to a location list */ 617690075Sobrien 617790075Sobrienstatic inline void 617890075Sobrienadd_loc_descr_to_loc_list (list_head, descr, begin, end, section) 617990075Sobrien dw_loc_list_ref *list_head; 618090075Sobrien dw_loc_descr_ref descr; 618190075Sobrien const char *begin; 618290075Sobrien const char *end; 618390075Sobrien const char *section; 618490075Sobrien{ 618590075Sobrien dw_loc_list_ref *d; 618690075Sobrien 618790075Sobrien /* Find the end of the chain. */ 618890075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 618990075Sobrien ; 619090075Sobrien 619190075Sobrien /* Add a new location list node to the list */ 619290075Sobrien *d = new_loc_list (descr, begin, end, section, 0); 619390075Sobrien} 619490075Sobrien 619590075Sobrien/* Output the location list given to us */ 619690075Sobrien 619750397Sobrienstatic void 619890075Sobrienoutput_loc_list (list_head) 619990075Sobrien dw_loc_list_ref list_head; 620050397Sobrien{ 620190075Sobrien dw_loc_list_ref curr = list_head; 620250397Sobrien 620390075Sobrien ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); 620490075Sobrien 620590075Sobrien /* ??? This shouldn't be needed now that we've forced the 620690075Sobrien compilation unit base address to zero when there is code 620790075Sobrien in more than one section. */ 620890075Sobrien if (strcmp (curr->section, ".text") == 0) 620950397Sobrien { 621090075Sobrien /* dw2_asm_output_data will mask off any extra bits in the ~0. */ 621190075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0, 621290075Sobrien "Location list base address specifier fake entry"); 621390075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section, 621490075Sobrien "Location list base address specifier base"); 621550397Sobrien } 621650397Sobrien 621790075Sobrien for (curr = list_head; curr != NULL; curr=curr->dw_loc_next) 621890075Sobrien { 621990075Sobrien unsigned long size; 622050397Sobrien 622190075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, 622290075Sobrien "Location list begin address (%s)", 622390075Sobrien list_head->ll_symbol); 622490075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section, 622590075Sobrien "Location list end address (%s)", 622690075Sobrien list_head->ll_symbol); 622790075Sobrien size = size_of_locs (curr->expr); 622890075Sobrien 622990075Sobrien /* Output the block length for this list of location operations. */ 623090075Sobrien if (size > 0xffff) 623190075Sobrien abort (); 623290075Sobrien dw2_asm_output_data (2, size, "%s", "Location expression size"); 623350397Sobrien 623490075Sobrien output_loc_sequence (curr->expr); 623590075Sobrien } 623650397Sobrien 623790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 623890075Sobrien "Location list terminator begin (%s)", 623990075Sobrien list_head->ll_symbol); 624090075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 624190075Sobrien "Location list terminator end (%s)", 624290075Sobrien list_head->ll_symbol); 624350397Sobrien} 624450397Sobrien 624550397Sobrien/* Output the DIE and its attributes. Called recursively to generate 624650397Sobrien the definitions of each child DIE. */ 624750397Sobrien 624850397Sobrienstatic void 624950397Sobrienoutput_die (die) 625090075Sobrien dw_die_ref die; 625150397Sobrien{ 625290075Sobrien dw_attr_ref a; 625390075Sobrien dw_die_ref c; 625490075Sobrien unsigned long size; 625550397Sobrien 625690075Sobrien /* If someone in another CU might refer to us, set up a symbol for 625790075Sobrien them to point to. */ 625890075Sobrien if (die->die_symbol) 625990075Sobrien output_die_symbol (die); 626050397Sobrien 626190075Sobrien dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)", 626290075Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 626350397Sobrien 626450397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 626550397Sobrien { 626690075Sobrien const char *name = dwarf_attr_name (a->dw_attr); 626790075Sobrien 626890075Sobrien switch (AT_class (a)) 626950397Sobrien { 627050397Sobrien case dw_val_class_addr: 627190075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); 627250397Sobrien break; 627350397Sobrien 627490075Sobrien case dw_val_class_offset: 627590075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset, 627690075Sobrien "%s", name); 627790075Sobrien break; 627850397Sobrien 627990075Sobrien case dw_val_class_range_list: 628090075Sobrien { 628190075Sobrien char *p = strchr (ranges_section_label, '\0'); 628250397Sobrien 628390075Sobrien sprintf (p, "+0x%lx", a->dw_attr_val.v.val_offset); 628490075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label, 628590075Sobrien "%s", name); 628690075Sobrien *p = '\0'; 628790075Sobrien } 628890075Sobrien break; 628950397Sobrien 629090075Sobrien case dw_val_class_loc: 629190075Sobrien size = size_of_locs (AT_loc (a)); 629250397Sobrien 629390075Sobrien /* Output the block length for this list of location operations. */ 629490075Sobrien dw2_asm_output_data (constant_size (size), size, "%s", name); 629550397Sobrien 629690075Sobrien output_loc_sequence (AT_loc (a)); 629750397Sobrien break; 629850397Sobrien 629950397Sobrien case dw_val_class_const: 630090075Sobrien /* ??? It would be slightly more efficient to use a scheme like is 630190075Sobrien used for unsigned constants below, but gdb 4.x does not sign 630290075Sobrien extend. Gdb 5.x does sign extend. */ 630390075Sobrien dw2_asm_output_data_sleb128 (AT_int (a), "%s", name); 630450397Sobrien break; 630550397Sobrien 630650397Sobrien case dw_val_class_unsigned_const: 630790075Sobrien dw2_asm_output_data (constant_size (AT_unsigned (a)), 630890075Sobrien AT_unsigned (a), "%s", name); 630950397Sobrien break; 631050397Sobrien 631150397Sobrien case dw_val_class_long_long: 631290075Sobrien { 631390075Sobrien unsigned HOST_WIDE_INT first, second; 631450397Sobrien 631590075Sobrien dw2_asm_output_data (1, 631690075Sobrien 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 631790075Sobrien "%s", name); 631850397Sobrien 631990075Sobrien if (WORDS_BIG_ENDIAN) 632090075Sobrien { 632190075Sobrien first = a->dw_attr_val.v.val_long_long.hi; 632290075Sobrien second = a->dw_attr_val.v.val_long_long.low; 632390075Sobrien } 632490075Sobrien else 632590075Sobrien { 632690075Sobrien first = a->dw_attr_val.v.val_long_long.low; 632790075Sobrien second = a->dw_attr_val.v.val_long_long.hi; 632890075Sobrien } 632990075Sobrien 633090075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 633190075Sobrien first, "long long constant"); 633290075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 633390075Sobrien second, NULL); 633490075Sobrien } 633550397Sobrien break; 633650397Sobrien 633750397Sobrien case dw_val_class_float: 633852284Sobrien { 633990075Sobrien unsigned int i; 634050397Sobrien 634190075Sobrien dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4, 634290075Sobrien "%s", name); 634350397Sobrien 634490075Sobrien for (i = 0; i < a->dw_attr_val.v.val_float.length; i++) 634590075Sobrien dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i], 634690075Sobrien "fp constant word %u", i); 634790075Sobrien break; 634852284Sobrien } 634950397Sobrien 635050397Sobrien case dw_val_class_flag: 635190075Sobrien dw2_asm_output_data (1, AT_flag (a), "%s", name); 635250397Sobrien break; 635350397Sobrien 635490075Sobrien case dw_val_class_loc_list: 635590075Sobrien { 635690075Sobrien char *sym = AT_loc_list (a)->ll_symbol; 635790075Sobrien 635890075Sobrien if (sym == 0) 635990075Sobrien abort (); 636090075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, 636190075Sobrien loc_section_label, "%s", name); 636290075Sobrien } 636390075Sobrien break; 636490075Sobrien 636550397Sobrien case dw_val_class_die_ref: 636690075Sobrien if (AT_ref_external (a)) 636790075Sobrien { 636890075Sobrien char *sym = AT_ref (a)->die_symbol; 636990075Sobrien 637090075Sobrien if (sym == 0) 637190075Sobrien abort (); 637290075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, sym, "%s", name); 637390075Sobrien } 637490075Sobrien else if (AT_ref (a)->die_offset == 0) 637590075Sobrien abort (); 637650397Sobrien else 637790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset, 637890075Sobrien "%s", name); 637950397Sobrien break; 638050397Sobrien 638150397Sobrien case dw_val_class_fde_ref: 638250397Sobrien { 638350397Sobrien char l1[20]; 638490075Sobrien 638590075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL, 638690075Sobrien a->dw_attr_val.v.val_fde_index * 2); 638790075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, "%s", name); 638850397Sobrien } 638950397Sobrien break; 639050397Sobrien 639150397Sobrien case dw_val_class_lbl_id: 639290075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name); 639350397Sobrien break; 639450397Sobrien 639552284Sobrien case dw_val_class_lbl_offset: 639690075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a), "%s", name); 639750397Sobrien break; 639850397Sobrien 639950397Sobrien case dw_val_class_str: 640090075Sobrien if (AT_string_form (a) == DW_FORM_strp) 640190075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, 640290075Sobrien a->dw_attr_val.v.val_str->label, 640390075Sobrien "%s: \"%s\"", name, AT_string (a)); 640450397Sobrien else 640590075Sobrien dw2_asm_output_nstring (AT_string (a), -1, "%s", name); 640650397Sobrien break; 640750397Sobrien 640850397Sobrien default: 640950397Sobrien abort (); 641050397Sobrien } 641150397Sobrien } 641250397Sobrien 641350397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 641450397Sobrien output_die (c); 641550397Sobrien 641690075Sobrien /* Add null byte to terminate sibling list. */ 641750397Sobrien if (die->die_child != NULL) 641890075Sobrien dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx", 641990075Sobrien die->die_offset); 642050397Sobrien} 642150397Sobrien 642250397Sobrien/* Output the compilation unit that appears at the beginning of the 642350397Sobrien .debug_info section, and precedes the DIE descriptions. */ 642450397Sobrien 642550397Sobrienstatic void 642650397Sobrienoutput_compilation_unit_header () 642750397Sobrien{ 642890075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset - DWARF_OFFSET_SIZE, 642990075Sobrien "Length of Compilation Unit Info"); 643090075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number"); 643190075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label, 643290075Sobrien "Offset Into Abbrev. Section"); 643390075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); 643490075Sobrien} 643550397Sobrien 643690075Sobrien/* Output the compilation unit DIE and its children. */ 643750397Sobrien 643890075Sobrienstatic void 643990075Sobrienoutput_comp_unit (die) 644090075Sobrien dw_die_ref die; 644190075Sobrien{ 644290075Sobrien const char *secname; 644350397Sobrien 644490075Sobrien /* Even if there are no children of this DIE, we must output the information 644590075Sobrien about the compilation unit. Otherwise, on an empty translation unit, we 644690075Sobrien will generate a present, but empty, .debug_info section. IRIX 6.5 `nm' 644790075Sobrien will then complain when examining the file. First mark all the DIEs in 644890075Sobrien this CU so we know which get local refs. */ 644990075Sobrien mark_dies (die); 645050397Sobrien 645190075Sobrien build_abbrev_table (die); 645290075Sobrien 645390075Sobrien /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ 645490075Sobrien next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; 645590075Sobrien calc_die_sizes (die); 645690075Sobrien 645790075Sobrien if (die->die_symbol) 645890075Sobrien { 645990075Sobrien char *tmp = (char *) alloca (strlen (die->die_symbol) + 24); 646090075Sobrien 646190075Sobrien sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol); 646290075Sobrien secname = tmp; 646390075Sobrien die->die_symbol = NULL; 646490075Sobrien } 646590075Sobrien else 646690075Sobrien secname = (const char *) DEBUG_INFO_SECTION; 646790075Sobrien 646890075Sobrien /* Output debugging information. */ 646990075Sobrien named_section_flags (secname, SECTION_DEBUG); 647090075Sobrien output_compilation_unit_header (); 647190075Sobrien output_die (die); 647290075Sobrien 647390075Sobrien /* Leave the marks on the main CU, so we can check them in 647490075Sobrien output_pubnames. */ 647590075Sobrien if (die->die_symbol) 647690075Sobrien unmark_dies (die); 647750397Sobrien} 647850397Sobrien 647950397Sobrien/* The DWARF2 pubname for a nested thingy looks like "A::f". The output 648050397Sobrien of decl_printable_name for C++ looks like "A::f(int)". Let's drop the 648150397Sobrien argument list, and maybe the scope. */ 648250397Sobrien 648390075Sobrienstatic const char * 648450397Sobriendwarf2_name (decl, scope) 648550397Sobrien tree decl; 648650397Sobrien int scope; 648750397Sobrien{ 648850397Sobrien return (*decl_printable_name) (decl, scope ? 1 : 0); 648950397Sobrien} 649050397Sobrien 649150397Sobrien/* Add a new entry to .debug_pubnames if appropriate. */ 649250397Sobrien 649350397Sobrienstatic void 649450397Sobrienadd_pubname (decl, die) 649550397Sobrien tree decl; 649650397Sobrien dw_die_ref die; 649750397Sobrien{ 649850397Sobrien pubname_ref p; 649950397Sobrien 650050397Sobrien if (! TREE_PUBLIC (decl)) 650150397Sobrien return; 650250397Sobrien 650350397Sobrien if (pubname_table_in_use == pubname_table_allocated) 650450397Sobrien { 650550397Sobrien pubname_table_allocated += PUBNAME_TABLE_INCREMENT; 650690075Sobrien pubname_table 650790075Sobrien = (pubname_ref) xrealloc (pubname_table, 650890075Sobrien (pubname_table_allocated 650990075Sobrien * sizeof (pubname_entry))); 651050397Sobrien } 651150397Sobrien 651250397Sobrien p = &pubname_table[pubname_table_in_use++]; 651350397Sobrien p->die = die; 651450397Sobrien p->name = xstrdup (dwarf2_name (decl, 1)); 651550397Sobrien} 651650397Sobrien 651750397Sobrien/* Output the public names table used to speed up access to externally 651850397Sobrien visible names. For now, only generate entries for externally 651950397Sobrien visible procedures. */ 652050397Sobrien 652150397Sobrienstatic void 652250397Sobrienoutput_pubnames () 652350397Sobrien{ 652490075Sobrien unsigned i; 652590075Sobrien unsigned long pubnames_length = size_of_pubnames (); 652650397Sobrien 652790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, 652890075Sobrien "Length of Public Names Info"); 652990075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 653090075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 653190075Sobrien "Offset of Compilation Unit Info"); 653290075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset, 653390075Sobrien "Compilation Unit Length"); 653450397Sobrien 653590075Sobrien for (i = 0; i < pubname_table_in_use; i++) 653650397Sobrien { 653790075Sobrien pubname_ref pub = &pubname_table[i]; 653850397Sobrien 653990075Sobrien /* We shouldn't see pubnames for DIEs outside of the main CU. */ 654090075Sobrien if (pub->die->die_mark == 0) 654190075Sobrien abort (); 654250397Sobrien 654390075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset, 654490075Sobrien "DIE offset"); 654550397Sobrien 654690075Sobrien dw2_asm_output_nstring (pub->name, -1, "external name"); 654750397Sobrien } 654850397Sobrien 654990075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); 655050397Sobrien} 655150397Sobrien 655250397Sobrien/* Add a new entry to .debug_aranges if appropriate. */ 655350397Sobrien 655450397Sobrienstatic void 655550397Sobrienadd_arange (decl, die) 655650397Sobrien tree decl; 655750397Sobrien dw_die_ref die; 655850397Sobrien{ 655950397Sobrien if (! DECL_SECTION_NAME (decl)) 656050397Sobrien return; 656150397Sobrien 656250397Sobrien if (arange_table_in_use == arange_table_allocated) 656350397Sobrien { 656450397Sobrien arange_table_allocated += ARANGE_TABLE_INCREMENT; 656590075Sobrien arange_table = (dw_die_ref *) 656690075Sobrien xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref)); 656750397Sobrien } 656850397Sobrien 656950397Sobrien arange_table[arange_table_in_use++] = die; 657050397Sobrien} 657150397Sobrien 657250397Sobrien/* Output the information that goes into the .debug_aranges table. 657350397Sobrien Namely, define the beginning and ending address range of the 657450397Sobrien text section generated for this compilation unit. */ 657550397Sobrien 657650397Sobrienstatic void 657750397Sobrienoutput_aranges () 657850397Sobrien{ 657990075Sobrien unsigned i; 658090075Sobrien unsigned long aranges_length = size_of_aranges (); 658150397Sobrien 658290075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length, 658390075Sobrien "Length of Address Ranges Info"); 658490075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 658590075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 658690075Sobrien "Offset of Compilation Unit Info"); 658790075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address"); 658890075Sobrien dw2_asm_output_data (1, 0, "Size of Segment Descriptor"); 658950397Sobrien 659090075Sobrien /* We need to align to twice the pointer size here. */ 659190075Sobrien if (DWARF_ARANGES_PAD_SIZE) 659290075Sobrien { 659390075Sobrien /* Pad using a 2 byte words so that padding is correct for any 659490075Sobrien pointer size. */ 659590075Sobrien dw2_asm_output_data (2, 0, "Pad to %d byte boundary", 659690075Sobrien 2 * DWARF2_ADDR_SIZE); 659790075Sobrien for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2) 659890075Sobrien dw2_asm_output_data (2, 0, NULL); 659990075Sobrien } 660050397Sobrien 660190075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); 660290075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, 660390075Sobrien text_section_label, "Length"); 660450397Sobrien 660590075Sobrien for (i = 0; i < arange_table_in_use; i++) 660690075Sobrien { 660790075Sobrien dw_die_ref die = arange_table[i]; 660850397Sobrien 660990075Sobrien /* We shouldn't see aranges for DIEs outside of the main CU. */ 661090075Sobrien if (die->die_mark == 0) 661190075Sobrien abort (); 661250397Sobrien 661390075Sobrien if (die->die_tag == DW_TAG_subprogram) 661490075Sobrien { 661590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die), 661690075Sobrien "Address"); 661790075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die), 661890075Sobrien get_AT_low_pc (die), "Length"); 661990075Sobrien } 662090075Sobrien else 662190075Sobrien { 662290075Sobrien /* A static variable; extract the symbol from DW_AT_location. 662390075Sobrien Note that this code isn't currently hit, as we only emit 662490075Sobrien aranges for functions (jason 9/23/99). */ 662590075Sobrien dw_attr_ref a = get_AT (die, DW_AT_location); 662690075Sobrien dw_loc_descr_ref loc; 662750397Sobrien 662890075Sobrien if (! a || AT_class (a) != dw_val_class_loc) 662990075Sobrien abort (); 663050397Sobrien 663190075Sobrien loc = AT_loc (a); 663290075Sobrien if (loc->dw_loc_opc != DW_OP_addr) 663390075Sobrien abort (); 663450397Sobrien 663590075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, 663690075Sobrien loc->dw_loc_oprnd1.v.val_addr, "Address"); 663790075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 663890075Sobrien get_AT_unsigned (die, DW_AT_byte_size), 663990075Sobrien "Length"); 664090075Sobrien } 664190075Sobrien } 664250397Sobrien 664390075Sobrien /* Output the terminator words. */ 664490075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 664590075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 664690075Sobrien} 664790075Sobrien 664890075Sobrien/* Add a new entry to .debug_ranges. Return the offset at which it 664990075Sobrien was placed. */ 665090075Sobrien 665190075Sobrienstatic unsigned int 665290075Sobrienadd_ranges (block) 665390075Sobrien tree block; 665490075Sobrien{ 665590075Sobrien unsigned int in_use = ranges_table_in_use; 665690075Sobrien 665790075Sobrien if (in_use == ranges_table_allocated) 665850397Sobrien { 665990075Sobrien ranges_table_allocated += RANGES_TABLE_INCREMENT; 666090075Sobrien ranges_table = (dw_ranges_ref) 666190075Sobrien xrealloc (ranges_table, (ranges_table_allocated 666290075Sobrien * sizeof (struct dw_ranges_struct))); 666390075Sobrien } 666450397Sobrien 666590075Sobrien ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0); 666690075Sobrien ranges_table_in_use = in_use + 1; 666790075Sobrien 666890075Sobrien return in_use * 2 * DWARF2_ADDR_SIZE; 666990075Sobrien} 667090075Sobrien 667190075Sobrienstatic void 667290075Sobrienoutput_ranges () 667390075Sobrien{ 667490075Sobrien unsigned i; 667590075Sobrien static const char *const start_fmt = "Offset 0x%x"; 667690075Sobrien const char *fmt = start_fmt; 667790075Sobrien 667890075Sobrien for (i = 0; i < ranges_table_in_use; i++) 667990075Sobrien { 668090075Sobrien int block_num = ranges_table[i].block_num; 668190075Sobrien 668290075Sobrien if (block_num) 668390075Sobrien { 668490075Sobrien char blabel[MAX_ARTIFICIAL_LABEL_BYTES]; 668590075Sobrien char elabel[MAX_ARTIFICIAL_LABEL_BYTES]; 668690075Sobrien 668790075Sobrien ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num); 668890075Sobrien ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num); 668990075Sobrien 669090075Sobrien /* If all code is in the text section, then the compilation 669190075Sobrien unit base address defaults to DW_AT_low_pc, which is the 669290075Sobrien base of the text section. */ 669390075Sobrien if (separate_line_info_table_in_use == 0) 669490075Sobrien { 669590075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, 669690075Sobrien text_section_label, 669790075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 669890075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, 669990075Sobrien text_section_label, NULL); 670090075Sobrien } 670190075Sobrien 670290075Sobrien /* Otherwise, we add a DW_AT_entry_pc attribute to force the 670390075Sobrien compilation unit base address to zero, which allows us to 670490075Sobrien use absolute addresses, and not worry about whether the 670590075Sobrien target supports cross-section arithmetic. */ 670690075Sobrien else 670790075Sobrien { 670890075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, 670990075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 671090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL); 671190075Sobrien } 671290075Sobrien 671390075Sobrien fmt = NULL; 671490075Sobrien } 671550397Sobrien else 671650397Sobrien { 671790075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 671890075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 671990075Sobrien fmt = start_fmt; 672090075Sobrien } 672190075Sobrien } 672290075Sobrien} 672350397Sobrien 672490075Sobrien/* Data structure containing information about input files. */ 672590075Sobrienstruct file_info 672690075Sobrien{ 672790075Sobrien char *path; /* Complete file name. */ 672890075Sobrien char *fname; /* File name part. */ 672990075Sobrien int length; /* Length of entire string. */ 673090075Sobrien int file_idx; /* Index in input file table. */ 673190075Sobrien int dir_idx; /* Index in directory table. */ 673290075Sobrien}; 673390075Sobrien 673490075Sobrien/* Data structure containing information about directories with source 673590075Sobrien files. */ 673690075Sobrienstruct dir_info 673790075Sobrien{ 673890075Sobrien char *path; /* Path including directory name. */ 673990075Sobrien int length; /* Path length. */ 674090075Sobrien int prefix; /* Index of directory entry which is a prefix. */ 674190075Sobrien int count; /* Number of files in this directory. */ 674290075Sobrien int dir_idx; /* Index of directory used as base. */ 674390075Sobrien int used; /* Used in the end? */ 674490075Sobrien}; 674590075Sobrien 674690075Sobrien/* Callback function for file_info comparison. We sort by looking at 674790075Sobrien the directories in the path. */ 674890075Sobrien 674990075Sobrienstatic int 675090075Sobrienfile_info_cmp (p1, p2) 675190075Sobrien const void *p1; 675290075Sobrien const void *p2; 675390075Sobrien{ 675490075Sobrien const struct file_info *s1 = p1; 675590075Sobrien const struct file_info *s2 = p2; 675690075Sobrien unsigned char *cp1; 675790075Sobrien unsigned char *cp2; 675890075Sobrien 675990075Sobrien /* Take care of file names without directories. We need to make sure that 676090075Sobrien we return consistent values to qsort since some will get confused if 676190075Sobrien we return the same value when identical operands are passed in opposite 676290075Sobrien orders. So if neither has a directory, return 0 and otherwise return 676390075Sobrien 1 or -1 depending on which one has the directory. */ 676490075Sobrien if ((s1->path == s1->fname || s2->path == s2->fname)) 676590075Sobrien return (s2->path == s2->fname) - (s1->path == s1->fname); 676690075Sobrien 676790075Sobrien cp1 = (unsigned char *) s1->path; 676890075Sobrien cp2 = (unsigned char *) s2->path; 676990075Sobrien 677090075Sobrien while (1) 677190075Sobrien { 677290075Sobrien ++cp1; 677390075Sobrien ++cp2; 677490075Sobrien /* Reached the end of the first path? If so, handle like above. */ 677590075Sobrien if ((cp1 == (unsigned char *) s1->fname) 677690075Sobrien || (cp2 == (unsigned char *) s2->fname)) 677790075Sobrien return ((cp2 == (unsigned char *) s2->fname) 677890075Sobrien - (cp1 == (unsigned char *) s1->fname)); 677990075Sobrien 678090075Sobrien /* Character of current path component the same? */ 678190075Sobrien else if (*cp1 != *cp2) 678290075Sobrien return *cp1 - *cp2; 678390075Sobrien } 678490075Sobrien} 678590075Sobrien 678690075Sobrien/* Output the directory table and the file name table. We try to minimize 678790075Sobrien the total amount of memory needed. A heuristic is used to avoid large 678890075Sobrien slowdowns with many input files. */ 678990075Sobrien 679090075Sobrienstatic void 679190075Sobrienoutput_file_names () 679290075Sobrien{ 679390075Sobrien struct file_info *files; 679490075Sobrien struct dir_info *dirs; 679590075Sobrien int *saved; 679690075Sobrien int *savehere; 679790075Sobrien int *backmap; 679890075Sobrien int ndirs; 679990075Sobrien int idx_offset; 680090075Sobrien int i; 680190075Sobrien int idx; 680290075Sobrien 680390075Sobrien /* Allocate the various arrays we need. */ 680490075Sobrien files = (struct file_info *) alloca (file_table.in_use 680590075Sobrien * sizeof (struct file_info)); 680690075Sobrien dirs = (struct dir_info *) alloca (file_table.in_use 680790075Sobrien * sizeof (struct dir_info)); 680890075Sobrien 680990075Sobrien /* Sort the file names. */ 681090075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 681190075Sobrien { 681290075Sobrien char *f; 681390075Sobrien 681490075Sobrien /* Skip all leading "./". */ 681590075Sobrien f = file_table.table[i]; 681690075Sobrien while (f[0] == '.' && f[1] == '/') 681790075Sobrien f += 2; 681890075Sobrien 681990075Sobrien /* Create a new array entry. */ 682090075Sobrien files[i].path = f; 682190075Sobrien files[i].length = strlen (f); 682290075Sobrien files[i].file_idx = i; 682390075Sobrien 682490075Sobrien /* Search for the file name part. */ 682590075Sobrien f = strrchr (f, '/'); 682690075Sobrien files[i].fname = f == NULL ? files[i].path : f + 1; 682790075Sobrien } 682890075Sobrien 682990075Sobrien qsort (files + 1, file_table.in_use - 1, sizeof (files[0]), file_info_cmp); 683090075Sobrien 683190075Sobrien /* Find all the different directories used. */ 683290075Sobrien dirs[0].path = files[1].path; 683390075Sobrien dirs[0].length = files[1].fname - files[1].path; 683490075Sobrien dirs[0].prefix = -1; 683590075Sobrien dirs[0].count = 1; 683690075Sobrien dirs[0].dir_idx = 0; 683790075Sobrien dirs[0].used = 0; 683890075Sobrien files[1].dir_idx = 0; 683990075Sobrien ndirs = 1; 684090075Sobrien 684190075Sobrien for (i = 2; i < (int) file_table.in_use; i++) 684290075Sobrien if (files[i].fname - files[i].path == dirs[ndirs - 1].length 684390075Sobrien && memcmp (dirs[ndirs - 1].path, files[i].path, 684490075Sobrien dirs[ndirs - 1].length) == 0) 684590075Sobrien { 684690075Sobrien /* Same directory as last entry. */ 684790075Sobrien files[i].dir_idx = ndirs - 1; 684890075Sobrien ++dirs[ndirs - 1].count; 684990075Sobrien } 685090075Sobrien else 685190075Sobrien { 685290075Sobrien int j; 685390075Sobrien 685490075Sobrien /* This is a new directory. */ 685590075Sobrien dirs[ndirs].path = files[i].path; 685690075Sobrien dirs[ndirs].length = files[i].fname - files[i].path; 685790075Sobrien dirs[ndirs].count = 1; 685890075Sobrien dirs[ndirs].dir_idx = ndirs; 685990075Sobrien dirs[ndirs].used = 0; 686090075Sobrien files[i].dir_idx = ndirs; 686190075Sobrien 686290075Sobrien /* Search for a prefix. */ 686390075Sobrien dirs[ndirs].prefix = -1; 686490075Sobrien for (j = 0; j < ndirs; j++) 686590075Sobrien if (dirs[j].length < dirs[ndirs].length 686690075Sobrien && dirs[j].length > 1 686790075Sobrien && (dirs[ndirs].prefix == -1 686890075Sobrien || dirs[j].length > dirs[dirs[ndirs].prefix].length) 686990075Sobrien && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0) 687090075Sobrien dirs[ndirs].prefix = j; 687190075Sobrien 687290075Sobrien ++ndirs; 687390075Sobrien } 687490075Sobrien 687590075Sobrien /* Now to the actual work. We have to find a subset of the directories which 687690075Sobrien allow expressing the file name using references to the directory table 687790075Sobrien with the least amount of characters. We do not do an exhaustive search 687890075Sobrien where we would have to check out every combination of every single 687990075Sobrien possible prefix. Instead we use a heuristic which provides nearly optimal 688090075Sobrien results in most cases and never is much off. */ 688190075Sobrien saved = (int *) alloca (ndirs * sizeof (int)); 688290075Sobrien savehere = (int *) alloca (ndirs * sizeof (int)); 688390075Sobrien 688490075Sobrien memset (saved, '\0', ndirs * sizeof (saved[0])); 688590075Sobrien for (i = 0; i < ndirs; i++) 688690075Sobrien { 688790075Sobrien int j; 688890075Sobrien int total; 688990075Sobrien 689090075Sobrien /* We can always save some space for the current directory. But this 689190075Sobrien does not mean it will be enough to justify adding the directory. */ 689290075Sobrien savehere[i] = dirs[i].length; 689390075Sobrien total = (savehere[i] - saved[i]) * dirs[i].count; 689490075Sobrien 689590075Sobrien for (j = i + 1; j < ndirs; j++) 689690075Sobrien { 689790075Sobrien savehere[j] = 0; 689890075Sobrien if (saved[j] < dirs[i].length) 689990075Sobrien { 690090075Sobrien /* Determine whether the dirs[i] path is a prefix of the 690190075Sobrien dirs[j] path. */ 690290075Sobrien int k; 690390075Sobrien 690490075Sobrien k = dirs[j].prefix; 690590075Sobrien while (k != -1 && k != i) 690690075Sobrien k = dirs[k].prefix; 690790075Sobrien 690890075Sobrien if (k == i) 690990075Sobrien { 691090075Sobrien /* Yes it is. We can possibly safe some memory but 691190075Sobrien writing the filenames in dirs[j] relative to 691290075Sobrien dirs[i]. */ 691390075Sobrien savehere[j] = dirs[i].length; 691490075Sobrien total += (savehere[j] - saved[j]) * dirs[j].count; 691590075Sobrien } 691690075Sobrien } 691750397Sobrien } 691850397Sobrien 691990075Sobrien /* Check whether we can safe enough to justify adding the dirs[i] 692090075Sobrien directory. */ 692190075Sobrien if (total > dirs[i].length + 1) 692290075Sobrien { 692390075Sobrien /* It's worthwhile adding. */ 692490075Sobrien for (j = i; j < ndirs; j++) 692590075Sobrien if (savehere[j] > 0) 692690075Sobrien { 692790075Sobrien /* Remember how much we saved for this directory so far. */ 692890075Sobrien saved[j] = savehere[j]; 692950397Sobrien 693090075Sobrien /* Remember the prefix directory. */ 693190075Sobrien dirs[j].dir_idx = i; 693290075Sobrien } 693390075Sobrien } 693490075Sobrien } 693550397Sobrien 693690075Sobrien /* We have to emit them in the order they appear in the file_table array 693790075Sobrien since the index is used in the debug info generation. To do this 693890075Sobrien efficiently we generate a back-mapping of the indices first. */ 693990075Sobrien backmap = (int *) alloca (file_table.in_use * sizeof (int)); 694090075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 694190075Sobrien { 694290075Sobrien backmap[files[i].file_idx] = i; 694350397Sobrien 694490075Sobrien /* Mark this directory as used. */ 694590075Sobrien dirs[dirs[files[i].dir_idx].dir_idx].used = 1; 694650397Sobrien } 694750397Sobrien 694890075Sobrien /* That was it. We are ready to emit the information. First emit the 694990075Sobrien directory name table. We have to make sure the first actually emitted 695090075Sobrien directory name has index one; zero is reserved for the current working 695190075Sobrien directory. Make sure we do not confuse these indices with the one for the 695290075Sobrien constructed table (even though most of the time they are identical). */ 695390075Sobrien idx = 1; 695490075Sobrien idx_offset = dirs[0].length > 0 ? 1 : 0; 695590075Sobrien for (i = 1 - idx_offset; i < ndirs; i++) 695690075Sobrien if (dirs[i].used != 0) 695790075Sobrien { 695890075Sobrien dirs[i].used = idx++; 695990075Sobrien dw2_asm_output_nstring (dirs[i].path, dirs[i].length - 1, 696090075Sobrien "Directory Entry: 0x%x", dirs[i].used); 696190075Sobrien } 696290075Sobrien 696390075Sobrien dw2_asm_output_data (1, 0, "End directory table"); 696490075Sobrien 696590075Sobrien /* Correct the index for the current working directory entry if it 696690075Sobrien exists. */ 696790075Sobrien if (idx_offset == 0) 696890075Sobrien dirs[0].used = 0; 696990075Sobrien 697090075Sobrien /* Now write all the file names. */ 697190075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 697290075Sobrien { 697390075Sobrien int file_idx = backmap[i]; 697490075Sobrien int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; 697590075Sobrien 697690075Sobrien dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, 697790075Sobrien "File Entry: 0x%x", i); 697890075Sobrien 697990075Sobrien /* Include directory index. */ 698090075Sobrien dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL); 698190075Sobrien 698290075Sobrien /* Modification time. */ 698390075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 698490075Sobrien 698590075Sobrien /* File length in bytes. */ 698690075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 698790075Sobrien } 698890075Sobrien 698990075Sobrien dw2_asm_output_data (1, 0, "End file name table"); 699050397Sobrien} 699150397Sobrien 699290075Sobrien 699350397Sobrien/* Output the source line number correspondence information. This 699490075Sobrien information goes into the .debug_line section. */ 699550397Sobrien 699650397Sobrienstatic void 699750397Sobrienoutput_line_info () 699850397Sobrien{ 699990075Sobrien char l1[20], l2[20], p1[20], p2[20]; 700050397Sobrien char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 700150397Sobrien char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 700290075Sobrien unsigned opc; 700390075Sobrien unsigned n_op_args; 700490075Sobrien unsigned long lt_index; 700590075Sobrien unsigned long current_line; 700690075Sobrien long line_offset; 700790075Sobrien long line_delta; 700890075Sobrien unsigned long current_file; 700990075Sobrien unsigned long function; 701050397Sobrien 701190075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0); 701290075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0); 701390075Sobrien ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0); 701490075Sobrien ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0); 701550397Sobrien 701690075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, 701790075Sobrien "Length of Source Line Info"); 701890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 701950397Sobrien 702090075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 702190075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length"); 702290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p1); 702350397Sobrien 702496263Sobrien /* Define the architecture-dependent minimum instruction length (in 702596263Sobrien bytes). In this implementation of DWARF, this field is used for 702696263Sobrien information purposes only. Since GCC generates assembly language, 702796263Sobrien we have no a priori knowledge of how many instruction bytes are 702896263Sobrien generated for each source line, and therefore can use only the 702996263Sobrien DW_LNE_set_address and DW_LNS_fixed_advance_pc line information 703096263Sobrien commands. Accordingly, we fix this as `1', which is "correct 703196263Sobrien enough" for all architectures, and don't let the target override. */ 703296263Sobrien dw2_asm_output_data (1, 1, 703390075Sobrien "Minimum Instruction Length"); 703496263Sobrien 703590075Sobrien dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, 703690075Sobrien "Default is_stmt_start flag"); 703790075Sobrien dw2_asm_output_data (1, DWARF_LINE_BASE, 703890075Sobrien "Line Base Value (Special Opcodes)"); 703990075Sobrien dw2_asm_output_data (1, DWARF_LINE_RANGE, 704090075Sobrien "Line Range Value (Special Opcodes)"); 704190075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE, 704290075Sobrien "Special Opcode Base"); 704350397Sobrien 704490075Sobrien for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++) 704550397Sobrien { 704650397Sobrien switch (opc) 704750397Sobrien { 704850397Sobrien case DW_LNS_advance_pc: 704950397Sobrien case DW_LNS_advance_line: 705050397Sobrien case DW_LNS_set_file: 705150397Sobrien case DW_LNS_set_column: 705250397Sobrien case DW_LNS_fixed_advance_pc: 705350397Sobrien n_op_args = 1; 705450397Sobrien break; 705550397Sobrien default: 705650397Sobrien n_op_args = 0; 705750397Sobrien break; 705850397Sobrien } 705950397Sobrien 706090075Sobrien dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args", 706190075Sobrien opc, n_op_args); 706250397Sobrien } 706350397Sobrien 706490075Sobrien /* Write out the information about the files we use. */ 706590075Sobrien output_file_names (); 706690075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p2); 706750397Sobrien 706852284Sobrien /* We used to set the address register to the first location in the text 706952284Sobrien section here, but that didn't accomplish anything since we already 707052284Sobrien have a line note for the opening brace of the first function. */ 707150397Sobrien 707250397Sobrien /* Generate the line number to PC correspondence table, encoded as 707350397Sobrien a series of state machine operations. */ 707450397Sobrien current_file = 1; 707550397Sobrien current_line = 1; 707652284Sobrien strcpy (prev_line_label, text_section_label); 707750397Sobrien for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) 707850397Sobrien { 707990075Sobrien dw_line_info_ref line_info = &line_info_table[lt_index]; 708050397Sobrien 708190075Sobrien#if 0 708290075Sobrien /* Disable this optimization for now; GDB wants to see two line notes 708390075Sobrien at the beginning of a function so it can find the end of the 708490075Sobrien prologue. */ 708590075Sobrien 708652284Sobrien /* Don't emit anything for redundant notes. Just updating the 708752284Sobrien address doesn't accomplish anything, because we already assume 708852284Sobrien that anything after the last address is this line. */ 708952284Sobrien if (line_info->dw_line_num == current_line 709052284Sobrien && line_info->dw_file_num == current_file) 709152284Sobrien continue; 709290075Sobrien#endif 709352284Sobrien 709490075Sobrien /* Emit debug info for the address of the current line. 709590075Sobrien 709690075Sobrien Unfortunately, we have little choice here currently, and must always 709790075Sobrien use the most general form. GCC does not know the address delta 709890075Sobrien itself, so we can't use DW_LNS_advance_pc. Many ports do have length 709990075Sobrien attributes which will give an upper bound on the address range. We 710090075Sobrien could perhaps use length attributes to determine when it is safe to 710190075Sobrien use DW_LNS_fixed_advance_pc. */ 710290075Sobrien 710350397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index); 710450397Sobrien if (0) 710550397Sobrien { 710650397Sobrien /* This can handle deltas up to 0xffff. This takes 3 bytes. */ 710790075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 710890075Sobrien "DW_LNS_fixed_advance_pc"); 710990075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 711050397Sobrien } 711150397Sobrien else 711250397Sobrien { 711390075Sobrien /* This can handle any delta. This takes 711490075Sobrien 4+DWARF2_ADDR_SIZE bytes. */ 711590075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 711690075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 711790075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 711890075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 711950397Sobrien } 712090075Sobrien 712150397Sobrien strcpy (prev_line_label, line_label); 712250397Sobrien 712350397Sobrien /* Emit debug info for the source file of the current line, if 712450397Sobrien different from the previous line. */ 712550397Sobrien if (line_info->dw_file_num != current_file) 712650397Sobrien { 712750397Sobrien current_file = line_info->dw_file_num; 712890075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 712990075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 713090075Sobrien file_table.table[current_file]); 713150397Sobrien } 713250397Sobrien 713350397Sobrien /* Emit debug info for the current line number, choosing the encoding 713450397Sobrien that uses the least amount of space. */ 713552284Sobrien if (line_info->dw_line_num != current_line) 713650397Sobrien { 713752284Sobrien line_offset = line_info->dw_line_num - current_line; 713852284Sobrien line_delta = line_offset - DWARF_LINE_BASE; 713952284Sobrien current_line = line_info->dw_line_num; 714052284Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 714190075Sobrien /* This can handle deltas from -10 to 234, using the current 714290075Sobrien definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This 714390075Sobrien takes 1 byte. */ 714490075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 714590075Sobrien "line %lu", current_line); 714652284Sobrien else 714752284Sobrien { 714852284Sobrien /* This can handle any delta. This takes at least 4 bytes, 714952284Sobrien depending on the value being encoded. */ 715090075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 715190075Sobrien "advance to line %lu", current_line); 715290075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 715390075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 715452284Sobrien } 715550397Sobrien } 715650397Sobrien else 715790075Sobrien /* We still need to start a new row, so output a copy insn. */ 715890075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 715950397Sobrien } 716050397Sobrien 716150397Sobrien /* Emit debug info for the address of the end of the function. */ 716250397Sobrien if (0) 716350397Sobrien { 716490075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 716590075Sobrien "DW_LNS_fixed_advance_pc"); 716690075Sobrien dw2_asm_output_delta (2, text_end_label, prev_line_label, NULL); 716750397Sobrien } 716850397Sobrien else 716950397Sobrien { 717090075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 717190075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 717290075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 717390075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_end_label, NULL); 717450397Sobrien } 717550397Sobrien 717690075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 717790075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 717890075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 717950397Sobrien 718050397Sobrien function = 0; 718150397Sobrien current_file = 1; 718250397Sobrien current_line = 1; 718390075Sobrien for (lt_index = 0; lt_index < separate_line_info_table_in_use;) 718450397Sobrien { 718590075Sobrien dw_separate_line_info_ref line_info 718650397Sobrien = &separate_line_info_table[lt_index]; 718750397Sobrien 718890075Sobrien#if 0 718952284Sobrien /* Don't emit anything for redundant notes. */ 719052284Sobrien if (line_info->dw_line_num == current_line 719152284Sobrien && line_info->dw_file_num == current_file 719252284Sobrien && line_info->function == function) 719352284Sobrien goto cont; 719490075Sobrien#endif 719552284Sobrien 719650397Sobrien /* Emit debug info for the address of the current line. If this is 719750397Sobrien a new function, or the first line of a function, then we need 719850397Sobrien to handle it differently. */ 719950397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL, 720050397Sobrien lt_index); 720150397Sobrien if (function != line_info->function) 720250397Sobrien { 720350397Sobrien function = line_info->function; 720450397Sobrien 720550397Sobrien /* Set the address register to the first line in the function */ 720690075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 720790075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 720890075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 720990075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 721050397Sobrien } 721150397Sobrien else 721250397Sobrien { 721350397Sobrien /* ??? See the DW_LNS_advance_pc comment above. */ 721450397Sobrien if (0) 721550397Sobrien { 721690075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 721790075Sobrien "DW_LNS_fixed_advance_pc"); 721890075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 721950397Sobrien } 722050397Sobrien else 722150397Sobrien { 722290075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 722390075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 722490075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 722590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 722650397Sobrien } 722750397Sobrien } 722890075Sobrien 722950397Sobrien strcpy (prev_line_label, line_label); 723050397Sobrien 723150397Sobrien /* Emit debug info for the source file of the current line, if 723250397Sobrien different from the previous line. */ 723350397Sobrien if (line_info->dw_file_num != current_file) 723450397Sobrien { 723550397Sobrien current_file = line_info->dw_file_num; 723690075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 723790075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 723890075Sobrien file_table.table[current_file]); 723950397Sobrien } 724050397Sobrien 724150397Sobrien /* Emit debug info for the current line number, choosing the encoding 724250397Sobrien that uses the least amount of space. */ 724350397Sobrien if (line_info->dw_line_num != current_line) 724450397Sobrien { 724550397Sobrien line_offset = line_info->dw_line_num - current_line; 724650397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 724750397Sobrien current_line = line_info->dw_line_num; 724850397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 724990075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 725090075Sobrien "line %lu", current_line); 725150397Sobrien else 725250397Sobrien { 725390075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 725490075Sobrien "advance to line %lu", current_line); 725590075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 725690075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 725750397Sobrien } 725850397Sobrien } 725952284Sobrien else 726090075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 726150397Sobrien 726290075Sobrien#if 0 726352284Sobrien cont: 726490075Sobrien#endif 726550397Sobrien 726690075Sobrien lt_index++; 726790075Sobrien 726850397Sobrien /* If we're done with a function, end its sequence. */ 726950397Sobrien if (lt_index == separate_line_info_table_in_use 727050397Sobrien || separate_line_info_table[lt_index].function != function) 727150397Sobrien { 727250397Sobrien current_file = 1; 727350397Sobrien current_line = 1; 727450397Sobrien 727550397Sobrien /* Emit debug info for the address of the end of the function. */ 727650397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function); 727750397Sobrien if (0) 727850397Sobrien { 727990075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 728090075Sobrien "DW_LNS_fixed_advance_pc"); 728190075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 728250397Sobrien } 728350397Sobrien else 728450397Sobrien { 728590075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 728690075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 728790075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 728890075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 728950397Sobrien } 729050397Sobrien 729150397Sobrien /* Output the marker for the end of this sequence. */ 729290075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 729390075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 729490075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 729550397Sobrien } 729650397Sobrien } 729790075Sobrien 729890075Sobrien /* Output the marker for the end of the line number info. */ 729990075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 730050397Sobrien} 730150397Sobrien 730250397Sobrien/* Given a pointer to a tree node for some base type, return a pointer to 730350397Sobrien a DIE that describes the given type. 730450397Sobrien 730550397Sobrien This routine must only be called for GCC type nodes that correspond to 730650397Sobrien Dwarf base (fundamental) types. */ 730750397Sobrien 730850397Sobrienstatic dw_die_ref 730950397Sobrienbase_type_die (type) 731090075Sobrien tree type; 731150397Sobrien{ 731290075Sobrien dw_die_ref base_type_result; 731390075Sobrien const char *type_name; 731490075Sobrien enum dwarf_type encoding; 731590075Sobrien tree name = TYPE_NAME (type); 731650397Sobrien 731790075Sobrien if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE) 731850397Sobrien return 0; 731950397Sobrien 732090075Sobrien if (name) 732190075Sobrien { 732290075Sobrien if (TREE_CODE (name) == TYPE_DECL) 732390075Sobrien name = DECL_NAME (name); 732450397Sobrien 732590075Sobrien type_name = IDENTIFIER_POINTER (name); 732690075Sobrien } 732790075Sobrien else 732890075Sobrien type_name = "__unknown__"; 732990075Sobrien 733050397Sobrien switch (TREE_CODE (type)) 733150397Sobrien { 733250397Sobrien case INTEGER_TYPE: 733350397Sobrien /* Carefully distinguish the C character types, without messing 733450397Sobrien up if the language is not C. Note that we check only for the names 733590075Sobrien that contain spaces; other names might occur by coincidence in other 733650397Sobrien languages. */ 733750397Sobrien if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE 733850397Sobrien && (type == char_type_node 733950397Sobrien || ! strcmp (type_name, "signed char") 734050397Sobrien || ! strcmp (type_name, "unsigned char")))) 734150397Sobrien { 734250397Sobrien if (TREE_UNSIGNED (type)) 734350397Sobrien encoding = DW_ATE_unsigned; 734450397Sobrien else 734550397Sobrien encoding = DW_ATE_signed; 734650397Sobrien break; 734750397Sobrien } 734890075Sobrien /* else fall through. */ 734950397Sobrien 735050397Sobrien case CHAR_TYPE: 735150397Sobrien /* GNU Pascal/Ada CHAR type. Not used in C. */ 735250397Sobrien if (TREE_UNSIGNED (type)) 735350397Sobrien encoding = DW_ATE_unsigned_char; 735450397Sobrien else 735550397Sobrien encoding = DW_ATE_signed_char; 735650397Sobrien break; 735750397Sobrien 735850397Sobrien case REAL_TYPE: 735950397Sobrien encoding = DW_ATE_float; 736050397Sobrien break; 736150397Sobrien 736290075Sobrien /* Dwarf2 doesn't know anything about complex ints, so use 736390075Sobrien a user defined type for it. */ 736450397Sobrien case COMPLEX_TYPE: 736590075Sobrien if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) 736690075Sobrien encoding = DW_ATE_complex_float; 736790075Sobrien else 736890075Sobrien encoding = DW_ATE_lo_user; 736950397Sobrien break; 737050397Sobrien 737150397Sobrien case BOOLEAN_TYPE: 737250397Sobrien /* GNU FORTRAN/Ada/C++ BOOLEAN type. */ 737350397Sobrien encoding = DW_ATE_boolean; 737450397Sobrien break; 737550397Sobrien 737650397Sobrien default: 737790075Sobrien /* No other TREE_CODEs are Dwarf fundamental types. */ 737890075Sobrien abort (); 737950397Sobrien } 738050397Sobrien 738190075Sobrien base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type); 738290075Sobrien if (demangle_name_func) 738390075Sobrien type_name = (*demangle_name_func) (type_name); 738490075Sobrien 738550397Sobrien add_AT_string (base_type_result, DW_AT_name, type_name); 738650397Sobrien add_AT_unsigned (base_type_result, DW_AT_byte_size, 738750397Sobrien int_size_in_bytes (type)); 738850397Sobrien add_AT_unsigned (base_type_result, DW_AT_encoding, encoding); 738950397Sobrien 739050397Sobrien return base_type_result; 739150397Sobrien} 739250397Sobrien 739350397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to 739450397Sobrien the Dwarf "root" type for the given input type. The Dwarf "root" type of 739550397Sobrien a given type is generally the same as the given type, except that if the 739650397Sobrien given type is a pointer or reference type, then the root type of the given 739750397Sobrien type is the root type of the "basis" type for the pointer or reference 739850397Sobrien type. (This definition of the "root" type is recursive.) Also, the root 739950397Sobrien type of a `const' qualified type or a `volatile' qualified type is the 740050397Sobrien root type of the given type without the qualifiers. */ 740150397Sobrien 740250397Sobrienstatic tree 740350397Sobrienroot_type (type) 740490075Sobrien tree type; 740550397Sobrien{ 740650397Sobrien if (TREE_CODE (type) == ERROR_MARK) 740750397Sobrien return error_mark_node; 740850397Sobrien 740950397Sobrien switch (TREE_CODE (type)) 741050397Sobrien { 741150397Sobrien case ERROR_MARK: 741250397Sobrien return error_mark_node; 741350397Sobrien 741450397Sobrien case POINTER_TYPE: 741550397Sobrien case REFERENCE_TYPE: 741650397Sobrien return type_main_variant (root_type (TREE_TYPE (type))); 741750397Sobrien 741850397Sobrien default: 741950397Sobrien return type_main_variant (type); 742050397Sobrien } 742150397Sobrien} 742250397Sobrien 742350397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the 742450397Sobrien given input type is a Dwarf "fundamental" type. Otherwise return null. */ 742550397Sobrien 742650397Sobrienstatic inline int 742750397Sobrienis_base_type (type) 742890075Sobrien tree type; 742950397Sobrien{ 743050397Sobrien switch (TREE_CODE (type)) 743150397Sobrien { 743250397Sobrien case ERROR_MARK: 743350397Sobrien case VOID_TYPE: 743450397Sobrien case INTEGER_TYPE: 743550397Sobrien case REAL_TYPE: 743650397Sobrien case COMPLEX_TYPE: 743750397Sobrien case BOOLEAN_TYPE: 743850397Sobrien case CHAR_TYPE: 743950397Sobrien return 1; 744050397Sobrien 744150397Sobrien case SET_TYPE: 744250397Sobrien case ARRAY_TYPE: 744350397Sobrien case RECORD_TYPE: 744450397Sobrien case UNION_TYPE: 744550397Sobrien case QUAL_UNION_TYPE: 744650397Sobrien case ENUMERAL_TYPE: 744750397Sobrien case FUNCTION_TYPE: 744850397Sobrien case METHOD_TYPE: 744950397Sobrien case POINTER_TYPE: 745050397Sobrien case REFERENCE_TYPE: 745150397Sobrien case FILE_TYPE: 745250397Sobrien case OFFSET_TYPE: 745350397Sobrien case LANG_TYPE: 745490075Sobrien case VECTOR_TYPE: 745550397Sobrien return 0; 745650397Sobrien 745750397Sobrien default: 745850397Sobrien abort (); 745950397Sobrien } 746050397Sobrien 746150397Sobrien return 0; 746250397Sobrien} 746350397Sobrien 746450397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging 746550397Sobrien entry that chains various modifiers in front of the given type. */ 746650397Sobrien 746750397Sobrienstatic dw_die_ref 746850397Sobrienmodified_type_die (type, is_const_type, is_volatile_type, context_die) 746990075Sobrien tree type; 747090075Sobrien int is_const_type; 747190075Sobrien int is_volatile_type; 747290075Sobrien dw_die_ref context_die; 747350397Sobrien{ 747490075Sobrien enum tree_code code = TREE_CODE (type); 747590075Sobrien dw_die_ref mod_type_die = NULL; 747690075Sobrien dw_die_ref sub_die = NULL; 747790075Sobrien tree item_type = NULL; 747850397Sobrien 747950397Sobrien if (code != ERROR_MARK) 748050397Sobrien { 748190075Sobrien tree qualified_type; 748250397Sobrien 748390075Sobrien /* See if we already have the appropriately qualified variant of 748490075Sobrien this type. */ 748590075Sobrien qualified_type 748690075Sobrien = get_qualified_type (type, 748790075Sobrien ((is_const_type ? TYPE_QUAL_CONST : 0) 748890075Sobrien | (is_volatile_type 748990075Sobrien ? TYPE_QUAL_VOLATILE : 0))); 749050397Sobrien 749190075Sobrien /* If we do, then we can just use its DIE, if it exists. */ 749290075Sobrien if (qualified_type) 749350397Sobrien { 749490075Sobrien mod_type_die = lookup_type_die (qualified_type); 749590075Sobrien if (mod_type_die) 749690075Sobrien return mod_type_die; 749790075Sobrien } 749890075Sobrien 749990075Sobrien /* Handle C typedef types. */ 750090075Sobrien if (qualified_type && TYPE_NAME (qualified_type) 750190075Sobrien && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL 750290075Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type))) 750390075Sobrien { 750490075Sobrien tree type_name = TYPE_NAME (qualified_type); 750590075Sobrien tree dtype = TREE_TYPE (type_name); 750690075Sobrien 750790075Sobrien if (qualified_type == dtype) 750850397Sobrien { 750950397Sobrien /* For a named type, use the typedef. */ 751090075Sobrien gen_type_die (qualified_type, context_die); 751190075Sobrien mod_type_die = lookup_type_die (qualified_type); 751250397Sobrien } 751350397Sobrien else if (is_const_type < TYPE_READONLY (dtype) 751450397Sobrien || is_volatile_type < TYPE_VOLATILE (dtype)) 751550397Sobrien /* cv-unqualified version of named type. Just use the unnamed 751650397Sobrien type to which it refers. */ 751750397Sobrien mod_type_die 751890075Sobrien = modified_type_die (DECL_ORIGINAL_TYPE (type_name), 751950397Sobrien is_const_type, is_volatile_type, 752050397Sobrien context_die); 752190075Sobrien 752250397Sobrien /* Else cv-qualified version of named type; fall through. */ 752350397Sobrien } 752450397Sobrien 752550397Sobrien if (mod_type_die) 752690075Sobrien /* OK. */ 752790075Sobrien ; 752850397Sobrien else if (is_const_type) 752950397Sobrien { 753090075Sobrien mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type); 753150397Sobrien sub_die = modified_type_die (type, 0, is_volatile_type, context_die); 753250397Sobrien } 753350397Sobrien else if (is_volatile_type) 753450397Sobrien { 753590075Sobrien mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type); 753650397Sobrien sub_die = modified_type_die (type, 0, 0, context_die); 753750397Sobrien } 753850397Sobrien else if (code == POINTER_TYPE) 753950397Sobrien { 754090075Sobrien mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); 754150397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 754250397Sobrien#if 0 754350397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 754450397Sobrien#endif 754550397Sobrien item_type = TREE_TYPE (type); 754650397Sobrien } 754750397Sobrien else if (code == REFERENCE_TYPE) 754850397Sobrien { 754990075Sobrien mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); 755050397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 755150397Sobrien#if 0 755250397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 755390075Sobrien#endif 755450397Sobrien item_type = TREE_TYPE (type); 755550397Sobrien } 755650397Sobrien else if (is_base_type (type)) 755750397Sobrien mod_type_die = base_type_die (type); 755850397Sobrien else 755950397Sobrien { 756050397Sobrien gen_type_die (type, context_die); 756150397Sobrien 756250397Sobrien /* We have to get the type_main_variant here (and pass that to the 756350397Sobrien `lookup_type_die' routine) because the ..._TYPE node we have 756450397Sobrien might simply be a *copy* of some original type node (where the 756550397Sobrien copy was created to help us keep track of typedef names) and 756650397Sobrien that copy might have a different TYPE_UID from the original 756750397Sobrien ..._TYPE node. */ 756850397Sobrien mod_type_die = lookup_type_die (type_main_variant (type)); 756950397Sobrien if (mod_type_die == NULL) 757050397Sobrien abort (); 757150397Sobrien } 757290075Sobrien 757390075Sobrien /* We want to equate the qualified type to the die below. */ 757490075Sobrien if (qualified_type) 757590075Sobrien type = qualified_type; 757650397Sobrien } 757750397Sobrien 757850397Sobrien equate_type_number_to_die (type, mod_type_die); 757950397Sobrien if (item_type) 758050397Sobrien /* We must do this after the equate_type_number_to_die call, in case 758150397Sobrien this is a recursive type. This ensures that the modified_type_die 758250397Sobrien recursion will terminate even if the type is recursive. Recursive 758350397Sobrien types are possible in Ada. */ 758450397Sobrien sub_die = modified_type_die (item_type, 758550397Sobrien TYPE_READONLY (item_type), 758650397Sobrien TYPE_VOLATILE (item_type), 758750397Sobrien context_die); 758850397Sobrien 758950397Sobrien if (sub_die != NULL) 759050397Sobrien add_AT_die_ref (mod_type_die, DW_AT_type, sub_die); 759150397Sobrien 759250397Sobrien return mod_type_die; 759350397Sobrien} 759450397Sobrien 759550397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is 759690075Sobrien an enumerated type. */ 759750397Sobrien 759850397Sobrienstatic inline int 759950397Sobrientype_is_enum (type) 760090075Sobrien tree type; 760150397Sobrien{ 760250397Sobrien return TREE_CODE (type) == ENUMERAL_TYPE; 760350397Sobrien} 760450397Sobrien 760590075Sobrien/* Return the register number described by a given RTL node. */ 760650397Sobrien 760790075Sobrienstatic unsigned int 760890075Sobrienreg_number (rtl) 760990075Sobrien rtx rtl; 761090075Sobrien{ 761190075Sobrien unsigned regno = REGNO (rtl); 761290075Sobrien 761390075Sobrien if (regno >= FIRST_PSEUDO_REGISTER) 761490075Sobrien abort (); 761590075Sobrien 761690075Sobrien return DBX_REGISTER_NUMBER (regno); 761790075Sobrien} 761890075Sobrien 761990075Sobrien/* Return a location descriptor that designates a machine register or 762090075Sobrien zero if there is no such. */ 762190075Sobrien 762250397Sobrienstatic dw_loc_descr_ref 762350397Sobrienreg_loc_descriptor (rtl) 762490075Sobrien rtx rtl; 762550397Sobrien{ 762690075Sobrien dw_loc_descr_ref loc_result = NULL; 762790075Sobrien unsigned reg; 762850397Sobrien 762990075Sobrien if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 763090075Sobrien return 0; 763190075Sobrien 763290075Sobrien reg = reg_number (rtl); 763350397Sobrien if (reg <= 31) 763450397Sobrien loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0); 763550397Sobrien else 763650397Sobrien loc_result = new_loc_descr (DW_OP_regx, reg, 0); 763750397Sobrien 763850397Sobrien return loc_result; 763950397Sobrien} 764050397Sobrien 764190075Sobrien/* Return a location descriptor that designates a constant. */ 764290075Sobrien 764390075Sobrienstatic dw_loc_descr_ref 764490075Sobrienint_loc_descriptor (i) 764590075Sobrien HOST_WIDE_INT i; 764690075Sobrien{ 764790075Sobrien enum dwarf_location_atom op; 764890075Sobrien 764990075Sobrien /* Pick the smallest representation of a constant, rather than just 765090075Sobrien defaulting to the LEB encoding. */ 765190075Sobrien if (i >= 0) 765290075Sobrien { 765390075Sobrien if (i <= 31) 765490075Sobrien op = DW_OP_lit0 + i; 765590075Sobrien else if (i <= 0xff) 765690075Sobrien op = DW_OP_const1u; 765790075Sobrien else if (i <= 0xffff) 765890075Sobrien op = DW_OP_const2u; 765990075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 766090075Sobrien || i <= 0xffffffff) 766190075Sobrien op = DW_OP_const4u; 766290075Sobrien else 766390075Sobrien op = DW_OP_constu; 766490075Sobrien } 766590075Sobrien else 766690075Sobrien { 766790075Sobrien if (i >= -0x80) 766890075Sobrien op = DW_OP_const1s; 766990075Sobrien else if (i >= -0x8000) 767090075Sobrien op = DW_OP_const2s; 767190075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 767290075Sobrien || i >= -0x80000000) 767390075Sobrien op = DW_OP_const4s; 767490075Sobrien else 767590075Sobrien op = DW_OP_consts; 767690075Sobrien } 767790075Sobrien 767890075Sobrien return new_loc_descr (op, i, 0); 767990075Sobrien} 768090075Sobrien 768150397Sobrien/* Return a location descriptor that designates a base+offset location. */ 768250397Sobrien 768350397Sobrienstatic dw_loc_descr_ref 768450397Sobrienbased_loc_descr (reg, offset) 768550397Sobrien unsigned reg; 768650397Sobrien long int offset; 768750397Sobrien{ 768890075Sobrien dw_loc_descr_ref loc_result; 768950397Sobrien /* For the "frame base", we use the frame pointer or stack pointer 769050397Sobrien registers, since the RTL for local variables is relative to one of 769150397Sobrien them. */ 769290075Sobrien unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed 769390075Sobrien ? HARD_FRAME_POINTER_REGNUM 769490075Sobrien : STACK_POINTER_REGNUM); 769550397Sobrien 769650397Sobrien if (reg == fp_reg) 769750397Sobrien loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); 769850397Sobrien else if (reg <= 31) 769950397Sobrien loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); 770050397Sobrien else 770150397Sobrien loc_result = new_loc_descr (DW_OP_bregx, reg, offset); 770250397Sobrien 770350397Sobrien return loc_result; 770450397Sobrien} 770550397Sobrien 770650397Sobrien/* Return true if this RTL expression describes a base+offset calculation. */ 770750397Sobrien 770850397Sobrienstatic inline int 770950397Sobrienis_based_loc (rtl) 771090075Sobrien rtx rtl; 771150397Sobrien{ 771290075Sobrien return (GET_CODE (rtl) == PLUS 771390075Sobrien && ((GET_CODE (XEXP (rtl, 0)) == REG 771490075Sobrien && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER 771590075Sobrien && GET_CODE (XEXP (rtl, 1)) == CONST_INT))); 771650397Sobrien} 771750397Sobrien 771850397Sobrien/* The following routine converts the RTL for a variable or parameter 771950397Sobrien (resident in memory) into an equivalent Dwarf representation of a 772050397Sobrien mechanism for getting the address of that same variable onto the top of a 772150397Sobrien hypothetical "address evaluation" stack. 772250397Sobrien 772350397Sobrien When creating memory location descriptors, we are effectively transforming 772450397Sobrien the RTL for a memory-resident object into its Dwarf postfix expression 772550397Sobrien equivalent. This routine recursively descends an RTL tree, turning 772690075Sobrien it into Dwarf postfix code as it goes. 772750397Sobrien 772890075Sobrien MODE is the mode of the memory reference, needed to handle some 772990075Sobrien autoincrement addressing modes. 773090075Sobrien 773190075Sobrien Return 0 if we can't represent the location. */ 773290075Sobrien 773350397Sobrienstatic dw_loc_descr_ref 773490075Sobrienmem_loc_descriptor (rtl, mode) 773590075Sobrien rtx rtl; 773690075Sobrien enum machine_mode mode; 773750397Sobrien{ 773850397Sobrien dw_loc_descr_ref mem_loc_result = NULL; 773990075Sobrien 774090075Sobrien /* Note that for a dynamically sized array, the location we will generate a 774150397Sobrien description of here will be the lowest numbered location which is 774250397Sobrien actually within the array. That's *not* necessarily the same as the 774350397Sobrien zeroth element of the array. */ 774450397Sobrien 774590075Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 774690075Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 774790075Sobrien#endif 774890075Sobrien 774950397Sobrien switch (GET_CODE (rtl)) 775050397Sobrien { 775190075Sobrien case POST_INC: 775290075Sobrien case POST_DEC: 775390075Sobrien case POST_MODIFY: 775490075Sobrien /* POST_INC and POST_DEC can be handled just like a SUBREG. So we 775590075Sobrien just fall into the SUBREG code. */ 775690075Sobrien 775790075Sobrien /* ... fall through ... */ 775890075Sobrien 775950397Sobrien case SUBREG: 776050397Sobrien /* The case of a subreg may arise when we have a local (register) 776150397Sobrien variable or a formal (register) parameter which doesn't quite fill 776250397Sobrien up an entire register. For now, just assume that it is 776350397Sobrien legitimate to make the Dwarf info refer to the whole register which 776450397Sobrien contains the given subreg. */ 776590075Sobrien rtl = SUBREG_REG (rtl); 776650397Sobrien 776790075Sobrien /* ... fall through ... */ 776850397Sobrien 776950397Sobrien case REG: 777050397Sobrien /* Whenever a register number forms a part of the description of the 777150397Sobrien method for calculating the (dynamic) address of a memory resident 777290075Sobrien object, DWARF rules require the register number be referred to as 777350397Sobrien a "base register". This distinction is not based in any way upon 777450397Sobrien what category of register the hardware believes the given register 777550397Sobrien belongs to. This is strictly DWARF terminology we're dealing with 777650397Sobrien here. Note that in cases where the location of a memory-resident 777750397Sobrien data object could be expressed as: OP_ADD (OP_BASEREG (basereg), 777850397Sobrien OP_CONST (0)) the actual DWARF location descriptor that we generate 777950397Sobrien may just be OP_BASEREG (basereg). This may look deceptively like 778050397Sobrien the object in question was allocated to a register (rather than in 778150397Sobrien memory) so DWARF consumers need to be aware of the subtle 778250397Sobrien distinction between OP_REG and OP_BASEREG. */ 778390075Sobrien if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) 778490075Sobrien mem_loc_result = based_loc_descr (reg_number (rtl), 0); 778550397Sobrien break; 778650397Sobrien 778750397Sobrien case MEM: 778890075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 778990075Sobrien if (mem_loc_result != 0) 779090075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); 779150397Sobrien break; 779250397Sobrien 779390075Sobrien case LABEL_REF: 779490075Sobrien /* Some ports can transform a symbol ref into a label ref, because 779590075Sobrien the symbol ref is too far away and has to be dumped into a constant 779690075Sobrien pool. */ 779750397Sobrien case CONST: 779850397Sobrien case SYMBOL_REF: 779990075Sobrien /* Alternatively, the symbol in the constant pool might be referenced 780090075Sobrien by a different symbol. */ 780190075Sobrien if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl)) 780290075Sobrien { 780396263Sobrien bool marked; 780496263Sobrien rtx tmp = get_pool_constant_mark (rtl, &marked); 780590075Sobrien 780690075Sobrien if (GET_CODE (tmp) == SYMBOL_REF) 780796263Sobrien { 780896263Sobrien rtl = tmp; 780996263Sobrien if (CONSTANT_POOL_ADDRESS_P (tmp)) 781096263Sobrien get_pool_constant_mark (tmp, &marked); 781196263Sobrien else 781296263Sobrien marked = true; 781396263Sobrien } 781496263Sobrien 781596263Sobrien /* If all references to this pool constant were optimized away, 781696263Sobrien it was not output and thus we can't represent it. 781796263Sobrien FIXME: might try to use DW_OP_const_value here, though 781896263Sobrien DW_OP_piece complicates it. */ 781996263Sobrien if (!marked) 782096263Sobrien return 0; 782190075Sobrien } 782290075Sobrien 782350397Sobrien mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); 782450397Sobrien mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; 782590075Sobrien mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl; 782690075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 782750397Sobrien break; 782850397Sobrien 782990075Sobrien case PRE_MODIFY: 783090075Sobrien /* Extract the PLUS expression nested inside and fall into 783190075Sobrien PLUS code below. */ 783290075Sobrien rtl = XEXP (rtl, 1); 783390075Sobrien goto plus; 783490075Sobrien 783590075Sobrien case PRE_INC: 783690075Sobrien case PRE_DEC: 783790075Sobrien /* Turn these into a PLUS expression and fall into the PLUS code 783890075Sobrien below. */ 783990075Sobrien rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0), 784090075Sobrien GEN_INT (GET_CODE (rtl) == PRE_INC 784190075Sobrien ? GET_MODE_UNIT_SIZE (mode) 784290075Sobrien : -GET_MODE_UNIT_SIZE (mode))); 784390075Sobrien 784490075Sobrien /* ... fall through ... */ 784590075Sobrien 784650397Sobrien case PLUS: 784790075Sobrien plus: 784850397Sobrien if (is_based_loc (rtl)) 784950397Sobrien mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), 785050397Sobrien INTVAL (XEXP (rtl, 1))); 785150397Sobrien else 785250397Sobrien { 785390075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode); 785490075Sobrien if (mem_loc_result == 0) 785590075Sobrien break; 785690075Sobrien 785790075Sobrien if (GET_CODE (XEXP (rtl, 1)) == CONST_INT 785890075Sobrien && INTVAL (XEXP (rtl, 1)) >= 0) 785990075Sobrien add_loc_descr (&mem_loc_result, 786090075Sobrien new_loc_descr (DW_OP_plus_uconst, 786190075Sobrien INTVAL (XEXP (rtl, 1)), 0)); 786290075Sobrien else 786390075Sobrien { 786490075Sobrien add_loc_descr (&mem_loc_result, 786590075Sobrien mem_loc_descriptor (XEXP (rtl, 1), mode)); 786690075Sobrien add_loc_descr (&mem_loc_result, 786790075Sobrien new_loc_descr (DW_OP_plus, 0, 0)); 786890075Sobrien } 786950397Sobrien } 787050397Sobrien break; 787150397Sobrien 787250397Sobrien case MULT: 787390075Sobrien { 787490075Sobrien /* If a pseudo-reg is optimized away, it is possible for it to 787590075Sobrien be replaced with a MEM containing a multiply. */ 787690075Sobrien dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); 787790075Sobrien dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); 787850397Sobrien 787990075Sobrien if (op0 == 0 || op1 == 0) 788090075Sobrien break; 788190075Sobrien 788290075Sobrien mem_loc_result = op0; 788390075Sobrien add_loc_descr (&mem_loc_result, op1); 788490075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); 788590075Sobrien break; 788690075Sobrien } 788790075Sobrien 788850397Sobrien case CONST_INT: 788990075Sobrien mem_loc_result = int_loc_descriptor (INTVAL (rtl)); 789050397Sobrien break; 789150397Sobrien 789290075Sobrien case ADDRESSOF: 789390075Sobrien /* If this is a MEM, return its address. Otherwise, we can't 789490075Sobrien represent this. */ 789590075Sobrien if (GET_CODE (XEXP (rtl, 0)) == MEM) 789690075Sobrien return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode); 789790075Sobrien else 789890075Sobrien return 0; 789990075Sobrien 790050397Sobrien default: 790150397Sobrien abort (); 790250397Sobrien } 790350397Sobrien 790450397Sobrien return mem_loc_result; 790550397Sobrien} 790650397Sobrien 790750397Sobrien/* Return a descriptor that describes the concatenation of two locations. 790850397Sobrien This is typically a complex variable. */ 790950397Sobrien 791050397Sobrienstatic dw_loc_descr_ref 791150397Sobrienconcat_loc_descriptor (x0, x1) 791290075Sobrien rtx x0, x1; 791350397Sobrien{ 791450397Sobrien dw_loc_descr_ref cc_loc_result = NULL; 791590075Sobrien dw_loc_descr_ref x0_ref = loc_descriptor (x0); 791690075Sobrien dw_loc_descr_ref x1_ref = loc_descriptor (x1); 791750397Sobrien 791890075Sobrien if (x0_ref == 0 || x1_ref == 0) 791990075Sobrien return 0; 792090075Sobrien 792190075Sobrien cc_loc_result = x0_ref; 792250397Sobrien add_loc_descr (&cc_loc_result, 792390075Sobrien new_loc_descr (DW_OP_piece, 792490075Sobrien GET_MODE_SIZE (GET_MODE (x0)), 0)); 792550397Sobrien 792690075Sobrien add_loc_descr (&cc_loc_result, x1_ref); 792750397Sobrien add_loc_descr (&cc_loc_result, 792890075Sobrien new_loc_descr (DW_OP_piece, 792990075Sobrien GET_MODE_SIZE (GET_MODE (x1)), 0)); 793050397Sobrien 793150397Sobrien return cc_loc_result; 793250397Sobrien} 793350397Sobrien 793450397Sobrien/* Output a proper Dwarf location descriptor for a variable or parameter 793550397Sobrien which is either allocated in a register or in a memory location. For a 793650397Sobrien register, we just generate an OP_REG and the register number. For a 793750397Sobrien memory location we provide a Dwarf postfix expression describing how to 793890075Sobrien generate the (dynamic) address of the object onto the address stack. 793950397Sobrien 794090075Sobrien If we don't know how to describe it, return 0. */ 794190075Sobrien 794250397Sobrienstatic dw_loc_descr_ref 794350397Sobrienloc_descriptor (rtl) 794490075Sobrien rtx rtl; 794550397Sobrien{ 794650397Sobrien dw_loc_descr_ref loc_result = NULL; 794790075Sobrien 794850397Sobrien switch (GET_CODE (rtl)) 794950397Sobrien { 795050397Sobrien case SUBREG: 795150397Sobrien /* The case of a subreg may arise when we have a local (register) 795250397Sobrien variable or a formal (register) parameter which doesn't quite fill 795350397Sobrien up an entire register. For now, just assume that it is 795450397Sobrien legitimate to make the Dwarf info refer to the whole register which 795550397Sobrien contains the given subreg. */ 795690075Sobrien rtl = SUBREG_REG (rtl); 795750397Sobrien 795890075Sobrien /* ... fall through ... */ 795950397Sobrien 796050397Sobrien case REG: 796150397Sobrien loc_result = reg_loc_descriptor (rtl); 796250397Sobrien break; 796350397Sobrien 796450397Sobrien case MEM: 796590075Sobrien loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 796650397Sobrien break; 796750397Sobrien 796850397Sobrien case CONCAT: 796950397Sobrien loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); 797050397Sobrien break; 797150397Sobrien 797250397Sobrien default: 797350397Sobrien abort (); 797450397Sobrien } 797550397Sobrien 797650397Sobrien return loc_result; 797750397Sobrien} 797850397Sobrien 797990075Sobrien/* Similar, but generate the descriptor from trees instead of rtl. This comes 798090075Sobrien up particularly with variable length arrays. If ADDRESSP is nonzero, we are 798190075Sobrien looking for an address. Otherwise, we return a value. If we can't make a 798290075Sobrien descriptor, return 0. */ 798390075Sobrien 798490075Sobrienstatic dw_loc_descr_ref 798590075Sobrienloc_descriptor_from_tree (loc, addressp) 798690075Sobrien tree loc; 798790075Sobrien int addressp; 798890075Sobrien{ 798990075Sobrien dw_loc_descr_ref ret, ret1; 799090075Sobrien int indirect_p = 0; 799190075Sobrien int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc)); 799290075Sobrien enum dwarf_location_atom op; 799390075Sobrien 799490075Sobrien /* ??? Most of the time we do not take proper care for sign/zero 799590075Sobrien extending the values properly. Hopefully this won't be a real 799690075Sobrien problem... */ 799790075Sobrien 799890075Sobrien switch (TREE_CODE (loc)) 799990075Sobrien { 800090075Sobrien case ERROR_MARK: 800190075Sobrien return 0; 800290075Sobrien 800390075Sobrien case WITH_RECORD_EXPR: 800490075Sobrien case PLACEHOLDER_EXPR: 800590075Sobrien /* This case involves extracting fields from an object to determine the 800690075Sobrien position of other fields. We don't try to encode this here. The 800790075Sobrien only user of this is Ada, which encodes the needed information using 800890075Sobrien the names of types. */ 800990075Sobrien return 0; 801090075Sobrien 801190075Sobrien case CALL_EXPR: 801290075Sobrien return 0; 801390075Sobrien 801490075Sobrien case ADDR_EXPR: 801590075Sobrien /* We can support this only if we can look through conversions and 801690075Sobrien find an INDIRECT_EXPR. */ 801790075Sobrien for (loc = TREE_OPERAND (loc, 0); 801890075Sobrien TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR 801990075Sobrien || TREE_CODE (loc) == NON_LVALUE_EXPR 802090075Sobrien || TREE_CODE (loc) == VIEW_CONVERT_EXPR 802190075Sobrien || TREE_CODE (loc) == SAVE_EXPR; 802290075Sobrien loc = TREE_OPERAND (loc, 0)) 802390075Sobrien ; 802490075Sobrien 802590075Sobrien return (TREE_CODE (loc) == INDIRECT_REF 802690075Sobrien ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp) 802790075Sobrien : 0); 802890075Sobrien 802990075Sobrien case VAR_DECL: 803090075Sobrien case PARM_DECL: 803190075Sobrien { 803290075Sobrien rtx rtl = rtl_for_decl_location (loc); 803390075Sobrien 803490075Sobrien if (rtl == NULL_RTX) 803590075Sobrien return 0; 803690075Sobrien else if (CONSTANT_P (rtl)) 803790075Sobrien { 803890075Sobrien ret = new_loc_descr (DW_OP_addr, 0, 0); 803990075Sobrien ret->dw_loc_oprnd1.val_class = dw_val_class_addr; 804090075Sobrien ret->dw_loc_oprnd1.v.val_addr = rtl; 804190075Sobrien indirect_p = 1; 804290075Sobrien } 804390075Sobrien else 804490075Sobrien { 804590075Sobrien enum machine_mode mode = GET_MODE (rtl); 804690075Sobrien 804790075Sobrien if (GET_CODE (rtl) == MEM) 804890075Sobrien { 804990075Sobrien indirect_p = 1; 805090075Sobrien rtl = XEXP (rtl, 0); 805190075Sobrien } 805290075Sobrien 805390075Sobrien ret = mem_loc_descriptor (rtl, mode); 805490075Sobrien } 805590075Sobrien } 805690075Sobrien break; 805790075Sobrien 805890075Sobrien case INDIRECT_REF: 805990075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 806090075Sobrien indirect_p = 1; 806190075Sobrien break; 806290075Sobrien 806390075Sobrien case COMPOUND_EXPR: 806490075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp); 806590075Sobrien 806690075Sobrien case NOP_EXPR: 806790075Sobrien case CONVERT_EXPR: 806890075Sobrien case NON_LVALUE_EXPR: 806990075Sobrien case VIEW_CONVERT_EXPR: 807090075Sobrien case SAVE_EXPR: 807190075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); 807290075Sobrien 807390075Sobrien case COMPONENT_REF: 807490075Sobrien case BIT_FIELD_REF: 807590075Sobrien case ARRAY_REF: 807690075Sobrien case ARRAY_RANGE_REF: 807790075Sobrien { 807890075Sobrien tree obj, offset; 807990075Sobrien HOST_WIDE_INT bitsize, bitpos, bytepos; 808090075Sobrien enum machine_mode mode; 808190075Sobrien int volatilep; 808290075Sobrien 808390075Sobrien obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, 808490075Sobrien &unsignedp, &volatilep); 808590075Sobrien 808690075Sobrien if (obj == loc) 808790075Sobrien return 0; 808890075Sobrien 808990075Sobrien ret = loc_descriptor_from_tree (obj, 1); 809090075Sobrien if (ret == 0 809190075Sobrien || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0) 809290075Sobrien return 0; 809390075Sobrien 809490075Sobrien if (offset != NULL_TREE) 809590075Sobrien { 809690075Sobrien /* Variable offset. */ 809790075Sobrien add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0)); 809890075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 809990075Sobrien } 810090075Sobrien 810190075Sobrien if (!addressp) 810290075Sobrien indirect_p = 1; 810390075Sobrien 810490075Sobrien bytepos = bitpos / BITS_PER_UNIT; 810590075Sobrien if (bytepos > 0) 810690075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); 810790075Sobrien else if (bytepos < 0) 810890075Sobrien { 810990075Sobrien add_loc_descr (&ret, int_loc_descriptor (bytepos)); 811090075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 811190075Sobrien } 811290075Sobrien break; 811390075Sobrien } 811490075Sobrien 811590075Sobrien case INTEGER_CST: 811690075Sobrien if (host_integerp (loc, 0)) 811790075Sobrien ret = int_loc_descriptor (tree_low_cst (loc, 0)); 811890075Sobrien else 811990075Sobrien return 0; 812090075Sobrien break; 812190075Sobrien 812290075Sobrien case TRUTH_AND_EXPR: 812390075Sobrien case TRUTH_ANDIF_EXPR: 812490075Sobrien case BIT_AND_EXPR: 812590075Sobrien op = DW_OP_and; 812690075Sobrien goto do_binop; 812790075Sobrien 812890075Sobrien case TRUTH_XOR_EXPR: 812990075Sobrien case BIT_XOR_EXPR: 813090075Sobrien op = DW_OP_xor; 813190075Sobrien goto do_binop; 813290075Sobrien 813390075Sobrien case TRUTH_OR_EXPR: 813490075Sobrien case TRUTH_ORIF_EXPR: 813590075Sobrien case BIT_IOR_EXPR: 813690075Sobrien op = DW_OP_or; 813790075Sobrien goto do_binop; 813890075Sobrien 813990075Sobrien case TRUNC_DIV_EXPR: 814090075Sobrien op = DW_OP_div; 814190075Sobrien goto do_binop; 814290075Sobrien 814390075Sobrien case MINUS_EXPR: 814490075Sobrien op = DW_OP_minus; 814590075Sobrien goto do_binop; 814690075Sobrien 814790075Sobrien case TRUNC_MOD_EXPR: 814890075Sobrien op = DW_OP_mod; 814990075Sobrien goto do_binop; 815090075Sobrien 815190075Sobrien case MULT_EXPR: 815290075Sobrien op = DW_OP_mul; 815390075Sobrien goto do_binop; 815490075Sobrien 815590075Sobrien case LSHIFT_EXPR: 815690075Sobrien op = DW_OP_shl; 815790075Sobrien goto do_binop; 815890075Sobrien 815990075Sobrien case RSHIFT_EXPR: 816090075Sobrien op = (unsignedp ? DW_OP_shr : DW_OP_shra); 816190075Sobrien goto do_binop; 816290075Sobrien 816390075Sobrien case PLUS_EXPR: 816490075Sobrien if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST 816590075Sobrien && host_integerp (TREE_OPERAND (loc, 1), 0)) 816690075Sobrien { 816790075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 816890075Sobrien if (ret == 0) 816990075Sobrien return 0; 817090075Sobrien 817190075Sobrien add_loc_descr (&ret, 817290075Sobrien new_loc_descr (DW_OP_plus_uconst, 817390075Sobrien tree_low_cst (TREE_OPERAND (loc, 1), 817490075Sobrien 0), 817590075Sobrien 0)); 817690075Sobrien break; 817790075Sobrien } 817890075Sobrien 817990075Sobrien op = DW_OP_plus; 818090075Sobrien goto do_binop; 818190075Sobrien 818290075Sobrien case LE_EXPR: 818390075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 818490075Sobrien return 0; 818590075Sobrien 818690075Sobrien op = DW_OP_le; 818790075Sobrien goto do_binop; 818890075Sobrien 818990075Sobrien case GE_EXPR: 819090075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 819190075Sobrien return 0; 819290075Sobrien 819390075Sobrien op = DW_OP_ge; 819490075Sobrien goto do_binop; 819590075Sobrien 819690075Sobrien case LT_EXPR: 819790075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 819890075Sobrien return 0; 819990075Sobrien 820090075Sobrien op = DW_OP_lt; 820190075Sobrien goto do_binop; 820290075Sobrien 820390075Sobrien case GT_EXPR: 820490075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 820590075Sobrien return 0; 820690075Sobrien 820790075Sobrien op = DW_OP_gt; 820890075Sobrien goto do_binop; 820990075Sobrien 821090075Sobrien case EQ_EXPR: 821190075Sobrien op = DW_OP_eq; 821290075Sobrien goto do_binop; 821390075Sobrien 821490075Sobrien case NE_EXPR: 821590075Sobrien op = DW_OP_ne; 821690075Sobrien goto do_binop; 821790075Sobrien 821890075Sobrien do_binop: 821990075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 822090075Sobrien ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 822190075Sobrien if (ret == 0 || ret1 == 0) 822290075Sobrien return 0; 822390075Sobrien 822490075Sobrien add_loc_descr (&ret, ret1); 822590075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 822690075Sobrien break; 822790075Sobrien 822890075Sobrien case TRUTH_NOT_EXPR: 822990075Sobrien case BIT_NOT_EXPR: 823090075Sobrien op = DW_OP_not; 823190075Sobrien goto do_unop; 823290075Sobrien 823390075Sobrien case ABS_EXPR: 823490075Sobrien op = DW_OP_abs; 823590075Sobrien goto do_unop; 823690075Sobrien 823790075Sobrien case NEGATE_EXPR: 823890075Sobrien op = DW_OP_neg; 823990075Sobrien goto do_unop; 824090075Sobrien 824190075Sobrien do_unop: 824290075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 824390075Sobrien if (ret == 0) 824490075Sobrien return 0; 824590075Sobrien 824690075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 824790075Sobrien break; 824890075Sobrien 824990075Sobrien case MAX_EXPR: 825090075Sobrien loc = build (COND_EXPR, TREE_TYPE (loc), 825190075Sobrien build (LT_EXPR, integer_type_node, 825290075Sobrien TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)), 825390075Sobrien TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0)); 825490075Sobrien 825590075Sobrien /* ... fall through ... */ 825690075Sobrien 825790075Sobrien case COND_EXPR: 825890075Sobrien { 825990075Sobrien dw_loc_descr_ref lhs 826090075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 826190075Sobrien dw_loc_descr_ref rhs 826290075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0); 826390075Sobrien dw_loc_descr_ref bra_node, jump_node, tmp; 826490075Sobrien 826590075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 826690075Sobrien if (ret == 0 || lhs == 0 || rhs == 0) 826790075Sobrien return 0; 826890075Sobrien 826990075Sobrien bra_node = new_loc_descr (DW_OP_bra, 0, 0); 827090075Sobrien add_loc_descr (&ret, bra_node); 827190075Sobrien 827290075Sobrien add_loc_descr (&ret, rhs); 827390075Sobrien jump_node = new_loc_descr (DW_OP_skip, 0, 0); 827490075Sobrien add_loc_descr (&ret, jump_node); 827590075Sobrien 827690075Sobrien add_loc_descr (&ret, lhs); 827790075Sobrien bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 827890075Sobrien bra_node->dw_loc_oprnd1.v.val_loc = lhs; 827990075Sobrien 828090075Sobrien /* ??? Need a node to point the skip at. Use a nop. */ 828190075Sobrien tmp = new_loc_descr (DW_OP_nop, 0, 0); 828290075Sobrien add_loc_descr (&ret, tmp); 828390075Sobrien jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 828490075Sobrien jump_node->dw_loc_oprnd1.v.val_loc = tmp; 828590075Sobrien } 828690075Sobrien break; 828790075Sobrien 828890075Sobrien default: 828990075Sobrien abort (); 829090075Sobrien } 829190075Sobrien 829290075Sobrien /* Show if we can't fill the request for an address. */ 829390075Sobrien if (addressp && indirect_p == 0) 829490075Sobrien return 0; 829590075Sobrien 829690075Sobrien /* If we've got an address and don't want one, dereference. */ 829790075Sobrien if (!addressp && indirect_p > 0) 829890075Sobrien { 829990075Sobrien HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc)); 830090075Sobrien 830190075Sobrien if (size > DWARF2_ADDR_SIZE || size == -1) 830290075Sobrien return 0; 830390075Sobrien else if (size == DWARF2_ADDR_SIZE) 830490075Sobrien op = DW_OP_deref; 830590075Sobrien else 830690075Sobrien op = DW_OP_deref_size; 830790075Sobrien 830890075Sobrien add_loc_descr (&ret, new_loc_descr (op, size, 0)); 830990075Sobrien } 831090075Sobrien 831190075Sobrien return ret; 831290075Sobrien} 831390075Sobrien 831490075Sobrien/* Given a value, round it up to the lowest multiple of `boundary' 831550397Sobrien which is not less than the value itself. */ 831650397Sobrien 831790075Sobrienstatic inline HOST_WIDE_INT 831850397Sobrienceiling (value, boundary) 831990075Sobrien HOST_WIDE_INT value; 832090075Sobrien unsigned int boundary; 832150397Sobrien{ 832250397Sobrien return (((value + boundary - 1) / boundary) * boundary); 832350397Sobrien} 832450397Sobrien 832550397Sobrien/* Given a pointer to what is assumed to be a FIELD_DECL node, return a 832650397Sobrien pointer to the declared type for the relevant field variable, or return 832750397Sobrien `integer_type_node' if the given node turns out to be an 832850397Sobrien ERROR_MARK node. */ 832950397Sobrien 833050397Sobrienstatic inline tree 833150397Sobrienfield_type (decl) 833290075Sobrien tree decl; 833350397Sobrien{ 833490075Sobrien tree type; 833550397Sobrien 833650397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 833750397Sobrien return integer_type_node; 833850397Sobrien 833950397Sobrien type = DECL_BIT_FIELD_TYPE (decl); 834050397Sobrien if (type == NULL_TREE) 834150397Sobrien type = TREE_TYPE (decl); 834250397Sobrien 834350397Sobrien return type; 834450397Sobrien} 834550397Sobrien 834690075Sobrien/* Given a pointer to a tree node, return the alignment in bits for 834790075Sobrien it, or else return BITS_PER_WORD if the node actually turns out to 834890075Sobrien be an ERROR_MARK node. */ 834950397Sobrien 835050397Sobrienstatic inline unsigned 835150397Sobriensimple_type_align_in_bits (type) 835290075Sobrien tree type; 835350397Sobrien{ 835450397Sobrien return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; 835550397Sobrien} 835650397Sobrien 835790075Sobrienstatic inline unsigned 835896263Sobriensimple_field_decl_align_in_bits (field) 835996263Sobrien tree field; 836090075Sobrien{ 836196263Sobrien unsigned align; 836296263Sobrien 836396263Sobrien if (TREE_CODE (field) == ERROR_MARK) 836496263Sobrien return BITS_PER_WORD; 836596263Sobrien 836696263Sobrien align = DECL_ALIGN (field); 836796263Sobrien 836896263Sobrien#ifdef BIGGEST_FIELD_ALIGNMENT 836996263Sobrien /* Some targets (i.e. i386) limit union field alignment 837096263Sobrien to a lower boundary than alignment of variables unless 837196263Sobrien it was overridden by attribute aligned. */ 837296263Sobrien if (! DECL_USER_ALIGN (field)) 837396263Sobrien align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); 837496263Sobrien#endif 837596263Sobrien 837696263Sobrien#ifdef ADJUST_FIELD_ALIGN 837796263Sobrien align = ADJUST_FIELD_ALIGN (field, align); 837896263Sobrien#endif 837996263Sobrien return align; 838090075Sobrien} 838190075Sobrien 838250397Sobrien/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE 838350397Sobrien node, return the size in bits for the type if it is a constant, or else 838450397Sobrien return the alignment for the type if the type's size is not constant, or 838550397Sobrien else return BITS_PER_WORD if the type actually turns out to be an 838650397Sobrien ERROR_MARK node. */ 838750397Sobrien 838890075Sobrienstatic inline unsigned HOST_WIDE_INT 838950397Sobriensimple_type_size_in_bits (type) 839090075Sobrien tree type; 839150397Sobrien{ 839290075Sobrien 839350397Sobrien if (TREE_CODE (type) == ERROR_MARK) 839450397Sobrien return BITS_PER_WORD; 839590075Sobrien else if (TYPE_SIZE (type) == NULL_TREE) 839690075Sobrien return 0; 839790075Sobrien else if (host_integerp (TYPE_SIZE (type), 1)) 839890075Sobrien return tree_low_cst (TYPE_SIZE (type), 1); 839950397Sobrien else 840090075Sobrien return TYPE_ALIGN (type); 840150397Sobrien} 840250397Sobrien 840390075Sobrien/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the 840490075Sobrien lowest addressed byte of the "containing object" for the given FIELD_DECL, 840590075Sobrien or return 0 if we are unable to determine what that offset is, either 840690075Sobrien because the argument turns out to be a pointer to an ERROR_MARK node, or 840790075Sobrien because the offset is actually variable. (We can't handle the latter case 840890075Sobrien just yet). */ 840950397Sobrien 841090075Sobrienstatic HOST_WIDE_INT 841150397Sobrienfield_byte_offset (decl) 841290075Sobrien tree decl; 841350397Sobrien{ 841490075Sobrien unsigned int type_align_in_bits; 841590075Sobrien unsigned int decl_align_in_bits; 841690075Sobrien unsigned HOST_WIDE_INT type_size_in_bits; 841790075Sobrien HOST_WIDE_INT object_offset_in_bits; 841890075Sobrien tree type; 841990075Sobrien tree field_size_tree; 842090075Sobrien HOST_WIDE_INT bitpos_int; 842190075Sobrien HOST_WIDE_INT deepest_bitpos; 842290075Sobrien unsigned HOST_WIDE_INT field_size_in_bits; 842350397Sobrien 842450397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 842550397Sobrien return 0; 842690075Sobrien else if (TREE_CODE (decl) != FIELD_DECL) 842750397Sobrien abort (); 842850397Sobrien 842950397Sobrien type = field_type (decl); 843050397Sobrien field_size_tree = DECL_SIZE (decl); 843150397Sobrien 843290075Sobrien /* The size could be unspecified if there was an error, or for 843390075Sobrien a flexible array member. */ 843490075Sobrien if (! field_size_tree) 843590075Sobrien field_size_tree = bitsize_zero_node; 843690075Sobrien 843790075Sobrien /* We cannot yet cope with fields whose positions are variable, so 843850397Sobrien for now, when we see such things, we simply return 0. Someday, we may 843950397Sobrien be able to handle such cases, but it will be damn difficult. */ 844090075Sobrien if (! host_integerp (bit_position (decl), 0)) 844150397Sobrien return 0; 844250397Sobrien 844390075Sobrien bitpos_int = int_bit_position (decl); 844450397Sobrien 844590075Sobrien /* If we don't know the size of the field, pretend it's a full word. */ 844690075Sobrien if (host_integerp (field_size_tree, 1)) 844790075Sobrien field_size_in_bits = tree_low_cst (field_size_tree, 1); 844890075Sobrien else 844990075Sobrien field_size_in_bits = BITS_PER_WORD; 845090075Sobrien 845150397Sobrien type_size_in_bits = simple_type_size_in_bits (type); 845250397Sobrien type_align_in_bits = simple_type_align_in_bits (type); 845396263Sobrien decl_align_in_bits = simple_field_decl_align_in_bits (decl); 845450397Sobrien 845590075Sobrien /* The GCC front-end doesn't make any attempt to keep track of the starting 845690075Sobrien bit offset (relative to the start of the containing structure type) of the 845790075Sobrien hypothetical "containing object" for a bit-field. Thus, when computing 845890075Sobrien the byte offset value for the start of the "containing object" of a 845990075Sobrien bit-field, we must deduce this information on our own. This can be rather 846090075Sobrien tricky to do in some cases. For example, handling the following structure 846190075Sobrien type definition when compiling for an i386/i486 target (which only aligns 846290075Sobrien long long's to 32-bit boundaries) can be very tricky: 846350397Sobrien 846450397Sobrien struct S { int field1; long long field2:31; }; 846550397Sobrien 846690075Sobrien Fortunately, there is a simple rule-of-thumb which can be used in such 846790075Sobrien cases. When compiling for an i386/i486, GCC will allocate 8 bytes for the 846890075Sobrien structure shown above. It decides to do this based upon one simple rule 846990075Sobrien for bit-field allocation. GCC allocates each "containing object" for each 847090075Sobrien bit-field at the first (i.e. lowest addressed) legitimate alignment 847190075Sobrien boundary (based upon the required minimum alignment for the declared type 847290075Sobrien of the field) which it can possibly use, subject to the condition that 847390075Sobrien there is still enough available space remaining in the containing object 847490075Sobrien (when allocated at the selected point) to fully accommodate all of the 847590075Sobrien bits of the bit-field itself. 847650397Sobrien 847790075Sobrien This simple rule makes it obvious why GCC allocates 8 bytes for each 847890075Sobrien object of the structure type shown above. When looking for a place to 847990075Sobrien allocate the "containing object" for `field2', the compiler simply tries 848090075Sobrien to allocate a 64-bit "containing object" at each successive 32-bit 848190075Sobrien boundary (starting at zero) until it finds a place to allocate that 64- 848290075Sobrien bit field such that at least 31 contiguous (and previously unallocated) 848390075Sobrien bits remain within that selected 64 bit field. (As it turns out, for the 848490075Sobrien example above, the compiler finds it is OK to allocate the "containing 848590075Sobrien object" 64-bit field at bit-offset zero within the structure type.) 848690075Sobrien 848790075Sobrien Here we attempt to work backwards from the limited set of facts we're 848890075Sobrien given, and we try to deduce from those facts, where GCC must have believed 848990075Sobrien that the containing object started (within the structure type). The value 849090075Sobrien we deduce is then used (by the callers of this routine) to generate 849190075Sobrien DW_AT_location and DW_AT_bit_offset attributes for fields (both bit-fields 849290075Sobrien and, in the case of DW_AT_location, regular fields as well). */ 849390075Sobrien 849450397Sobrien /* Figure out the bit-distance from the start of the structure to the 849550397Sobrien "deepest" bit of the bit-field. */ 849650397Sobrien deepest_bitpos = bitpos_int + field_size_in_bits; 849750397Sobrien 849850397Sobrien /* This is the tricky part. Use some fancy footwork to deduce where the 849950397Sobrien lowest addressed bit of the containing object must be. */ 850090075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 850150397Sobrien 850290075Sobrien /* Round up to type_align by default. This works best for bitfields. */ 850390075Sobrien object_offset_in_bits += type_align_in_bits - 1; 850490075Sobrien object_offset_in_bits /= type_align_in_bits; 850590075Sobrien object_offset_in_bits *= type_align_in_bits; 850650397Sobrien 850790075Sobrien if (object_offset_in_bits > bitpos_int) 850890075Sobrien { 850990075Sobrien /* Sigh, the decl must be packed. */ 851090075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 851150397Sobrien 851290075Sobrien /* Round up to decl_align instead. */ 851390075Sobrien object_offset_in_bits += decl_align_in_bits - 1; 851490075Sobrien object_offset_in_bits /= decl_align_in_bits; 851590075Sobrien object_offset_in_bits *= decl_align_in_bits; 851690075Sobrien } 851790075Sobrien 851890075Sobrien return object_offset_in_bits / BITS_PER_UNIT; 851950397Sobrien} 852050397Sobrien 852150397Sobrien/* The following routines define various Dwarf attributes and any data 852250397Sobrien associated with them. */ 852350397Sobrien 852450397Sobrien/* Add a location description attribute value to a DIE. 852550397Sobrien 852650397Sobrien This emits location attributes suitable for whole variables and 852750397Sobrien whole parameters. Note that the location attributes for struct fields are 852850397Sobrien generated by the routine `data_member_location_attribute' below. */ 852950397Sobrien 853050397Sobrienstatic void 853150397Sobrienadd_AT_location_description (die, attr_kind, rtl) 853250397Sobrien dw_die_ref die; 853350397Sobrien enum dwarf_attribute attr_kind; 853490075Sobrien rtx rtl; 853550397Sobrien{ 853690075Sobrien dw_loc_descr_ref descr = loc_descriptor (rtl); 853750397Sobrien 853890075Sobrien if (descr != 0) 853990075Sobrien add_AT_loc (die, attr_kind, descr); 854050397Sobrien} 854150397Sobrien 854290075Sobrien/* Attach the specialized form of location attribute used for data members of 854390075Sobrien struct and union types. In the special case of a FIELD_DECL node which 854490075Sobrien represents a bit-field, the "offset" part of this special location 854590075Sobrien descriptor must indicate the distance in bytes from the lowest-addressed 854690075Sobrien byte of the containing struct or union type to the lowest-addressed byte of 854790075Sobrien the "containing object" for the bit-field. (See the `field_byte_offset' 854890075Sobrien function above). 854950397Sobrien 855090075Sobrien For any given bit-field, the "containing object" is a hypothetical object 855190075Sobrien (of some integral or enum type) within which the given bit-field lives. The 855290075Sobrien type of this hypothetical "containing object" is always the same as the 855390075Sobrien declared type of the individual bit-field itself (for GCC anyway... the 855490075Sobrien DWARF spec doesn't actually mandate this). Note that it is the size (in 855590075Sobrien bytes) of the hypothetical "containing object" which will be given in the 855690075Sobrien DW_AT_byte_size attribute for this bit-field. (See the 855790075Sobrien `byte_size_attribute' function below.) It is also used when calculating the 855890075Sobrien value of the DW_AT_bit_offset attribute. (See the `bit_offset_attribute' 855990075Sobrien function below.) */ 856090075Sobrien 856150397Sobrienstatic void 856250397Sobrienadd_data_member_location_attribute (die, decl) 856390075Sobrien dw_die_ref die; 856490075Sobrien tree decl; 856550397Sobrien{ 856690075Sobrien long offset; 856790075Sobrien dw_loc_descr_ref loc_descr = 0; 856850397Sobrien 856950397Sobrien if (TREE_CODE (decl) == TREE_VEC) 857090075Sobrien { 857190075Sobrien /* We're working on the TAG_inheritance for a base class. */ 857290075Sobrien if (TREE_VIA_VIRTUAL (decl) && is_cxx ()) 857390075Sobrien { 857490075Sobrien /* For C++ virtual bases we can't just use BINFO_OFFSET, as they 857590075Sobrien aren't at a fixed offset from all (sub)objects of the same 857690075Sobrien type. We need to extract the appropriate offset from our 857790075Sobrien vtable. The following dwarf expression means 857890075Sobrien 857990075Sobrien BaseAddr = ObAddr + *((*ObAddr) - Offset) 858090075Sobrien 858190075Sobrien This is specific to the V3 ABI, of course. */ 858290075Sobrien 858390075Sobrien dw_loc_descr_ref tmp; 858490075Sobrien 858590075Sobrien /* Make a copy of the object address. */ 858690075Sobrien tmp = new_loc_descr (DW_OP_dup, 0, 0); 858790075Sobrien add_loc_descr (&loc_descr, tmp); 858890075Sobrien 858990075Sobrien /* Extract the vtable address. */ 859090075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 859190075Sobrien add_loc_descr (&loc_descr, tmp); 859290075Sobrien 859390075Sobrien /* Calculate the address of the offset. */ 859490075Sobrien offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0); 859590075Sobrien if (offset >= 0) 859690075Sobrien abort (); 859790075Sobrien 859890075Sobrien tmp = int_loc_descriptor (-offset); 859990075Sobrien add_loc_descr (&loc_descr, tmp); 860090075Sobrien tmp = new_loc_descr (DW_OP_minus, 0, 0); 860190075Sobrien add_loc_descr (&loc_descr, tmp); 860290075Sobrien 860390075Sobrien /* Extract the offset. */ 860490075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 860590075Sobrien add_loc_descr (&loc_descr, tmp); 860690075Sobrien 860790075Sobrien /* Add it to the object address. */ 860890075Sobrien tmp = new_loc_descr (DW_OP_plus, 0, 0); 860990075Sobrien add_loc_descr (&loc_descr, tmp); 861090075Sobrien } 861190075Sobrien else 861290075Sobrien offset = tree_low_cst (BINFO_OFFSET (decl), 0); 861390075Sobrien } 861450397Sobrien else 861550397Sobrien offset = field_byte_offset (decl); 861650397Sobrien 861790075Sobrien if (! loc_descr) 861890075Sobrien { 861990075Sobrien enum dwarf_location_atom op; 862050397Sobrien 862190075Sobrien /* The DWARF2 standard says that we should assume that the structure 862290075Sobrien address is already on the stack, so we can specify a structure field 862390075Sobrien address by using DW_OP_plus_uconst. */ 862490075Sobrien 862550397Sobrien#ifdef MIPS_DEBUGGING_INFO 862690075Sobrien /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst 862790075Sobrien operator correctly. It works only if we leave the offset on the 862890075Sobrien stack. */ 862990075Sobrien op = DW_OP_constu; 863050397Sobrien#else 863190075Sobrien op = DW_OP_plus_uconst; 863250397Sobrien#endif 863350397Sobrien 863490075Sobrien loc_descr = new_loc_descr (op, offset, 0); 863590075Sobrien } 863690075Sobrien 863750397Sobrien add_AT_loc (die, DW_AT_data_member_location, loc_descr); 863850397Sobrien} 863950397Sobrien 864050397Sobrien/* Attach an DW_AT_const_value attribute for a variable or a parameter which 864150397Sobrien does not have a "location" either in memory or in a register. These 864250397Sobrien things can arise in GNU C when a constant is passed as an actual parameter 864350397Sobrien to an inlined function. They can also arise in C++ where declared 864450397Sobrien constants do not necessarily get memory "homes". */ 864550397Sobrien 864650397Sobrienstatic void 864750397Sobrienadd_const_value_attribute (die, rtl) 864890075Sobrien dw_die_ref die; 864990075Sobrien rtx rtl; 865050397Sobrien{ 865150397Sobrien switch (GET_CODE (rtl)) 865250397Sobrien { 865350397Sobrien case CONST_INT: 865490075Sobrien /* Note that a CONST_INT rtx could represent either an integer 865590075Sobrien or a floating-point constant. A CONST_INT is used whenever 865690075Sobrien the constant will fit into a single word. In all such 865790075Sobrien cases, the original mode of the constant value is wiped 865890075Sobrien out, and the CONST_INT rtx is assigned VOIDmode. */ 865990075Sobrien { 866090075Sobrien HOST_WIDE_INT val = INTVAL (rtl); 866190075Sobrien 866290075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 866390075Sobrien if (val < 0 && (long) val == val) 866490075Sobrien add_AT_int (die, DW_AT_const_value, (long) val); 866590075Sobrien else if ((unsigned long) val == (unsigned HOST_WIDE_INT) val) 866690075Sobrien add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val); 866790075Sobrien else 866890075Sobrien { 866990075Sobrien#if HOST_BITS_PER_LONG * 2 == HOST_BITS_PER_WIDE_INT 867090075Sobrien add_AT_long_long (die, DW_AT_const_value, 867190075Sobrien val >> HOST_BITS_PER_LONG, val); 867290075Sobrien#else 867390075Sobrien abort (); 867490075Sobrien#endif 867590075Sobrien } 867690075Sobrien } 867750397Sobrien break; 867850397Sobrien 867950397Sobrien case CONST_DOUBLE: 868050397Sobrien /* Note that a CONST_DOUBLE rtx could represent either an integer or a 868150397Sobrien floating-point constant. A CONST_DOUBLE is used whenever the 868250397Sobrien constant requires more than one word in order to be adequately 868350397Sobrien represented. We output CONST_DOUBLEs as blocks. */ 868450397Sobrien { 868590075Sobrien enum machine_mode mode = GET_MODE (rtl); 868650397Sobrien 868750397Sobrien if (GET_MODE_CLASS (mode) == MODE_FLOAT) 868850397Sobrien { 868990075Sobrien unsigned length = GET_MODE_SIZE (mode) / 4; 869090075Sobrien long *array = (long *) xmalloc (sizeof (long) * length); 869150397Sobrien REAL_VALUE_TYPE rv; 869250397Sobrien 869350397Sobrien REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); 869450397Sobrien switch (mode) 869550397Sobrien { 869650397Sobrien case SFmode: 869750397Sobrien REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); 869850397Sobrien break; 869950397Sobrien 870050397Sobrien case DFmode: 870150397Sobrien REAL_VALUE_TO_TARGET_DOUBLE (rv, array); 870250397Sobrien break; 870350397Sobrien 870450397Sobrien case XFmode: 870550397Sobrien case TFmode: 870650397Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); 870750397Sobrien break; 870850397Sobrien 870950397Sobrien default: 871050397Sobrien abort (); 871150397Sobrien } 871250397Sobrien 871350397Sobrien add_AT_float (die, DW_AT_const_value, length, array); 871450397Sobrien } 871550397Sobrien else 871690075Sobrien { 871790075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 871890075Sobrien if (HOST_BITS_PER_LONG != HOST_BITS_PER_WIDE_INT) 871990075Sobrien abort (); 872090075Sobrien 872190075Sobrien add_AT_long_long (die, DW_AT_const_value, 872290075Sobrien CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl)); 872390075Sobrien } 872450397Sobrien } 872550397Sobrien break; 872650397Sobrien 872750397Sobrien case CONST_STRING: 872850397Sobrien add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); 872950397Sobrien break; 873050397Sobrien 873150397Sobrien case SYMBOL_REF: 873250397Sobrien case LABEL_REF: 873350397Sobrien case CONST: 873490075Sobrien add_AT_addr (die, DW_AT_const_value, rtl); 873590075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 873650397Sobrien break; 873750397Sobrien 873850397Sobrien case PLUS: 873950397Sobrien /* In cases where an inlined instance of an inline function is passed 874050397Sobrien the address of an `auto' variable (which is local to the caller) we 874150397Sobrien can get a situation where the DECL_RTL of the artificial local 874250397Sobrien variable (for the inlining) which acts as a stand-in for the 874350397Sobrien corresponding formal parameter (of the inline function) will look 874450397Sobrien like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not 874590075Sobrien exactly a compile-time constant expression, but it isn't the address 874690075Sobrien of the (artificial) local variable either. Rather, it represents the 874750397Sobrien *value* which the artificial local variable always has during its 874890075Sobrien lifetime. We currently have no way to represent such quasi-constant 874950397Sobrien values in Dwarf, so for now we just punt and generate nothing. */ 875050397Sobrien break; 875150397Sobrien 875250397Sobrien default: 875350397Sobrien /* No other kinds of rtx should be possible here. */ 875450397Sobrien abort (); 875550397Sobrien } 875650397Sobrien 875750397Sobrien} 875850397Sobrien 875990075Sobrienstatic rtx 876090075Sobrienrtl_for_decl_location (decl) 876190075Sobrien tree decl; 876250397Sobrien{ 876390075Sobrien rtx rtl; 876450397Sobrien 876550397Sobrien /* Here we have to decide where we are going to say the parameter "lives" 876650397Sobrien (as far as the debugger is concerned). We only have a couple of 876750397Sobrien choices. GCC provides us with DECL_RTL and with DECL_INCOMING_RTL. 876850397Sobrien 876990075Sobrien DECL_RTL normally indicates where the parameter lives during most of the 877050397Sobrien activation of the function. If optimization is enabled however, this 877190075Sobrien could be either NULL or else a pseudo-reg. Both of those cases indicate 877250397Sobrien that the parameter doesn't really live anywhere (as far as the code 877350397Sobrien generation parts of GCC are concerned) during most of the function's 877450397Sobrien activation. That will happen (for example) if the parameter is never 877550397Sobrien referenced within the function. 877650397Sobrien 877750397Sobrien We could just generate a location descriptor here for all non-NULL 877850397Sobrien non-pseudo values of DECL_RTL and ignore all of the rest, but we can be 877950397Sobrien a little nicer than that if we also consider DECL_INCOMING_RTL in cases 878050397Sobrien where DECL_RTL is NULL or is a pseudo-reg. 878150397Sobrien 878250397Sobrien Note however that we can only get away with using DECL_INCOMING_RTL as 878350397Sobrien a backup substitute for DECL_RTL in certain limited cases. In cases 878450397Sobrien where DECL_ARG_TYPE (decl) indicates the same type as TREE_TYPE (decl), 878550397Sobrien we can be sure that the parameter was passed using the same type as it is 878650397Sobrien declared to have within the function, and that its DECL_INCOMING_RTL 878750397Sobrien points us to a place where a value of that type is passed. 878850397Sobrien 878950397Sobrien In cases where DECL_ARG_TYPE (decl) and TREE_TYPE (decl) are different, 879050397Sobrien we cannot (in general) use DECL_INCOMING_RTL as a substitute for DECL_RTL 879150397Sobrien because in these cases DECL_INCOMING_RTL points us to a value of some 879250397Sobrien type which is *different* from the type of the parameter itself. Thus, 879350397Sobrien if we tried to use DECL_INCOMING_RTL to generate a location attribute in 879450397Sobrien such cases, the debugger would end up (for example) trying to fetch a 879550397Sobrien `float' from a place which actually contains the first part of a 879650397Sobrien `double'. That would lead to really incorrect and confusing 879750397Sobrien output at debug-time. 879850397Sobrien 879950397Sobrien So, in general, we *do not* use DECL_INCOMING_RTL as a backup for DECL_RTL 880050397Sobrien in cases where DECL_ARG_TYPE (decl) != TREE_TYPE (decl). There 880150397Sobrien are a couple of exceptions however. On little-endian machines we can 880250397Sobrien get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE (decl) is 880350397Sobrien not the same as TREE_TYPE (decl), but only when DECL_ARG_TYPE (decl) is 880450397Sobrien an integral type that is smaller than TREE_TYPE (decl). These cases arise 880550397Sobrien when (on a little-endian machine) a non-prototyped function has a 880650397Sobrien parameter declared to be of type `short' or `char'. In such cases, 880750397Sobrien TREE_TYPE (decl) will be `short' or `char', DECL_ARG_TYPE (decl) will 880850397Sobrien be `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the 880950397Sobrien passed `int' value. If the debugger then uses that address to fetch 881050397Sobrien a `short' or a `char' (on a little-endian machine) the result will be 881150397Sobrien the correct data, so we allow for such exceptional cases below. 881250397Sobrien 881350397Sobrien Note that our goal here is to describe the place where the given formal 881490075Sobrien parameter lives during most of the function's activation (i.e. between the 881590075Sobrien end of the prologue and the start of the epilogue). We'll do that as best 881690075Sobrien as we can. Note however that if the given formal parameter is modified 881790075Sobrien sometime during the execution of the function, then a stack backtrace (at 881890075Sobrien debug-time) will show the function as having been called with the *new* 881990075Sobrien value rather than the value which was originally passed in. This happens 882090075Sobrien rarely enough that it is not a major problem, but it *is* a problem, and 882190075Sobrien I'd like to fix it. 882250397Sobrien 882390075Sobrien A future version of dwarf2out.c may generate two additional attributes for 882490075Sobrien any given DW_TAG_formal_parameter DIE which will describe the "passed 882590075Sobrien type" and the "passed location" for the given formal parameter in addition 882690075Sobrien to the attributes we now generate to indicate the "declared type" and the 882790075Sobrien "active location" for each parameter. This additional set of attributes 882890075Sobrien could be used by debuggers for stack backtraces. Separately, note that 882990075Sobrien sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL can be NULL also. 883090075Sobrien This happens (for example) for inlined-instances of inline function formal 883190075Sobrien parameters which are never referenced. This really shouldn't be 883290075Sobrien happening. All PARM_DECL nodes should get valid non-NULL 883390075Sobrien DECL_INCOMING_RTL values, but integrate.c doesn't currently generate these 883490075Sobrien values for inlined instances of inline function parameters, so when we see 883590075Sobrien such cases, we are just out-of-luck for the time being (until integrate.c 883650397Sobrien gets fixed). */ 883750397Sobrien 883850397Sobrien /* Use DECL_RTL as the "location" unless we find something better. */ 883990075Sobrien rtl = DECL_RTL_IF_SET (decl); 884050397Sobrien 884190075Sobrien /* When generating abstract instances, ignore everything except 884290075Sobrien constants and symbols living in memory. */ 884390075Sobrien if (! reload_completed) 884450397Sobrien { 884590075Sobrien if (rtl 884690075Sobrien && (CONSTANT_P (rtl) 884790075Sobrien || (GET_CODE (rtl) == MEM 884890075Sobrien && CONSTANT_P (XEXP (rtl, 0))))) 884996263Sobrien { 885096263Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 885196263Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 885296263Sobrien#endif 885396263Sobrien return rtl; 885496263Sobrien } 885590075Sobrien rtl = NULL_RTX; 885690075Sobrien } 885790075Sobrien else if (TREE_CODE (decl) == PARM_DECL) 885890075Sobrien { 885950397Sobrien if (rtl == NULL_RTX || is_pseudo_reg (rtl)) 886050397Sobrien { 886190075Sobrien tree declared_type = type_main_variant (TREE_TYPE (decl)); 886290075Sobrien tree passed_type = type_main_variant (DECL_ARG_TYPE (decl)); 886350397Sobrien 886450397Sobrien /* This decl represents a formal parameter which was optimized out. 886550397Sobrien Note that DECL_INCOMING_RTL may be NULL in here, but we handle 886690075Sobrien all cases where (rtl == NULL_RTX) just below. */ 886750397Sobrien if (declared_type == passed_type) 886850397Sobrien rtl = DECL_INCOMING_RTL (decl); 886950397Sobrien else if (! BYTES_BIG_ENDIAN 887050397Sobrien && TREE_CODE (declared_type) == INTEGER_TYPE 887152284Sobrien && (GET_MODE_SIZE (TYPE_MODE (declared_type)) 887252284Sobrien <= GET_MODE_SIZE (TYPE_MODE (passed_type)))) 887390075Sobrien rtl = DECL_INCOMING_RTL (decl); 887450397Sobrien } 887552284Sobrien 887652284Sobrien /* If the parm was passed in registers, but lives on the stack, then 887752284Sobrien make a big endian correction if the mode of the type of the 887852284Sobrien parameter is not the same as the mode of the rtl. */ 887952284Sobrien /* ??? This is the same series of checks that are made in dbxout.c before 888052284Sobrien we reach the big endian correction code there. It isn't clear if all 888152284Sobrien of these checks are necessary here, but keeping them all is the safe 888252284Sobrien thing to do. */ 888352284Sobrien else if (GET_CODE (rtl) == MEM 888452284Sobrien && XEXP (rtl, 0) != const0_rtx 888552284Sobrien && ! CONSTANT_P (XEXP (rtl, 0)) 888652284Sobrien /* Not passed in memory. */ 888752284Sobrien && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM 888852284Sobrien /* Not passed by invisible reference. */ 888952284Sobrien && (GET_CODE (XEXP (rtl, 0)) != REG 889052284Sobrien || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM 889152284Sobrien || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM 889252284Sobrien#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 889352284Sobrien || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM 889452284Sobrien#endif 889552284Sobrien ) 889652284Sobrien /* Big endian correction check. */ 889752284Sobrien && BYTES_BIG_ENDIAN 889852284Sobrien && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl) 889952284Sobrien && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))) 890052284Sobrien < UNITS_PER_WORD)) 890152284Sobrien { 890252284Sobrien int offset = (UNITS_PER_WORD 890352284Sobrien - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))); 890490075Sobrien 890552284Sobrien rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)), 890652284Sobrien plus_constant (XEXP (rtl, 0), offset)); 890752284Sobrien } 890850397Sobrien } 890950397Sobrien 891090075Sobrien if (rtl != NULL_RTX) 891190075Sobrien { 891290075Sobrien rtl = eliminate_regs (rtl, 0, NULL_RTX); 891390075Sobrien#ifdef LEAF_REG_REMAP 891490075Sobrien if (current_function_uses_only_leaf_regs) 891590075Sobrien leaf_renumber_regs_insn (rtl); 891690075Sobrien#endif 891790075Sobrien } 891890075Sobrien 891990075Sobrien /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant, 892090075Sobrien and will have been substituted directly into all expressions that use it. 892190075Sobrien C does not have such a concept, but C++ and other languages do. */ 892290075Sobrien else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) 892396263Sobrien { 892496263Sobrien /* If a variable is initialized with a string constant without embedded 892596263Sobrien zeros, build CONST_STRING. */ 892696263Sobrien if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST 892796263Sobrien && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) 892896263Sobrien { 892996263Sobrien tree arrtype = TREE_TYPE (decl); 893096263Sobrien tree enttype = TREE_TYPE (arrtype); 893196263Sobrien tree domain = TYPE_DOMAIN (arrtype); 893296263Sobrien tree init = DECL_INITIAL (decl); 893396263Sobrien enum machine_mode mode = TYPE_MODE (enttype); 893490075Sobrien 893596263Sobrien if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1 893696263Sobrien && domain 893796263Sobrien && integer_zerop (TYPE_MIN_VALUE (domain)) 893896263Sobrien && compare_tree_int (TYPE_MAX_VALUE (domain), 893996263Sobrien TREE_STRING_LENGTH (init) - 1) == 0 894096263Sobrien && ((size_t) TREE_STRING_LENGTH (init) 894196263Sobrien == strlen (TREE_STRING_POINTER (init)) + 1)) 894296263Sobrien rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init)); 894396263Sobrien } 894496263Sobrien 894596263Sobrien#if 0 894696263Sobrien /* We mustn't actually emit anything here, as we might not get a 894796263Sobrien chance to emit any symbols we refer to. For the release, don't 894896263Sobrien try to get this right. */ 894996263Sobrien if (rtl == NULL) 895096263Sobrien { 895196263Sobrien rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode, 895296263Sobrien EXPAND_INITIALIZER); 895396263Sobrien /* If expand_expr returned a MEM, we cannot use it, since 895496263Sobrien it won't be output, leading to unresolved symbol. */ 895596263Sobrien if (rtl && GET_CODE (rtl) == MEM) 895696263Sobrien rtl = NULL; 895796263Sobrien } 895896263Sobrien#endif 895996263Sobrien } 896096263Sobrien 896196263Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 896296263Sobrien if (rtl) 896396263Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 896496263Sobrien#endif 896590075Sobrien return rtl; 896690075Sobrien} 896790075Sobrien 896890075Sobrien/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value 896990075Sobrien data attribute for a variable or a parameter. We generate the 897090075Sobrien DW_AT_const_value attribute only in those cases where the given variable 897190075Sobrien or parameter does not have a true "location" either in memory or in a 897290075Sobrien register. This can happen (for example) when a constant is passed as an 897390075Sobrien actual argument in a call to an inline function. (It's possible that 897490075Sobrien these things can crop up in other ways also.) Note that one type of 897590075Sobrien constant value which can be passed into an inlined function is a constant 897690075Sobrien pointer. This can happen for example if an actual argument in an inlined 897790075Sobrien function call evaluates to a compile-time constant address. */ 897890075Sobrien 897990075Sobrienstatic void 898090075Sobrienadd_location_or_const_value_attribute (die, decl) 898190075Sobrien dw_die_ref die; 898290075Sobrien tree decl; 898390075Sobrien{ 898490075Sobrien rtx rtl; 898590075Sobrien 898690075Sobrien if (TREE_CODE (decl) == ERROR_MARK) 898790075Sobrien return; 898890075Sobrien else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 898990075Sobrien abort (); 899090075Sobrien 899190075Sobrien rtl = rtl_for_decl_location (decl); 899250397Sobrien if (rtl == NULL_RTX) 899350397Sobrien return; 899450397Sobrien 899590075Sobrien /* If we don't look past the constant pool, we risk emitting a 899690075Sobrien reference to a constant pool entry that isn't referenced from 899790075Sobrien code, and thus is not emitted. */ 899890075Sobrien rtl = avoid_constant_pool_reference (rtl); 899950397Sobrien 900050397Sobrien switch (GET_CODE (rtl)) 900150397Sobrien { 900250397Sobrien case ADDRESSOF: 900350397Sobrien /* The address of a variable that was optimized away; don't emit 900450397Sobrien anything. */ 900550397Sobrien break; 900650397Sobrien 900750397Sobrien case CONST_INT: 900850397Sobrien case CONST_DOUBLE: 900950397Sobrien case CONST_STRING: 901050397Sobrien case SYMBOL_REF: 901150397Sobrien case LABEL_REF: 901250397Sobrien case CONST: 901350397Sobrien case PLUS: 901450397Sobrien /* DECL_RTL could be (plus (reg ...) (const_int ...)) */ 901550397Sobrien add_const_value_attribute (die, rtl); 901650397Sobrien break; 901750397Sobrien 901850397Sobrien case MEM: 901950397Sobrien case REG: 902050397Sobrien case SUBREG: 902150397Sobrien case CONCAT: 902250397Sobrien add_AT_location_description (die, DW_AT_location, rtl); 902350397Sobrien break; 902450397Sobrien 902550397Sobrien default: 902650397Sobrien abort (); 902750397Sobrien } 902850397Sobrien} 902950397Sobrien 903090075Sobrien/* If we don't have a copy of this variable in memory for some reason (such 903190075Sobrien as a C++ member constant that doesn't have an out-of-line definition), 903290075Sobrien we should tell the debugger about the constant value. */ 903390075Sobrien 903490075Sobrienstatic void 903590075Sobrientree_add_const_value_attribute (var_die, decl) 903690075Sobrien dw_die_ref var_die; 903790075Sobrien tree decl; 903890075Sobrien{ 903990075Sobrien tree init = DECL_INITIAL (decl); 904090075Sobrien tree type = TREE_TYPE (decl); 904190075Sobrien 904290075Sobrien if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init 904390075Sobrien && initializer_constant_valid_p (init, type) == null_pointer_node) 904490075Sobrien /* OK */; 904590075Sobrien else 904690075Sobrien return; 904790075Sobrien 904890075Sobrien switch (TREE_CODE (type)) 904990075Sobrien { 905090075Sobrien case INTEGER_TYPE: 905190075Sobrien if (host_integerp (init, 0)) 905290075Sobrien add_AT_unsigned (var_die, DW_AT_const_value, 905390075Sobrien tree_low_cst (init, 0)); 905490075Sobrien else 905590075Sobrien add_AT_long_long (var_die, DW_AT_const_value, 905690075Sobrien TREE_INT_CST_HIGH (init), 905790075Sobrien TREE_INT_CST_LOW (init)); 905890075Sobrien break; 905990075Sobrien 906090075Sobrien default:; 906190075Sobrien } 906290075Sobrien} 906390075Sobrien 906450397Sobrien/* Generate an DW_AT_name attribute given some string value to be included as 906550397Sobrien the value of the attribute. */ 906650397Sobrien 906750397Sobrienstatic inline void 906850397Sobrienadd_name_attribute (die, name_string) 906990075Sobrien dw_die_ref die; 907090075Sobrien const char *name_string; 907150397Sobrien{ 907250397Sobrien if (name_string != NULL && *name_string != 0) 907390075Sobrien { 907490075Sobrien if (demangle_name_func) 907590075Sobrien name_string = (*demangle_name_func) (name_string); 907690075Sobrien 907790075Sobrien add_AT_string (die, DW_AT_name, name_string); 907890075Sobrien } 907950397Sobrien} 908050397Sobrien 908150397Sobrien/* Given a tree node describing an array bound (either lower or upper) output 908250397Sobrien a representation for that bound. */ 908350397Sobrien 908450397Sobrienstatic void 908550397Sobrienadd_bound_info (subrange_die, bound_attr, bound) 908690075Sobrien dw_die_ref subrange_die; 908790075Sobrien enum dwarf_attribute bound_attr; 908890075Sobrien tree bound; 908950397Sobrien{ 909050397Sobrien switch (TREE_CODE (bound)) 909150397Sobrien { 909250397Sobrien case ERROR_MARK: 909350397Sobrien return; 909450397Sobrien 909590075Sobrien /* All fixed-bounds are represented by INTEGER_CST nodes. */ 909650397Sobrien case INTEGER_CST: 909790075Sobrien if (! host_integerp (bound, 0) 909890075Sobrien || (bound_attr == DW_AT_lower_bound 909990075Sobrien && (((is_c_family () || is_java ()) && integer_zerop (bound)) 910090075Sobrien || (is_fortran () && integer_onep (bound))))) 910190075Sobrien /* use the default */ 910290075Sobrien ; 910350397Sobrien else 910490075Sobrien add_AT_unsigned (subrange_die, bound_attr, tree_low_cst (bound, 0)); 910550397Sobrien break; 910650397Sobrien 910750397Sobrien case CONVERT_EXPR: 910850397Sobrien case NOP_EXPR: 910950397Sobrien case NON_LVALUE_EXPR: 911090075Sobrien case VIEW_CONVERT_EXPR: 911150397Sobrien add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); 911250397Sobrien break; 911390075Sobrien 911450397Sobrien case SAVE_EXPR: 911550397Sobrien /* If optimization is turned on, the SAVE_EXPRs that describe how to 911650397Sobrien access the upper bound values may be bogus. If they refer to a 911750397Sobrien register, they may only describe how to get at these values at the 911850397Sobrien points in the generated code right after they have just been 911950397Sobrien computed. Worse yet, in the typical case, the upper bound values 912050397Sobrien will not even *be* computed in the optimized code (though the 912150397Sobrien number of elements will), so these SAVE_EXPRs are entirely 912250397Sobrien bogus. In order to compensate for this fact, we check here to see 912350397Sobrien if optimization is enabled, and if so, we don't add an attribute 912450397Sobrien for the (unknown and unknowable) upper bound. This should not 912550397Sobrien cause too much trouble for existing (stupid?) debuggers because 912650397Sobrien they have to deal with empty upper bounds location descriptions 912750397Sobrien anyway in order to be able to deal with incomplete array types. 912850397Sobrien Of course an intelligent debugger (GDB?) should be able to 912990075Sobrien comprehend that a missing upper bound specification in an array 913050397Sobrien type used for a storage class `auto' local array variable 913150397Sobrien indicates that the upper bound is both unknown (at compile- time) 913250397Sobrien and unknowable (at run-time) due to optimization. 913350397Sobrien 913450397Sobrien We assume that a MEM rtx is safe because gcc wouldn't put the 913550397Sobrien value there unless it was going to be used repeatedly in the 913650397Sobrien function, i.e. for cleanups. */ 913790075Sobrien if (SAVE_EXPR_RTL (bound) 913890075Sobrien && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM)) 913950397Sobrien { 914090075Sobrien dw_die_ref ctx = lookup_decl_die (current_function_decl); 914190075Sobrien dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound); 914290075Sobrien rtx loc = SAVE_EXPR_RTL (bound); 914350397Sobrien 914450397Sobrien /* If the RTL for the SAVE_EXPR is memory, handle the case where 914550397Sobrien it references an outer function's frame. */ 914650397Sobrien if (GET_CODE (loc) == MEM) 914750397Sobrien { 914850397Sobrien rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound); 914950397Sobrien 915050397Sobrien if (XEXP (loc, 0) != new_addr) 915190075Sobrien loc = gen_rtx_MEM (GET_MODE (loc), new_addr); 915250397Sobrien } 915350397Sobrien 915450397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 915550397Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 915650397Sobrien add_AT_location_description (decl_die, DW_AT_location, loc); 915750397Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 915850397Sobrien } 915950397Sobrien 916050397Sobrien /* Else leave out the attribute. */ 916150397Sobrien break; 916250397Sobrien 916350397Sobrien case VAR_DECL: 916490075Sobrien case PARM_DECL: 916590075Sobrien { 916690075Sobrien dw_die_ref decl_die = lookup_decl_die (bound); 916750397Sobrien 916890075Sobrien /* ??? Can this happen, or should the variable have been bound 916990075Sobrien first? Probably it can, since I imagine that we try to create 917090075Sobrien the types of parameters in the order in which they exist in 917190075Sobrien the list, and won't have created a forward reference to a 917290075Sobrien later parameter. */ 917390075Sobrien if (decl_die != NULL) 917490075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 917590075Sobrien break; 917690075Sobrien } 917790075Sobrien 917850397Sobrien default: 917990075Sobrien { 918090075Sobrien /* Otherwise try to create a stack operation procedure to 918190075Sobrien evaluate the value of the array bound. */ 918290075Sobrien 918390075Sobrien dw_die_ref ctx, decl_die; 918490075Sobrien dw_loc_descr_ref loc; 918590075Sobrien 918690075Sobrien loc = loc_descriptor_from_tree (bound, 0); 918790075Sobrien if (loc == NULL) 918890075Sobrien break; 918990075Sobrien 919090075Sobrien if (current_function_decl == 0) 919190075Sobrien ctx = comp_unit_die; 919290075Sobrien else 919390075Sobrien ctx = lookup_decl_die (current_function_decl); 919490075Sobrien 919590075Sobrien /* If we weren't able to find a context, it's most likely the case 919690075Sobrien that we are processing the return type of the function. So 919790075Sobrien make a SAVE_EXPR to point to it and have the limbo DIE code 919890075Sobrien find the proper die. The save_expr function doesn't always 919990075Sobrien make a SAVE_EXPR, so do it ourselves. */ 920090075Sobrien if (ctx == 0) 920190075Sobrien bound = build (SAVE_EXPR, TREE_TYPE (bound), bound, 920290075Sobrien current_function_decl, NULL_TREE); 920390075Sobrien 920490075Sobrien decl_die = new_die (DW_TAG_variable, ctx, bound); 920590075Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 920690075Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 920790075Sobrien add_AT_loc (decl_die, DW_AT_location, loc); 920890075Sobrien 920990075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 921090075Sobrien break; 921190075Sobrien } 921250397Sobrien } 921350397Sobrien} 921450397Sobrien 921550397Sobrien/* Note that the block of subscript information for an array type also 921650397Sobrien includes information about the element type of type given array type. */ 921750397Sobrien 921850397Sobrienstatic void 921950397Sobrienadd_subscript_info (type_die, type) 922090075Sobrien dw_die_ref type_die; 922190075Sobrien tree type; 922250397Sobrien{ 922350397Sobrien#ifndef MIPS_DEBUGGING_INFO 922490075Sobrien unsigned dimension_number; 922550397Sobrien#endif 922690075Sobrien tree lower, upper; 922790075Sobrien dw_die_ref subrange_die; 922850397Sobrien 922990075Sobrien /* The GNU compilers represent multidimensional array types as sequences of 923050397Sobrien one dimensional array types whose element types are themselves array 923150397Sobrien types. Here we squish that down, so that each multidimensional array 923290075Sobrien type gets only one array_type DIE in the Dwarf debugging info. The draft 923350397Sobrien Dwarf specification say that we are allowed to do this kind of 923450397Sobrien compression in C (because there is no difference between an array or 923590075Sobrien arrays and a multidimensional array in C) but for other source languages 923650397Sobrien (e.g. Ada) we probably shouldn't do this. */ 923750397Sobrien 923850397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 923950397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 924050397Sobrien We work around this by disabling this feature. See also 924150397Sobrien gen_array_type_die. */ 924250397Sobrien#ifndef MIPS_DEBUGGING_INFO 924350397Sobrien for (dimension_number = 0; 924450397Sobrien TREE_CODE (type) == ARRAY_TYPE; 924550397Sobrien type = TREE_TYPE (type), dimension_number++) 924690075Sobrien#endif 924750397Sobrien { 924890075Sobrien tree domain = TYPE_DOMAIN (type); 924950397Sobrien 925050397Sobrien /* Arrays come in three flavors: Unspecified bounds, fixed bounds, 925190075Sobrien and (in GNU C only) variable bounds. Handle all three forms 925250397Sobrien here. */ 925390075Sobrien subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL); 925450397Sobrien if (domain) 925550397Sobrien { 925650397Sobrien /* We have an array type with specified bounds. */ 925750397Sobrien lower = TYPE_MIN_VALUE (domain); 925850397Sobrien upper = TYPE_MAX_VALUE (domain); 925950397Sobrien 926050397Sobrien /* define the index type. */ 926150397Sobrien if (TREE_TYPE (domain)) 926250397Sobrien { 926350397Sobrien /* ??? This is probably an Ada unnamed subrange type. Ignore the 926450397Sobrien TREE_TYPE field. We can't emit debug info for this 926550397Sobrien because it is an unnamed integral type. */ 926650397Sobrien if (TREE_CODE (domain) == INTEGER_TYPE 926750397Sobrien && TYPE_NAME (domain) == NULL_TREE 926850397Sobrien && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE 926950397Sobrien && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE) 927090075Sobrien ; 927150397Sobrien else 927250397Sobrien add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0, 927350397Sobrien type_die); 927450397Sobrien } 927550397Sobrien 927650397Sobrien /* ??? If upper is NULL, the array has unspecified length, 927750397Sobrien but it does have a lower bound. This happens with Fortran 927850397Sobrien dimension arr(N:*) 927950397Sobrien Since the debugger is definitely going to need to know N 928050397Sobrien to produce useful results, go ahead and output the lower 928150397Sobrien bound solo, and hope the debugger can cope. */ 928250397Sobrien 928350397Sobrien add_bound_info (subrange_die, DW_AT_lower_bound, lower); 928450397Sobrien if (upper) 928550397Sobrien add_bound_info (subrange_die, DW_AT_upper_bound, upper); 928650397Sobrien } 928750397Sobrien 928890075Sobrien /* Otherwise we have an array type with an unspecified length. The 928990075Sobrien DWARF-2 spec does not say how to handle this; let's just leave out the 929090075Sobrien bounds. */ 929150397Sobrien } 929250397Sobrien} 929350397Sobrien 929450397Sobrienstatic void 929550397Sobrienadd_byte_size_attribute (die, tree_node) 929650397Sobrien dw_die_ref die; 929790075Sobrien tree tree_node; 929850397Sobrien{ 929990075Sobrien unsigned size; 930050397Sobrien 930150397Sobrien switch (TREE_CODE (tree_node)) 930250397Sobrien { 930350397Sobrien case ERROR_MARK: 930450397Sobrien size = 0; 930550397Sobrien break; 930650397Sobrien case ENUMERAL_TYPE: 930750397Sobrien case RECORD_TYPE: 930850397Sobrien case UNION_TYPE: 930950397Sobrien case QUAL_UNION_TYPE: 931050397Sobrien size = int_size_in_bytes (tree_node); 931150397Sobrien break; 931250397Sobrien case FIELD_DECL: 931350397Sobrien /* For a data member of a struct or union, the DW_AT_byte_size is 931450397Sobrien generally given as the number of bytes normally allocated for an 931550397Sobrien object of the *declared* type of the member itself. This is true 931650397Sobrien even for bit-fields. */ 931750397Sobrien size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT; 931850397Sobrien break; 931950397Sobrien default: 932050397Sobrien abort (); 932150397Sobrien } 932250397Sobrien 932350397Sobrien /* Note that `size' might be -1 when we get to this point. If it is, that 932450397Sobrien indicates that the byte size of the entity in question is variable. We 932550397Sobrien have no good way of expressing this fact in Dwarf at the present time, 932650397Sobrien so just let the -1 pass on through. */ 932750397Sobrien add_AT_unsigned (die, DW_AT_byte_size, size); 932850397Sobrien} 932950397Sobrien 933050397Sobrien/* For a FIELD_DECL node which represents a bit-field, output an attribute 933150397Sobrien which specifies the distance in bits from the highest order bit of the 933250397Sobrien "containing object" for the bit-field to the highest order bit of the 933350397Sobrien bit-field itself. 933450397Sobrien 933590075Sobrien For any given bit-field, the "containing object" is a hypothetical object 933690075Sobrien (of some integral or enum type) within which the given bit-field lives. The 933790075Sobrien type of this hypothetical "containing object" is always the same as the 933890075Sobrien declared type of the individual bit-field itself. The determination of the 933990075Sobrien exact location of the "containing object" for a bit-field is rather 934090075Sobrien complicated. It's handled by the `field_byte_offset' function (above). 934150397Sobrien 934250397Sobrien Note that it is the size (in bytes) of the hypothetical "containing object" 934350397Sobrien which will be given in the DW_AT_byte_size attribute for this bit-field. 934450397Sobrien (See `byte_size_attribute' above). */ 934550397Sobrien 934650397Sobrienstatic inline void 934750397Sobrienadd_bit_offset_attribute (die, decl) 934890075Sobrien dw_die_ref die; 934990075Sobrien tree decl; 935050397Sobrien{ 935190075Sobrien HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl); 935290075Sobrien tree type = DECL_BIT_FIELD_TYPE (decl); 935390075Sobrien HOST_WIDE_INT bitpos_int; 935490075Sobrien HOST_WIDE_INT highest_order_object_bit_offset; 935590075Sobrien HOST_WIDE_INT highest_order_field_bit_offset; 935690075Sobrien HOST_WIDE_INT unsigned bit_offset; 935750397Sobrien 935850397Sobrien /* Must be a field and a bit field. */ 935950397Sobrien if (!type 936050397Sobrien || TREE_CODE (decl) != FIELD_DECL) 936150397Sobrien abort (); 936250397Sobrien 936350397Sobrien /* We can't yet handle bit-fields whose offsets are variable, so if we 936450397Sobrien encounter such things, just return without generating any attribute 936590075Sobrien whatsoever. Likewise for variable or too large size. */ 936690075Sobrien if (! host_integerp (bit_position (decl), 0) 936790075Sobrien || ! host_integerp (DECL_SIZE (decl), 1)) 936850397Sobrien return; 936950397Sobrien 937090075Sobrien bitpos_int = int_bit_position (decl); 937150397Sobrien 937250397Sobrien /* Note that the bit offset is always the distance (in bits) from the 937390075Sobrien highest-order bit of the "containing object" to the highest-order bit of 937490075Sobrien the bit-field itself. Since the "high-order end" of any object or field 937550397Sobrien is different on big-endian and little-endian machines, the computation 937650397Sobrien below must take account of these differences. */ 937750397Sobrien highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT; 937850397Sobrien highest_order_field_bit_offset = bitpos_int; 937950397Sobrien 938050397Sobrien if (! BYTES_BIG_ENDIAN) 938150397Sobrien { 938290075Sobrien highest_order_field_bit_offset += tree_low_cst (DECL_SIZE (decl), 0); 938350397Sobrien highest_order_object_bit_offset += simple_type_size_in_bits (type); 938450397Sobrien } 938550397Sobrien 938650397Sobrien bit_offset 938750397Sobrien = (! BYTES_BIG_ENDIAN 938850397Sobrien ? highest_order_object_bit_offset - highest_order_field_bit_offset 938950397Sobrien : highest_order_field_bit_offset - highest_order_object_bit_offset); 939050397Sobrien 939150397Sobrien add_AT_unsigned (die, DW_AT_bit_offset, bit_offset); 939250397Sobrien} 939350397Sobrien 939450397Sobrien/* For a FIELD_DECL node which represents a bit field, output an attribute 939550397Sobrien which specifies the length in bits of the given field. */ 939650397Sobrien 939750397Sobrienstatic inline void 939850397Sobrienadd_bit_size_attribute (die, decl) 939990075Sobrien dw_die_ref die; 940090075Sobrien tree decl; 940150397Sobrien{ 940250397Sobrien /* Must be a field and a bit field. */ 940350397Sobrien if (TREE_CODE (decl) != FIELD_DECL 940450397Sobrien || ! DECL_BIT_FIELD_TYPE (decl)) 940550397Sobrien abort (); 940690075Sobrien 940790075Sobrien if (host_integerp (DECL_SIZE (decl), 1)) 940890075Sobrien add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1)); 940950397Sobrien} 941050397Sobrien 941150397Sobrien/* If the compiled language is ANSI C, then add a 'prototyped' 941250397Sobrien attribute, if arg types are given for the parameters of a function. */ 941350397Sobrien 941450397Sobrienstatic inline void 941550397Sobrienadd_prototyped_attribute (die, func_type) 941690075Sobrien dw_die_ref die; 941790075Sobrien tree func_type; 941850397Sobrien{ 941950397Sobrien if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 942050397Sobrien && TYPE_ARG_TYPES (func_type) != NULL) 942150397Sobrien add_AT_flag (die, DW_AT_prototyped, 1); 942250397Sobrien} 942350397Sobrien 942450397Sobrien/* Add an 'abstract_origin' attribute below a given DIE. The DIE is found 942550397Sobrien by looking in either the type declaration or object declaration 942650397Sobrien equate table. */ 942750397Sobrien 942850397Sobrienstatic inline void 942950397Sobrienadd_abstract_origin_attribute (die, origin) 943090075Sobrien dw_die_ref die; 943190075Sobrien tree origin; 943250397Sobrien{ 943350397Sobrien dw_die_ref origin_die = NULL; 943490075Sobrien 943590075Sobrien if (TREE_CODE (origin) != FUNCTION_DECL) 943690075Sobrien { 943790075Sobrien /* We may have gotten separated from the block for the inlined 943890075Sobrien function, if we're in an exception handler or some such; make 943990075Sobrien sure that the abstract function has been written out. 944090075Sobrien 944190075Sobrien Doing this for nested functions is wrong, however; functions are 944290075Sobrien distinct units, and our context might not even be inline. */ 944390075Sobrien tree fn = origin; 944490075Sobrien 944590075Sobrien if (TYPE_P (fn)) 944690075Sobrien fn = TYPE_STUB_DECL (fn); 944790075Sobrien 944890075Sobrien fn = decl_function_context (fn); 944990075Sobrien if (fn) 945090075Sobrien dwarf2out_abstract_function (fn); 945190075Sobrien } 945290075Sobrien 945390075Sobrien if (DECL_P (origin)) 945450397Sobrien origin_die = lookup_decl_die (origin); 945590075Sobrien else if (TYPE_P (origin)) 945650397Sobrien origin_die = lookup_type_die (origin); 945750397Sobrien 945890075Sobrien if (origin_die == NULL) 945990075Sobrien abort (); 946090075Sobrien 946150397Sobrien add_AT_die_ref (die, DW_AT_abstract_origin, origin_die); 946250397Sobrien} 946350397Sobrien 946450397Sobrien/* We do not currently support the pure_virtual attribute. */ 946550397Sobrien 946650397Sobrienstatic inline void 946750397Sobrienadd_pure_or_virtual_attribute (die, func_decl) 946890075Sobrien dw_die_ref die; 946990075Sobrien tree func_decl; 947050397Sobrien{ 947150397Sobrien if (DECL_VINDEX (func_decl)) 947250397Sobrien { 947350397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 947450397Sobrien 947590075Sobrien if (host_integerp (DECL_VINDEX (func_decl), 0)) 947690075Sobrien add_AT_loc (die, DW_AT_vtable_elem_location, 947790075Sobrien new_loc_descr (DW_OP_constu, 947890075Sobrien tree_low_cst (DECL_VINDEX (func_decl), 0), 947990075Sobrien 0)); 948090075Sobrien 948150397Sobrien /* GNU extension: Record what type this method came from originally. */ 948250397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 948350397Sobrien add_AT_die_ref (die, DW_AT_containing_type, 948450397Sobrien lookup_type_die (DECL_CONTEXT (func_decl))); 948550397Sobrien } 948650397Sobrien} 948750397Sobrien 948850397Sobrien/* Add source coordinate attributes for the given decl. */ 948950397Sobrien 949050397Sobrienstatic void 949150397Sobrienadd_src_coords_attributes (die, decl) 949290075Sobrien dw_die_ref die; 949390075Sobrien tree decl; 949450397Sobrien{ 949590075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 949650397Sobrien 949750397Sobrien add_AT_unsigned (die, DW_AT_decl_file, file_index); 949850397Sobrien add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 949950397Sobrien} 950050397Sobrien 950150397Sobrien/* Add an DW_AT_name attribute and source coordinate attribute for the 950250397Sobrien given decl, but only if it actually has a name. */ 950350397Sobrien 950450397Sobrienstatic void 950550397Sobrienadd_name_and_src_coords_attributes (die, decl) 950690075Sobrien dw_die_ref die; 950790075Sobrien tree decl; 950850397Sobrien{ 950990075Sobrien tree decl_name; 951050397Sobrien 951190075Sobrien decl_name = DECL_NAME (decl); 951250397Sobrien if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) 951350397Sobrien { 951450397Sobrien add_name_attribute (die, dwarf2_name (decl, 0)); 951590075Sobrien if (! DECL_ARTIFICIAL (decl)) 951690075Sobrien add_src_coords_attributes (die, decl); 951790075Sobrien 951850397Sobrien if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) 951990075Sobrien && TREE_PUBLIC (decl) 952090075Sobrien && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) 952190075Sobrien && !DECL_ABSTRACT (decl)) 952250397Sobrien add_AT_string (die, DW_AT_MIPS_linkage_name, 952350397Sobrien IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 952450397Sobrien } 952590075Sobrien 952690075Sobrien#ifdef VMS_DEBUGGING_INFO 952790075Sobrien /* Get the function's name, as described by its RTL. This may be different 952890075Sobrien from the DECL_NAME name used in the source file. */ 952990075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) 953090075Sobrien { 953190075Sobrien add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address, 953290075Sobrien XEXP (DECL_RTL (decl), 0)); 953390075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, XEXP (DECL_RTL (decl), 0)); 953490075Sobrien } 953590075Sobrien#endif 953650397Sobrien} 953750397Sobrien 953890075Sobrien/* Push a new declaration scope. */ 953950397Sobrien 954050397Sobrienstatic void 954150397Sobrienpush_decl_scope (scope) 954250397Sobrien tree scope; 954350397Sobrien{ 954490075Sobrien VARRAY_PUSH_TREE (decl_scope_table, scope); 954590075Sobrien} 954650397Sobrien 954790075Sobrien/* Pop a declaration scope. */ 954850397Sobrien 954990075Sobrienstatic inline void 955090075Sobrienpop_decl_scope () 955190075Sobrien{ 955290075Sobrien if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0) 955390075Sobrien abort (); 955450397Sobrien 955590075Sobrien VARRAY_POP (decl_scope_table); 955650397Sobrien} 955750397Sobrien 955890075Sobrien/* Return the DIE for the scope that immediately contains this type. 955990075Sobrien Non-named types get global scope. Named types nested in other 956090075Sobrien types get their containing scope if it's open, or global scope 956190075Sobrien otherwise. All other types (i.e. function-local named types) get 956290075Sobrien the current active scope. */ 956350397Sobrien 956450397Sobrienstatic dw_die_ref 956550397Sobrienscope_die_for (t, context_die) 956690075Sobrien tree t; 956790075Sobrien dw_die_ref context_die; 956850397Sobrien{ 956990075Sobrien dw_die_ref scope_die = NULL; 957090075Sobrien tree containing_scope; 957190075Sobrien int i; 957250397Sobrien 957390075Sobrien /* Non-types always go in the current scope. */ 957490075Sobrien if (! TYPE_P (t)) 957590075Sobrien abort (); 957650397Sobrien 957790075Sobrien containing_scope = TYPE_CONTEXT (t); 957890075Sobrien 957950397Sobrien /* Ignore namespaces for the moment. */ 958050397Sobrien if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL) 958150397Sobrien containing_scope = NULL_TREE; 958250397Sobrien 958352284Sobrien /* Ignore function type "scopes" from the C frontend. They mean that 958452284Sobrien a tagged type is local to a parmlist of a function declarator, but 958552284Sobrien that isn't useful to DWARF. */ 958652284Sobrien if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE) 958752284Sobrien containing_scope = NULL_TREE; 958852284Sobrien 958950397Sobrien if (containing_scope == NULL_TREE) 959050397Sobrien scope_die = comp_unit_die; 959190075Sobrien else if (TYPE_P (containing_scope)) 959250397Sobrien { 959390075Sobrien /* For types, we can just look up the appropriate DIE. But 959490075Sobrien first we check to see if we're in the middle of emitting it 959590075Sobrien so we know where the new DIE should go. */ 959690075Sobrien for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i) 959790075Sobrien if (VARRAY_TREE (decl_scope_table, i) == containing_scope) 959890075Sobrien break; 959950397Sobrien 960050397Sobrien if (i < 0) 960150397Sobrien { 960250397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE 960350397Sobrien && !TREE_ASM_WRITTEN (containing_scope)) 960450397Sobrien abort (); 960552284Sobrien 960652284Sobrien /* If none of the current dies are suitable, we get file scope. */ 960752284Sobrien scope_die = comp_unit_die; 960850397Sobrien } 960990075Sobrien else 961090075Sobrien scope_die = lookup_type_die (containing_scope); 961150397Sobrien } 961290075Sobrien else 961390075Sobrien scope_die = context_die; 961450397Sobrien 961550397Sobrien return scope_die; 961650397Sobrien} 961750397Sobrien 961890075Sobrien/* Returns nonzero if CONTEXT_DIE is internal to a function. */ 961990075Sobrien 962090075Sobrienstatic inline int 962190075Sobrienlocal_scope_p (context_die) 962290075Sobrien dw_die_ref context_die; 962350397Sobrien{ 962490075Sobrien for (; context_die; context_die = context_die->die_parent) 962590075Sobrien if (context_die->die_tag == DW_TAG_inlined_subroutine 962690075Sobrien || context_die->die_tag == DW_TAG_subprogram) 962790075Sobrien return 1; 962890075Sobrien 962990075Sobrien return 0; 963050397Sobrien} 963150397Sobrien 963290075Sobrien/* Returns nonzero if CONTEXT_DIE is a class. */ 963390075Sobrien 963490075Sobrienstatic inline int 963590075Sobrienclass_scope_p (context_die) 963690075Sobrien dw_die_ref context_die; 963790075Sobrien{ 963890075Sobrien return (context_die 963990075Sobrien && (context_die->die_tag == DW_TAG_structure_type 964090075Sobrien || context_die->die_tag == DW_TAG_union_type)); 964190075Sobrien} 964290075Sobrien 964350397Sobrien/* Many forms of DIEs require a "type description" attribute. This 964450397Sobrien routine locates the proper "type descriptor" die for the type given 964550397Sobrien by 'type', and adds an DW_AT_type attribute below the given die. */ 964650397Sobrien 964750397Sobrienstatic void 964850397Sobrienadd_type_attribute (object_die, type, decl_const, decl_volatile, context_die) 964990075Sobrien dw_die_ref object_die; 965090075Sobrien tree type; 965190075Sobrien int decl_const; 965290075Sobrien int decl_volatile; 965390075Sobrien dw_die_ref context_die; 965450397Sobrien{ 965590075Sobrien enum tree_code code = TREE_CODE (type); 965690075Sobrien dw_die_ref type_die = NULL; 965750397Sobrien 965850397Sobrien /* ??? If this type is an unnamed subrange type of an integral or 965950397Sobrien floating-point type, use the inner type. This is because we have no 966050397Sobrien support for unnamed types in base_type_die. This can happen if this is 966150397Sobrien an Ada subrange type. Correct solution is emit a subrange type die. */ 966250397Sobrien if ((code == INTEGER_TYPE || code == REAL_TYPE) 966350397Sobrien && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0) 966450397Sobrien type = TREE_TYPE (type), code = TREE_CODE (type); 966550397Sobrien 966690075Sobrien if (code == ERROR_MARK 966790075Sobrien /* Handle a special case. For functions whose return type is void, we 966890075Sobrien generate *no* type attribute. (Note that no object may have type 966990075Sobrien `void', so this only applies to function return types). */ 967090075Sobrien || code == VOID_TYPE) 967150397Sobrien return; 967250397Sobrien 967350397Sobrien type_die = modified_type_die (type, 967450397Sobrien decl_const || TYPE_READONLY (type), 967550397Sobrien decl_volatile || TYPE_VOLATILE (type), 967650397Sobrien context_die); 967790075Sobrien 967850397Sobrien if (type_die != NULL) 967950397Sobrien add_AT_die_ref (object_die, DW_AT_type, type_die); 968050397Sobrien} 968150397Sobrien 968250397Sobrien/* Given a tree pointer to a struct, class, union, or enum type node, return 968350397Sobrien a pointer to the (string) tag name for the given type, or zero if the type 968450397Sobrien was declared without a tag. */ 968550397Sobrien 968690075Sobrienstatic const char * 968750397Sobrientype_tag (type) 968890075Sobrien tree type; 968950397Sobrien{ 969090075Sobrien const char *name = 0; 969150397Sobrien 969250397Sobrien if (TYPE_NAME (type) != 0) 969350397Sobrien { 969490075Sobrien tree t = 0; 969550397Sobrien 969650397Sobrien /* Find the IDENTIFIER_NODE for the type name. */ 969750397Sobrien if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 969850397Sobrien t = TYPE_NAME (type); 969950397Sobrien 970090075Sobrien /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 970150397Sobrien a TYPE_DECL node, regardless of whether or not a `typedef' was 970250397Sobrien involved. */ 970350397Sobrien else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 970450397Sobrien && ! DECL_IGNORED_P (TYPE_NAME (type))) 970550397Sobrien t = DECL_NAME (TYPE_NAME (type)); 970650397Sobrien 970750397Sobrien /* Now get the name as a string, or invent one. */ 970850397Sobrien if (t != 0) 970950397Sobrien name = IDENTIFIER_POINTER (t); 971050397Sobrien } 971150397Sobrien 971250397Sobrien return (name == 0 || *name == '\0') ? 0 : name; 971350397Sobrien} 971450397Sobrien 971550397Sobrien/* Return the type associated with a data member, make a special check 971650397Sobrien for bit field types. */ 971750397Sobrien 971850397Sobrienstatic inline tree 971950397Sobrienmember_declared_type (member) 972090075Sobrien tree member; 972150397Sobrien{ 972250397Sobrien return (DECL_BIT_FIELD_TYPE (member) 972390075Sobrien ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member)); 972450397Sobrien} 972550397Sobrien 972650397Sobrien/* Get the decl's label, as described by its RTL. This may be different 972750397Sobrien from the DECL_NAME name used in the source file. */ 972850397Sobrien 972950397Sobrien#if 0 973090075Sobrienstatic const char * 973150397Sobriendecl_start_label (decl) 973290075Sobrien tree decl; 973350397Sobrien{ 973450397Sobrien rtx x; 973590075Sobrien const char *fnname; 973690075Sobrien 973750397Sobrien x = DECL_RTL (decl); 973850397Sobrien if (GET_CODE (x) != MEM) 973950397Sobrien abort (); 974050397Sobrien 974150397Sobrien x = XEXP (x, 0); 974250397Sobrien if (GET_CODE (x) != SYMBOL_REF) 974350397Sobrien abort (); 974450397Sobrien 974550397Sobrien fnname = XSTR (x, 0); 974650397Sobrien return fnname; 974750397Sobrien} 974850397Sobrien#endif 974950397Sobrien 975050397Sobrien/* These routines generate the internal representation of the DIE's for 975150397Sobrien the compilation unit. Debugging information is collected by walking 975250397Sobrien the declaration trees passed in from dwarf2out_decl(). */ 975350397Sobrien 975450397Sobrienstatic void 975550397Sobriengen_array_type_die (type, context_die) 975690075Sobrien tree type; 975790075Sobrien dw_die_ref context_die; 975850397Sobrien{ 975990075Sobrien dw_die_ref scope_die = scope_die_for (type, context_die); 976090075Sobrien dw_die_ref array_die; 976190075Sobrien tree element_type; 976250397Sobrien 976350397Sobrien /* ??? The SGI dwarf reader fails for array of array of enum types unless 976450397Sobrien the inner array type comes before the outer array type. Thus we must 976550397Sobrien call gen_type_die before we call new_die. See below also. */ 976650397Sobrien#ifdef MIPS_DEBUGGING_INFO 976750397Sobrien gen_type_die (TREE_TYPE (type), context_die); 976850397Sobrien#endif 976950397Sobrien 977090075Sobrien array_die = new_die (DW_TAG_array_type, scope_die, type); 977196263Sobrien add_name_attribute (array_die, type_tag (type)); 977296263Sobrien equate_type_number_to_die (type, array_die); 977350397Sobrien 977496263Sobrien if (TREE_CODE (type) == VECTOR_TYPE) 977596263Sobrien { 977696263Sobrien /* The frontend feeds us a representation for the vector as a struct 977796263Sobrien containing an array. Pull out the array type. */ 977896263Sobrien type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type))); 977996263Sobrien add_AT_flag (array_die, DW_AT_GNU_vector, 1); 978096263Sobrien } 978196263Sobrien 978250397Sobrien#if 0 978350397Sobrien /* We default the array ordering. SDB will probably do 978450397Sobrien the right things even if DW_AT_ordering is not present. It's not even 978550397Sobrien an issue until we start to get into multidimensional arrays anyway. If 978650397Sobrien SDB is ever caught doing the Wrong Thing for multi-dimensional arrays, 978750397Sobrien then we'll have to put the DW_AT_ordering attribute back in. (But if 978850397Sobrien and when we find out that we need to put these in, we will only do so 978950397Sobrien for multidimensional arrays. */ 979050397Sobrien add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major); 979150397Sobrien#endif 979250397Sobrien 979350397Sobrien#ifdef MIPS_DEBUGGING_INFO 979450397Sobrien /* The SGI compilers handle arrays of unknown bound by setting 979550397Sobrien AT_declaration and not emitting any subrange DIEs. */ 979650397Sobrien if (! TYPE_DOMAIN (type)) 979750397Sobrien add_AT_unsigned (array_die, DW_AT_declaration, 1); 979850397Sobrien else 979950397Sobrien#endif 980050397Sobrien add_subscript_info (array_die, type); 980150397Sobrien 980250397Sobrien /* Add representation of the type of the elements of this array type. */ 980350397Sobrien element_type = TREE_TYPE (type); 980450397Sobrien 980550397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 980650397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 980750397Sobrien We work around this by disabling this feature. See also 980850397Sobrien add_subscript_info. */ 980950397Sobrien#ifndef MIPS_DEBUGGING_INFO 981050397Sobrien while (TREE_CODE (element_type) == ARRAY_TYPE) 981150397Sobrien element_type = TREE_TYPE (element_type); 981250397Sobrien 981350397Sobrien gen_type_die (element_type, context_die); 981450397Sobrien#endif 981550397Sobrien 981650397Sobrien add_type_attribute (array_die, element_type, 0, 0, context_die); 981750397Sobrien} 981850397Sobrien 981950397Sobrienstatic void 982050397Sobriengen_set_type_die (type, context_die) 982190075Sobrien tree type; 982290075Sobrien dw_die_ref context_die; 982350397Sobrien{ 982490075Sobrien dw_die_ref type_die 982590075Sobrien = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type); 982650397Sobrien 982750397Sobrien equate_type_number_to_die (type, type_die); 982850397Sobrien add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die); 982950397Sobrien} 983050397Sobrien 983150397Sobrien#if 0 983250397Sobrienstatic void 983350397Sobriengen_entry_point_die (decl, context_die) 983490075Sobrien tree decl; 983590075Sobrien dw_die_ref context_die; 983650397Sobrien{ 983790075Sobrien tree origin = decl_ultimate_origin (decl); 983890075Sobrien dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl); 983990075Sobrien 984050397Sobrien if (origin != NULL) 984150397Sobrien add_abstract_origin_attribute (decl_die, origin); 984250397Sobrien else 984350397Sobrien { 984450397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 984550397Sobrien add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)), 984650397Sobrien 0, 0, context_die); 984750397Sobrien } 984850397Sobrien 984950397Sobrien if (DECL_ABSTRACT (decl)) 985050397Sobrien equate_decl_number_to_die (decl, decl_die); 985150397Sobrien else 985250397Sobrien add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl)); 985350397Sobrien} 985450397Sobrien#endif 985550397Sobrien 985652284Sobrien/* Walk through the list of incomplete types again, trying once more to 985752284Sobrien emit full debugging info for them. */ 985852284Sobrien 985952284Sobrienstatic void 986052284Sobrienretry_incomplete_types () 986152284Sobrien{ 986290075Sobrien int i; 986352284Sobrien 986490075Sobrien for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--) 986590075Sobrien gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die); 986652284Sobrien} 986752284Sobrien 986850397Sobrien/* Generate a DIE to represent an inlined instance of an enumeration type. */ 986950397Sobrien 987050397Sobrienstatic void 987150397Sobriengen_inlined_enumeration_type_die (type, context_die) 987290075Sobrien tree type; 987390075Sobrien dw_die_ref context_die; 987450397Sobrien{ 987590075Sobrien dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type); 987650397Sobrien 987790075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 987890075Sobrien be incomplete and such types are not marked. */ 987950397Sobrien add_abstract_origin_attribute (type_die, type); 988050397Sobrien} 988150397Sobrien 988250397Sobrien/* Generate a DIE to represent an inlined instance of a structure type. */ 988350397Sobrien 988450397Sobrienstatic void 988550397Sobriengen_inlined_structure_type_die (type, context_die) 988690075Sobrien tree type; 988790075Sobrien dw_die_ref context_die; 988850397Sobrien{ 988990075Sobrien dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type); 989050397Sobrien 989190075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 989290075Sobrien be incomplete and such types are not marked. */ 989350397Sobrien add_abstract_origin_attribute (type_die, type); 989450397Sobrien} 989550397Sobrien 989650397Sobrien/* Generate a DIE to represent an inlined instance of a union type. */ 989750397Sobrien 989850397Sobrienstatic void 989950397Sobriengen_inlined_union_type_die (type, context_die) 990090075Sobrien tree type; 990190075Sobrien dw_die_ref context_die; 990250397Sobrien{ 990390075Sobrien dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type); 990450397Sobrien 990590075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 990690075Sobrien be incomplete and such types are not marked. */ 990750397Sobrien add_abstract_origin_attribute (type_die, type); 990850397Sobrien} 990950397Sobrien 991050397Sobrien/* Generate a DIE to represent an enumeration type. Note that these DIEs 991150397Sobrien include all of the information about the enumeration values also. Each 991250397Sobrien enumerated type name/value is listed as a child of the enumerated type 991350397Sobrien DIE. */ 991450397Sobrien 991550397Sobrienstatic void 991650397Sobriengen_enumeration_type_die (type, context_die) 991790075Sobrien tree type; 991890075Sobrien dw_die_ref context_die; 991950397Sobrien{ 992090075Sobrien dw_die_ref type_die = lookup_type_die (type); 992150397Sobrien 992250397Sobrien if (type_die == NULL) 992350397Sobrien { 992450397Sobrien type_die = new_die (DW_TAG_enumeration_type, 992590075Sobrien scope_die_for (type, context_die), type); 992650397Sobrien equate_type_number_to_die (type, type_die); 992750397Sobrien add_name_attribute (type_die, type_tag (type)); 992850397Sobrien } 992950397Sobrien else if (! TYPE_SIZE (type)) 993050397Sobrien return; 993150397Sobrien else 993250397Sobrien remove_AT (type_die, DW_AT_declaration); 993350397Sobrien 993450397Sobrien /* Handle a GNU C/C++ extension, i.e. incomplete enum types. If the 993550397Sobrien given enum type is incomplete, do not generate the DW_AT_byte_size 993650397Sobrien attribute or the DW_AT_element_list attribute. */ 993750397Sobrien if (TYPE_SIZE (type)) 993850397Sobrien { 993990075Sobrien tree link; 994050397Sobrien 994150397Sobrien TREE_ASM_WRITTEN (type) = 1; 994250397Sobrien add_byte_size_attribute (type_die, type); 994350397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 994450397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 994550397Sobrien 994650397Sobrien /* If the first reference to this type was as the return type of an 994750397Sobrien inline function, then it may not have a parent. Fix this now. */ 994850397Sobrien if (type_die->die_parent == NULL) 994950397Sobrien add_child_die (scope_die_for (type, context_die), type_die); 995050397Sobrien 995150397Sobrien for (link = TYPE_FIELDS (type); 995250397Sobrien link != NULL; link = TREE_CHAIN (link)) 995350397Sobrien { 995490075Sobrien dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link); 995550397Sobrien 995650397Sobrien add_name_attribute (enum_die, 995750397Sobrien IDENTIFIER_POINTER (TREE_PURPOSE (link))); 995890075Sobrien 995990075Sobrien if (host_integerp (TREE_VALUE (link), 0)) 996090075Sobrien { 996190075Sobrien if (tree_int_cst_sgn (TREE_VALUE (link)) < 0) 996290075Sobrien add_AT_int (enum_die, DW_AT_const_value, 996390075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 996490075Sobrien else 996590075Sobrien add_AT_unsigned (enum_die, DW_AT_const_value, 996690075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 996790075Sobrien } 996850397Sobrien } 996950397Sobrien } 997050397Sobrien else 997150397Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 997250397Sobrien} 997350397Sobrien 997450397Sobrien/* Generate a DIE to represent either a real live formal parameter decl or to 997550397Sobrien represent just the type of some formal parameter position in some function 997650397Sobrien type. 997750397Sobrien 997850397Sobrien Note that this routine is a bit unusual because its argument may be a 997950397Sobrien ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which 998050397Sobrien represents an inlining of some PARM_DECL) or else some sort of a ..._TYPE 998150397Sobrien node. If it's the former then this function is being called to output a 998250397Sobrien DIE to represent a formal parameter object (or some inlining thereof). If 998350397Sobrien it's the latter, then this function is only being called to output a 998450397Sobrien DW_TAG_formal_parameter DIE to stand as a placeholder for some formal 998550397Sobrien argument type of some subprogram type. */ 998650397Sobrien 998750397Sobrienstatic dw_die_ref 998850397Sobriengen_formal_parameter_die (node, context_die) 998990075Sobrien tree node; 999090075Sobrien dw_die_ref context_die; 999150397Sobrien{ 999290075Sobrien dw_die_ref parm_die 999390075Sobrien = new_die (DW_TAG_formal_parameter, context_die, node); 999490075Sobrien tree origin; 999550397Sobrien 999650397Sobrien switch (TREE_CODE_CLASS (TREE_CODE (node))) 999750397Sobrien { 999850397Sobrien case 'd': 999950397Sobrien origin = decl_ultimate_origin (node); 1000050397Sobrien if (origin != NULL) 1000150397Sobrien add_abstract_origin_attribute (parm_die, origin); 1000250397Sobrien else 1000350397Sobrien { 1000450397Sobrien add_name_and_src_coords_attributes (parm_die, node); 1000550397Sobrien add_type_attribute (parm_die, TREE_TYPE (node), 1000650397Sobrien TREE_READONLY (node), 1000750397Sobrien TREE_THIS_VOLATILE (node), 1000850397Sobrien context_die); 1000950397Sobrien if (DECL_ARTIFICIAL (node)) 1001050397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 1001150397Sobrien } 1001250397Sobrien 1001350397Sobrien equate_decl_number_to_die (node, parm_die); 1001450397Sobrien if (! DECL_ABSTRACT (node)) 1001550397Sobrien add_location_or_const_value_attribute (parm_die, node); 1001650397Sobrien 1001750397Sobrien break; 1001850397Sobrien 1001950397Sobrien case 't': 1002050397Sobrien /* We were called with some kind of a ..._TYPE node. */ 1002150397Sobrien add_type_attribute (parm_die, node, 0, 0, context_die); 1002250397Sobrien break; 1002350397Sobrien 1002450397Sobrien default: 1002550397Sobrien abort (); 1002650397Sobrien } 1002750397Sobrien 1002850397Sobrien return parm_die; 1002950397Sobrien} 1003050397Sobrien 1003150397Sobrien/* Generate a special type of DIE used as a stand-in for a trailing ellipsis 1003250397Sobrien at the end of an (ANSI prototyped) formal parameters list. */ 1003350397Sobrien 1003450397Sobrienstatic void 1003550397Sobriengen_unspecified_parameters_die (decl_or_type, context_die) 1003690075Sobrien tree decl_or_type; 1003790075Sobrien dw_die_ref context_die; 1003850397Sobrien{ 1003990075Sobrien new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type); 1004050397Sobrien} 1004150397Sobrien 1004250397Sobrien/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a 1004350397Sobrien DW_TAG_unspecified_parameters DIE) to represent the types of the formal 1004450397Sobrien parameters as specified in some function type specification (except for 1004590075Sobrien those which appear as part of a function *definition*). */ 1004650397Sobrien 1004750397Sobrienstatic void 1004850397Sobriengen_formal_types_die (function_or_method_type, context_die) 1004990075Sobrien tree function_or_method_type; 1005090075Sobrien dw_die_ref context_die; 1005150397Sobrien{ 1005290075Sobrien tree link; 1005390075Sobrien tree formal_type = NULL; 1005490075Sobrien tree first_parm_type; 1005590075Sobrien tree arg; 1005650397Sobrien 1005790075Sobrien if (TREE_CODE (function_or_method_type) == FUNCTION_DECL) 1005890075Sobrien { 1005990075Sobrien arg = DECL_ARGUMENTS (function_or_method_type); 1006090075Sobrien function_or_method_type = TREE_TYPE (function_or_method_type); 1006190075Sobrien } 1006290075Sobrien else 1006390075Sobrien arg = NULL_TREE; 1006490075Sobrien 1006590075Sobrien first_parm_type = TYPE_ARG_TYPES (function_or_method_type); 1006650397Sobrien 1006790075Sobrien /* Make our first pass over the list of formal parameter types and output a 1006850397Sobrien DW_TAG_formal_parameter DIE for each one. */ 1006990075Sobrien for (link = first_parm_type; link; ) 1007050397Sobrien { 1007190075Sobrien dw_die_ref parm_die; 1007290075Sobrien 1007350397Sobrien formal_type = TREE_VALUE (link); 1007450397Sobrien if (formal_type == void_type_node) 1007550397Sobrien break; 1007650397Sobrien 1007750397Sobrien /* Output a (nameless) DIE to represent the formal parameter itself. */ 1007850397Sobrien parm_die = gen_formal_parameter_die (formal_type, context_die); 1007990075Sobrien if ((TREE_CODE (function_or_method_type) == METHOD_TYPE 1008090075Sobrien && link == first_parm_type) 1008190075Sobrien || (arg && DECL_ARTIFICIAL (arg))) 1008250397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 1008390075Sobrien 1008490075Sobrien link = TREE_CHAIN (link); 1008590075Sobrien if (arg) 1008690075Sobrien arg = TREE_CHAIN (arg); 1008750397Sobrien } 1008850397Sobrien 1008950397Sobrien /* If this function type has an ellipsis, add a 1009050397Sobrien DW_TAG_unspecified_parameters DIE to the end of the parameter list. */ 1009150397Sobrien if (formal_type != void_type_node) 1009250397Sobrien gen_unspecified_parameters_die (function_or_method_type, context_die); 1009350397Sobrien 1009490075Sobrien /* Make our second (and final) pass over the list of formal parameter types 1009550397Sobrien and output DIEs to represent those types (as necessary). */ 1009650397Sobrien for (link = TYPE_ARG_TYPES (function_or_method_type); 1009790075Sobrien link && TREE_VALUE (link); 1009850397Sobrien link = TREE_CHAIN (link)) 1009990075Sobrien gen_type_die (TREE_VALUE (link), context_die); 1010090075Sobrien} 1010190075Sobrien 1010290075Sobrien/* We want to generate the DIE for TYPE so that we can generate the 1010390075Sobrien die for MEMBER, which has been defined; we will need to refer back 1010490075Sobrien to the member declaration nested within TYPE. If we're trying to 1010590075Sobrien generate minimal debug info for TYPE, processing TYPE won't do the 1010690075Sobrien trick; we need to attach the member declaration by hand. */ 1010790075Sobrien 1010890075Sobrienstatic void 1010990075Sobriengen_type_die_for_member (type, member, context_die) 1011090075Sobrien tree type, member; 1011190075Sobrien dw_die_ref context_die; 1011290075Sobrien{ 1011390075Sobrien gen_type_die (type, context_die); 1011490075Sobrien 1011590075Sobrien /* If we're trying to avoid duplicate debug info, we may not have 1011690075Sobrien emitted the member decl for this function. Emit it now. */ 1011790075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) 1011890075Sobrien && ! lookup_decl_die (member)) 1011950397Sobrien { 1012090075Sobrien if (decl_ultimate_origin (member)) 1012190075Sobrien abort (); 1012250397Sobrien 1012390075Sobrien push_decl_scope (type); 1012490075Sobrien if (TREE_CODE (member) == FUNCTION_DECL) 1012590075Sobrien gen_subprogram_die (member, lookup_type_die (type)); 1012690075Sobrien else 1012790075Sobrien gen_variable_die (member, lookup_type_die (type)); 1012890075Sobrien 1012990075Sobrien pop_decl_scope (); 1013050397Sobrien } 1013150397Sobrien} 1013250397Sobrien 1013390075Sobrien/* Generate the DWARF2 info for the "abstract" instance of a function which we 1013490075Sobrien may later generate inlined and/or out-of-line instances of. */ 1013590075Sobrien 1013690075Sobrienstatic void 1013790075Sobriendwarf2out_abstract_function (decl) 1013890075Sobrien tree decl; 1013990075Sobrien{ 1014090075Sobrien dw_die_ref old_die; 1014190075Sobrien tree save_fn; 1014290075Sobrien tree context; 1014390075Sobrien int was_abstract = DECL_ABSTRACT (decl); 1014490075Sobrien 1014590075Sobrien /* Make sure we have the actual abstract inline, not a clone. */ 1014690075Sobrien decl = DECL_ORIGIN (decl); 1014790075Sobrien 1014890075Sobrien old_die = lookup_decl_die (decl); 1014990075Sobrien if (old_die && get_AT_unsigned (old_die, DW_AT_inline)) 1015090075Sobrien /* We've already generated the abstract instance. */ 1015190075Sobrien return; 1015290075Sobrien 1015390075Sobrien /* Be sure we've emitted the in-class declaration DIE (if any) first, so 1015490075Sobrien we don't get confused by DECL_ABSTRACT. */ 1015590075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1015690075Sobrien { 1015790075Sobrien context = decl_class_context (decl); 1015890075Sobrien if (context) 1015990075Sobrien gen_type_die_for_member 1016090075Sobrien (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); 1016190075Sobrien } 1016290075Sobrien 1016390075Sobrien /* Pretend we've just finished compiling this function. */ 1016490075Sobrien save_fn = current_function_decl; 1016590075Sobrien current_function_decl = decl; 1016690075Sobrien 1016790075Sobrien set_decl_abstract_flags (decl, 1); 1016890075Sobrien dwarf2out_decl (decl); 1016990075Sobrien if (! was_abstract) 1017090075Sobrien set_decl_abstract_flags (decl, 0); 1017190075Sobrien 1017290075Sobrien current_function_decl = save_fn; 1017390075Sobrien} 1017490075Sobrien 1017550397Sobrien/* Generate a DIE to represent a declared function (either file-scope or 1017650397Sobrien block-local). */ 1017750397Sobrien 1017850397Sobrienstatic void 1017950397Sobriengen_subprogram_die (decl, context_die) 1018090075Sobrien tree decl; 1018190075Sobrien dw_die_ref context_die; 1018250397Sobrien{ 1018350397Sobrien char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 1018490075Sobrien tree origin = decl_ultimate_origin (decl); 1018590075Sobrien dw_die_ref subr_die; 1018690075Sobrien rtx fp_reg; 1018790075Sobrien tree fn_arg_types; 1018890075Sobrien tree outer_scope; 1018990075Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1019090075Sobrien int declaration = (current_function_decl != decl 1019190075Sobrien || class_scope_p (context_die)); 1019250397Sobrien 1019390075Sobrien /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we 1019490075Sobrien started to generate the abstract instance of an inline, decided to output 1019590075Sobrien its containing class, and proceeded to emit the declaration of the inline 1019690075Sobrien from the member list for the class. If so, DECLARATION takes priority; 1019790075Sobrien we'll get back to the abstract instance when done with the class. */ 1019890075Sobrien 1019990075Sobrien /* The class-scope declaration DIE must be the primary DIE. */ 1020090075Sobrien if (origin && declaration && class_scope_p (context_die)) 1020150397Sobrien { 1020290075Sobrien origin = NULL; 1020390075Sobrien if (old_die) 1020490075Sobrien abort (); 1020550397Sobrien } 1020690075Sobrien 1020790075Sobrien if (origin != NULL) 1020850397Sobrien { 1020990075Sobrien if (declaration && ! local_scope_p (context_die)) 1021090075Sobrien abort (); 1021150397Sobrien 1021290075Sobrien /* Fixup die_parent for the abstract instance of a nested 1021390075Sobrien inline function. */ 1021490075Sobrien if (old_die && old_die->die_parent == NULL) 1021590075Sobrien add_child_die (context_die, old_die); 1021690075Sobrien 1021790075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1021890075Sobrien add_abstract_origin_attribute (subr_die, origin); 1021950397Sobrien } 1022050397Sobrien else if (old_die) 1022150397Sobrien { 1022290075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1022350397Sobrien 1022490075Sobrien if (!get_AT_flag (old_die, DW_AT_declaration) 1022590075Sobrien /* We can have a normal definition following an inline one in the 1022690075Sobrien case of redefinition of GNU C extern inlines. 1022790075Sobrien It seems reasonable to use AT_specification in this case. */ 1022890075Sobrien && !get_AT_unsigned (old_die, DW_AT_inline)) 1022952284Sobrien { 1023052284Sobrien /* ??? This can happen if there is a bug in the program, for 1023152284Sobrien instance, if it has duplicate function definitions. Ideally, 1023252284Sobrien we should detect this case and ignore it. For now, if we have 1023352284Sobrien already reported an error, any error at all, then assume that 1023490075Sobrien we got here because of an input error, not a dwarf2 bug. */ 1023552284Sobrien if (errorcount) 1023652284Sobrien return; 1023752284Sobrien abort (); 1023852284Sobrien } 1023950397Sobrien 1024050397Sobrien /* If the definition comes from the same place as the declaration, 1024150397Sobrien maybe use the old DIE. We always want the DIE for this function 1024250397Sobrien that has the *_pc attributes to be under comp_unit_die so the 1024390075Sobrien debugger can find it. We also need to do this for abstract 1024490075Sobrien instances of inlines, since the spec requires the out-of-line copy 1024590075Sobrien to have the same parent. For local class methods, this doesn't 1024690075Sobrien apply; we just use the old DIE. */ 1024790075Sobrien if ((old_die->die_parent == comp_unit_die || context_die == NULL) 1024890075Sobrien && (DECL_ARTIFICIAL (decl) 1024990075Sobrien || (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index 1025090075Sobrien && (get_AT_unsigned (old_die, DW_AT_decl_line) 1025190075Sobrien == (unsigned) DECL_SOURCE_LINE (decl))))) 1025250397Sobrien { 1025350397Sobrien subr_die = old_die; 1025450397Sobrien 1025550397Sobrien /* Clear out the declaration attribute and the parm types. */ 1025650397Sobrien remove_AT (subr_die, DW_AT_declaration); 1025750397Sobrien remove_children (subr_die); 1025850397Sobrien } 1025950397Sobrien else 1026050397Sobrien { 1026190075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1026250397Sobrien add_AT_die_ref (subr_die, DW_AT_specification, old_die); 1026350397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1026450397Sobrien add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); 1026550397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1026690075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1026750397Sobrien add_AT_unsigned 1026850397Sobrien (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 1026950397Sobrien } 1027050397Sobrien } 1027150397Sobrien else 1027250397Sobrien { 1027390075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1027450397Sobrien 1027550397Sobrien if (TREE_PUBLIC (decl)) 1027650397Sobrien add_AT_flag (subr_die, DW_AT_external, 1); 1027750397Sobrien 1027850397Sobrien add_name_and_src_coords_attributes (subr_die, decl); 1027950397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1028050397Sobrien { 1028190075Sobrien add_prototyped_attribute (subr_die, TREE_TYPE (decl)); 1028290075Sobrien add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)), 1028390075Sobrien 0, 0, context_die); 1028450397Sobrien } 1028550397Sobrien 1028650397Sobrien add_pure_or_virtual_attribute (subr_die, decl); 1028750397Sobrien if (DECL_ARTIFICIAL (decl)) 1028850397Sobrien add_AT_flag (subr_die, DW_AT_artificial, 1); 1028990075Sobrien 1029050397Sobrien if (TREE_PROTECTED (decl)) 1029150397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected); 1029250397Sobrien else if (TREE_PRIVATE (decl)) 1029350397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private); 1029450397Sobrien } 1029550397Sobrien 1029650397Sobrien if (declaration) 1029750397Sobrien { 1029890075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1029990075Sobrien { 1030090075Sobrien add_AT_flag (subr_die, DW_AT_declaration, 1); 1030150397Sobrien 1030290075Sobrien /* The first time we see a member function, it is in the context of 1030390075Sobrien the class to which it belongs. We make sure of this by emitting 1030490075Sobrien the class first. The next time is the definition, which is 1030590075Sobrien handled above. The two may come from the same source text. */ 1030690075Sobrien if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl)) 1030790075Sobrien equate_decl_number_to_die (decl, subr_die); 1030890075Sobrien } 1030950397Sobrien } 1031050397Sobrien else if (DECL_ABSTRACT (decl)) 1031150397Sobrien { 1031290075Sobrien if (DECL_INLINE (decl) && !flag_no_inline) 1031350397Sobrien { 1031490075Sobrien /* ??? Checking DECL_DEFER_OUTPUT is correct for static 1031590075Sobrien inline functions, but not for extern inline functions. 1031690075Sobrien We can't get this completely correct because information 1031790075Sobrien about whether the function was declared inline is not 1031890075Sobrien saved anywhere. */ 1031990075Sobrien if (DECL_DEFER_OUTPUT (decl)) 1032050397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined); 1032150397Sobrien else 1032290075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); 1032350397Sobrien } 1032450397Sobrien else 1032590075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined); 1032650397Sobrien 1032750397Sobrien equate_decl_number_to_die (decl, subr_die); 1032850397Sobrien } 1032950397Sobrien else if (!DECL_EXTERNAL (decl)) 1033050397Sobrien { 1033190075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1033250397Sobrien equate_decl_number_to_die (decl, subr_die); 1033350397Sobrien 1033450397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, 1033550397Sobrien current_funcdef_number); 1033650397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); 1033750397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, 1033850397Sobrien current_funcdef_number); 1033950397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); 1034050397Sobrien 1034150397Sobrien add_pubname (decl, subr_die); 1034250397Sobrien add_arange (decl, subr_die); 1034350397Sobrien 1034450397Sobrien#ifdef MIPS_DEBUGGING_INFO 1034550397Sobrien /* Add a reference to the FDE for this routine. */ 1034650397Sobrien add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); 1034750397Sobrien#endif 1034850397Sobrien 1034950397Sobrien /* Define the "frame base" location for this routine. We use the 1035050397Sobrien frame pointer or stack pointer registers, since the RTL for local 1035150397Sobrien variables is relative to one of them. */ 1035250397Sobrien fp_reg 1035350397Sobrien = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; 1035450397Sobrien add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); 1035550397Sobrien 1035650397Sobrien#if 0 1035750397Sobrien /* ??? This fails for nested inline functions, because context_display 1035850397Sobrien is not part of the state saved/restored for inline functions. */ 1035950397Sobrien if (current_function_needs_context) 1036050397Sobrien add_AT_location_description (subr_die, DW_AT_static_link, 1036150397Sobrien lookup_static_chain (decl)); 1036250397Sobrien#endif 1036350397Sobrien } 1036450397Sobrien 1036550397Sobrien /* Now output descriptions of the arguments for this function. This gets 1036690075Sobrien (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list 1036750397Sobrien for a FUNCTION_DECL doesn't indicate cases where there was a trailing 1036850397Sobrien `...' at the end of the formal parameter list. In order to find out if 1036950397Sobrien there was a trailing ellipsis or not, we must instead look at the type 1037050397Sobrien associated with the FUNCTION_DECL. This will be a node of type 1037150397Sobrien FUNCTION_TYPE. If the chain of type nodes hanging off of this 1037290075Sobrien FUNCTION_TYPE node ends with a void_type_node then there should *not* be 1037350397Sobrien an ellipsis at the end. */ 1037450397Sobrien 1037550397Sobrien /* In the case where we are describing a mere function declaration, all we 1037690075Sobrien need to do here (and all we *can* do here) is to describe the *types* of 1037750397Sobrien its formal parameters. */ 1037850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1037950397Sobrien ; 1038050397Sobrien else if (declaration) 1038190075Sobrien gen_formal_types_die (decl, subr_die); 1038250397Sobrien else 1038350397Sobrien { 1038450397Sobrien /* Generate DIEs to represent all known formal parameters */ 1038590075Sobrien tree arg_decls = DECL_ARGUMENTS (decl); 1038690075Sobrien tree parm; 1038750397Sobrien 1038850397Sobrien /* When generating DIEs, generate the unspecified_parameters DIE 1038950397Sobrien instead if we come across the arg "__builtin_va_alist" */ 1039050397Sobrien for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) 1039150397Sobrien if (TREE_CODE (parm) == PARM_DECL) 1039250397Sobrien { 1039350397Sobrien if (DECL_NAME (parm) 1039450397Sobrien && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), 1039550397Sobrien "__builtin_va_alist")) 1039650397Sobrien gen_unspecified_parameters_die (parm, subr_die); 1039750397Sobrien else 1039850397Sobrien gen_decl_die (parm, subr_die); 1039950397Sobrien } 1040050397Sobrien 1040190075Sobrien /* Decide whether we need an unspecified_parameters DIE at the end. 1040290075Sobrien There are 2 more cases to do this for: 1) the ansi ... declaration - 1040350397Sobrien this is detectable when the end of the arg list is not a 1040450397Sobrien void_type_node 2) an unprototyped function declaration (not a 1040550397Sobrien definition). This just means that we have no info about the 1040650397Sobrien parameters at all. */ 1040750397Sobrien fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); 1040850397Sobrien if (fn_arg_types != NULL) 1040950397Sobrien { 1041050397Sobrien /* this is the prototyped case, check for ... */ 1041150397Sobrien if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) 1041250397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1041350397Sobrien } 1041450397Sobrien else if (DECL_INITIAL (decl) == NULL_TREE) 1041550397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1041650397Sobrien } 1041750397Sobrien 1041850397Sobrien /* Output Dwarf info for all of the stuff within the body of the function 1041950397Sobrien (if it has one - it may be just a declaration). */ 1042050397Sobrien outer_scope = DECL_INITIAL (decl); 1042150397Sobrien 1042290075Sobrien /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent 1042390075Sobrien a function. This BLOCK actually represents the outermost binding contour 1042490075Sobrien for the function, i.e. the contour in which the function's formal 1042590075Sobrien parameters and labels get declared. Curiously, it appears that the front 1042690075Sobrien end doesn't actually put the PARM_DECL nodes for the current function onto 1042790075Sobrien the BLOCK_VARS list for this outer scope, but are strung off of the 1042890075Sobrien DECL_ARGUMENTS list for the function instead. 1042990075Sobrien 1043090075Sobrien The BLOCK_VARS list for the `outer_scope' does provide us with a list of 1043190075Sobrien the LABEL_DECL nodes for the function however, and we output DWARF info 1043290075Sobrien for those in decls_for_scope. Just within the `outer_scope' there will be 1043390075Sobrien a BLOCK node representing the function's outermost pair of curly braces, 1043490075Sobrien and any blocks used for the base and member initializers of a C++ 1043550397Sobrien constructor function. */ 1043650397Sobrien if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK) 1043750397Sobrien { 1043850397Sobrien current_function_has_inlines = 0; 1043950397Sobrien decls_for_scope (outer_scope, subr_die, 0); 1044050397Sobrien 1044150397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 1044250397Sobrien if (current_function_has_inlines) 1044350397Sobrien { 1044450397Sobrien add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1); 1044550397Sobrien if (! comp_unit_has_inlines) 1044650397Sobrien { 1044750397Sobrien add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1); 1044850397Sobrien comp_unit_has_inlines = 1; 1044950397Sobrien } 1045050397Sobrien } 1045150397Sobrien#endif 1045250397Sobrien } 1045350397Sobrien} 1045450397Sobrien 1045550397Sobrien/* Generate a DIE to represent a declared data object. */ 1045650397Sobrien 1045750397Sobrienstatic void 1045850397Sobriengen_variable_die (decl, context_die) 1045990075Sobrien tree decl; 1046090075Sobrien dw_die_ref context_die; 1046150397Sobrien{ 1046290075Sobrien tree origin = decl_ultimate_origin (decl); 1046390075Sobrien dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl); 1046450397Sobrien 1046550397Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1046690075Sobrien int declaration = (DECL_EXTERNAL (decl) 1046790075Sobrien || class_scope_p (context_die)); 1046850397Sobrien 1046950397Sobrien if (origin != NULL) 1047050397Sobrien add_abstract_origin_attribute (var_die, origin); 1047190075Sobrien 1047250397Sobrien /* Loop unrolling can create multiple blocks that refer to the same 1047390075Sobrien static variable, so we must test for the DW_AT_declaration flag. 1047490075Sobrien 1047590075Sobrien ??? Loop unrolling/reorder_blocks should perhaps be rewritten to 1047650397Sobrien copy decls and set the DECL_ABSTRACT flag on them instead of 1047790075Sobrien sharing them. 1047890075Sobrien 1047990075Sobrien ??? Duplicated blocks have been rewritten to use .debug_ranges. */ 1048050397Sobrien else if (old_die && TREE_STATIC (decl) 1048150397Sobrien && get_AT_flag (old_die, DW_AT_declaration) == 1) 1048250397Sobrien { 1048390075Sobrien /* This is a definition of a C++ class level static. */ 1048450397Sobrien add_AT_die_ref (var_die, DW_AT_specification, old_die); 1048550397Sobrien if (DECL_NAME (decl)) 1048650397Sobrien { 1048790075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1048850397Sobrien 1048950397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1049050397Sobrien add_AT_unsigned (var_die, DW_AT_decl_file, file_index); 1049150397Sobrien 1049250397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1049390075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1049450397Sobrien 1049550397Sobrien add_AT_unsigned (var_die, DW_AT_decl_line, 1049650397Sobrien DECL_SOURCE_LINE (decl)); 1049750397Sobrien } 1049850397Sobrien } 1049950397Sobrien else 1050050397Sobrien { 1050150397Sobrien add_name_and_src_coords_attributes (var_die, decl); 1050290075Sobrien add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl), 1050350397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1050450397Sobrien 1050550397Sobrien if (TREE_PUBLIC (decl)) 1050650397Sobrien add_AT_flag (var_die, DW_AT_external, 1); 1050750397Sobrien 1050850397Sobrien if (DECL_ARTIFICIAL (decl)) 1050950397Sobrien add_AT_flag (var_die, DW_AT_artificial, 1); 1051050397Sobrien 1051150397Sobrien if (TREE_PROTECTED (decl)) 1051250397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); 1051350397Sobrien else if (TREE_PRIVATE (decl)) 1051450397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); 1051550397Sobrien } 1051650397Sobrien 1051750397Sobrien if (declaration) 1051850397Sobrien add_AT_flag (var_die, DW_AT_declaration, 1); 1051990075Sobrien 1052090075Sobrien if (class_scope_p (context_die) || DECL_ABSTRACT (decl)) 1052150397Sobrien equate_decl_number_to_die (decl, var_die); 1052250397Sobrien 1052350397Sobrien if (! declaration && ! DECL_ABSTRACT (decl)) 1052450397Sobrien { 1052550397Sobrien add_location_or_const_value_attribute (var_die, decl); 1052650397Sobrien add_pubname (decl, var_die); 1052750397Sobrien } 1052890075Sobrien else 1052990075Sobrien tree_add_const_value_attribute (var_die, decl); 1053050397Sobrien} 1053150397Sobrien 1053250397Sobrien/* Generate a DIE to represent a label identifier. */ 1053350397Sobrien 1053450397Sobrienstatic void 1053550397Sobriengen_label_die (decl, context_die) 1053690075Sobrien tree decl; 1053790075Sobrien dw_die_ref context_die; 1053850397Sobrien{ 1053990075Sobrien tree origin = decl_ultimate_origin (decl); 1054090075Sobrien dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl); 1054190075Sobrien rtx insn; 1054250397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1054350397Sobrien 1054450397Sobrien if (origin != NULL) 1054550397Sobrien add_abstract_origin_attribute (lbl_die, origin); 1054650397Sobrien else 1054750397Sobrien add_name_and_src_coords_attributes (lbl_die, decl); 1054850397Sobrien 1054950397Sobrien if (DECL_ABSTRACT (decl)) 1055050397Sobrien equate_decl_number_to_die (decl, lbl_die); 1055150397Sobrien else 1055250397Sobrien { 1055350397Sobrien insn = DECL_RTL (decl); 1055452284Sobrien 1055552284Sobrien /* Deleted labels are programmer specified labels which have been 1055652284Sobrien eliminated because of various optimisations. We still emit them 1055752284Sobrien here so that it is possible to put breakpoints on them. */ 1055852284Sobrien if (GET_CODE (insn) == CODE_LABEL 1055952284Sobrien || ((GET_CODE (insn) == NOTE 1056052284Sobrien && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))) 1056150397Sobrien { 1056290075Sobrien /* When optimization is enabled (via -O) some parts of the compiler 1056390075Sobrien (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which 1056450397Sobrien represent source-level labels which were explicitly declared by 1056550397Sobrien the user. This really shouldn't be happening though, so catch 1056650397Sobrien it if it ever does happen. */ 1056750397Sobrien if (INSN_DELETED_P (insn)) 1056850397Sobrien abort (); 1056950397Sobrien 1057090075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn)); 1057150397Sobrien add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); 1057250397Sobrien } 1057350397Sobrien } 1057450397Sobrien} 1057550397Sobrien 1057650397Sobrien/* Generate a DIE for a lexical block. */ 1057750397Sobrien 1057850397Sobrienstatic void 1057950397Sobriengen_lexical_block_die (stmt, context_die, depth) 1058090075Sobrien tree stmt; 1058190075Sobrien dw_die_ref context_die; 1058250397Sobrien int depth; 1058350397Sobrien{ 1058490075Sobrien dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); 1058550397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1058650397Sobrien 1058750397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1058850397Sobrien { 1058990075Sobrien if (BLOCK_FRAGMENT_CHAIN (stmt)) 1059090075Sobrien { 1059190075Sobrien tree chain; 1059290075Sobrien 1059390075Sobrien add_AT_range_list (stmt_die, DW_AT_ranges, add_ranges (stmt)); 1059490075Sobrien 1059590075Sobrien chain = BLOCK_FRAGMENT_CHAIN (stmt); 1059690075Sobrien do 1059790075Sobrien { 1059890075Sobrien add_ranges (chain); 1059990075Sobrien chain = BLOCK_FRAGMENT_CHAIN (chain); 1060090075Sobrien } 1060190075Sobrien while (chain); 1060290075Sobrien add_ranges (NULL); 1060390075Sobrien } 1060490075Sobrien else 1060590075Sobrien { 1060690075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1060790075Sobrien BLOCK_NUMBER (stmt)); 1060890075Sobrien add_AT_lbl_id (stmt_die, DW_AT_low_pc, label); 1060990075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1061090075Sobrien BLOCK_NUMBER (stmt)); 1061190075Sobrien add_AT_lbl_id (stmt_die, DW_AT_high_pc, label); 1061290075Sobrien } 1061350397Sobrien } 1061450397Sobrien 1061550397Sobrien decls_for_scope (stmt, stmt_die, depth); 1061650397Sobrien} 1061750397Sobrien 1061850397Sobrien/* Generate a DIE for an inlined subprogram. */ 1061950397Sobrien 1062050397Sobrienstatic void 1062150397Sobriengen_inlined_subroutine_die (stmt, context_die, depth) 1062290075Sobrien tree stmt; 1062390075Sobrien dw_die_ref context_die; 1062450397Sobrien int depth; 1062550397Sobrien{ 1062650397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1062750397Sobrien { 1062890075Sobrien dw_die_ref subr_die 1062990075Sobrien = new_die (DW_TAG_inlined_subroutine, context_die, stmt); 1063090075Sobrien tree decl = block_ultimate_origin (stmt); 1063150397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1063250397Sobrien 1063390075Sobrien /* Emit info for the abstract instance first, if we haven't yet. */ 1063490075Sobrien dwarf2out_abstract_function (decl); 1063590075Sobrien 1063650397Sobrien add_abstract_origin_attribute (subr_die, decl); 1063750397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1063890075Sobrien BLOCK_NUMBER (stmt)); 1063950397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label); 1064090075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1064190075Sobrien BLOCK_NUMBER (stmt)); 1064250397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label); 1064350397Sobrien decls_for_scope (stmt, subr_die, depth); 1064450397Sobrien current_function_has_inlines = 1; 1064550397Sobrien } 1064696263Sobrien else 1064796263Sobrien /* We may get here if we're the outer block of function A that was 1064896263Sobrien inlined into function B that was inlined into function C. When 1064996263Sobrien generating debugging info for C, dwarf2out_abstract_function(B) 1065096263Sobrien would mark all inlined blocks as abstract, including this one. 1065196263Sobrien So, we wouldn't (and shouldn't) expect labels to be generated 1065296263Sobrien for this one. Instead, just emit debugging info for 1065396263Sobrien declarations within the block. This is particularly important 1065496263Sobrien in the case of initializers of arguments passed from B to us: 1065596263Sobrien if they're statement expressions containing declarations, we 1065696263Sobrien wouldn't generate dies for their abstract variables, and then, 1065796263Sobrien when generating dies for the real variables, we'd die (pun 1065896263Sobrien intended :-) */ 1065996263Sobrien gen_lexical_block_die (stmt, context_die, depth); 1066050397Sobrien} 1066150397Sobrien 1066250397Sobrien/* Generate a DIE for a field in a record, or structure. */ 1066350397Sobrien 1066450397Sobrienstatic void 1066550397Sobriengen_field_die (decl, context_die) 1066690075Sobrien tree decl; 1066790075Sobrien dw_die_ref context_die; 1066850397Sobrien{ 1066990075Sobrien dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl); 1067050397Sobrien 1067150397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 1067250397Sobrien add_type_attribute (decl_die, member_declared_type (decl), 1067350397Sobrien TREE_READONLY (decl), TREE_THIS_VOLATILE (decl), 1067450397Sobrien context_die); 1067550397Sobrien 1067650397Sobrien if (DECL_BIT_FIELD_TYPE (decl)) 1067750397Sobrien { 1067850397Sobrien add_byte_size_attribute (decl_die, decl); 1067950397Sobrien add_bit_size_attribute (decl_die, decl); 1068050397Sobrien add_bit_offset_attribute (decl_die, decl); 1068150397Sobrien } 1068250397Sobrien 1068350397Sobrien if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE) 1068450397Sobrien add_data_member_location_attribute (decl_die, decl); 1068550397Sobrien 1068650397Sobrien if (DECL_ARTIFICIAL (decl)) 1068750397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 1068850397Sobrien 1068950397Sobrien if (TREE_PROTECTED (decl)) 1069050397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected); 1069150397Sobrien else if (TREE_PRIVATE (decl)) 1069250397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private); 1069350397Sobrien} 1069450397Sobrien 1069550397Sobrien#if 0 1069650397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1069750397Sobrien Use modified_type_die instead. 1069850397Sobrien We keep this code here just in case these types of DIEs may be needed to 1069950397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1070090075Sobrien 1070150397Sobrienstatic void 1070250397Sobriengen_pointer_type_die (type, context_die) 1070390075Sobrien tree type; 1070490075Sobrien dw_die_ref context_die; 1070550397Sobrien{ 1070690075Sobrien dw_die_ref ptr_die 1070790075Sobrien = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type); 1070850397Sobrien 1070950397Sobrien equate_type_number_to_die (type, ptr_die); 1071050397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1071150397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1071250397Sobrien} 1071350397Sobrien 1071450397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1071550397Sobrien Use modified_type_die instead. 1071650397Sobrien We keep this code here just in case these types of DIEs may be needed to 1071750397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1071890075Sobrien 1071950397Sobrienstatic void 1072050397Sobriengen_reference_type_die (type, context_die) 1072190075Sobrien tree type; 1072290075Sobrien dw_die_ref context_die; 1072350397Sobrien{ 1072490075Sobrien dw_die_ref ref_die 1072590075Sobrien = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type); 1072650397Sobrien 1072750397Sobrien equate_type_number_to_die (type, ref_die); 1072850397Sobrien add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die); 1072950397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1073050397Sobrien} 1073150397Sobrien#endif 1073250397Sobrien 1073350397Sobrien/* Generate a DIE for a pointer to a member type. */ 1073490075Sobrien 1073550397Sobrienstatic void 1073650397Sobriengen_ptr_to_mbr_type_die (type, context_die) 1073790075Sobrien tree type; 1073890075Sobrien dw_die_ref context_die; 1073950397Sobrien{ 1074090075Sobrien dw_die_ref ptr_die 1074190075Sobrien = new_die (DW_TAG_ptr_to_member_type, 1074290075Sobrien scope_die_for (type, context_die), type); 1074350397Sobrien 1074450397Sobrien equate_type_number_to_die (type, ptr_die); 1074550397Sobrien add_AT_die_ref (ptr_die, DW_AT_containing_type, 1074650397Sobrien lookup_type_die (TYPE_OFFSET_BASETYPE (type))); 1074750397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1074850397Sobrien} 1074950397Sobrien 1075050397Sobrien/* Generate the DIE for the compilation unit. */ 1075150397Sobrien 1075290075Sobrienstatic dw_die_ref 1075390075Sobriengen_compile_unit_die (filename) 1075490075Sobrien const char *filename; 1075550397Sobrien{ 1075690075Sobrien dw_die_ref die; 1075750397Sobrien char producer[250]; 1075890075Sobrien const char *wd = getpwd (); 1075990075Sobrien const char *language_string = lang_hooks.name; 1076090075Sobrien int language; 1076150397Sobrien 1076290075Sobrien die = new_die (DW_TAG_compile_unit, NULL, NULL); 1076390075Sobrien add_name_attribute (die, filename); 1076450397Sobrien 1076590075Sobrien if (wd != NULL && filename[0] != DIR_SEPARATOR) 1076690075Sobrien add_AT_string (die, DW_AT_comp_dir, wd); 1076750397Sobrien 1076850397Sobrien sprintf (producer, "%s %s", language_string, version_string); 1076950397Sobrien 1077050397Sobrien#ifdef MIPS_DEBUGGING_INFO 1077150397Sobrien /* The MIPS/SGI compilers place the 'cc' command line options in the producer 1077250397Sobrien string. The SGI debugger looks for -g, -g1, -g2, or -g3; if they do 1077350397Sobrien not appear in the producer string, the debugger reaches the conclusion 1077450397Sobrien that the object file is stripped and has no debugging information. 1077550397Sobrien To get the MIPS/SGI debugger to believe that there is debugging 1077650397Sobrien information in the object file, we add a -g to the producer string. */ 1077750397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1077850397Sobrien strcat (producer, " -g"); 1077950397Sobrien#endif 1078050397Sobrien 1078190075Sobrien add_AT_string (die, DW_AT_producer, producer); 1078250397Sobrien 1078350397Sobrien if (strcmp (language_string, "GNU C++") == 0) 1078490075Sobrien language = DW_LANG_C_plus_plus; 1078550397Sobrien else if (strcmp (language_string, "GNU Ada") == 0) 1078690075Sobrien language = DW_LANG_Ada83; 1078750397Sobrien else if (strcmp (language_string, "GNU F77") == 0) 1078890075Sobrien language = DW_LANG_Fortran77; 1078950397Sobrien else if (strcmp (language_string, "GNU Pascal") == 0) 1079090075Sobrien language = DW_LANG_Pascal83; 1079190075Sobrien else if (strcmp (language_string, "GNU Java") == 0) 1079290075Sobrien language = DW_LANG_Java; 1079350397Sobrien else if (flag_traditional) 1079490075Sobrien language = DW_LANG_C; 1079550397Sobrien else 1079690075Sobrien language = DW_LANG_C89; 1079750397Sobrien 1079890075Sobrien add_AT_unsigned (die, DW_AT_language, language); 1079990075Sobrien return die; 1080050397Sobrien} 1080150397Sobrien 1080250397Sobrien/* Generate a DIE for a string type. */ 1080350397Sobrien 1080450397Sobrienstatic void 1080550397Sobriengen_string_type_die (type, context_die) 1080690075Sobrien tree type; 1080790075Sobrien dw_die_ref context_die; 1080850397Sobrien{ 1080990075Sobrien dw_die_ref type_die 1081090075Sobrien = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type); 1081150397Sobrien 1081250397Sobrien equate_type_number_to_die (type, type_die); 1081350397Sobrien 1081490075Sobrien /* ??? Fudge the string length attribute for now. 1081590075Sobrien TODO: add string length info. */ 1081690075Sobrien#if 0 1081790075Sobrien string_length_attribute (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 1081890075Sobrien bound_representation (upper_bound, 0, 'u'); 1081990075Sobrien#endif 1082050397Sobrien} 1082150397Sobrien 1082250397Sobrien/* Generate the DIE for a base class. */ 1082350397Sobrien 1082450397Sobrienstatic void 1082550397Sobriengen_inheritance_die (binfo, context_die) 1082690075Sobrien tree binfo; 1082790075Sobrien dw_die_ref context_die; 1082850397Sobrien{ 1082990075Sobrien dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo); 1083050397Sobrien 1083150397Sobrien add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die); 1083250397Sobrien add_data_member_location_attribute (die, binfo); 1083350397Sobrien 1083450397Sobrien if (TREE_VIA_VIRTUAL (binfo)) 1083550397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 1083690075Sobrien 1083750397Sobrien if (TREE_VIA_PUBLIC (binfo)) 1083850397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); 1083950397Sobrien else if (TREE_VIA_PROTECTED (binfo)) 1084050397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); 1084150397Sobrien} 1084250397Sobrien 1084350397Sobrien/* Generate a DIE for a class member. */ 1084450397Sobrien 1084550397Sobrienstatic void 1084650397Sobriengen_member_die (type, context_die) 1084790075Sobrien tree type; 1084890075Sobrien dw_die_ref context_die; 1084950397Sobrien{ 1085090075Sobrien tree member; 1085190075Sobrien dw_die_ref child; 1085250397Sobrien 1085350397Sobrien /* If this is not an incomplete type, output descriptions of each of its 1085450397Sobrien members. Note that as we output the DIEs necessary to represent the 1085550397Sobrien members of this record or union type, we will also be trying to output 1085650397Sobrien DIEs to represent the *types* of those members. However the `type' 1085790075Sobrien function (above) will specifically avoid generating type DIEs for member 1085890075Sobrien types *within* the list of member DIEs for this (containing) type except 1085950397Sobrien for those types (of members) which are explicitly marked as also being 1086050397Sobrien members of this (containing) type themselves. The g++ front- end can 1086190075Sobrien force any given type to be treated as a member of some other (containing) 1086290075Sobrien type by setting the TYPE_CONTEXT of the given (member) type to point to 1086390075Sobrien the TREE node representing the appropriate (containing) type. */ 1086450397Sobrien 1086550397Sobrien /* First output info about the base classes. */ 1086650397Sobrien if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) 1086750397Sobrien { 1086890075Sobrien tree bases = TYPE_BINFO_BASETYPES (type); 1086990075Sobrien int n_bases = TREE_VEC_LENGTH (bases); 1087090075Sobrien int i; 1087150397Sobrien 1087250397Sobrien for (i = 0; i < n_bases; i++) 1087350397Sobrien gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die); 1087450397Sobrien } 1087550397Sobrien 1087650397Sobrien /* Now output info about the data members and type members. */ 1087750397Sobrien for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) 1087890075Sobrien { 1087990075Sobrien /* If we thought we were generating minimal debug info for TYPE 1088090075Sobrien and then changed our minds, some of the member declarations 1088190075Sobrien may have already been defined. Don't define them again, but 1088290075Sobrien do put them in the right order. */ 1088350397Sobrien 1088490075Sobrien child = lookup_decl_die (member); 1088590075Sobrien if (child) 1088690075Sobrien splice_child_die (context_die, child); 1088790075Sobrien else 1088890075Sobrien gen_decl_die (member, context_die); 1088990075Sobrien } 1089090075Sobrien 1089150397Sobrien /* Now output info about the function members (if any). */ 1089250397Sobrien for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member)) 1089390075Sobrien { 1089490075Sobrien /* Don't include clones in the member list. */ 1089590075Sobrien if (DECL_ABSTRACT_ORIGIN (member)) 1089690075Sobrien continue; 1089790075Sobrien 1089890075Sobrien child = lookup_decl_die (member); 1089990075Sobrien if (child) 1090090075Sobrien splice_child_die (context_die, child); 1090190075Sobrien else 1090290075Sobrien gen_decl_die (member, context_die); 1090390075Sobrien } 1090450397Sobrien} 1090550397Sobrien 1090690075Sobrien/* Generate a DIE for a structure or union type. If TYPE_DECL_SUPPRESS_DEBUG 1090790075Sobrien is set, we pretend that the type was never defined, so we only get the 1090890075Sobrien member DIEs needed by later specification DIEs. */ 1090950397Sobrien 1091050397Sobrienstatic void 1091150397Sobriengen_struct_or_union_type_die (type, context_die) 1091290075Sobrien tree type; 1091390075Sobrien dw_die_ref context_die; 1091450397Sobrien{ 1091590075Sobrien dw_die_ref type_die = lookup_type_die (type); 1091690075Sobrien dw_die_ref scope_die = 0; 1091790075Sobrien int nested = 0; 1091890075Sobrien int complete = (TYPE_SIZE (type) 1091990075Sobrien && (! TYPE_STUB_DECL (type) 1092090075Sobrien || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)))); 1092150397Sobrien 1092290075Sobrien if (type_die && ! complete) 1092350397Sobrien return; 1092450397Sobrien 1092550397Sobrien if (TYPE_CONTEXT (type) != NULL_TREE 1092652284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))) 1092750397Sobrien nested = 1; 1092850397Sobrien 1092950397Sobrien scope_die = scope_die_for (type, context_die); 1093050397Sobrien 1093150397Sobrien if (! type_die || (nested && scope_die == comp_unit_die)) 1093250397Sobrien /* First occurrence of type or toplevel definition of nested class. */ 1093350397Sobrien { 1093490075Sobrien dw_die_ref old_die = type_die; 1093550397Sobrien 1093650397Sobrien type_die = new_die (TREE_CODE (type) == RECORD_TYPE 1093750397Sobrien ? DW_TAG_structure_type : DW_TAG_union_type, 1093890075Sobrien scope_die, type); 1093950397Sobrien equate_type_number_to_die (type, type_die); 1094050397Sobrien if (old_die) 1094150397Sobrien add_AT_die_ref (type_die, DW_AT_specification, old_die); 1094290075Sobrien else 1094390075Sobrien add_name_attribute (type_die, type_tag (type)); 1094450397Sobrien } 1094550397Sobrien else 1094650397Sobrien remove_AT (type_die, DW_AT_declaration); 1094750397Sobrien 1094850397Sobrien /* If this type has been completed, then give it a byte_size attribute and 1094950397Sobrien then give a list of members. */ 1095090075Sobrien if (complete) 1095150397Sobrien { 1095290075Sobrien /* Prevent infinite recursion in cases where the type of some member of 1095350397Sobrien this type is expressed in terms of this type itself. */ 1095450397Sobrien TREE_ASM_WRITTEN (type) = 1; 1095550397Sobrien add_byte_size_attribute (type_die, type); 1095650397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 1095750397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 1095850397Sobrien 1095950397Sobrien /* If the first reference to this type was as the return type of an 1096050397Sobrien inline function, then it may not have a parent. Fix this now. */ 1096150397Sobrien if (type_die->die_parent == NULL) 1096250397Sobrien add_child_die (scope_die, type_die); 1096350397Sobrien 1096450397Sobrien push_decl_scope (type); 1096550397Sobrien gen_member_die (type, type_die); 1096650397Sobrien pop_decl_scope (); 1096750397Sobrien 1096850397Sobrien /* GNU extension: Record what type our vtable lives in. */ 1096950397Sobrien if (TYPE_VFIELD (type)) 1097050397Sobrien { 1097150397Sobrien tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type)); 1097250397Sobrien 1097350397Sobrien gen_type_die (vtype, context_die); 1097450397Sobrien add_AT_die_ref (type_die, DW_AT_containing_type, 1097550397Sobrien lookup_type_die (vtype)); 1097650397Sobrien } 1097750397Sobrien } 1097850397Sobrien else 1097952284Sobrien { 1098052284Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 1098152284Sobrien 1098290075Sobrien /* We don't need to do this for function-local types. */ 1098390075Sobrien if (TYPE_STUB_DECL (type) 1098490075Sobrien && ! decl_function_context (TYPE_STUB_DECL (type))) 1098590075Sobrien VARRAY_PUSH_TREE (incomplete_types, type); 1098652284Sobrien } 1098750397Sobrien} 1098850397Sobrien 1098950397Sobrien/* Generate a DIE for a subroutine _type_. */ 1099050397Sobrien 1099150397Sobrienstatic void 1099250397Sobriengen_subroutine_type_die (type, context_die) 1099390075Sobrien tree type; 1099490075Sobrien dw_die_ref context_die; 1099550397Sobrien{ 1099690075Sobrien tree return_type = TREE_TYPE (type); 1099790075Sobrien dw_die_ref subr_die 1099890075Sobrien = new_die (DW_TAG_subroutine_type, 1099990075Sobrien scope_die_for (type, context_die), type); 1100050397Sobrien 1100150397Sobrien equate_type_number_to_die (type, subr_die); 1100250397Sobrien add_prototyped_attribute (subr_die, type); 1100350397Sobrien add_type_attribute (subr_die, return_type, 0, 0, context_die); 1100450397Sobrien gen_formal_types_die (type, subr_die); 1100550397Sobrien} 1100650397Sobrien 1100750397Sobrien/* Generate a DIE for a type definition */ 1100850397Sobrien 1100950397Sobrienstatic void 1101050397Sobriengen_typedef_die (decl, context_die) 1101190075Sobrien tree decl; 1101290075Sobrien dw_die_ref context_die; 1101350397Sobrien{ 1101490075Sobrien dw_die_ref type_die; 1101590075Sobrien tree origin; 1101650397Sobrien 1101750397Sobrien if (TREE_ASM_WRITTEN (decl)) 1101850397Sobrien return; 1101990075Sobrien 1102050397Sobrien TREE_ASM_WRITTEN (decl) = 1; 1102190075Sobrien type_die = new_die (DW_TAG_typedef, context_die, decl); 1102250397Sobrien origin = decl_ultimate_origin (decl); 1102350397Sobrien if (origin != NULL) 1102450397Sobrien add_abstract_origin_attribute (type_die, origin); 1102550397Sobrien else 1102650397Sobrien { 1102790075Sobrien tree type; 1102890075Sobrien 1102950397Sobrien add_name_and_src_coords_attributes (type_die, decl); 1103050397Sobrien if (DECL_ORIGINAL_TYPE (decl)) 1103150397Sobrien { 1103250397Sobrien type = DECL_ORIGINAL_TYPE (decl); 1103390075Sobrien 1103490075Sobrien if (type == TREE_TYPE (decl)) 1103590075Sobrien abort (); 1103690075Sobrien else 1103790075Sobrien equate_type_number_to_die (TREE_TYPE (decl), type_die); 1103850397Sobrien } 1103950397Sobrien else 1104050397Sobrien type = TREE_TYPE (decl); 1104190075Sobrien 1104250397Sobrien add_type_attribute (type_die, type, TREE_READONLY (decl), 1104350397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1104450397Sobrien } 1104550397Sobrien 1104650397Sobrien if (DECL_ABSTRACT (decl)) 1104750397Sobrien equate_decl_number_to_die (decl, type_die); 1104850397Sobrien} 1104950397Sobrien 1105050397Sobrien/* Generate a type description DIE. */ 1105150397Sobrien 1105250397Sobrienstatic void 1105350397Sobriengen_type_die (type, context_die) 1105490075Sobrien tree type; 1105590075Sobrien dw_die_ref context_die; 1105650397Sobrien{ 1105790075Sobrien int need_pop; 1105890075Sobrien 1105950397Sobrien if (type == NULL_TREE || type == error_mark_node) 1106050397Sobrien return; 1106150397Sobrien 1106250397Sobrien /* We are going to output a DIE to represent the unqualified version of 1106350397Sobrien this type (i.e. without any const or volatile qualifiers) so get the 1106450397Sobrien main variant (i.e. the unqualified version) of this type now. */ 1106550397Sobrien type = type_main_variant (type); 1106650397Sobrien 1106750397Sobrien if (TREE_ASM_WRITTEN (type)) 1106850397Sobrien return; 1106950397Sobrien 1107050397Sobrien if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 1107150397Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 1107290075Sobrien { 1107350397Sobrien TREE_ASM_WRITTEN (type) = 1; 1107450397Sobrien gen_decl_die (TYPE_NAME (type), context_die); 1107550397Sobrien return; 1107650397Sobrien } 1107750397Sobrien 1107850397Sobrien switch (TREE_CODE (type)) 1107950397Sobrien { 1108050397Sobrien case ERROR_MARK: 1108150397Sobrien break; 1108250397Sobrien 1108350397Sobrien case POINTER_TYPE: 1108450397Sobrien case REFERENCE_TYPE: 1108550397Sobrien /* We must set TREE_ASM_WRITTEN in case this is a recursive type. This 1108650397Sobrien ensures that the gen_type_die recursion will terminate even if the 1108750397Sobrien type is recursive. Recursive types are possible in Ada. */ 1108850397Sobrien /* ??? We could perhaps do this for all types before the switch 1108950397Sobrien statement. */ 1109050397Sobrien TREE_ASM_WRITTEN (type) = 1; 1109150397Sobrien 1109250397Sobrien /* For these types, all that is required is that we output a DIE (or a 1109350397Sobrien set of DIEs) to represent the "basis" type. */ 1109450397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1109550397Sobrien break; 1109650397Sobrien 1109750397Sobrien case OFFSET_TYPE: 1109890075Sobrien /* This code is used for C++ pointer-to-data-member types. 1109950397Sobrien Output a description of the relevant class type. */ 1110050397Sobrien gen_type_die (TYPE_OFFSET_BASETYPE (type), context_die); 1110150397Sobrien 1110250397Sobrien /* Output a description of the type of the object pointed to. */ 1110350397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1110450397Sobrien 1110550397Sobrien /* Now output a DIE to represent this pointer-to-data-member type 1110650397Sobrien itself. */ 1110750397Sobrien gen_ptr_to_mbr_type_die (type, context_die); 1110850397Sobrien break; 1110950397Sobrien 1111050397Sobrien case SET_TYPE: 1111150397Sobrien gen_type_die (TYPE_DOMAIN (type), context_die); 1111250397Sobrien gen_set_type_die (type, context_die); 1111350397Sobrien break; 1111450397Sobrien 1111550397Sobrien case FILE_TYPE: 1111650397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1111750397Sobrien abort (); /* No way to represent these in Dwarf yet! */ 1111850397Sobrien break; 1111950397Sobrien 1112050397Sobrien case FUNCTION_TYPE: 1112150397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1112250397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1112350397Sobrien gen_subroutine_type_die (type, context_die); 1112450397Sobrien break; 1112550397Sobrien 1112650397Sobrien case METHOD_TYPE: 1112750397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1112850397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1112950397Sobrien gen_subroutine_type_die (type, context_die); 1113050397Sobrien break; 1113150397Sobrien 1113250397Sobrien case ARRAY_TYPE: 1113350397Sobrien if (TYPE_STRING_FLAG (type) && TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) 1113450397Sobrien { 1113550397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1113650397Sobrien gen_string_type_die (type, context_die); 1113750397Sobrien } 1113850397Sobrien else 1113950397Sobrien gen_array_type_die (type, context_die); 1114050397Sobrien break; 1114150397Sobrien 1114290075Sobrien case VECTOR_TYPE: 1114396263Sobrien gen_array_type_die (type, context_die); 1114490075Sobrien break; 1114590075Sobrien 1114650397Sobrien case ENUMERAL_TYPE: 1114750397Sobrien case RECORD_TYPE: 1114850397Sobrien case UNION_TYPE: 1114950397Sobrien case QUAL_UNION_TYPE: 1115090075Sobrien /* If this is a nested type whose containing class hasn't been written 1115190075Sobrien out yet, writing it out will cover this one, too. This does not apply 1115290075Sobrien to instantiations of member class templates; they need to be added to 1115390075Sobrien the containing class as they are generated. FIXME: This hurts the 1115490075Sobrien idea of combining type decls from multiple TUs, since we can't predict 1115590075Sobrien what set of template instantiations we'll get. */ 1115650397Sobrien if (TYPE_CONTEXT (type) 1115752284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) 1115850397Sobrien && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 1115950397Sobrien { 1116050397Sobrien gen_type_die (TYPE_CONTEXT (type), context_die); 1116150397Sobrien 1116290075Sobrien if (TREE_ASM_WRITTEN (type)) 1116350397Sobrien return; 1116450397Sobrien 1116550397Sobrien /* If that failed, attach ourselves to the stub. */ 1116650397Sobrien push_decl_scope (TYPE_CONTEXT (type)); 1116750397Sobrien context_die = lookup_type_die (TYPE_CONTEXT (type)); 1116890075Sobrien need_pop = 1; 1116950397Sobrien } 1117090075Sobrien else 1117190075Sobrien need_pop = 0; 1117250397Sobrien 1117350397Sobrien if (TREE_CODE (type) == ENUMERAL_TYPE) 1117450397Sobrien gen_enumeration_type_die (type, context_die); 1117550397Sobrien else 1117650397Sobrien gen_struct_or_union_type_die (type, context_die); 1117750397Sobrien 1117890075Sobrien if (need_pop) 1117950397Sobrien pop_decl_scope (); 1118050397Sobrien 1118150397Sobrien /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix 1118250397Sobrien it up if it is ever completed. gen_*_type_die will set it for us 1118350397Sobrien when appropriate. */ 1118450397Sobrien return; 1118550397Sobrien 1118650397Sobrien case VOID_TYPE: 1118750397Sobrien case INTEGER_TYPE: 1118850397Sobrien case REAL_TYPE: 1118950397Sobrien case COMPLEX_TYPE: 1119050397Sobrien case BOOLEAN_TYPE: 1119150397Sobrien case CHAR_TYPE: 1119250397Sobrien /* No DIEs needed for fundamental types. */ 1119350397Sobrien break; 1119450397Sobrien 1119550397Sobrien case LANG_TYPE: 1119650397Sobrien /* No Dwarf representation currently defined. */ 1119750397Sobrien break; 1119850397Sobrien 1119950397Sobrien default: 1120050397Sobrien abort (); 1120150397Sobrien } 1120250397Sobrien 1120350397Sobrien TREE_ASM_WRITTEN (type) = 1; 1120450397Sobrien} 1120550397Sobrien 1120650397Sobrien/* Generate a DIE for a tagged type instantiation. */ 1120750397Sobrien 1120850397Sobrienstatic void 1120950397Sobriengen_tagged_type_instantiation_die (type, context_die) 1121090075Sobrien tree type; 1121190075Sobrien dw_die_ref context_die; 1121250397Sobrien{ 1121350397Sobrien if (type == NULL_TREE || type == error_mark_node) 1121450397Sobrien return; 1121550397Sobrien 1121650397Sobrien /* We are going to output a DIE to represent the unqualified version of 1121750397Sobrien this type (i.e. without any const or volatile qualifiers) so make sure 1121850397Sobrien that we have the main variant (i.e. the unqualified version) of this 1121950397Sobrien type now. */ 1122090075Sobrien if (type != type_main_variant (type)) 1122150397Sobrien abort (); 1122250397Sobrien 1122390075Sobrien /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is 1122490075Sobrien an instance of an unresolved type. */ 1122590075Sobrien 1122650397Sobrien switch (TREE_CODE (type)) 1122750397Sobrien { 1122850397Sobrien case ERROR_MARK: 1122950397Sobrien break; 1123050397Sobrien 1123150397Sobrien case ENUMERAL_TYPE: 1123250397Sobrien gen_inlined_enumeration_type_die (type, context_die); 1123350397Sobrien break; 1123450397Sobrien 1123550397Sobrien case RECORD_TYPE: 1123650397Sobrien gen_inlined_structure_type_die (type, context_die); 1123750397Sobrien break; 1123850397Sobrien 1123950397Sobrien case UNION_TYPE: 1124050397Sobrien case QUAL_UNION_TYPE: 1124150397Sobrien gen_inlined_union_type_die (type, context_die); 1124250397Sobrien break; 1124350397Sobrien 1124450397Sobrien default: 1124550397Sobrien abort (); 1124650397Sobrien } 1124750397Sobrien} 1124850397Sobrien 1124950397Sobrien/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the 1125050397Sobrien things which are local to the given block. */ 1125150397Sobrien 1125250397Sobrienstatic void 1125350397Sobriengen_block_die (stmt, context_die, depth) 1125490075Sobrien tree stmt; 1125590075Sobrien dw_die_ref context_die; 1125650397Sobrien int depth; 1125750397Sobrien{ 1125890075Sobrien int must_output_die = 0; 1125990075Sobrien tree origin; 1126090075Sobrien tree decl; 1126190075Sobrien enum tree_code origin_code; 1126250397Sobrien 1126350397Sobrien /* Ignore blocks never really used to make RTL. */ 1126490075Sobrien if (stmt == NULL_TREE || !TREE_USED (stmt) 1126590075Sobrien || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt))) 1126650397Sobrien return; 1126750397Sobrien 1126890075Sobrien /* If the block is one fragment of a non-contiguous block, do not 1126990075Sobrien process the variables, since they will have been done by the 1127090075Sobrien origin block. Do process subblocks. */ 1127190075Sobrien if (BLOCK_FRAGMENT_ORIGIN (stmt)) 1127290075Sobrien { 1127390075Sobrien tree sub; 1127490075Sobrien 1127590075Sobrien for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub)) 1127690075Sobrien gen_block_die (sub, context_die, depth + 1); 1127790075Sobrien 1127890075Sobrien return; 1127990075Sobrien } 1128090075Sobrien 1128150397Sobrien /* Determine the "ultimate origin" of this block. This block may be an 1128250397Sobrien inlined instance of an inlined instance of inline function, so we have 1128350397Sobrien to trace all of the way back through the origin chain to find out what 1128450397Sobrien sort of node actually served as the original seed for the creation of 1128550397Sobrien the current block. */ 1128650397Sobrien origin = block_ultimate_origin (stmt); 1128750397Sobrien origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK; 1128850397Sobrien 1128950397Sobrien /* Determine if we need to output any Dwarf DIEs at all to represent this 1129050397Sobrien block. */ 1129150397Sobrien if (origin_code == FUNCTION_DECL) 1129250397Sobrien /* The outer scopes for inlinings *must* always be represented. We 1129350397Sobrien generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */ 1129450397Sobrien must_output_die = 1; 1129550397Sobrien else 1129650397Sobrien { 1129750397Sobrien /* In the case where the current block represents an inlining of the 1129890075Sobrien "body block" of an inline function, we must *NOT* output any DIE for 1129990075Sobrien this block because we have already output a DIE to represent the whole 1130090075Sobrien inlined function scope and the "body block" of any function doesn't 1130190075Sobrien really represent a different scope according to ANSI C rules. So we 1130290075Sobrien check here to make sure that this block does not represent a "body 1130390075Sobrien block inlining" before trying to set the MUST_OUTPUT_DIE flag. */ 1130450397Sobrien if (! is_body_block (origin ? origin : stmt)) 1130550397Sobrien { 1130650397Sobrien /* Determine if this block directly contains any "significant" 1130750397Sobrien local declarations which we will need to output DIEs for. */ 1130850397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1130950397Sobrien /* We are not in terse mode so *any* local declaration counts 1131050397Sobrien as being a "significant" one. */ 1131150397Sobrien must_output_die = (BLOCK_VARS (stmt) != NULL); 1131250397Sobrien else 1131350397Sobrien /* We are in terse mode, so only local (nested) function 1131450397Sobrien definitions count as "significant" local declarations. */ 1131550397Sobrien for (decl = BLOCK_VARS (stmt); 1131650397Sobrien decl != NULL; decl = TREE_CHAIN (decl)) 1131750397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1131850397Sobrien && DECL_INITIAL (decl)) 1131950397Sobrien { 1132050397Sobrien must_output_die = 1; 1132150397Sobrien break; 1132250397Sobrien } 1132350397Sobrien } 1132450397Sobrien } 1132550397Sobrien 1132650397Sobrien /* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block 1132750397Sobrien DIE for any block which contains no significant local declarations at 1132850397Sobrien all. Rather, in such cases we just call `decls_for_scope' so that any 1132950397Sobrien needed Dwarf info for any sub-blocks will get properly generated. Note 1133050397Sobrien that in terse mode, our definition of what constitutes a "significant" 1133150397Sobrien local declaration gets restricted to include only inlined function 1133250397Sobrien instances and local (nested) function definitions. */ 1133350397Sobrien if (must_output_die) 1133450397Sobrien { 1133550397Sobrien if (origin_code == FUNCTION_DECL) 1133650397Sobrien gen_inlined_subroutine_die (stmt, context_die, depth); 1133750397Sobrien else 1133850397Sobrien gen_lexical_block_die (stmt, context_die, depth); 1133950397Sobrien } 1134050397Sobrien else 1134150397Sobrien decls_for_scope (stmt, context_die, depth); 1134250397Sobrien} 1134350397Sobrien 1134450397Sobrien/* Generate all of the decls declared within a given scope and (recursively) 1134550397Sobrien all of its sub-blocks. */ 1134650397Sobrien 1134750397Sobrienstatic void 1134850397Sobriendecls_for_scope (stmt, context_die, depth) 1134990075Sobrien tree stmt; 1135090075Sobrien dw_die_ref context_die; 1135150397Sobrien int depth; 1135250397Sobrien{ 1135390075Sobrien tree decl; 1135490075Sobrien tree subblocks; 1135550397Sobrien 1135650397Sobrien /* Ignore blocks never really used to make RTL. */ 1135750397Sobrien if (stmt == NULL_TREE || ! TREE_USED (stmt)) 1135850397Sobrien return; 1135950397Sobrien 1136050397Sobrien /* Output the DIEs to represent all of the data objects and typedefs 1136150397Sobrien declared directly within this block but not within any nested 1136250397Sobrien sub-blocks. Also, nested function and tag DIEs have been 1136350397Sobrien generated with a parent of NULL; fix that up now. */ 1136490075Sobrien for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl)) 1136550397Sobrien { 1136690075Sobrien dw_die_ref die; 1136750397Sobrien 1136850397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 1136950397Sobrien die = lookup_decl_die (decl); 1137050397Sobrien else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)) 1137150397Sobrien die = lookup_type_die (TREE_TYPE (decl)); 1137250397Sobrien else 1137350397Sobrien die = NULL; 1137450397Sobrien 1137550397Sobrien if (die != NULL && die->die_parent == NULL) 1137650397Sobrien add_child_die (context_die, die); 1137750397Sobrien else 1137850397Sobrien gen_decl_die (decl, context_die); 1137950397Sobrien } 1138050397Sobrien 1138150397Sobrien /* Output the DIEs to represent all sub-blocks (and the items declared 1138250397Sobrien therein) of this block. */ 1138350397Sobrien for (subblocks = BLOCK_SUBBLOCKS (stmt); 1138450397Sobrien subblocks != NULL; 1138550397Sobrien subblocks = BLOCK_CHAIN (subblocks)) 1138650397Sobrien gen_block_die (subblocks, context_die, depth + 1); 1138750397Sobrien} 1138850397Sobrien 1138950397Sobrien/* Is this a typedef we can avoid emitting? */ 1139050397Sobrien 1139150397Sobrienstatic inline int 1139250397Sobrienis_redundant_typedef (decl) 1139390075Sobrien tree decl; 1139450397Sobrien{ 1139550397Sobrien if (TYPE_DECL_IS_STUB (decl)) 1139650397Sobrien return 1; 1139750397Sobrien 1139850397Sobrien if (DECL_ARTIFICIAL (decl) 1139950397Sobrien && DECL_CONTEXT (decl) 1140050397Sobrien && is_tagged_type (DECL_CONTEXT (decl)) 1140150397Sobrien && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL 1140250397Sobrien && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))) 1140350397Sobrien /* Also ignore the artificial member typedef for the class name. */ 1140450397Sobrien return 1; 1140550397Sobrien 1140650397Sobrien return 0; 1140750397Sobrien} 1140850397Sobrien 1140950397Sobrien/* Generate Dwarf debug information for a decl described by DECL. */ 1141050397Sobrien 1141150397Sobrienstatic void 1141250397Sobriengen_decl_die (decl, context_die) 1141390075Sobrien tree decl; 1141490075Sobrien dw_die_ref context_die; 1141550397Sobrien{ 1141690075Sobrien tree origin; 1141750397Sobrien 1141890075Sobrien if (DECL_P (decl) && DECL_IGNORED_P (decl)) 1141950397Sobrien return; 1142050397Sobrien 1142150397Sobrien switch (TREE_CODE (decl)) 1142250397Sobrien { 1142390075Sobrien case ERROR_MARK: 1142490075Sobrien break; 1142590075Sobrien 1142650397Sobrien case CONST_DECL: 1142790075Sobrien /* The individual enumerators of an enum type get output when we output 1142850397Sobrien the Dwarf representation of the relevant enum type itself. */ 1142950397Sobrien break; 1143050397Sobrien 1143150397Sobrien case FUNCTION_DECL: 1143250397Sobrien /* Don't output any DIEs to represent mere function declarations, 1143350397Sobrien unless they are class members or explicit block externs. */ 1143450397Sobrien if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE 1143590075Sobrien && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl))) 1143650397Sobrien break; 1143750397Sobrien 1143890075Sobrien /* If we're emitting a clone, emit info for the abstract instance. */ 1143990075Sobrien if (DECL_ORIGIN (decl) != decl) 1144090075Sobrien dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl)); 1144190075Sobrien 1144290075Sobrien /* If we're emitting an out-of-line copy of an inline function, 1144390075Sobrien emit info for the abstract instance and set up to refer to it. */ 1144490075Sobrien else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl) 1144590075Sobrien && ! class_scope_p (context_die) 1144690075Sobrien /* dwarf2out_abstract_function won't emit a die if this is just 1144790075Sobrien a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in 1144890075Sobrien that case, because that works only if we have a die. */ 1144990075Sobrien && DECL_INITIAL (decl) != NULL_TREE) 1145050397Sobrien { 1145190075Sobrien dwarf2out_abstract_function (decl); 1145290075Sobrien set_decl_origin_self (decl); 1145390075Sobrien } 1145490075Sobrien 1145590075Sobrien /* Otherwise we're emitting the primary DIE for this decl. */ 1145690075Sobrien else if (debug_info_level > DINFO_LEVEL_TERSE) 1145790075Sobrien { 1145850397Sobrien /* Before we describe the FUNCTION_DECL itself, make sure that we 1145950397Sobrien have described its return type. */ 1146050397Sobrien gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die); 1146150397Sobrien 1146290075Sobrien /* And its virtual context. */ 1146390075Sobrien if (DECL_VINDEX (decl) != NULL_TREE) 1146490075Sobrien gen_type_die (DECL_CONTEXT (decl), context_die); 1146590075Sobrien 1146650397Sobrien /* And its containing type. */ 1146750397Sobrien origin = decl_class_context (decl); 1146850397Sobrien if (origin != NULL_TREE) 1146990075Sobrien gen_type_die_for_member (origin, decl, context_die); 1147050397Sobrien } 1147150397Sobrien 1147250397Sobrien /* Now output a DIE to represent the function itself. */ 1147350397Sobrien gen_subprogram_die (decl, context_die); 1147450397Sobrien break; 1147550397Sobrien 1147650397Sobrien case TYPE_DECL: 1147750397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1147850397Sobrien actual typedefs. */ 1147950397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1148050397Sobrien break; 1148150397Sobrien 1148290075Sobrien /* In the special case of a TYPE_DECL node representing the declaration 1148390075Sobrien of some type tag, if the given TYPE_DECL is marked as having been 1148490075Sobrien instantiated from some other (original) TYPE_DECL node (e.g. one which 1148590075Sobrien was generated within the original definition of an inline function) we 1148690075Sobrien have to generate a special (abbreviated) DW_TAG_structure_type, 1148790075Sobrien DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */ 1148890075Sobrien if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE) 1148950397Sobrien { 1149050397Sobrien gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die); 1149150397Sobrien break; 1149250397Sobrien } 1149350397Sobrien 1149450397Sobrien if (is_redundant_typedef (decl)) 1149550397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1149650397Sobrien else 1149750397Sobrien /* Output a DIE to represent the typedef itself. */ 1149850397Sobrien gen_typedef_die (decl, context_die); 1149950397Sobrien break; 1150050397Sobrien 1150150397Sobrien case LABEL_DECL: 1150250397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1150350397Sobrien gen_label_die (decl, context_die); 1150450397Sobrien break; 1150550397Sobrien 1150650397Sobrien case VAR_DECL: 1150750397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1150850397Sobrien variable declarations or definitions. */ 1150950397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1151050397Sobrien break; 1151150397Sobrien 1151250397Sobrien /* Output any DIEs that are needed to specify the type of this data 1151350397Sobrien object. */ 1151450397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1151550397Sobrien 1151650397Sobrien /* And its containing type. */ 1151750397Sobrien origin = decl_class_context (decl); 1151850397Sobrien if (origin != NULL_TREE) 1151990075Sobrien gen_type_die_for_member (origin, decl, context_die); 1152050397Sobrien 1152150397Sobrien /* Now output the DIE to represent the data object itself. This gets 1152250397Sobrien complicated because of the possibility that the VAR_DECL really 1152350397Sobrien represents an inlined instance of a formal parameter for an inline 1152450397Sobrien function. */ 1152550397Sobrien origin = decl_ultimate_origin (decl); 1152650397Sobrien if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) 1152750397Sobrien gen_formal_parameter_die (decl, context_die); 1152850397Sobrien else 1152950397Sobrien gen_variable_die (decl, context_die); 1153050397Sobrien break; 1153150397Sobrien 1153250397Sobrien case FIELD_DECL: 1153390075Sobrien /* Ignore the nameless fields that are used to skip bits but handle C++ 1153490075Sobrien anonymous unions. */ 1153550397Sobrien if (DECL_NAME (decl) != NULL_TREE 1153650397Sobrien || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE) 1153750397Sobrien { 1153850397Sobrien gen_type_die (member_declared_type (decl), context_die); 1153950397Sobrien gen_field_die (decl, context_die); 1154050397Sobrien } 1154150397Sobrien break; 1154250397Sobrien 1154350397Sobrien case PARM_DECL: 1154450397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1154550397Sobrien gen_formal_parameter_die (decl, context_die); 1154650397Sobrien break; 1154750397Sobrien 1154890075Sobrien case NAMESPACE_DECL: 1154990075Sobrien /* Ignore for now. */ 1155090075Sobrien break; 1155190075Sobrien 1155250397Sobrien default: 1155350397Sobrien abort (); 1155450397Sobrien } 1155550397Sobrien} 1155690075Sobrien 1155790075Sobrienstatic void 1155890075Sobrienmark_limbo_die_list (ptr) 1155990075Sobrien void *ptr ATTRIBUTE_UNUSED; 1156090075Sobrien{ 1156190075Sobrien limbo_die_node *node; 1156290075Sobrien for (node = limbo_die_list; node ; node = node->next) 1156390075Sobrien ggc_mark_tree (node->created_for); 1156490075Sobrien} 1156550397Sobrien 1156690075Sobrien/* Add Ada "use" clause information for SGI Workshop debugger. */ 1156750397Sobrien 1156850397Sobrienvoid 1156990075Sobriendwarf2out_add_library_unit_info (filename, context_list) 1157090075Sobrien const char *filename; 1157190075Sobrien const char *context_list; 1157250397Sobrien{ 1157390075Sobrien unsigned int file_index; 1157450397Sobrien 1157590075Sobrien if (filename != NULL) 1157650397Sobrien { 1157790075Sobrien dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die, NULL); 1157890075Sobrien tree context_list_decl 1157990075Sobrien = build_decl (LABEL_DECL, get_identifier (context_list), 1158090075Sobrien void_type_node); 1158150397Sobrien 1158290075Sobrien TREE_PUBLIC (context_list_decl) = TRUE; 1158390075Sobrien add_name_attribute (unit_die, context_list); 1158490075Sobrien file_index = lookup_filename (filename); 1158590075Sobrien add_AT_unsigned (unit_die, DW_AT_decl_file, file_index); 1158690075Sobrien add_pubname (context_list_decl, unit_die); 1158750397Sobrien } 1158890075Sobrien} 1158950397Sobrien 1159090075Sobrien/* Output debug information for global decl DECL. Called from toplev.c after 1159190075Sobrien compilation proper has finished. */ 1159290075Sobrien 1159390075Sobrienstatic void 1159490075Sobriendwarf2out_global_decl (decl) 1159590075Sobrien tree decl; 1159690075Sobrien{ 1159790075Sobrien /* Output DWARF2 information for file-scope tentative data object 1159890075Sobrien declarations, file-scope (extern) function declarations (which had no 1159990075Sobrien corresponding body) and file-scope tagged type declarations and 1160090075Sobrien definitions which have not yet been forced out. */ 1160190075Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) 1160290075Sobrien dwarf2out_decl (decl); 1160390075Sobrien} 1160490075Sobrien 1160590075Sobrien/* Write the debugging output for DECL. */ 1160690075Sobrien 1160790075Sobrienvoid 1160890075Sobriendwarf2out_decl (decl) 1160990075Sobrien tree decl; 1161090075Sobrien{ 1161190075Sobrien dw_die_ref context_die = comp_unit_die; 1161290075Sobrien 1161350397Sobrien switch (TREE_CODE (decl)) 1161450397Sobrien { 1161590075Sobrien case ERROR_MARK: 1161690075Sobrien return; 1161790075Sobrien 1161850397Sobrien case FUNCTION_DECL: 1161990075Sobrien /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a 1162050397Sobrien builtin function. Explicit programmer-supplied declarations of 1162150397Sobrien these same functions should NOT be ignored however. */ 1162290075Sobrien if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl)) 1162350397Sobrien return; 1162450397Sobrien 1162550397Sobrien /* What we would really like to do here is to filter out all mere 1162650397Sobrien file-scope declarations of file-scope functions which are never 1162750397Sobrien referenced later within this translation unit (and keep all of ones 1162890075Sobrien that *are* referenced later on) but we aren't clairvoyant, so we have 1162990075Sobrien no idea which functions will be referenced in the future (i.e. later 1163050397Sobrien on within the current translation unit). So here we just ignore all 1163190075Sobrien file-scope function declarations which are not also definitions. If 1163250397Sobrien and when the debugger needs to know something about these functions, 1163390075Sobrien it will have to hunt around and find the DWARF information associated 1163490075Sobrien with the definition of the function. 1163590075Sobrien 1163690075Sobrien We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL 1163790075Sobrien nodes represent definitions and which ones represent mere 1163890075Sobrien declarations. We have to check DECL_INITIAL instead. That's because 1163990075Sobrien the C front-end supports some weird semantics for "extern inline" 1164090075Sobrien function definitions. These can get inlined within the current 1164190075Sobrien translation unit (an thus, we need to generate Dwarf info for their 1164290075Sobrien abstract instances so that the Dwarf info for the concrete inlined 1164390075Sobrien instances can have something to refer to) but the compiler never 1164490075Sobrien generates any out-of-lines instances of such things (despite the fact 1164590075Sobrien that they *are* definitions). 1164690075Sobrien 1164790075Sobrien The important point is that the C front-end marks these "extern 1164890075Sobrien inline" functions as DECL_EXTERNAL, but we need to generate DWARF for 1164990075Sobrien them anyway. Note that the C++ front-end also plays some similar games 1165090075Sobrien for inline function definitions appearing within include files which 1165190075Sobrien also contain `#pragma interface' pragmas. */ 1165250397Sobrien if (DECL_INITIAL (decl) == NULL_TREE) 1165350397Sobrien return; 1165450397Sobrien 1165550397Sobrien /* If we're a nested function, initially use a parent of NULL; if we're 1165650397Sobrien a plain function, this will be fixed up in decls_for_scope. If 1165750397Sobrien we're a method, it will be ignored, since we already have a DIE. */ 1165850397Sobrien if (decl_function_context (decl)) 1165950397Sobrien context_die = NULL; 1166050397Sobrien break; 1166150397Sobrien 1166250397Sobrien case VAR_DECL: 1166390075Sobrien /* Ignore this VAR_DECL if it refers to a file-scope extern data object 1166450397Sobrien declaration and if the declaration was never even referenced from 1166550397Sobrien within this entire compilation unit. We suppress these DIEs in 1166650397Sobrien order to save space in the .debug section (by eliminating entries 1166750397Sobrien which are probably useless). Note that we must not suppress 1166850397Sobrien block-local extern declarations (whether used or not) because that 1166950397Sobrien would screw-up the debugger's name lookup mechanism and cause it to 1167050397Sobrien miss things which really ought to be in scope at a given point. */ 1167150397Sobrien if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) 1167250397Sobrien return; 1167350397Sobrien 1167450397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1167550397Sobrien variable declarations or definitions. */ 1167650397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1167750397Sobrien return; 1167850397Sobrien break; 1167950397Sobrien 1168050397Sobrien case TYPE_DECL: 1168190075Sobrien /* Don't emit stubs for types unless they are needed by other DIEs. */ 1168290075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (decl)) 1168390075Sobrien return; 1168490075Sobrien 1168550397Sobrien /* Don't bother trying to generate any DIEs to represent any of the 1168650397Sobrien normal built-in types for the language we are compiling. */ 1168750397Sobrien if (DECL_SOURCE_LINE (decl) == 0) 1168850397Sobrien { 1168950397Sobrien /* OK, we need to generate one for `bool' so GDB knows what type 1169050397Sobrien comparisons have. */ 1169150397Sobrien if ((get_AT_unsigned (comp_unit_die, DW_AT_language) 1169250397Sobrien == DW_LANG_C_plus_plus) 1169390075Sobrien && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE 1169490075Sobrien && ! DECL_IGNORED_P (decl)) 1169550397Sobrien modified_type_die (TREE_TYPE (decl), 0, 0, NULL); 1169650397Sobrien 1169750397Sobrien return; 1169850397Sobrien } 1169950397Sobrien 1170050397Sobrien /* If we are in terse mode, don't generate any DIEs for types. */ 1170150397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1170250397Sobrien return; 1170350397Sobrien 1170450397Sobrien /* If we're a function-scope tag, initially use a parent of NULL; 1170550397Sobrien this will be fixed up in decls_for_scope. */ 1170650397Sobrien if (decl_function_context (decl)) 1170750397Sobrien context_die = NULL; 1170850397Sobrien 1170950397Sobrien break; 1171050397Sobrien 1171150397Sobrien default: 1171250397Sobrien return; 1171350397Sobrien } 1171450397Sobrien 1171550397Sobrien gen_decl_die (decl, context_die); 1171650397Sobrien} 1171750397Sobrien 1171850397Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for 1171950397Sobrien a lexical block. */ 1172050397Sobrien 1172190075Sobrienstatic void 1172290075Sobriendwarf2out_begin_block (line, blocknum) 1172390075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1172490075Sobrien unsigned int blocknum; 1172550397Sobrien{ 1172650397Sobrien function_section (current_function_decl); 1172790075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 1172850397Sobrien} 1172950397Sobrien 1173050397Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a 1173150397Sobrien lexical block. */ 1173250397Sobrien 1173390075Sobrienstatic void 1173490075Sobriendwarf2out_end_block (line, blocknum) 1173590075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1173690075Sobrien unsigned int blocknum; 1173750397Sobrien{ 1173850397Sobrien function_section (current_function_decl); 1173990075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); 1174050397Sobrien} 1174150397Sobrien 1174290075Sobrien/* Returns nonzero if it is appropriate not to emit any debugging 1174390075Sobrien information for BLOCK, because it doesn't contain any instructions. 1174450397Sobrien 1174590075Sobrien Don't allow this for blocks with nested functions or local classes 1174690075Sobrien as we would end up with orphans, and in the presence of scheduling 1174790075Sobrien we may end up calling them anyway. */ 1174890075Sobrien 1174990075Sobrienstatic bool 1175090075Sobriendwarf2out_ignore_block (block) 1175190075Sobrien tree block; 1175250397Sobrien{ 1175390075Sobrien tree decl; 1175450397Sobrien 1175590075Sobrien for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl)) 1175690075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1175790075Sobrien || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))) 1175890075Sobrien return 0; 1175990075Sobrien 1176090075Sobrien return 1; 1176150397Sobrien} 1176250397Sobrien 1176390075Sobrien/* Lookup FILE_NAME (in the list of filenames that we know about here in 1176450397Sobrien dwarf2out.c) and return its "index". The index of each (known) filename is 1176590075Sobrien just a unique number which is associated with only that one filename. We 1176690075Sobrien need such numbers for the sake of generating labels (in the .debug_sfnames 1176790075Sobrien section) and references to those files numbers (in the .debug_srcinfo 1176890075Sobrien and.debug_macinfo sections). If the filename given as an argument is not 1176990075Sobrien found in our current list, add it to the list and assign it the next 1177090075Sobrien available unique index number. In order to speed up searches, we remember 1177190075Sobrien the index of the filename was looked up last. This handles the majority of 1177290075Sobrien all searches. */ 1177350397Sobrien 1177450397Sobrienstatic unsigned 1177550397Sobrienlookup_filename (file_name) 1177690075Sobrien const char *file_name; 1177750397Sobrien{ 1177890075Sobrien unsigned i; 1177950397Sobrien 1178090075Sobrien /* ??? Why isn't DECL_SOURCE_FILE left null instead. */ 1178190075Sobrien if (strcmp (file_name, "<internal>") == 0 1178290075Sobrien || strcmp (file_name, "<built-in>") == 0) 1178390075Sobrien return 0; 1178450397Sobrien 1178590075Sobrien /* Check to see if the file name that was searched on the previous 1178690075Sobrien call matches this file name. If so, return the index. */ 1178790075Sobrien if (file_table.last_lookup_index != 0) 1178890075Sobrien if (0 == strcmp (file_name, 1178990075Sobrien file_table.table[file_table.last_lookup_index])) 1179090075Sobrien return file_table.last_lookup_index; 1179190075Sobrien 1179250397Sobrien /* Didn't match the previous lookup, search the table */ 1179390075Sobrien for (i = 1; i < file_table.in_use; i++) 1179490075Sobrien if (strcmp (file_name, file_table.table[i]) == 0) 1179550397Sobrien { 1179690075Sobrien file_table.last_lookup_index = i; 1179750397Sobrien return i; 1179850397Sobrien } 1179950397Sobrien 1180090075Sobrien /* Prepare to add a new table entry by making sure there is enough space in 1180150397Sobrien the table to do so. If not, expand the current table. */ 1180290075Sobrien if (i == file_table.allocated) 1180350397Sobrien { 1180490075Sobrien file_table.allocated = i + FILE_TABLE_INCREMENT; 1180590075Sobrien file_table.table = (char **) 1180690075Sobrien xrealloc (file_table.table, file_table.allocated * sizeof (char *)); 1180750397Sobrien } 1180850397Sobrien 1180950397Sobrien /* Add the new entry to the end of the filename table. */ 1181090075Sobrien file_table.table[i] = xstrdup (file_name); 1181190075Sobrien file_table.in_use = i + 1; 1181290075Sobrien file_table.last_lookup_index = i; 1181350397Sobrien 1181490075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1181590075Sobrien fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name); 1181690075Sobrien 1181790075Sobrien return i; 1181850397Sobrien} 1181950397Sobrien 1182090075Sobrienstatic void 1182190075Sobrieninit_file_table () 1182290075Sobrien{ 1182390075Sobrien /* Allocate the initial hunk of the file_table. */ 1182490075Sobrien file_table.table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *)); 1182590075Sobrien file_table.allocated = FILE_TABLE_INCREMENT; 1182690075Sobrien 1182790075Sobrien /* Skip the first entry - file numbers begin at 1. */ 1182890075Sobrien file_table.in_use = 1; 1182990075Sobrien file_table.last_lookup_index = 0; 1183090075Sobrien} 1183190075Sobrien 1183250397Sobrien/* Output a label to mark the beginning of a source code line entry 1183350397Sobrien and record information relating to this source line, in 1183450397Sobrien 'line_info_table' for later output of the .debug_line section. */ 1183550397Sobrien 1183690075Sobrienstatic void 1183790075Sobriendwarf2out_source_line (line, filename) 1183890075Sobrien unsigned int line; 1183990075Sobrien const char *filename; 1184050397Sobrien{ 1184150397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1184250397Sobrien { 1184350397Sobrien function_section (current_function_decl); 1184450397Sobrien 1184590075Sobrien /* If requested, emit something human-readable. */ 1184690075Sobrien if (flag_debug_asm) 1184790075Sobrien fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, 1184890075Sobrien filename, line); 1184990075Sobrien 1185090075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1185150397Sobrien { 1185290075Sobrien unsigned file_num = lookup_filename (filename); 1185390075Sobrien 1185490075Sobrien /* Emit the .loc directive understood by GNU as. */ 1185590075Sobrien fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); 1185690075Sobrien 1185790075Sobrien /* Indicate that line number info exists. */ 1185890075Sobrien line_info_table_in_use++; 1185990075Sobrien 1186090075Sobrien /* Indicate that multiple line number tables exist. */ 1186190075Sobrien if (DECL_SECTION_NAME (current_function_decl)) 1186290075Sobrien separate_line_info_table_in_use++; 1186390075Sobrien } 1186490075Sobrien else if (DECL_SECTION_NAME (current_function_decl)) 1186590075Sobrien { 1186690075Sobrien dw_separate_line_info_ref line_info; 1186750397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, 1186850397Sobrien separate_line_info_table_in_use); 1186950397Sobrien 1187050397Sobrien /* expand the line info table if necessary */ 1187150397Sobrien if (separate_line_info_table_in_use 1187250397Sobrien == separate_line_info_table_allocated) 1187350397Sobrien { 1187450397Sobrien separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1187550397Sobrien separate_line_info_table 1187650397Sobrien = (dw_separate_line_info_ref) 1187750397Sobrien xrealloc (separate_line_info_table, 1187850397Sobrien separate_line_info_table_allocated 1187950397Sobrien * sizeof (dw_separate_line_info_entry)); 1188050397Sobrien } 1188150397Sobrien 1188250397Sobrien /* Add the new entry at the end of the line_info_table. */ 1188350397Sobrien line_info 1188450397Sobrien = &separate_line_info_table[separate_line_info_table_in_use++]; 1188550397Sobrien line_info->dw_file_num = lookup_filename (filename); 1188650397Sobrien line_info->dw_line_num = line; 1188750397Sobrien line_info->function = current_funcdef_number; 1188850397Sobrien } 1188950397Sobrien else 1189050397Sobrien { 1189190075Sobrien dw_line_info_ref line_info; 1189250397Sobrien 1189350397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, 1189450397Sobrien line_info_table_in_use); 1189550397Sobrien 1189650397Sobrien /* Expand the line info table if necessary. */ 1189750397Sobrien if (line_info_table_in_use == line_info_table_allocated) 1189850397Sobrien { 1189950397Sobrien line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1190050397Sobrien line_info_table 1190150397Sobrien = (dw_line_info_ref) 1190250397Sobrien xrealloc (line_info_table, 1190350397Sobrien (line_info_table_allocated 1190450397Sobrien * sizeof (dw_line_info_entry))); 1190550397Sobrien } 1190650397Sobrien 1190750397Sobrien /* Add the new entry at the end of the line_info_table. */ 1190850397Sobrien line_info = &line_info_table[line_info_table_in_use++]; 1190950397Sobrien line_info->dw_file_num = lookup_filename (filename); 1191050397Sobrien line_info->dw_line_num = line; 1191150397Sobrien } 1191250397Sobrien } 1191350397Sobrien} 1191450397Sobrien 1191590075Sobrien/* Record the beginning of a new source file. */ 1191650397Sobrien 1191790075Sobrienstatic void 1191890075Sobriendwarf2out_start_source_file (lineno, filename) 1191990075Sobrien unsigned int lineno; 1192090075Sobrien const char *filename; 1192150397Sobrien{ 1192290075Sobrien if (flag_eliminate_dwarf2_dups) 1192390075Sobrien { 1192490075Sobrien /* Record the beginning of the file for break_out_includes. */ 1192590075Sobrien dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); 1192690075Sobrien add_AT_string (bincl_die, DW_AT_name, filename); 1192790075Sobrien } 1192890075Sobrien 1192990075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1193090075Sobrien { 1193190075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1193290075Sobrien dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); 1193390075Sobrien dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", 1193490075Sobrien lineno); 1193590075Sobrien dw2_asm_output_data_uleb128 (lookup_filename (filename), 1193690075Sobrien "Filename we just started"); 1193790075Sobrien } 1193850397Sobrien} 1193950397Sobrien 1194090075Sobrien/* Record the end of a source file. */ 1194150397Sobrien 1194290075Sobrienstatic void 1194390075Sobriendwarf2out_end_source_file (lineno) 1194490075Sobrien unsigned int lineno ATTRIBUTE_UNUSED; 1194550397Sobrien{ 1194690075Sobrien if (flag_eliminate_dwarf2_dups) 1194790075Sobrien /* Record the end of the file for break_out_includes. */ 1194890075Sobrien new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL); 1194990075Sobrien 1195090075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1195190075Sobrien { 1195290075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1195390075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1195490075Sobrien } 1195550397Sobrien} 1195650397Sobrien 1195790075Sobrien/* Called from debug_define in toplev.c. The `buffer' parameter contains 1195850397Sobrien the tail part of the directive line, i.e. the part which is past the 1195950397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1196050397Sobrien 1196190075Sobrienstatic void 1196250397Sobriendwarf2out_define (lineno, buffer) 1196390075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1196490075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1196550397Sobrien{ 1196690075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1196790075Sobrien { 1196890075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1196990075Sobrien dw2_asm_output_data (1, DW_MACINFO_define, "Define macro"); 1197090075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1197190075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1197290075Sobrien } 1197350397Sobrien} 1197450397Sobrien 1197590075Sobrien/* Called from debug_undef in toplev.c. The `buffer' parameter contains 1197650397Sobrien the tail part of the directive line, i.e. the part which is past the 1197750397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1197850397Sobrien 1197990075Sobrienstatic void 1198050397Sobriendwarf2out_undef (lineno, buffer) 1198190075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1198290075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1198350397Sobrien{ 1198490075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1198590075Sobrien { 1198690075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1198790075Sobrien dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro"); 1198890075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1198990075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1199090075Sobrien } 1199150397Sobrien} 1199250397Sobrien 1199350397Sobrien/* Set up for Dwarf output at the start of compilation. */ 1199450397Sobrien 1199590075Sobrienstatic void 1199690075Sobriendwarf2out_init (main_input_filename) 1199790075Sobrien const char *main_input_filename; 1199850397Sobrien{ 1199990075Sobrien init_file_table (); 1200090075Sobrien 1200150397Sobrien /* Remember the name of the primary input file. */ 1200250397Sobrien primary_filename = main_input_filename; 1200350397Sobrien 1200490075Sobrien /* Add it to the file table first, under the assumption that we'll 1200590075Sobrien be emitting line number data for it first, which avoids having 1200690075Sobrien to add an initial DW_LNS_set_file. */ 1200790075Sobrien lookup_filename (main_input_filename); 1200850397Sobrien 1200950397Sobrien /* Allocate the initial hunk of the decl_die_table. */ 1201050397Sobrien decl_die_table 1201190075Sobrien = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref)); 1201250397Sobrien decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT; 1201350397Sobrien decl_die_table_in_use = 0; 1201450397Sobrien 1201550397Sobrien /* Allocate the initial hunk of the decl_scope_table. */ 1201690075Sobrien VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table"); 1201790075Sobrien ggc_add_tree_varray_root (&decl_scope_table, 1); 1201850397Sobrien 1201950397Sobrien /* Allocate the initial hunk of the abbrev_die_table. */ 1202050397Sobrien abbrev_die_table 1202190075Sobrien = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT, 1202290075Sobrien sizeof (dw_die_ref)); 1202350397Sobrien abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; 1202450397Sobrien /* Zero-th entry is allocated, but unused */ 1202550397Sobrien abbrev_die_table_in_use = 1; 1202650397Sobrien 1202750397Sobrien /* Allocate the initial hunk of the line_info_table. */ 1202850397Sobrien line_info_table 1202990075Sobrien = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, 1203090075Sobrien sizeof (dw_line_info_entry)); 1203150397Sobrien line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 1203290075Sobrien 1203350397Sobrien /* Zero-th entry is allocated, but unused */ 1203450397Sobrien line_info_table_in_use = 1; 1203550397Sobrien 1203690075Sobrien /* Generate the initial DIE for the .debug section. Note that the (string) 1203750397Sobrien value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE 1203890075Sobrien will (typically) be a relative pathname and that this pathname should be 1203950397Sobrien taken as being relative to the directory from which the compiler was 1204050397Sobrien invoked when the given (base) source file was compiled. */ 1204190075Sobrien comp_unit_die = gen_compile_unit_die (main_input_filename); 1204250397Sobrien 1204390075Sobrien VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types"); 1204490075Sobrien ggc_add_tree_varray_root (&incomplete_types, 1); 1204590075Sobrien 1204690075Sobrien VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray"); 1204790075Sobrien ggc_add_rtx_varray_root (&used_rtx_varray, 1); 1204890075Sobrien 1204990075Sobrien ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list); 1205090075Sobrien 1205150397Sobrien ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1205290075Sobrien ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, 1205390075Sobrien DEBUG_ABBREV_SECTION_LABEL, 0); 1205490075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1205590075Sobrien ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0); 1205690075Sobrien else 1205790075Sobrien strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME)); 1205890075Sobrien 1205990075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, 1206052284Sobrien DEBUG_INFO_SECTION_LABEL, 0); 1206190075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, 1206252284Sobrien DEBUG_LINE_SECTION_LABEL, 0); 1206390075Sobrien ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, 1206490075Sobrien DEBUG_RANGES_SECTION_LABEL, 0); 1206590075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1206652284Sobrien ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); 1206790075Sobrien named_section_flags (DEBUG_INFO_SECTION, SECTION_DEBUG); 1206852284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label); 1206990075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1207052284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); 1207190075Sobrien 1207290075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1207390075Sobrien { 1207490075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1207590075Sobrien ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label, 1207690075Sobrien DEBUG_MACINFO_SECTION_LABEL, 0); 1207790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label); 1207890075Sobrien } 1207990075Sobrien 1208090075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1208190075Sobrien { 1208290075Sobrien text_section (); 1208390075Sobrien ASM_OUTPUT_LABEL (asm_out_file, text_section_label); 1208490075Sobrien } 1208550397Sobrien} 1208650397Sobrien 1208790075Sobrien/* Allocate a string in .debug_str hash table. */ 1208890075Sobrien 1208990075Sobrienstatic hashnode 1209090075Sobrienindirect_string_alloc (tab) 1209190075Sobrien hash_table *tab ATTRIBUTE_UNUSED; 1209290075Sobrien{ 1209390075Sobrien struct indirect_string_node *node; 1209490075Sobrien 1209590075Sobrien node = xmalloc (sizeof (struct indirect_string_node)); 1209690075Sobrien node->refcount = 0; 1209790075Sobrien node->form = 0; 1209890075Sobrien node->label = NULL; 1209990075Sobrien 1210090075Sobrien return (hashnode) node; 1210190075Sobrien} 1210290075Sobrien 1210390075Sobrien/* A helper function for dwarf2out_finish called through 1210490075Sobrien ht_forall. Emit one queued .debug_str string. */ 1210590075Sobrien 1210690075Sobrienstatic int 1210790075Sobrienoutput_indirect_string (pfile, h, v) 1210890075Sobrien struct cpp_reader *pfile ATTRIBUTE_UNUSED; 1210990075Sobrien hashnode h; 1211090075Sobrien const PTR v ATTRIBUTE_UNUSED; 1211190075Sobrien{ 1211290075Sobrien struct indirect_string_node *node = (struct indirect_string_node *) h; 1211390075Sobrien 1211490075Sobrien if (node->form == DW_FORM_strp) 1211590075Sobrien { 1211690075Sobrien named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS); 1211790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, node->label); 1211890075Sobrien assemble_string ((const char *) HT_STR (&node->id), 1211990075Sobrien HT_LEN (&node->id) + 1); 1212090075Sobrien } 1212190075Sobrien 1212290075Sobrien return 1; 1212390075Sobrien} 1212490075Sobrien 1212550397Sobrien/* Output stuff that dwarf requires at the end of every file, 1212650397Sobrien and generate the DWARF-2 debugging info. */ 1212750397Sobrien 1212890075Sobrienstatic void 1212990075Sobriendwarf2out_finish (input_filename) 1213090075Sobrien const char *input_filename ATTRIBUTE_UNUSED; 1213150397Sobrien{ 1213250397Sobrien limbo_die_node *node, *next_node; 1213390075Sobrien dw_die_ref die = 0; 1213450397Sobrien 1213550397Sobrien /* Traverse the limbo die list, and add parent/child links. The only 1213650397Sobrien dies without parents that should be here are concrete instances of 1213750397Sobrien inline functions, and the comp_unit_die. We can ignore the comp_unit_die. 1213850397Sobrien For concrete instances, we can get the parent die from the abstract 1213950397Sobrien instance. */ 1214050397Sobrien for (node = limbo_die_list; node; node = next_node) 1214150397Sobrien { 1214250397Sobrien next_node = node->next; 1214350397Sobrien die = node->die; 1214450397Sobrien 1214550397Sobrien if (die->die_parent == NULL) 1214650397Sobrien { 1214790075Sobrien dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); 1214890075Sobrien tree context; 1214990075Sobrien 1215090075Sobrien if (origin) 1215190075Sobrien add_child_die (origin->die_parent, die); 1215250397Sobrien else if (die == comp_unit_die) 1215390075Sobrien ; 1215490075Sobrien /* If this was an expression for a bound involved in a function 1215590075Sobrien return type, it may be a SAVE_EXPR for which we weren't able 1215690075Sobrien to find a DIE previously. So try now. */ 1215790075Sobrien else if (node->created_for 1215890075Sobrien && TREE_CODE (node->created_for) == SAVE_EXPR 1215990075Sobrien && 0 != (origin = (lookup_decl_die 1216090075Sobrien (SAVE_EXPR_CONTEXT 1216190075Sobrien (node->created_for))))) 1216290075Sobrien add_child_die (origin, die); 1216390075Sobrien else if (errorcount > 0 || sorrycount > 0) 1216490075Sobrien /* It's OK to be confused by errors in the input. */ 1216590075Sobrien add_child_die (comp_unit_die, die); 1216690075Sobrien else if (node->created_for 1216790075Sobrien && ((DECL_P (node->created_for) 1216890075Sobrien && (context = DECL_CONTEXT (node->created_for))) 1216990075Sobrien || (TYPE_P (node->created_for) 1217090075Sobrien && (context = TYPE_CONTEXT (node->created_for)))) 1217190075Sobrien && TREE_CODE (context) == FUNCTION_DECL) 1217290075Sobrien { 1217390075Sobrien /* In certain situations, the lexical block containing a 1217490075Sobrien nested function can be optimized away, which results 1217590075Sobrien in the nested function die being orphaned. Likewise 1217690075Sobrien with the return type of that nested function. Force 1217790075Sobrien this to be a child of the containing function. */ 1217890075Sobrien origin = lookup_decl_die (context); 1217990075Sobrien if (! origin) 1218090075Sobrien abort (); 1218190075Sobrien add_child_die (origin, die); 1218290075Sobrien } 1218350397Sobrien else 1218450397Sobrien abort (); 1218550397Sobrien } 1218690075Sobrien 1218750397Sobrien free (node); 1218850397Sobrien } 1218950397Sobrien 1219090075Sobrien limbo_die_list = NULL; 1219190075Sobrien 1219252284Sobrien /* Walk through the list of incomplete types again, trying once more to 1219352284Sobrien emit full debugging info for them. */ 1219452284Sobrien retry_incomplete_types (); 1219552284Sobrien 1219690075Sobrien /* We need to reverse all the dies before break_out_includes, or 1219790075Sobrien we'll see the end of an include file before the beginning. */ 1219890075Sobrien reverse_all_dies (comp_unit_die); 1219990075Sobrien 1220090075Sobrien /* Generate separate CUs for each of the include files we've seen. 1220190075Sobrien They will go into limbo_die_list. */ 1220290075Sobrien if (flag_eliminate_dwarf2_dups) 1220390075Sobrien break_out_includes (comp_unit_die); 1220490075Sobrien 1220590075Sobrien /* Traverse the DIE's and add add sibling attributes to those DIE's 1220650397Sobrien that have children. */ 1220750397Sobrien add_sibling_attributes (comp_unit_die); 1220890075Sobrien for (node = limbo_die_list; node; node = node->next) 1220990075Sobrien add_sibling_attributes (node->die); 1221050397Sobrien 1221150397Sobrien /* Output a terminator label for the .text section. */ 1221290075Sobrien text_section (); 1221350397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); 1221450397Sobrien 1221590075Sobrien /* Output the source line correspondence table. We must do this 1221690075Sobrien even if there is no line information. Otherwise, on an empty 1221790075Sobrien translation unit, we will generate a present, but empty, 1221890075Sobrien .debug_info section. IRIX 6.5 `nm' will then complain when 1221990075Sobrien examining the file. */ 1222090075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 1222150397Sobrien { 1222290075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1222350397Sobrien output_line_info (); 1222490075Sobrien } 1222550397Sobrien 1222690075Sobrien /* Output location list section if necessary. */ 1222790075Sobrien if (have_location_lists) 1222890075Sobrien { 1222990075Sobrien /* Output the location lists info. */ 1223090075Sobrien named_section_flags (DEBUG_LOC_SECTION, SECTION_DEBUG); 1223190075Sobrien ASM_GENERATE_INTERNAL_LABEL (loc_section_label, 1223290075Sobrien DEBUG_LOC_SECTION_LABEL, 0); 1223390075Sobrien ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); 1223490075Sobrien output_location_lists (die); 1223590075Sobrien have_location_lists = 0; 1223690075Sobrien } 1223750397Sobrien 1223890075Sobrien /* We can only use the low/high_pc attributes if all of the code was 1223990075Sobrien in .text. */ 1224090075Sobrien if (separate_line_info_table_in_use == 0) 1224190075Sobrien { 1224290075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); 1224390075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); 1224450397Sobrien } 1224550397Sobrien 1224690075Sobrien /* If it wasn't, we need to give .debug_loc and .debug_ranges an appropriate 1224790075Sobrien "base address". Use zero so that these addresses become absolute. */ 1224890075Sobrien else if (have_location_lists || ranges_table_in_use) 1224990075Sobrien add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); 1225090075Sobrien 1225190075Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1225290075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, 1225390075Sobrien debug_line_section_label); 1225490075Sobrien 1225590075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1225690075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_macro_info, macinfo_section_label); 1225790075Sobrien 1225890075Sobrien /* Output all of the compilation units. We put the main one last so that 1225990075Sobrien the offsets are available to output_pubnames. */ 1226090075Sobrien for (node = limbo_die_list; node; node = node->next) 1226190075Sobrien output_comp_unit (node->die); 1226290075Sobrien 1226390075Sobrien output_comp_unit (comp_unit_die); 1226490075Sobrien 1226550397Sobrien /* Output the abbreviation table. */ 1226690075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1226750397Sobrien output_abbrev_section (); 1226850397Sobrien 1226990075Sobrien /* Output public names table if necessary. */ 1227050397Sobrien if (pubname_table_in_use) 1227150397Sobrien { 1227290075Sobrien named_section_flags (DEBUG_PUBNAMES_SECTION, SECTION_DEBUG); 1227350397Sobrien output_pubnames (); 1227450397Sobrien } 1227550397Sobrien 1227690075Sobrien /* Output the address range information. We only put functions in the arange 1227790075Sobrien table, so don't write it out if we don't have any. */ 1227850397Sobrien if (fde_table_in_use) 1227950397Sobrien { 1228090075Sobrien named_section_flags (DEBUG_ARANGES_SECTION, SECTION_DEBUG); 1228150397Sobrien output_aranges (); 1228250397Sobrien } 1228390075Sobrien 1228490075Sobrien /* Output ranges section if necessary. */ 1228590075Sobrien if (ranges_table_in_use) 1228690075Sobrien { 1228790075Sobrien named_section_flags (DEBUG_RANGES_SECTION, SECTION_DEBUG); 1228890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label); 1228990075Sobrien output_ranges (); 1229090075Sobrien } 1229190075Sobrien 1229290075Sobrien /* Have to end the primary source file. */ 1229390075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1229490075Sobrien { 1229590075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1229690075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1229790075Sobrien } 1229890075Sobrien 1229990075Sobrien /* If we emitted any DW_FORM_strp form attribute, output the string 1230090075Sobrien table too. */ 1230190075Sobrien if (debug_str_hash) 1230290075Sobrien ht_forall (debug_str_hash, output_indirect_string, NULL); 1230350397Sobrien} 1230490075Sobrien#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */ 12305