dwarf2out.c revision 102780
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 420102780Skan for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 421102780Skan if (DWARF_FRAME_REGNUM (i) < DWARF_FRAME_REGISTERS) 422102780Skan { 423102780Skan HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode); 424102780Skan HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]); 42550397Sobrien 426102780Skan if (offset < 0) 427102780Skan continue; 42850397Sobrien 429102780Skan emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); 430102780Skan } 43150397Sobrien} 43250397Sobrien 43350397Sobrien/* Convert a DWARF call frame info. operation to its string name */ 43450397Sobrien 43590075Sobrienstatic const char * 43650397Sobriendwarf_cfi_name (cfi_opc) 43790075Sobrien unsigned cfi_opc; 43850397Sobrien{ 43950397Sobrien switch (cfi_opc) 44050397Sobrien { 44150397Sobrien case DW_CFA_advance_loc: 44250397Sobrien return "DW_CFA_advance_loc"; 44350397Sobrien case DW_CFA_offset: 44450397Sobrien return "DW_CFA_offset"; 44550397Sobrien case DW_CFA_restore: 44650397Sobrien return "DW_CFA_restore"; 44750397Sobrien case DW_CFA_nop: 44850397Sobrien return "DW_CFA_nop"; 44950397Sobrien case DW_CFA_set_loc: 45050397Sobrien return "DW_CFA_set_loc"; 45150397Sobrien case DW_CFA_advance_loc1: 45250397Sobrien return "DW_CFA_advance_loc1"; 45350397Sobrien case DW_CFA_advance_loc2: 45450397Sobrien return "DW_CFA_advance_loc2"; 45550397Sobrien case DW_CFA_advance_loc4: 45650397Sobrien return "DW_CFA_advance_loc4"; 45750397Sobrien case DW_CFA_offset_extended: 45850397Sobrien return "DW_CFA_offset_extended"; 45950397Sobrien case DW_CFA_restore_extended: 46050397Sobrien return "DW_CFA_restore_extended"; 46150397Sobrien case DW_CFA_undefined: 46250397Sobrien return "DW_CFA_undefined"; 46350397Sobrien case DW_CFA_same_value: 46450397Sobrien return "DW_CFA_same_value"; 46550397Sobrien case DW_CFA_register: 46650397Sobrien return "DW_CFA_register"; 46750397Sobrien case DW_CFA_remember_state: 46850397Sobrien return "DW_CFA_remember_state"; 46950397Sobrien case DW_CFA_restore_state: 47050397Sobrien return "DW_CFA_restore_state"; 47150397Sobrien case DW_CFA_def_cfa: 47250397Sobrien return "DW_CFA_def_cfa"; 47350397Sobrien case DW_CFA_def_cfa_register: 47450397Sobrien return "DW_CFA_def_cfa_register"; 47550397Sobrien case DW_CFA_def_cfa_offset: 47650397Sobrien return "DW_CFA_def_cfa_offset"; 47750397Sobrien 47890075Sobrien /* DWARF 3 */ 47990075Sobrien case DW_CFA_def_cfa_expression: 48090075Sobrien return "DW_CFA_def_cfa_expression"; 48190075Sobrien case DW_CFA_expression: 48290075Sobrien return "DW_CFA_expression"; 48390075Sobrien case DW_CFA_offset_extended_sf: 48490075Sobrien return "DW_CFA_offset_extended_sf"; 48590075Sobrien case DW_CFA_def_cfa_sf: 48690075Sobrien return "DW_CFA_def_cfa_sf"; 48790075Sobrien case DW_CFA_def_cfa_offset_sf: 48890075Sobrien return "DW_CFA_def_cfa_offset_sf"; 48990075Sobrien 49050397Sobrien /* SGI/MIPS specific */ 49150397Sobrien case DW_CFA_MIPS_advance_loc8: 49250397Sobrien return "DW_CFA_MIPS_advance_loc8"; 49350397Sobrien 49450397Sobrien /* GNU extensions */ 49550397Sobrien case DW_CFA_GNU_window_save: 49650397Sobrien return "DW_CFA_GNU_window_save"; 49750397Sobrien case DW_CFA_GNU_args_size: 49850397Sobrien return "DW_CFA_GNU_args_size"; 49970635Sobrien case DW_CFA_GNU_negative_offset_extended: 50070635Sobrien return "DW_CFA_GNU_negative_offset_extended"; 50150397Sobrien 50250397Sobrien default: 50350397Sobrien return "DW_CFA_<unknown>"; 50450397Sobrien } 50550397Sobrien} 50650397Sobrien 50750397Sobrien/* Return a pointer to a newly allocated Call Frame Instruction. */ 50850397Sobrien 50950397Sobrienstatic inline dw_cfi_ref 51050397Sobriennew_cfi () 51150397Sobrien{ 51290075Sobrien dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node)); 51350397Sobrien 51450397Sobrien cfi->dw_cfi_next = NULL; 51550397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0; 51650397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0; 51750397Sobrien 51850397Sobrien return cfi; 51950397Sobrien} 52050397Sobrien 52150397Sobrien/* Add a Call Frame Instruction to list of instructions. */ 52250397Sobrien 52350397Sobrienstatic inline void 52450397Sobrienadd_cfi (list_head, cfi) 52590075Sobrien dw_cfi_ref *list_head; 52690075Sobrien dw_cfi_ref cfi; 52750397Sobrien{ 52890075Sobrien dw_cfi_ref *p; 52950397Sobrien 53050397Sobrien /* Find the end of the chain. */ 53150397Sobrien for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next) 53250397Sobrien ; 53350397Sobrien 53450397Sobrien *p = cfi; 53550397Sobrien} 53650397Sobrien 53750397Sobrien/* Generate a new label for the CFI info to refer to. */ 53850397Sobrien 53950397Sobrienchar * 54050397Sobriendwarf2out_cfi_label () 54150397Sobrien{ 54250397Sobrien static char label[20]; 54350397Sobrien static unsigned long label_num = 0; 54490075Sobrien 54550397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++); 54650397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 54750397Sobrien return label; 54850397Sobrien} 54950397Sobrien 55050397Sobrien/* Add CFI to the current fde at the PC value indicated by LABEL if specified, 55150397Sobrien or to the CIE if LABEL is NULL. */ 55250397Sobrien 55350397Sobrienstatic void 55450397Sobrienadd_fde_cfi (label, cfi) 55590075Sobrien const char *label; 55690075Sobrien dw_cfi_ref cfi; 55750397Sobrien{ 55850397Sobrien if (label) 55950397Sobrien { 56090075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 56150397Sobrien 56250397Sobrien if (*label == 0) 56350397Sobrien label = dwarf2out_cfi_label (); 56450397Sobrien 56550397Sobrien if (fde->dw_fde_current_label == NULL 56650397Sobrien || strcmp (label, fde->dw_fde_current_label) != 0) 56750397Sobrien { 56890075Sobrien dw_cfi_ref xcfi; 56950397Sobrien 57050397Sobrien fde->dw_fde_current_label = label = xstrdup (label); 57150397Sobrien 57250397Sobrien /* Set the location counter to the new label. */ 57350397Sobrien xcfi = new_cfi (); 57450397Sobrien xcfi->dw_cfi_opc = DW_CFA_advance_loc4; 57550397Sobrien xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; 57650397Sobrien add_cfi (&fde->dw_fde_cfi, xcfi); 57750397Sobrien } 57850397Sobrien 57950397Sobrien add_cfi (&fde->dw_fde_cfi, cfi); 58050397Sobrien } 58150397Sobrien 58250397Sobrien else 58350397Sobrien add_cfi (&cie_cfi_head, cfi); 58450397Sobrien} 58550397Sobrien 58650397Sobrien/* Subroutine of lookup_cfa. */ 58750397Sobrien 58850397Sobrienstatic inline void 58990075Sobrienlookup_cfa_1 (cfi, loc) 59090075Sobrien dw_cfi_ref cfi; 59190075Sobrien dw_cfa_location *loc; 59250397Sobrien{ 59350397Sobrien switch (cfi->dw_cfi_opc) 59450397Sobrien { 59550397Sobrien case DW_CFA_def_cfa_offset: 59690075Sobrien loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset; 59750397Sobrien break; 59850397Sobrien case DW_CFA_def_cfa_register: 59990075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 60050397Sobrien break; 60150397Sobrien case DW_CFA_def_cfa: 60290075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 60390075Sobrien loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset; 60450397Sobrien break; 60590075Sobrien case DW_CFA_def_cfa_expression: 60690075Sobrien get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc); 60790075Sobrien break; 60850397Sobrien default: 60950397Sobrien break; 61050397Sobrien } 61150397Sobrien} 61250397Sobrien 61350397Sobrien/* Find the previous value for the CFA. */ 61450397Sobrien 61550397Sobrienstatic void 61690075Sobrienlookup_cfa (loc) 61790075Sobrien dw_cfa_location *loc; 61850397Sobrien{ 61990075Sobrien dw_cfi_ref cfi; 62050397Sobrien 62190075Sobrien loc->reg = (unsigned long) -1; 62290075Sobrien loc->offset = 0; 62390075Sobrien loc->indirect = 0; 62490075Sobrien loc->base_offset = 0; 62550397Sobrien 62650397Sobrien for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next) 62790075Sobrien lookup_cfa_1 (cfi, loc); 62850397Sobrien 62950397Sobrien if (fde_table_in_use) 63050397Sobrien { 63190075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 63250397Sobrien for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) 63390075Sobrien lookup_cfa_1 (cfi, loc); 63450397Sobrien } 63550397Sobrien} 63650397Sobrien 63750397Sobrien/* The current rule for calculating the DWARF2 canonical frame address. */ 63890075Sobrienstatic dw_cfa_location cfa; 63950397Sobrien 64050397Sobrien/* The register used for saving registers to the stack, and its offset 64150397Sobrien from the CFA. */ 64290075Sobrienstatic dw_cfa_location cfa_store; 64350397Sobrien 64450397Sobrien/* The running total of the size of arguments pushed onto the stack. */ 64550397Sobrienstatic long args_size; 64650397Sobrien 64750397Sobrien/* The last args_size we actually output. */ 64850397Sobrienstatic long old_args_size; 64950397Sobrien 65050397Sobrien/* Entry point to update the canonical frame address (CFA). 65150397Sobrien LABEL is passed to add_fde_cfi. The value of CFA is now to be 65250397Sobrien calculated from REG+OFFSET. */ 65350397Sobrien 65450397Sobrienvoid 65550397Sobriendwarf2out_def_cfa (label, reg, offset) 65690075Sobrien const char *label; 65790075Sobrien unsigned reg; 65890075Sobrien long offset; 65950397Sobrien{ 66090075Sobrien dw_cfa_location loc; 66190075Sobrien loc.indirect = 0; 66290075Sobrien loc.base_offset = 0; 66390075Sobrien loc.reg = reg; 66490075Sobrien loc.offset = offset; 66590075Sobrien def_cfa_1 (label, &loc); 66690075Sobrien} 66750397Sobrien 66890075Sobrien/* This routine does the actual work. The CFA is now calculated from 66990075Sobrien the dw_cfa_location structure. */ 67050397Sobrien 67190075Sobrienstatic void 67290075Sobriendef_cfa_1 (label, loc_p) 67390075Sobrien const char *label; 67490075Sobrien dw_cfa_location *loc_p; 67590075Sobrien{ 67690075Sobrien dw_cfi_ref cfi; 67790075Sobrien dw_cfa_location old_cfa, loc; 67850397Sobrien 67990075Sobrien cfa = *loc_p; 68090075Sobrien loc = *loc_p; 68190075Sobrien 68290075Sobrien if (cfa_store.reg == loc.reg && loc.indirect == 0) 68390075Sobrien cfa_store.offset = loc.offset; 68490075Sobrien 68590075Sobrien loc.reg = DWARF_FRAME_REGNUM (loc.reg); 68690075Sobrien lookup_cfa (&old_cfa); 68790075Sobrien 68890075Sobrien /* If nothing changed, no need to issue any call frame instructions. */ 68990075Sobrien if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset 69090075Sobrien && loc.indirect == old_cfa.indirect 69190075Sobrien && (loc.indirect == 0 || loc.base_offset == old_cfa.base_offset)) 69250397Sobrien return; 69350397Sobrien 69450397Sobrien cfi = new_cfi (); 69550397Sobrien 69690075Sobrien if (loc.reg == old_cfa.reg && !loc.indirect) 69750397Sobrien { 69890075Sobrien /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, 69990075Sobrien indicating the CFA register did not change but the offset 70090075Sobrien did. */ 70150397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; 70290075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset; 70350397Sobrien } 70450397Sobrien 70550397Sobrien#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ 70690075Sobrien else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1 70790075Sobrien && !loc.indirect) 70850397Sobrien { 70990075Sobrien /* Construct a "DW_CFA_def_cfa_register <register>" instruction, 71090075Sobrien indicating the CFA register has changed to <register> but the 71190075Sobrien offset has not changed. */ 71250397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_register; 71390075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 71450397Sobrien } 71550397Sobrien#endif 71650397Sobrien 71790075Sobrien else if (loc.indirect == 0) 71850397Sobrien { 71990075Sobrien /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction, 72090075Sobrien indicating the CFA register has changed to <register> with 72190075Sobrien the specified offset. */ 72250397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa; 72390075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 72490075Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset; 72550397Sobrien } 72690075Sobrien else 72790075Sobrien { 72890075Sobrien /* Construct a DW_CFA_def_cfa_expression instruction to 72990075Sobrien calculate the CFA using a full location expression since no 73090075Sobrien register-offset pair is available. */ 73190075Sobrien struct dw_loc_descr_struct *loc_list; 73250397Sobrien 73390075Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_expression; 73490075Sobrien loc_list = build_cfa_loc (&loc); 73590075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list; 73690075Sobrien } 73790075Sobrien 73850397Sobrien add_fde_cfi (label, cfi); 73950397Sobrien} 74050397Sobrien 74150397Sobrien/* Add the CFI for saving a register. REG is the CFA column number. 74250397Sobrien LABEL is passed to add_fde_cfi. 74350397Sobrien If SREG is -1, the register is saved at OFFSET from the CFA; 74450397Sobrien otherwise it is saved in SREG. */ 74550397Sobrien 74650397Sobrienstatic void 74750397Sobrienreg_save (label, reg, sreg, offset) 74890075Sobrien const char *label; 74990075Sobrien unsigned reg; 75090075Sobrien unsigned sreg; 75190075Sobrien long offset; 75250397Sobrien{ 75390075Sobrien dw_cfi_ref cfi = new_cfi (); 75450397Sobrien 75550397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 75650397Sobrien 75750397Sobrien /* The following comparison is correct. -1 is used to indicate that 75850397Sobrien the value isn't a register number. */ 75950397Sobrien if (sreg == (unsigned int) -1) 76050397Sobrien { 76150397Sobrien if (reg & ~0x3f) 76250397Sobrien /* The register number won't fit in 6 bits, so we have to use 76350397Sobrien the long form. */ 76450397Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended; 76550397Sobrien else 76650397Sobrien cfi->dw_cfi_opc = DW_CFA_offset; 76750397Sobrien 76890075Sobrien#ifdef ENABLE_CHECKING 76990075Sobrien { 77090075Sobrien /* If we get an offset that is not a multiple of 77190075Sobrien DWARF_CIE_DATA_ALIGNMENT, there is either a bug in the 77290075Sobrien definition of DWARF_CIE_DATA_ALIGNMENT, or a bug in the machine 77390075Sobrien description. */ 77490075Sobrien long check_offset = offset / DWARF_CIE_DATA_ALIGNMENT; 77590075Sobrien 77690075Sobrien if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset) 77790075Sobrien abort (); 77890075Sobrien } 77990075Sobrien#endif 78050397Sobrien offset /= DWARF_CIE_DATA_ALIGNMENT; 78150397Sobrien if (offset < 0) 78290075Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended_sf; 78390075Sobrien 78450397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; 78550397Sobrien } 78690075Sobrien else if (sreg == reg) 78790075Sobrien /* We could emit a DW_CFA_same_value in this case, but don't bother. */ 78890075Sobrien return; 78950397Sobrien else 79050397Sobrien { 79150397Sobrien cfi->dw_cfi_opc = DW_CFA_register; 79250397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg; 79350397Sobrien } 79450397Sobrien 79550397Sobrien add_fde_cfi (label, cfi); 79650397Sobrien} 79750397Sobrien 79850397Sobrien/* Add the CFI for saving a register window. LABEL is passed to reg_save. 79950397Sobrien This CFI tells the unwinder that it needs to restore the window registers 80050397Sobrien from the previous frame's window save area. 80190075Sobrien 80250397Sobrien ??? Perhaps we should note in the CIE where windows are saved (instead of 80350397Sobrien assuming 0(cfa)) and what registers are in the window. */ 80450397Sobrien 80550397Sobrienvoid 80650397Sobriendwarf2out_window_save (label) 80790075Sobrien const char *label; 80850397Sobrien{ 80990075Sobrien dw_cfi_ref cfi = new_cfi (); 81090075Sobrien 81150397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_window_save; 81250397Sobrien add_fde_cfi (label, cfi); 81350397Sobrien} 81450397Sobrien 81550397Sobrien/* Add a CFI to update the running total of the size of arguments 81650397Sobrien pushed onto the stack. */ 81750397Sobrien 81850397Sobrienvoid 81950397Sobriendwarf2out_args_size (label, size) 82090075Sobrien const char *label; 82150397Sobrien long size; 82250397Sobrien{ 82390075Sobrien dw_cfi_ref cfi; 82450397Sobrien 82550397Sobrien if (size == old_args_size) 82650397Sobrien return; 82790075Sobrien 82850397Sobrien old_args_size = size; 82950397Sobrien 83050397Sobrien cfi = new_cfi (); 83150397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_args_size; 83250397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = size; 83350397Sobrien add_fde_cfi (label, cfi); 83450397Sobrien} 83550397Sobrien 83650397Sobrien/* Entry point for saving a register to the stack. REG is the GCC register 83750397Sobrien number. LABEL and OFFSET are passed to reg_save. */ 83850397Sobrien 83950397Sobrienvoid 84050397Sobriendwarf2out_reg_save (label, reg, offset) 84190075Sobrien const char *label; 84290075Sobrien unsigned reg; 84390075Sobrien long offset; 84450397Sobrien{ 84550397Sobrien reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset); 84650397Sobrien} 84750397Sobrien 84850397Sobrien/* Entry point for saving the return address in the stack. 84950397Sobrien LABEL and OFFSET are passed to reg_save. */ 85050397Sobrien 85150397Sobrienvoid 85250397Sobriendwarf2out_return_save (label, offset) 85390075Sobrien const char *label; 85490075Sobrien long offset; 85550397Sobrien{ 85650397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset); 85750397Sobrien} 85850397Sobrien 85950397Sobrien/* Entry point for saving the return address in a register. 86050397Sobrien LABEL and SREG are passed to reg_save. */ 86150397Sobrien 86250397Sobrienvoid 86350397Sobriendwarf2out_return_reg (label, sreg) 86490075Sobrien const char *label; 86590075Sobrien unsigned sreg; 86650397Sobrien{ 86750397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0); 86850397Sobrien} 86950397Sobrien 87050397Sobrien/* Record the initial position of the return address. RTL is 87150397Sobrien INCOMING_RETURN_ADDR_RTX. */ 87250397Sobrien 87350397Sobrienstatic void 87450397Sobrieninitial_return_save (rtl) 87590075Sobrien rtx rtl; 87650397Sobrien{ 87752284Sobrien unsigned int reg = (unsigned int) -1; 87890075Sobrien HOST_WIDE_INT offset = 0; 87950397Sobrien 88050397Sobrien switch (GET_CODE (rtl)) 88150397Sobrien { 88250397Sobrien case REG: 88350397Sobrien /* RA is in a register. */ 88490075Sobrien reg = DWARF_FRAME_REGNUM (REGNO (rtl)); 88550397Sobrien break; 88690075Sobrien 88750397Sobrien case MEM: 88850397Sobrien /* RA is on the stack. */ 88950397Sobrien rtl = XEXP (rtl, 0); 89050397Sobrien switch (GET_CODE (rtl)) 89150397Sobrien { 89250397Sobrien case REG: 89350397Sobrien if (REGNO (rtl) != STACK_POINTER_REGNUM) 89450397Sobrien abort (); 89550397Sobrien offset = 0; 89650397Sobrien break; 89790075Sobrien 89850397Sobrien case PLUS: 89950397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 90050397Sobrien abort (); 90150397Sobrien offset = INTVAL (XEXP (rtl, 1)); 90250397Sobrien break; 90390075Sobrien 90450397Sobrien case MINUS: 90550397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 90650397Sobrien abort (); 90750397Sobrien offset = -INTVAL (XEXP (rtl, 1)); 90850397Sobrien break; 90990075Sobrien 91050397Sobrien default: 91150397Sobrien abort (); 91250397Sobrien } 91390075Sobrien 91450397Sobrien break; 91590075Sobrien 91650397Sobrien case PLUS: 91750397Sobrien /* The return address is at some offset from any value we can 91850397Sobrien actually load. For instance, on the SPARC it is in %i7+8. Just 91950397Sobrien ignore the offset for now; it doesn't matter for unwinding frames. */ 92050397Sobrien if (GET_CODE (XEXP (rtl, 1)) != CONST_INT) 92150397Sobrien abort (); 92250397Sobrien initial_return_save (XEXP (rtl, 0)); 92350397Sobrien return; 92490075Sobrien 92550397Sobrien default: 92650397Sobrien abort (); 92750397Sobrien } 92850397Sobrien 92990075Sobrien reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset); 93050397Sobrien} 93150397Sobrien 93290075Sobrien/* Given a SET, calculate the amount of stack adjustment it 93390075Sobrien contains. */ 93490075Sobrien 93590075Sobrienstatic long 93690075Sobrienstack_adjust_offset (pattern) 93790075Sobrien rtx pattern; 93890075Sobrien{ 93990075Sobrien rtx src = SET_SRC (pattern); 94090075Sobrien rtx dest = SET_DEST (pattern); 94190075Sobrien HOST_WIDE_INT offset = 0; 94290075Sobrien enum rtx_code code; 94390075Sobrien 94490075Sobrien if (dest == stack_pointer_rtx) 94590075Sobrien { 94690075Sobrien /* (set (reg sp) (plus (reg sp) (const_int))) */ 94790075Sobrien code = GET_CODE (src); 94890075Sobrien if (! (code == PLUS || code == MINUS) 94990075Sobrien || XEXP (src, 0) != stack_pointer_rtx 95090075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 95190075Sobrien return 0; 95290075Sobrien 95390075Sobrien offset = INTVAL (XEXP (src, 1)); 95490075Sobrien } 95590075Sobrien else if (GET_CODE (dest) == MEM) 95690075Sobrien { 95790075Sobrien /* (set (mem (pre_dec (reg sp))) (foo)) */ 95890075Sobrien src = XEXP (dest, 0); 95990075Sobrien code = GET_CODE (src); 96090075Sobrien 96190075Sobrien if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY) 96290075Sobrien || XEXP (src, 0) != stack_pointer_rtx) 96390075Sobrien return 0; 96490075Sobrien 96590075Sobrien if (code == PRE_MODIFY) 96690075Sobrien { 96790075Sobrien rtx val = XEXP (XEXP (src, 1), 1); 96890075Sobrien 96990075Sobrien /* We handle only adjustments by constant amount. */ 97090075Sobrien if (GET_CODE (XEXP (src, 1)) != PLUS || 97190075Sobrien GET_CODE (val) != CONST_INT) 97290075Sobrien abort (); 97390075Sobrien 97490075Sobrien offset = -INTVAL (val); 97590075Sobrien } 97690075Sobrien else 97790075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 97890075Sobrien } 97990075Sobrien else 98090075Sobrien return 0; 98190075Sobrien 98290075Sobrien if (code == PLUS || code == PRE_INC) 98390075Sobrien offset = -offset; 98490075Sobrien 98590075Sobrien return offset; 98690075Sobrien} 98790075Sobrien 98850397Sobrien/* Check INSN to see if it looks like a push or a stack adjustment, and 98950397Sobrien make a note of it if it does. EH uses this information to find out how 99050397Sobrien much extra space it needs to pop off the stack. */ 99150397Sobrien 99250397Sobrienstatic void 99350397Sobriendwarf2out_stack_adjust (insn) 99450397Sobrien rtx insn; 99550397Sobrien{ 99690075Sobrien HOST_WIDE_INT offset; 99790075Sobrien const char *label; 99890075Sobrien int i; 99950397Sobrien 100090075Sobrien if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN) 100150397Sobrien { 100250397Sobrien /* Extract the size of the args from the CALL rtx itself. */ 100350397Sobrien insn = PATTERN (insn); 100450397Sobrien if (GET_CODE (insn) == PARALLEL) 100550397Sobrien insn = XVECEXP (insn, 0, 0); 100650397Sobrien if (GET_CODE (insn) == SET) 100750397Sobrien insn = SET_SRC (insn); 100890075Sobrien if (GET_CODE (insn) != CALL) 100990075Sobrien abort (); 101090075Sobrien 101150397Sobrien dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); 101250397Sobrien return; 101350397Sobrien } 101450397Sobrien 101550397Sobrien /* If only calls can throw, and we have a frame pointer, 101650397Sobrien save up adjustments until we see the CALL_INSN. */ 101790075Sobrien else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM) 101850397Sobrien return; 101950397Sobrien 102050397Sobrien if (GET_CODE (insn) == BARRIER) 102150397Sobrien { 102250397Sobrien /* When we see a BARRIER, we know to reset args_size to 0. Usually 102350397Sobrien the compiler will have already emitted a stack adjustment, but 102450397Sobrien doesn't bother for calls to noreturn functions. */ 102550397Sobrien#ifdef STACK_GROWS_DOWNWARD 102650397Sobrien offset = -args_size; 102750397Sobrien#else 102850397Sobrien offset = args_size; 102950397Sobrien#endif 103050397Sobrien } 103150397Sobrien else if (GET_CODE (PATTERN (insn)) == SET) 103290075Sobrien offset = stack_adjust_offset (PATTERN (insn)); 103390075Sobrien else if (GET_CODE (PATTERN (insn)) == PARALLEL 103490075Sobrien || GET_CODE (PATTERN (insn)) == SEQUENCE) 103550397Sobrien { 103690075Sobrien /* There may be stack adjustments inside compound insns. Search 103790075Sobrien for them. */ 103890075Sobrien for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) 103990075Sobrien if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 104090075Sobrien offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i)); 104150397Sobrien } 104250397Sobrien else 104350397Sobrien return; 104450397Sobrien 104550397Sobrien if (offset == 0) 104650397Sobrien return; 104750397Sobrien 104890075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 104990075Sobrien cfa.offset += offset; 105050397Sobrien 105150397Sobrien#ifndef STACK_GROWS_DOWNWARD 105250397Sobrien offset = -offset; 105350397Sobrien#endif 105490075Sobrien 105550397Sobrien args_size += offset; 105650397Sobrien if (args_size < 0) 105750397Sobrien args_size = 0; 105850397Sobrien 105950397Sobrien label = dwarf2out_cfi_label (); 106090075Sobrien def_cfa_1 (label, &cfa); 106150397Sobrien dwarf2out_args_size (label, args_size); 106250397Sobrien} 106350397Sobrien 106490075Sobrien/* We delay emitting a register save until either (a) we reach the end 106590075Sobrien of the prologue or (b) the register is clobbered. This clusters 106690075Sobrien register saves so that there are fewer pc advances. */ 106752284Sobrien 106890075Sobrienstruct queued_reg_save 106990075Sobrien{ 107090075Sobrien struct queued_reg_save *next; 107190075Sobrien rtx reg; 107290075Sobrien long cfa_offset; 107390075Sobrien}; 107452284Sobrien 107590075Sobrienstatic struct queued_reg_save *queued_reg_saves; 107690075Sobrienstatic const char *last_reg_save_label; 107750397Sobrien 107852284Sobrienstatic void 107990075Sobrienqueue_reg_save (label, reg, offset) 108090075Sobrien const char *label; 108190075Sobrien rtx reg; 108290075Sobrien long offset; 108390075Sobrien{ 108490075Sobrien struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q)); 108590075Sobrien 108690075Sobrien q->next = queued_reg_saves; 108790075Sobrien q->reg = reg; 108890075Sobrien q->cfa_offset = offset; 108990075Sobrien queued_reg_saves = q; 109090075Sobrien 109190075Sobrien last_reg_save_label = label; 109290075Sobrien} 109390075Sobrien 109490075Sobrienstatic void 109590075Sobrienflush_queued_reg_saves () 109690075Sobrien{ 109790075Sobrien struct queued_reg_save *q, *next; 109890075Sobrien 109990075Sobrien for (q = queued_reg_saves; q ; q = next) 110090075Sobrien { 110190075Sobrien dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset); 110290075Sobrien next = q->next; 110390075Sobrien free (q); 110490075Sobrien } 110590075Sobrien 110690075Sobrien queued_reg_saves = NULL; 110790075Sobrien last_reg_save_label = NULL; 110890075Sobrien} 110990075Sobrien 111090075Sobrienstatic bool 111190075Sobrienclobbers_queued_reg_save (insn) 111290075Sobrien rtx insn; 111390075Sobrien{ 111490075Sobrien struct queued_reg_save *q; 111590075Sobrien 111690075Sobrien for (q = queued_reg_saves; q ; q = q->next) 111790075Sobrien if (modified_in_p (q->reg, insn)) 111890075Sobrien return true; 111990075Sobrien 112090075Sobrien return false; 112190075Sobrien} 112290075Sobrien 112390075Sobrien 112490075Sobrien/* A temporary register holding an integral value used in adjusting SP 112590075Sobrien or setting up the store_reg. The "offset" field holds the integer 112690075Sobrien value, not an offset. */ 112790075Sobrienstatic dw_cfa_location cfa_temp; 112890075Sobrien 112990075Sobrien/* Record call frame debugging information for an expression EXPR, 113090075Sobrien which either sets SP or FP (adjusting how we calculate the frame 113190075Sobrien address) or saves a register to the stack. LABEL indicates the 113290075Sobrien address of EXPR. 113390075Sobrien 113490075Sobrien This function encodes a state machine mapping rtxes to actions on 113590075Sobrien cfa, cfa_store, and cfa_temp.reg. We describe these rules so 113690075Sobrien users need not read the source code. 113790075Sobrien 113890075Sobrien The High-Level Picture 113990075Sobrien 114090075Sobrien Changes in the register we use to calculate the CFA: Currently we 114190075Sobrien assume that if you copy the CFA register into another register, we 114290075Sobrien should take the other one as the new CFA register; this seems to 114390075Sobrien work pretty well. If it's wrong for some target, it's simple 114490075Sobrien enough not to set RTX_FRAME_RELATED_P on the insn in question. 114590075Sobrien 114690075Sobrien Changes in the register we use for saving registers to the stack: 114790075Sobrien This is usually SP, but not always. Again, we deduce that if you 114890075Sobrien copy SP into another register (and SP is not the CFA register), 114990075Sobrien then the new register is the one we will be using for register 115090075Sobrien saves. This also seems to work. 115190075Sobrien 115290075Sobrien Register saves: There's not much guesswork about this one; if 115390075Sobrien RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a 115490075Sobrien register save, and the register used to calculate the destination 115590075Sobrien had better be the one we think we're using for this purpose. 115690075Sobrien 115790075Sobrien Except: If the register being saved is the CFA register, and the 115890075Sobrien offset is non-zero, we are saving the CFA, so we assume we have to 115990075Sobrien use DW_CFA_def_cfa_expression. If the offset is 0, we assume that 116090075Sobrien the intent is to save the value of SP from the previous frame. 116190075Sobrien 116290075Sobrien Invariants / Summaries of Rules 116390075Sobrien 116490075Sobrien cfa current rule for calculating the CFA. It usually 116590075Sobrien consists of a register and an offset. 116690075Sobrien cfa_store register used by prologue code to save things to the stack 116790075Sobrien cfa_store.offset is the offset from the value of 116890075Sobrien cfa_store.reg to the actual CFA 116990075Sobrien cfa_temp register holding an integral value. cfa_temp.offset 117090075Sobrien stores the value, which will be used to adjust the 117190075Sobrien stack pointer. cfa_temp is also used like cfa_store, 117290075Sobrien to track stores to the stack via fp or a temp reg. 117390075Sobrien 117490075Sobrien Rules 1- 4: Setting a register's value to cfa.reg or an expression 117590075Sobrien with cfa.reg as the first operand changes the cfa.reg and its 117690075Sobrien cfa.offset. Rule 1 and 4 also set cfa_temp.reg and 117790075Sobrien cfa_temp.offset. 117890075Sobrien 117990075Sobrien Rules 6- 9: Set a non-cfa.reg register value to a constant or an 118090075Sobrien expression yielding a constant. This sets cfa_temp.reg 118190075Sobrien and cfa_temp.offset. 118290075Sobrien 118390075Sobrien Rule 5: Create a new register cfa_store used to save items to the 118490075Sobrien stack. 118590075Sobrien 118690075Sobrien Rules 10-14: Save a register to the stack. Define offset as the 118790075Sobrien difference of the original location and cfa_store's 118890075Sobrien location (or cfa_temp's location if cfa_temp is used). 118990075Sobrien 119090075Sobrien The Rules 119190075Sobrien 119290075Sobrien "{a,b}" indicates a choice of a xor b. 119390075Sobrien "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg. 119490075Sobrien 119590075Sobrien Rule 1: 119690075Sobrien (set <reg1> <reg2>:cfa.reg) 119790075Sobrien effects: cfa.reg = <reg1> 119890075Sobrien cfa.offset unchanged 119990075Sobrien cfa_temp.reg = <reg1> 120090075Sobrien cfa_temp.offset = cfa.offset 120190075Sobrien 120290075Sobrien Rule 2: 120390075Sobrien (set sp ({minus,plus,losum} {sp,fp}:cfa.reg 120490075Sobrien {<const_int>,<reg>:cfa_temp.reg})) 120590075Sobrien effects: cfa.reg = sp if fp used 120690075Sobrien cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp 120790075Sobrien cfa_store.offset += {+/- <const_int>, cfa_temp.offset} 120890075Sobrien if cfa_store.reg==sp 120990075Sobrien 121090075Sobrien Rule 3: 121190075Sobrien (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>)) 121290075Sobrien effects: cfa.reg = fp 121390075Sobrien cfa_offset += +/- <const_int> 121490075Sobrien 121590075Sobrien Rule 4: 121690075Sobrien (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>)) 121790075Sobrien constraints: <reg1> != fp 121890075Sobrien <reg1> != sp 121990075Sobrien effects: cfa.reg = <reg1> 122090075Sobrien cfa_temp.reg = <reg1> 122190075Sobrien cfa_temp.offset = cfa.offset 122290075Sobrien 122390075Sobrien Rule 5: 122490075Sobrien (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg)) 122590075Sobrien constraints: <reg1> != fp 122690075Sobrien <reg1> != sp 122790075Sobrien effects: cfa_store.reg = <reg1> 122890075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset 122990075Sobrien 123090075Sobrien Rule 6: 123190075Sobrien (set <reg> <const_int>) 123290075Sobrien effects: cfa_temp.reg = <reg> 123390075Sobrien cfa_temp.offset = <const_int> 123490075Sobrien 123590075Sobrien Rule 7: 123690075Sobrien (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>)) 123790075Sobrien effects: cfa_temp.reg = <reg1> 123890075Sobrien cfa_temp.offset |= <const_int> 123990075Sobrien 124090075Sobrien Rule 8: 124190075Sobrien (set <reg> (high <exp>)) 124290075Sobrien effects: none 124390075Sobrien 124490075Sobrien Rule 9: 124590075Sobrien (set <reg> (lo_sum <exp> <const_int>)) 124690075Sobrien effects: cfa_temp.reg = <reg> 124790075Sobrien cfa_temp.offset = <const_int> 124890075Sobrien 124990075Sobrien Rule 10: 125090075Sobrien (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>) 125190075Sobrien effects: cfa_store.offset -= <const_int> 125290075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 125390075Sobrien cfa.reg = sp 125490075Sobrien cfa.base_offset = -cfa_store.offset 125590075Sobrien 125690075Sobrien Rule 11: 125790075Sobrien (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>) 125890075Sobrien effects: cfa_store.offset += -/+ mode_size(mem) 125990075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 126090075Sobrien cfa.reg = sp 126190075Sobrien cfa.base_offset = -cfa_store.offset 126290075Sobrien 126390075Sobrien Rule 12: 126490075Sobrien (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) 126590075Sobrien 126690075Sobrien <reg2>) 126790075Sobrien effects: cfa.reg = <reg1> 126890075Sobrien cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset 126990075Sobrien 127090075Sobrien Rule 13: 127190075Sobrien (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>) 127290075Sobrien effects: cfa.reg = <reg1> 127390075Sobrien cfa.base_offset = -{cfa_store,cfa_temp}.offset 127490075Sobrien 127590075Sobrien Rule 14: 127690075Sobrien (set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>) 127790075Sobrien effects: cfa.reg = <reg1> 127890075Sobrien cfa.base_offset = -cfa_temp.offset 127990075Sobrien cfa_temp.offset -= mode_size(mem) */ 128090075Sobrien 128190075Sobrienstatic void 128252284Sobriendwarf2out_frame_debug_expr (expr, label) 128352284Sobrien rtx expr; 128490075Sobrien const char *label; 128550397Sobrien{ 128650397Sobrien rtx src, dest; 128790075Sobrien HOST_WIDE_INT offset; 128850397Sobrien 128990075Sobrien /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of 129090075Sobrien the PARALLEL independently. The first element is always processed if 129190075Sobrien it is a SET. This is for backward compatibility. Other elements 129290075Sobrien are processed only if they are SETs and the RTX_FRAME_RELATED_P 129390075Sobrien flag is set in them. */ 129490075Sobrien if (GET_CODE (expr) == PARALLEL || GET_CODE (expr) == SEQUENCE) 129590075Sobrien { 129652284Sobrien int par_index; 129752284Sobrien int limit = XVECLEN (expr, 0); 129850397Sobrien 129952284Sobrien for (par_index = 0; par_index < limit; par_index++) 130090075Sobrien if (GET_CODE (XVECEXP (expr, 0, par_index)) == SET 130190075Sobrien && (RTX_FRAME_RELATED_P (XVECEXP (expr, 0, par_index)) 130290075Sobrien || par_index == 0)) 130390075Sobrien dwarf2out_frame_debug_expr (XVECEXP (expr, 0, par_index), label); 130490075Sobrien 130550397Sobrien return; 130650397Sobrien } 130790075Sobrien 130852284Sobrien if (GET_CODE (expr) != SET) 130950397Sobrien abort (); 131050397Sobrien 131152284Sobrien src = SET_SRC (expr); 131252284Sobrien dest = SET_DEST (expr); 131350397Sobrien 131450397Sobrien switch (GET_CODE (dest)) 131550397Sobrien { 131650397Sobrien case REG: 131790075Sobrien /* Rule 1 */ 131850397Sobrien /* Update the CFA rule wrt SP or FP. Make sure src is 131952284Sobrien relative to the current CFA register. */ 132050397Sobrien switch (GET_CODE (src)) 132190075Sobrien { 132290075Sobrien /* Setting FP from SP. */ 132390075Sobrien case REG: 132490075Sobrien if (cfa.reg == (unsigned) REGNO (src)) 132590075Sobrien /* OK. */ 132690075Sobrien ; 132790075Sobrien else 132890075Sobrien abort (); 132950397Sobrien 133090075Sobrien /* We used to require that dest be either SP or FP, but the 133190075Sobrien ARM copies SP to a temporary register, and from there to 133290075Sobrien FP. So we just rely on the backends to only set 133390075Sobrien RTX_FRAME_RELATED_P on appropriate insns. */ 133490075Sobrien cfa.reg = REGNO (dest); 133590075Sobrien cfa_temp.reg = cfa.reg; 133690075Sobrien cfa_temp.offset = cfa.offset; 133790075Sobrien break; 133850397Sobrien 133990075Sobrien case PLUS: 134090075Sobrien case MINUS: 134190075Sobrien case LO_SUM: 134290075Sobrien if (dest == stack_pointer_rtx) 134390075Sobrien { 134490075Sobrien /* Rule 2 */ 134590075Sobrien /* Adjusting SP. */ 134690075Sobrien switch (GET_CODE (XEXP (src, 1))) 134790075Sobrien { 134890075Sobrien case CONST_INT: 134990075Sobrien offset = INTVAL (XEXP (src, 1)); 135090075Sobrien break; 135190075Sobrien case REG: 135290075Sobrien if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg) 135390075Sobrien abort (); 135490075Sobrien offset = cfa_temp.offset; 135590075Sobrien break; 135690075Sobrien default: 135790075Sobrien abort (); 135890075Sobrien } 135950397Sobrien 136090075Sobrien if (XEXP (src, 0) == hard_frame_pointer_rtx) 136190075Sobrien { 136290075Sobrien /* Restoring SP from FP in the epilogue. */ 136390075Sobrien if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM) 136490075Sobrien abort (); 136590075Sobrien cfa.reg = STACK_POINTER_REGNUM; 136690075Sobrien } 136790075Sobrien else if (GET_CODE (src) == LO_SUM) 136890075Sobrien /* Assume we've set the source reg of the LO_SUM from sp. */ 136990075Sobrien ; 137090075Sobrien else if (XEXP (src, 0) != stack_pointer_rtx) 137190075Sobrien abort (); 137250397Sobrien 137390075Sobrien if (GET_CODE (src) != MINUS) 137490075Sobrien offset = -offset; 137590075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 137690075Sobrien cfa.offset += offset; 137790075Sobrien if (cfa_store.reg == STACK_POINTER_REGNUM) 137890075Sobrien cfa_store.offset += offset; 137990075Sobrien } 138090075Sobrien else if (dest == hard_frame_pointer_rtx) 138190075Sobrien { 138290075Sobrien /* Rule 3 */ 138390075Sobrien /* Either setting the FP from an offset of the SP, 138490075Sobrien or adjusting the FP */ 138590075Sobrien if (! frame_pointer_needed) 138690075Sobrien abort (); 138750397Sobrien 138890075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 138990075Sobrien && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg 139090075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 139190075Sobrien { 139290075Sobrien offset = INTVAL (XEXP (src, 1)); 139390075Sobrien if (GET_CODE (src) != MINUS) 139490075Sobrien offset = -offset; 139590075Sobrien cfa.offset += offset; 139690075Sobrien cfa.reg = HARD_FRAME_POINTER_REGNUM; 139790075Sobrien } 139890075Sobrien else 139990075Sobrien abort (); 140090075Sobrien } 140190075Sobrien else 140290075Sobrien { 140390075Sobrien if (GET_CODE (src) == MINUS) 140490075Sobrien abort (); 140550397Sobrien 140690075Sobrien /* Rule 4 */ 140790075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 140890075Sobrien && REGNO (XEXP (src, 0)) == cfa.reg 140990075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 141090075Sobrien { 141190075Sobrien /* Setting a temporary CFA register that will be copied 141290075Sobrien into the FP later on. */ 141390075Sobrien offset = - INTVAL (XEXP (src, 1)); 141490075Sobrien cfa.offset += offset; 141590075Sobrien cfa.reg = REGNO (dest); 141690075Sobrien /* Or used to save regs to the stack. */ 141790075Sobrien cfa_temp.reg = cfa.reg; 141890075Sobrien cfa_temp.offset = cfa.offset; 141990075Sobrien } 142050397Sobrien 142190075Sobrien /* Rule 5 */ 142290075Sobrien else if (GET_CODE (XEXP (src, 0)) == REG 142390075Sobrien && REGNO (XEXP (src, 0)) == cfa_temp.reg 142490075Sobrien && XEXP (src, 1) == stack_pointer_rtx) 142590075Sobrien { 142690075Sobrien /* Setting a scratch register that we will use instead 142790075Sobrien of SP for saving registers to the stack. */ 142890075Sobrien if (cfa.reg != STACK_POINTER_REGNUM) 142990075Sobrien abort (); 143090075Sobrien cfa_store.reg = REGNO (dest); 143190075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset; 143290075Sobrien } 143350397Sobrien 143490075Sobrien /* Rule 9 */ 143590075Sobrien else if (GET_CODE (src) == LO_SUM 143690075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 143790075Sobrien { 143890075Sobrien cfa_temp.reg = REGNO (dest); 143990075Sobrien cfa_temp.offset = INTVAL (XEXP (src, 1)); 144090075Sobrien } 144190075Sobrien else 144290075Sobrien abort (); 144390075Sobrien } 144490075Sobrien break; 144550397Sobrien 144690075Sobrien /* Rule 6 */ 144790075Sobrien case CONST_INT: 144890075Sobrien cfa_temp.reg = REGNO (dest); 144990075Sobrien cfa_temp.offset = INTVAL (src); 145090075Sobrien break; 145150397Sobrien 145290075Sobrien /* Rule 7 */ 145390075Sobrien case IOR: 145490075Sobrien if (GET_CODE (XEXP (src, 0)) != REG 145590075Sobrien || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg 145690075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 145790075Sobrien abort (); 145850397Sobrien 145990075Sobrien if ((unsigned) REGNO (dest) != cfa_temp.reg) 146090075Sobrien cfa_temp.reg = REGNO (dest); 146190075Sobrien cfa_temp.offset |= INTVAL (XEXP (src, 1)); 146290075Sobrien break; 146350397Sobrien 146490075Sobrien /* Skip over HIGH, assuming it will be followed by a LO_SUM, 146590075Sobrien which will fill in all of the bits. */ 146690075Sobrien /* Rule 8 */ 146790075Sobrien case HIGH: 146890075Sobrien break; 146950397Sobrien 147090075Sobrien default: 147190075Sobrien abort (); 147290075Sobrien } 147350397Sobrien 147490075Sobrien def_cfa_1 (label, &cfa); 147590075Sobrien break; 147650397Sobrien 147790075Sobrien case MEM: 147890075Sobrien if (GET_CODE (src) != REG) 147990075Sobrien abort (); 148052284Sobrien 148190075Sobrien /* Saving a register to the stack. Make sure dest is relative to the 148290075Sobrien CFA register. */ 148390075Sobrien switch (GET_CODE (XEXP (dest, 0))) 148490075Sobrien { 148590075Sobrien /* Rule 10 */ 148690075Sobrien /* With a push. */ 148790075Sobrien case PRE_MODIFY: 148890075Sobrien /* We can't handle variable size modifications. */ 148990075Sobrien if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT) 149090075Sobrien abort (); 149190075Sobrien offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)); 149290075Sobrien 149390075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 149490075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 149590075Sobrien abort (); 149690075Sobrien 149790075Sobrien cfa_store.offset += offset; 149890075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 149990075Sobrien cfa.offset = cfa_store.offset; 150090075Sobrien 150190075Sobrien offset = -cfa_store.offset; 150290075Sobrien break; 150390075Sobrien 150490075Sobrien /* Rule 11 */ 150590075Sobrien case PRE_INC: 150690075Sobrien case PRE_DEC: 150790075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 150890075Sobrien if (GET_CODE (XEXP (dest, 0)) == PRE_INC) 150990075Sobrien offset = -offset; 151090075Sobrien 151190075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 151290075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 151390075Sobrien abort (); 151490075Sobrien 151590075Sobrien cfa_store.offset += offset; 151690075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 151790075Sobrien cfa.offset = cfa_store.offset; 151890075Sobrien 151990075Sobrien offset = -cfa_store.offset; 152090075Sobrien break; 152190075Sobrien 152290075Sobrien /* Rule 12 */ 152390075Sobrien /* With an offset. */ 152490075Sobrien case PLUS: 152590075Sobrien case MINUS: 152690075Sobrien case LO_SUM: 152790075Sobrien if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT) 152890075Sobrien abort (); 152990075Sobrien offset = INTVAL (XEXP (XEXP (dest, 0), 1)); 153090075Sobrien if (GET_CODE (XEXP (dest, 0)) == MINUS) 153190075Sobrien offset = -offset; 153290075Sobrien 153390075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153490075Sobrien offset -= cfa_store.offset; 153590075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153690075Sobrien offset -= cfa_temp.offset; 153790075Sobrien else 153890075Sobrien abort (); 153990075Sobrien break; 154090075Sobrien 154190075Sobrien /* Rule 13 */ 154290075Sobrien /* Without an offset. */ 154390075Sobrien case REG: 154490075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0))) 154590075Sobrien offset = -cfa_store.offset; 154690075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0))) 154790075Sobrien offset = -cfa_temp.offset; 154890075Sobrien else 154990075Sobrien abort (); 155090075Sobrien break; 155190075Sobrien 155290075Sobrien /* Rule 14 */ 155390075Sobrien case POST_INC: 155490075Sobrien if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 155590075Sobrien abort (); 155690075Sobrien offset = -cfa_temp.offset; 155790075Sobrien cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest)); 155890075Sobrien break; 155990075Sobrien 156090075Sobrien default: 156190075Sobrien abort (); 156290075Sobrien } 156390075Sobrien 156490075Sobrien if (REGNO (src) != STACK_POINTER_REGNUM 156590075Sobrien && REGNO (src) != HARD_FRAME_POINTER_REGNUM 156690075Sobrien && (unsigned) REGNO (src) == cfa.reg) 156790075Sobrien { 156890075Sobrien /* We're storing the current CFA reg into the stack. */ 156990075Sobrien 157090075Sobrien if (cfa.offset == 0) 157190075Sobrien { 157290075Sobrien /* If the source register is exactly the CFA, assume 157390075Sobrien we're saving SP like any other register; this happens 157490075Sobrien on the ARM. */ 157590075Sobrien def_cfa_1 (label, &cfa); 157690075Sobrien queue_reg_save (label, stack_pointer_rtx, offset); 157790075Sobrien break; 157890075Sobrien } 157990075Sobrien else 158090075Sobrien { 158190075Sobrien /* Otherwise, we'll need to look in the stack to 158290075Sobrien calculate the CFA. */ 158390075Sobrien rtx x = XEXP (dest, 0); 158490075Sobrien 158590075Sobrien if (GET_CODE (x) != REG) 158690075Sobrien x = XEXP (x, 0); 158790075Sobrien if (GET_CODE (x) != REG) 158890075Sobrien abort (); 158990075Sobrien 159090075Sobrien cfa.reg = REGNO (x); 159190075Sobrien cfa.base_offset = offset; 159290075Sobrien cfa.indirect = 1; 159390075Sobrien def_cfa_1 (label, &cfa); 159490075Sobrien break; 159590075Sobrien } 159690075Sobrien } 159790075Sobrien 159890075Sobrien def_cfa_1 (label, &cfa); 159990075Sobrien queue_reg_save (label, src, offset); 160090075Sobrien break; 160190075Sobrien 160290075Sobrien default: 160390075Sobrien abort (); 160490075Sobrien } 160552284Sobrien} 160652284Sobrien 160752284Sobrien/* Record call frame debugging information for INSN, which either 160852284Sobrien sets SP or FP (adjusting how we calculate the frame address) or saves a 160952284Sobrien register to the stack. If INSN is NULL_RTX, initialize our state. */ 161052284Sobrien 161152284Sobrienvoid 161252284Sobriendwarf2out_frame_debug (insn) 161352284Sobrien rtx insn; 161452284Sobrien{ 161590075Sobrien const char *label; 161652284Sobrien rtx src; 161752284Sobrien 161852284Sobrien if (insn == NULL_RTX) 161952284Sobrien { 162090075Sobrien /* Flush any queued register saves. */ 162190075Sobrien flush_queued_reg_saves (); 162290075Sobrien 162352284Sobrien /* Set up state for generating call frame debug info. */ 162490075Sobrien lookup_cfa (&cfa); 162590075Sobrien if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)) 162652284Sobrien abort (); 162790075Sobrien 162890075Sobrien cfa.reg = STACK_POINTER_REGNUM; 162990075Sobrien cfa_store = cfa; 163090075Sobrien cfa_temp.reg = -1; 163190075Sobrien cfa_temp.offset = 0; 163252284Sobrien return; 163350397Sobrien } 163452284Sobrien 163590075Sobrien if (GET_CODE (insn) != INSN || clobbers_queued_reg_save (insn)) 163690075Sobrien flush_queued_reg_saves (); 163790075Sobrien 163852284Sobrien if (! RTX_FRAME_RELATED_P (insn)) 163952284Sobrien { 164090075Sobrien if (!ACCUMULATE_OUTGOING_ARGS) 164190075Sobrien dwarf2out_stack_adjust (insn); 164290075Sobrien 164352284Sobrien return; 164452284Sobrien } 164552284Sobrien 164652284Sobrien label = dwarf2out_cfi_label (); 164752284Sobrien src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 164852284Sobrien if (src) 164952284Sobrien insn = XEXP (src, 0); 165090075Sobrien else 165152284Sobrien insn = PATTERN (insn); 165252284Sobrien 165352284Sobrien dwarf2out_frame_debug_expr (insn, label); 165450397Sobrien} 165550397Sobrien 165650397Sobrien/* Output a Call Frame Information opcode and its operand(s). */ 165750397Sobrien 165850397Sobrienstatic void 165990075Sobrienoutput_cfi (cfi, fde, for_eh) 166090075Sobrien dw_cfi_ref cfi; 166190075Sobrien dw_fde_ref fde; 166290075Sobrien int for_eh; 166350397Sobrien{ 166450397Sobrien if (cfi->dw_cfi_opc == DW_CFA_advance_loc) 166590075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 166690075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)), 166790075Sobrien "DW_CFA_advance_loc 0x%lx", 166890075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset); 166950397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_offset) 167050397Sobrien { 167190075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167290075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 167390075Sobrien "DW_CFA_offset, column 0x%lx", 167490075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 167590075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 167650397Sobrien } 167750397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_restore) 167890075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167990075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 168090075Sobrien "DW_CFA_restore, column 0x%lx", 168190075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 168250397Sobrien else 168350397Sobrien { 168490075Sobrien dw2_asm_output_data (1, cfi->dw_cfi_opc, 168590075Sobrien "%s", dwarf_cfi_name (cfi->dw_cfi_opc)); 168650397Sobrien 168750397Sobrien switch (cfi->dw_cfi_opc) 168850397Sobrien { 168950397Sobrien case DW_CFA_set_loc: 169090075Sobrien if (for_eh) 169190075Sobrien dw2_asm_output_encoded_addr_rtx ( 169290075Sobrien ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0), 169390075Sobrien gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr), 169490075Sobrien NULL); 169590075Sobrien else 169690075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, 169790075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL); 169850397Sobrien break; 169990075Sobrien 170050397Sobrien case DW_CFA_advance_loc1: 170190075Sobrien dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170290075Sobrien fde->dw_fde_current_label, NULL); 170350397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 170450397Sobrien break; 170590075Sobrien 170650397Sobrien case DW_CFA_advance_loc2: 170790075Sobrien dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170890075Sobrien fde->dw_fde_current_label, NULL); 170950397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 171050397Sobrien break; 171190075Sobrien 171250397Sobrien case DW_CFA_advance_loc4: 171390075Sobrien dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr, 171490075Sobrien fde->dw_fde_current_label, NULL); 171550397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 171650397Sobrien break; 171790075Sobrien 171850397Sobrien case DW_CFA_MIPS_advance_loc8: 171990075Sobrien dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr, 172090075Sobrien fde->dw_fde_current_label, NULL); 172190075Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 172250397Sobrien break; 172390075Sobrien 172450397Sobrien case DW_CFA_offset_extended: 172550397Sobrien case DW_CFA_def_cfa: 172690075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 172790075Sobrien NULL); 172890075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 172950397Sobrien break; 173090075Sobrien 173190075Sobrien case DW_CFA_offset_extended_sf: 173290075Sobrien case DW_CFA_def_cfa_sf: 173390075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 173490075Sobrien NULL); 173590075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 173690075Sobrien break; 173790075Sobrien 173850397Sobrien case DW_CFA_restore_extended: 173950397Sobrien case DW_CFA_undefined: 174050397Sobrien case DW_CFA_same_value: 174150397Sobrien case DW_CFA_def_cfa_register: 174290075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174390075Sobrien NULL); 174450397Sobrien break; 174590075Sobrien 174650397Sobrien case DW_CFA_register: 174790075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174890075Sobrien NULL); 174990075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 175090075Sobrien NULL); 175150397Sobrien break; 175290075Sobrien 175350397Sobrien case DW_CFA_def_cfa_offset: 175490075Sobrien case DW_CFA_GNU_args_size: 175590075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 175650397Sobrien break; 175790075Sobrien 175890075Sobrien case DW_CFA_def_cfa_offset_sf: 175990075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 176090075Sobrien break; 176190075Sobrien 176250397Sobrien case DW_CFA_GNU_window_save: 176350397Sobrien break; 176490075Sobrien 176590075Sobrien case DW_CFA_def_cfa_expression: 176690075Sobrien case DW_CFA_expression: 176790075Sobrien output_cfa_loc (cfi); 176850397Sobrien break; 176990075Sobrien 177090075Sobrien case DW_CFA_GNU_negative_offset_extended: 177190075Sobrien /* Obsoleted by DW_CFA_offset_extended_sf. */ 177290075Sobrien abort (); 177390075Sobrien 177450397Sobrien default: 177550397Sobrien break; 177650397Sobrien } 177790075Sobrien } 177850397Sobrien} 177950397Sobrien 178050397Sobrien/* Output the call frame information used to used to record information 178150397Sobrien that relates to calculating the frame pointer, and records the 178250397Sobrien location of saved registers. */ 178350397Sobrien 178450397Sobrienstatic void 178550397Sobrienoutput_call_frame_info (for_eh) 178650397Sobrien int for_eh; 178750397Sobrien{ 178890075Sobrien unsigned int i; 178990075Sobrien dw_fde_ref fde; 179090075Sobrien dw_cfi_ref cfi; 179190075Sobrien char l1[20], l2[20], section_start_label[20]; 179290075Sobrien int any_lsda_needed = 0; 179390075Sobrien char augmentation[6]; 179490075Sobrien int augmentation_size; 179590075Sobrien int fde_encoding = DW_EH_PE_absptr; 179690075Sobrien int per_encoding = DW_EH_PE_absptr; 179790075Sobrien int lsda_encoding = DW_EH_PE_absptr; 179850397Sobrien 179990075Sobrien /* If we don't have any functions we'll want to unwind out of, don't emit any 180090075Sobrien EH unwind information. */ 180190075Sobrien if (for_eh) 180290075Sobrien { 180390075Sobrien int any_eh_needed = flag_asynchronous_unwind_tables; 180450397Sobrien 180590075Sobrien for (i = 0; i < fde_table_in_use; i++) 180690075Sobrien if (fde_table[i].uses_eh_lsda) 180790075Sobrien any_eh_needed = any_lsda_needed = 1; 180890075Sobrien else if (! fde_table[i].nothrow) 180990075Sobrien any_eh_needed = 1; 181050397Sobrien 181190075Sobrien if (! any_eh_needed) 181290075Sobrien return; 181390075Sobrien } 181490075Sobrien 181550397Sobrien /* We're going to be generating comments, so turn on app. */ 181650397Sobrien if (flag_debug_asm) 181750397Sobrien app_enable (); 181850397Sobrien 181950397Sobrien if (for_eh) 182090075Sobrien (*targetm.asm_out.eh_frame_section) (); 182150397Sobrien else 182290075Sobrien named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG); 182350397Sobrien 182490075Sobrien ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh); 182590075Sobrien ASM_OUTPUT_LABEL (asm_out_file, section_start_label); 182690075Sobrien 182790075Sobrien /* Output the CIE. */ 182850397Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); 182950397Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); 183090075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 183190075Sobrien "Length of Common Information Entry"); 183250397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 183350397Sobrien 183490075Sobrien /* Now that the CIE pointer is PC-relative for EH, 183590075Sobrien use 0 to identify the CIE. */ 183690075Sobrien dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE), 183790075Sobrien (for_eh ? 0 : DW_CIE_ID), 183890075Sobrien "CIE Identifier Tag"); 183950397Sobrien 184090075Sobrien dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version"); 184150397Sobrien 184290075Sobrien augmentation[0] = 0; 184390075Sobrien augmentation_size = 0; 184490075Sobrien if (for_eh) 184550397Sobrien { 184690075Sobrien char *p; 184750397Sobrien 184890075Sobrien /* Augmentation: 184990075Sobrien z Indicates that a uleb128 is present to size the 185090075Sobrien augmentation section. 185190075Sobrien L Indicates the encoding (and thus presence) of 185290075Sobrien an LSDA pointer in the FDE augmentation. 185390075Sobrien R Indicates a non-default pointer encoding for 185490075Sobrien FDE code pointers. 185590075Sobrien P Indicates the presence of an encoding + language 185690075Sobrien personality routine in the CIE augmentation. */ 185750397Sobrien 185890075Sobrien fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0); 185990075Sobrien per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); 186090075Sobrien lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); 186190075Sobrien 186290075Sobrien p = augmentation + 1; 186390075Sobrien if (eh_personality_libfunc) 186450397Sobrien { 186590075Sobrien *p++ = 'P'; 186690075Sobrien augmentation_size += 1 + size_of_encoded_value (per_encoding); 186750397Sobrien } 186890075Sobrien if (any_lsda_needed) 186950397Sobrien { 187090075Sobrien *p++ = 'L'; 187190075Sobrien augmentation_size += 1; 187250397Sobrien } 187390075Sobrien if (fde_encoding != DW_EH_PE_absptr) 187490075Sobrien { 187590075Sobrien *p++ = 'R'; 187690075Sobrien augmentation_size += 1; 187790075Sobrien } 187890075Sobrien if (p > augmentation + 1) 187990075Sobrien { 188090075Sobrien augmentation[0] = 'z'; 188190075Sobrien *p = '\0'; 188290075Sobrien } 188350397Sobrien 188490075Sobrien /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ 188590075Sobrien if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) 188690075Sobrien { 188790075Sobrien int offset = ( 4 /* Length */ 188890075Sobrien + 4 /* CIE Id */ 188990075Sobrien + 1 /* CIE version */ 189090075Sobrien + strlen (augmentation) + 1 /* Augmentation */ 189190075Sobrien + size_of_uleb128 (1) /* Code alignment */ 189290075Sobrien + size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT) 189390075Sobrien + 1 /* RA column */ 189490075Sobrien + 1 /* Augmentation size */ 189590075Sobrien + 1 /* Personality encoding */ ); 189690075Sobrien int pad = -offset & (PTR_SIZE - 1); 189790075Sobrien 189890075Sobrien augmentation_size += pad; 189990075Sobrien 190090075Sobrien /* Augmentations should be small, so there's scarce need to 190190075Sobrien iterate for a solution. Die if we exceed one uleb128 byte. */ 190290075Sobrien if (size_of_uleb128 (augmentation_size) != 1) 190390075Sobrien abort (); 190490075Sobrien } 190550397Sobrien } 190650397Sobrien 190790075Sobrien dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); 190890075Sobrien dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); 190990075Sobrien dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT, 191090075Sobrien "CIE Data Alignment Factor"); 191190075Sobrien dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column"); 191250397Sobrien 191390075Sobrien if (augmentation[0]) 191490075Sobrien { 191590075Sobrien dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); 191690075Sobrien if (eh_personality_libfunc) 191790075Sobrien { 191890075Sobrien dw2_asm_output_data (1, per_encoding, "Personality (%s)", 191990075Sobrien eh_data_format_name (per_encoding)); 192090075Sobrien dw2_asm_output_encoded_addr_rtx (per_encoding, 192190075Sobrien eh_personality_libfunc, NULL); 192290075Sobrien } 192350397Sobrien 192490075Sobrien if (any_lsda_needed) 192590075Sobrien dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)", 192690075Sobrien eh_data_format_name (lsda_encoding)); 192750397Sobrien 192890075Sobrien if (fde_encoding != DW_EH_PE_absptr) 192990075Sobrien dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)", 193090075Sobrien eh_data_format_name (fde_encoding)); 193190075Sobrien } 193250397Sobrien 193350397Sobrien for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next) 193490075Sobrien output_cfi (cfi, NULL, for_eh); 193550397Sobrien 193650397Sobrien /* Pad the CIE out to an address sized boundary. */ 193790075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 193890075Sobrien floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)); 193950397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 194050397Sobrien 194150397Sobrien /* Loop through all of the FDE's. */ 194290075Sobrien for (i = 0; i < fde_table_in_use; i++) 194350397Sobrien { 194450397Sobrien fde = &fde_table[i]; 194550397Sobrien 194690075Sobrien /* Don't emit EH unwind info for leaf functions that don't need it. */ 1947102780Skan if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow 1948102780Skan && ! fde->uses_eh_lsda) 194990075Sobrien continue; 195090075Sobrien 195190075Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2); 195290075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2); 195390075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2); 195490075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 195590075Sobrien "FDE Length"); 195690075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 195790075Sobrien 195850397Sobrien if (for_eh) 195990075Sobrien dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset"); 196050397Sobrien else 196190075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label, 196290075Sobrien "FDE CIE offset"); 196350397Sobrien 196450397Sobrien if (for_eh) 196590075Sobrien { 196690075Sobrien dw2_asm_output_encoded_addr_rtx (fde_encoding, 196790075Sobrien gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin), 196890075Sobrien "FDE initial location"); 196990075Sobrien dw2_asm_output_delta (size_of_encoded_value (fde_encoding), 197090075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 197190075Sobrien "FDE address range"); 197290075Sobrien } 197350397Sobrien else 197490075Sobrien { 197590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, 197690075Sobrien "FDE initial location"); 197790075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, 197890075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 197990075Sobrien "FDE address range"); 198090075Sobrien } 198150397Sobrien 198290075Sobrien if (augmentation[0]) 198390075Sobrien { 198490075Sobrien if (any_lsda_needed) 198590075Sobrien { 198690075Sobrien int size = size_of_encoded_value (lsda_encoding); 198750397Sobrien 198890075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 198990075Sobrien { 199090075Sobrien int offset = ( 4 /* Length */ 199190075Sobrien + 4 /* CIE offset */ 199290075Sobrien + 2 * size_of_encoded_value (fde_encoding) 199390075Sobrien + 1 /* Augmentation size */ ); 199490075Sobrien int pad = -offset & (PTR_SIZE - 1); 199550397Sobrien 199690075Sobrien size += pad; 199790075Sobrien if (size_of_uleb128 (size) != 1) 199890075Sobrien abort (); 199990075Sobrien } 200050397Sobrien 200190075Sobrien dw2_asm_output_data_uleb128 (size, "Augmentation size"); 200290075Sobrien 200390075Sobrien if (fde->uses_eh_lsda) 200490075Sobrien { 200590075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", 200690075Sobrien fde->funcdef_number); 200790075Sobrien dw2_asm_output_encoded_addr_rtx ( 200890075Sobrien lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1), 200990075Sobrien "Language Specific Data Area"); 201090075Sobrien } 201190075Sobrien else 201290075Sobrien { 201390075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 201490075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 201590075Sobrien dw2_asm_output_data 201690075Sobrien (size_of_encoded_value (lsda_encoding), 0, 201790075Sobrien "Language Specific Data Area (none)"); 201890075Sobrien } 201990075Sobrien } 202090075Sobrien else 202190075Sobrien dw2_asm_output_data_uleb128 (0, "Augmentation size"); 202290075Sobrien } 202390075Sobrien 202450397Sobrien /* Loop through the Call Frame Instructions associated with 202550397Sobrien this FDE. */ 202650397Sobrien fde->dw_fde_current_label = fde->dw_fde_begin; 202750397Sobrien for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) 202890075Sobrien output_cfi (cfi, fde, for_eh); 202950397Sobrien 203050397Sobrien /* Pad the FDE out to an address sized boundary. */ 203190075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 203290075Sobrien floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); 203350397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 203450397Sobrien } 203590075Sobrien 203690075Sobrien#ifndef EH_FRAME_SECTION_NAME 203750397Sobrien if (for_eh) 203890075Sobrien dw2_asm_output_data (4, 0, "End of Table"); 203950397Sobrien#endif 204050397Sobrien#ifdef MIPS_DEBUGGING_INFO 204150397Sobrien /* Work around Irix 6 assembler bug whereby labels at the end of a section 204250397Sobrien get a value of 0. Putting .align 0 after the label fixes it. */ 204350397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 0); 204450397Sobrien#endif 204550397Sobrien 204650397Sobrien /* Turn off app to make assembly quicker. */ 204750397Sobrien if (flag_debug_asm) 204850397Sobrien app_disable (); 204950397Sobrien} 205050397Sobrien 205150397Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before 205250397Sobrien the prologue. */ 205350397Sobrien 205450397Sobrienvoid 205590075Sobriendwarf2out_begin_prologue (line, file) 205690075Sobrien unsigned int line ATTRIBUTE_UNUSED; 205790075Sobrien const char *file ATTRIBUTE_UNUSED; 205850397Sobrien{ 205950397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 206090075Sobrien dw_fde_ref fde; 206150397Sobrien 206290075Sobrien current_function_func_begin_label = 0; 206350397Sobrien 206490075Sobrien#ifdef IA64_UNWIND_INFO 206590075Sobrien /* ??? current_function_func_begin_label is also used by except.c 206690075Sobrien for call-site information. We must emit this label if it might 206790075Sobrien be used. */ 206890075Sobrien if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS) 206990075Sobrien && ! dwarf2out_do_frame ()) 207090075Sobrien return; 207190075Sobrien#else 207290075Sobrien if (! dwarf2out_do_frame ()) 207390075Sobrien return; 207490075Sobrien#endif 207590075Sobrien 207690075Sobrien current_funcdef_number++; 207750397Sobrien function_section (current_function_decl); 207850397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 207950397Sobrien current_funcdef_number); 208090075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL, 208190075Sobrien current_funcdef_number); 208290075Sobrien current_function_func_begin_label = get_identifier (label); 208350397Sobrien 208490075Sobrien#ifdef IA64_UNWIND_INFO 208590075Sobrien /* We can elide the fde allocation if we're not emitting debug info. */ 208690075Sobrien if (! dwarf2out_do_frame ()) 208790075Sobrien return; 208890075Sobrien#endif 208990075Sobrien 209050397Sobrien /* Expand the fde table if necessary. */ 209150397Sobrien if (fde_table_in_use == fde_table_allocated) 209250397Sobrien { 209350397Sobrien fde_table_allocated += FDE_TABLE_INCREMENT; 209450397Sobrien fde_table 209550397Sobrien = (dw_fde_ref) xrealloc (fde_table, 209650397Sobrien fde_table_allocated * sizeof (dw_fde_node)); 209750397Sobrien } 209850397Sobrien 209950397Sobrien /* Record the FDE associated with this function. */ 210050397Sobrien current_funcdef_fde = fde_table_in_use; 210150397Sobrien 210250397Sobrien /* Add the new FDE at the end of the fde_table. */ 210350397Sobrien fde = &fde_table[fde_table_in_use++]; 210450397Sobrien fde->dw_fde_begin = xstrdup (label); 210550397Sobrien fde->dw_fde_current_label = NULL; 210650397Sobrien fde->dw_fde_end = NULL; 210750397Sobrien fde->dw_fde_cfi = NULL; 210890075Sobrien fde->funcdef_number = current_funcdef_number; 210990075Sobrien fde->nothrow = current_function_nothrow; 211090075Sobrien fde->uses_eh_lsda = cfun->uses_eh_lsda; 211150397Sobrien 211250397Sobrien args_size = old_args_size = 0; 211390075Sobrien 211490075Sobrien /* We only want to output line number information for the genuine dwarf2 211590075Sobrien prologue case, not the eh frame case. */ 211690075Sobrien#ifdef DWARF2_DEBUGGING_INFO 211790075Sobrien if (file) 211890075Sobrien dwarf2out_source_line (line, file); 211990075Sobrien#endif 212050397Sobrien} 212150397Sobrien 212250397Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code 212350397Sobrien for a function definition. This gets called *after* the epilogue code has 212450397Sobrien been generated. */ 212550397Sobrien 212650397Sobrienvoid 212750397Sobriendwarf2out_end_epilogue () 212850397Sobrien{ 212950397Sobrien dw_fde_ref fde; 213050397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 213150397Sobrien 213250397Sobrien /* Output a label to mark the endpoint of the code generated for this 213390075Sobrien function. */ 213450397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number); 213550397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 213650397Sobrien fde = &fde_table[fde_table_in_use - 1]; 213750397Sobrien fde->dw_fde_end = xstrdup (label); 213850397Sobrien} 213950397Sobrien 214050397Sobrienvoid 214150397Sobriendwarf2out_frame_init () 214250397Sobrien{ 214350397Sobrien /* Allocate the initial hunk of the fde_table. */ 214490075Sobrien fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node)); 214550397Sobrien fde_table_allocated = FDE_TABLE_INCREMENT; 214650397Sobrien fde_table_in_use = 0; 214750397Sobrien 214850397Sobrien /* Generate the CFA instructions common to all FDE's. Do it now for the 214950397Sobrien sake of lookup_cfa. */ 215050397Sobrien 215150397Sobrien#ifdef DWARF2_UNWIND_INFO 215250397Sobrien /* On entry, the Canonical Frame Address is at SP. */ 215350397Sobrien dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); 215450397Sobrien initial_return_save (INCOMING_RETURN_ADDR_RTX); 215550397Sobrien#endif 215650397Sobrien} 215750397Sobrien 215850397Sobrienvoid 215950397Sobriendwarf2out_frame_finish () 216050397Sobrien{ 216150397Sobrien /* Output call frame information. */ 216290075Sobrien if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) 216350397Sobrien output_call_frame_info (0); 216490075Sobrien 216590075Sobrien if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions)) 216650397Sobrien output_call_frame_info (1); 216790075Sobrien} 216890075Sobrien 216990075Sobrien/* And now, the subset of the debugging information support code necessary 217090075Sobrien for emitting location expressions. */ 217150397Sobrien 217290075Sobrientypedef struct dw_val_struct *dw_val_ref; 217390075Sobrientypedef struct die_struct *dw_die_ref; 217490075Sobrientypedef struct dw_loc_descr_struct *dw_loc_descr_ref; 217590075Sobrientypedef struct dw_loc_list_struct *dw_loc_list_ref; 217650397Sobrien 217750397Sobrien/* Each DIE may have a series of attribute/value pairs. Values 217850397Sobrien can take on several forms. The forms that are used in this 217950397Sobrien implementation are listed below. */ 218050397Sobrien 218150397Sobrientypedef enum 218250397Sobrien{ 218350397Sobrien dw_val_class_addr, 218490075Sobrien dw_val_class_offset, 218550397Sobrien dw_val_class_loc, 218690075Sobrien dw_val_class_loc_list, 218790075Sobrien dw_val_class_range_list, 218850397Sobrien dw_val_class_const, 218950397Sobrien dw_val_class_unsigned_const, 219050397Sobrien dw_val_class_long_long, 219150397Sobrien dw_val_class_float, 219250397Sobrien dw_val_class_flag, 219350397Sobrien dw_val_class_die_ref, 219450397Sobrien dw_val_class_fde_ref, 219550397Sobrien dw_val_class_lbl_id, 219652284Sobrien dw_val_class_lbl_offset, 219750397Sobrien dw_val_class_str 219850397Sobrien} 219950397Sobriendw_val_class; 220050397Sobrien 220150397Sobrien/* Describe a double word constant value. */ 220290075Sobrien/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */ 220350397Sobrien 220450397Sobrientypedef struct dw_long_long_struct 220550397Sobrien{ 220650397Sobrien unsigned long hi; 220750397Sobrien unsigned long low; 220850397Sobrien} 220950397Sobriendw_long_long_const; 221050397Sobrien 221150397Sobrien/* Describe a floating point constant value. */ 221250397Sobrien 221350397Sobrientypedef struct dw_fp_struct 221450397Sobrien{ 221550397Sobrien long *array; 221650397Sobrien unsigned length; 221750397Sobrien} 221850397Sobriendw_float_const; 221950397Sobrien 222050397Sobrien/* The dw_val_node describes an attribute's value, as it is 222150397Sobrien represented internally. */ 222250397Sobrien 222350397Sobrientypedef struct dw_val_struct 222450397Sobrien{ 222550397Sobrien dw_val_class val_class; 222650397Sobrien union 222750397Sobrien { 222890075Sobrien rtx val_addr; 222990075Sobrien long unsigned val_offset; 223090075Sobrien dw_loc_list_ref val_loc_list; 223150397Sobrien dw_loc_descr_ref val_loc; 223250397Sobrien long int val_int; 223350397Sobrien long unsigned val_unsigned; 223450397Sobrien dw_long_long_const val_long_long; 223550397Sobrien dw_float_const val_float; 223690075Sobrien struct 223790075Sobrien { 223890075Sobrien dw_die_ref die; 223990075Sobrien int external; 224090075Sobrien } val_die_ref; 224150397Sobrien unsigned val_fde_index; 224290075Sobrien struct indirect_string_node *val_str; 224350397Sobrien char *val_lbl_id; 224450397Sobrien unsigned char val_flag; 224550397Sobrien } 224650397Sobrien v; 224750397Sobrien} 224850397Sobriendw_val_node; 224950397Sobrien 225050397Sobrien/* Locations in memory are described using a sequence of stack machine 225150397Sobrien operations. */ 225250397Sobrien 225350397Sobrientypedef struct dw_loc_descr_struct 225450397Sobrien{ 225550397Sobrien dw_loc_descr_ref dw_loc_next; 225650397Sobrien enum dwarf_location_atom dw_loc_opc; 225750397Sobrien dw_val_node dw_loc_oprnd1; 225850397Sobrien dw_val_node dw_loc_oprnd2; 225990075Sobrien int dw_loc_addr; 226050397Sobrien} 226150397Sobriendw_loc_descr_node; 226250397Sobrien 226390075Sobrien/* Location lists are ranges + location descriptions for that range, 226490075Sobrien so you can track variables that are in different places over 226590075Sobrien their entire life. */ 226690075Sobrientypedef struct dw_loc_list_struct 226790075Sobrien{ 226890075Sobrien dw_loc_list_ref dw_loc_next; 226990075Sobrien const char *begin; /* Label for begin address of range */ 227090075Sobrien const char *end; /* Label for end address of range */ 227190075Sobrien char *ll_symbol; /* Label for beginning of location list. 227290075Sobrien Only on head of list */ 227390075Sobrien const char *section; /* Section this loclist is relative to */ 227490075Sobrien dw_loc_descr_ref expr; 227590075Sobrien} dw_loc_list_node; 227690075Sobrien 227790075Sobrienstatic const char *dwarf_stack_op_name PARAMS ((unsigned)); 227890075Sobrienstatic dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom, 227990075Sobrien unsigned long, 228090075Sobrien unsigned long)); 228190075Sobrienstatic void add_loc_descr PARAMS ((dw_loc_descr_ref *, 228290075Sobrien dw_loc_descr_ref)); 228390075Sobrienstatic unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref)); 228490075Sobrienstatic unsigned long size_of_locs PARAMS ((dw_loc_descr_ref)); 228590075Sobrienstatic void output_loc_operands PARAMS ((dw_loc_descr_ref)); 228690075Sobrienstatic void output_loc_sequence PARAMS ((dw_loc_descr_ref)); 228790075Sobrien 228890075Sobrien/* Convert a DWARF stack opcode into its string name. */ 228990075Sobrien 229090075Sobrienstatic const char * 229190075Sobriendwarf_stack_op_name (op) 229290075Sobrien unsigned op; 229390075Sobrien{ 229490075Sobrien switch (op) 229590075Sobrien { 229690075Sobrien case DW_OP_addr: 229790075Sobrien return "DW_OP_addr"; 229890075Sobrien case DW_OP_deref: 229990075Sobrien return "DW_OP_deref"; 230090075Sobrien case DW_OP_const1u: 230190075Sobrien return "DW_OP_const1u"; 230290075Sobrien case DW_OP_const1s: 230390075Sobrien return "DW_OP_const1s"; 230490075Sobrien case DW_OP_const2u: 230590075Sobrien return "DW_OP_const2u"; 230690075Sobrien case DW_OP_const2s: 230790075Sobrien return "DW_OP_const2s"; 230890075Sobrien case DW_OP_const4u: 230990075Sobrien return "DW_OP_const4u"; 231090075Sobrien case DW_OP_const4s: 231190075Sobrien return "DW_OP_const4s"; 231290075Sobrien case DW_OP_const8u: 231390075Sobrien return "DW_OP_const8u"; 231490075Sobrien case DW_OP_const8s: 231590075Sobrien return "DW_OP_const8s"; 231690075Sobrien case DW_OP_constu: 231790075Sobrien return "DW_OP_constu"; 231890075Sobrien case DW_OP_consts: 231990075Sobrien return "DW_OP_consts"; 232090075Sobrien case DW_OP_dup: 232190075Sobrien return "DW_OP_dup"; 232290075Sobrien case DW_OP_drop: 232390075Sobrien return "DW_OP_drop"; 232490075Sobrien case DW_OP_over: 232590075Sobrien return "DW_OP_over"; 232690075Sobrien case DW_OP_pick: 232790075Sobrien return "DW_OP_pick"; 232890075Sobrien case DW_OP_swap: 232990075Sobrien return "DW_OP_swap"; 233090075Sobrien case DW_OP_rot: 233190075Sobrien return "DW_OP_rot"; 233290075Sobrien case DW_OP_xderef: 233390075Sobrien return "DW_OP_xderef"; 233490075Sobrien case DW_OP_abs: 233590075Sobrien return "DW_OP_abs"; 233690075Sobrien case DW_OP_and: 233790075Sobrien return "DW_OP_and"; 233890075Sobrien case DW_OP_div: 233990075Sobrien return "DW_OP_div"; 234090075Sobrien case DW_OP_minus: 234190075Sobrien return "DW_OP_minus"; 234290075Sobrien case DW_OP_mod: 234390075Sobrien return "DW_OP_mod"; 234490075Sobrien case DW_OP_mul: 234590075Sobrien return "DW_OP_mul"; 234690075Sobrien case DW_OP_neg: 234790075Sobrien return "DW_OP_neg"; 234890075Sobrien case DW_OP_not: 234990075Sobrien return "DW_OP_not"; 235090075Sobrien case DW_OP_or: 235190075Sobrien return "DW_OP_or"; 235290075Sobrien case DW_OP_plus: 235390075Sobrien return "DW_OP_plus"; 235490075Sobrien case DW_OP_plus_uconst: 235590075Sobrien return "DW_OP_plus_uconst"; 235690075Sobrien case DW_OP_shl: 235790075Sobrien return "DW_OP_shl"; 235890075Sobrien case DW_OP_shr: 235990075Sobrien return "DW_OP_shr"; 236090075Sobrien case DW_OP_shra: 236190075Sobrien return "DW_OP_shra"; 236290075Sobrien case DW_OP_xor: 236390075Sobrien return "DW_OP_xor"; 236490075Sobrien case DW_OP_bra: 236590075Sobrien return "DW_OP_bra"; 236690075Sobrien case DW_OP_eq: 236790075Sobrien return "DW_OP_eq"; 236890075Sobrien case DW_OP_ge: 236990075Sobrien return "DW_OP_ge"; 237090075Sobrien case DW_OP_gt: 237190075Sobrien return "DW_OP_gt"; 237290075Sobrien case DW_OP_le: 237390075Sobrien return "DW_OP_le"; 237490075Sobrien case DW_OP_lt: 237590075Sobrien return "DW_OP_lt"; 237690075Sobrien case DW_OP_ne: 237790075Sobrien return "DW_OP_ne"; 237890075Sobrien case DW_OP_skip: 237990075Sobrien return "DW_OP_skip"; 238090075Sobrien case DW_OP_lit0: 238190075Sobrien return "DW_OP_lit0"; 238290075Sobrien case DW_OP_lit1: 238390075Sobrien return "DW_OP_lit1"; 238490075Sobrien case DW_OP_lit2: 238590075Sobrien return "DW_OP_lit2"; 238690075Sobrien case DW_OP_lit3: 238790075Sobrien return "DW_OP_lit3"; 238890075Sobrien case DW_OP_lit4: 238990075Sobrien return "DW_OP_lit4"; 239090075Sobrien case DW_OP_lit5: 239190075Sobrien return "DW_OP_lit5"; 239290075Sobrien case DW_OP_lit6: 239390075Sobrien return "DW_OP_lit6"; 239490075Sobrien case DW_OP_lit7: 239590075Sobrien return "DW_OP_lit7"; 239690075Sobrien case DW_OP_lit8: 239790075Sobrien return "DW_OP_lit8"; 239890075Sobrien case DW_OP_lit9: 239990075Sobrien return "DW_OP_lit9"; 240090075Sobrien case DW_OP_lit10: 240190075Sobrien return "DW_OP_lit10"; 240290075Sobrien case DW_OP_lit11: 240390075Sobrien return "DW_OP_lit11"; 240490075Sobrien case DW_OP_lit12: 240590075Sobrien return "DW_OP_lit12"; 240690075Sobrien case DW_OP_lit13: 240790075Sobrien return "DW_OP_lit13"; 240890075Sobrien case DW_OP_lit14: 240990075Sobrien return "DW_OP_lit14"; 241090075Sobrien case DW_OP_lit15: 241190075Sobrien return "DW_OP_lit15"; 241290075Sobrien case DW_OP_lit16: 241390075Sobrien return "DW_OP_lit16"; 241490075Sobrien case DW_OP_lit17: 241590075Sobrien return "DW_OP_lit17"; 241690075Sobrien case DW_OP_lit18: 241790075Sobrien return "DW_OP_lit18"; 241890075Sobrien case DW_OP_lit19: 241990075Sobrien return "DW_OP_lit19"; 242090075Sobrien case DW_OP_lit20: 242190075Sobrien return "DW_OP_lit20"; 242290075Sobrien case DW_OP_lit21: 242390075Sobrien return "DW_OP_lit21"; 242490075Sobrien case DW_OP_lit22: 242590075Sobrien return "DW_OP_lit22"; 242690075Sobrien case DW_OP_lit23: 242790075Sobrien return "DW_OP_lit23"; 242890075Sobrien case DW_OP_lit24: 242990075Sobrien return "DW_OP_lit24"; 243090075Sobrien case DW_OP_lit25: 243190075Sobrien return "DW_OP_lit25"; 243290075Sobrien case DW_OP_lit26: 243390075Sobrien return "DW_OP_lit26"; 243490075Sobrien case DW_OP_lit27: 243590075Sobrien return "DW_OP_lit27"; 243690075Sobrien case DW_OP_lit28: 243790075Sobrien return "DW_OP_lit28"; 243890075Sobrien case DW_OP_lit29: 243990075Sobrien return "DW_OP_lit29"; 244090075Sobrien case DW_OP_lit30: 244190075Sobrien return "DW_OP_lit30"; 244290075Sobrien case DW_OP_lit31: 244390075Sobrien return "DW_OP_lit31"; 244490075Sobrien case DW_OP_reg0: 244590075Sobrien return "DW_OP_reg0"; 244690075Sobrien case DW_OP_reg1: 244790075Sobrien return "DW_OP_reg1"; 244890075Sobrien case DW_OP_reg2: 244990075Sobrien return "DW_OP_reg2"; 245090075Sobrien case DW_OP_reg3: 245190075Sobrien return "DW_OP_reg3"; 245290075Sobrien case DW_OP_reg4: 245390075Sobrien return "DW_OP_reg4"; 245490075Sobrien case DW_OP_reg5: 245590075Sobrien return "DW_OP_reg5"; 245690075Sobrien case DW_OP_reg6: 245790075Sobrien return "DW_OP_reg6"; 245890075Sobrien case DW_OP_reg7: 245990075Sobrien return "DW_OP_reg7"; 246090075Sobrien case DW_OP_reg8: 246190075Sobrien return "DW_OP_reg8"; 246290075Sobrien case DW_OP_reg9: 246390075Sobrien return "DW_OP_reg9"; 246490075Sobrien case DW_OP_reg10: 246590075Sobrien return "DW_OP_reg10"; 246690075Sobrien case DW_OP_reg11: 246790075Sobrien return "DW_OP_reg11"; 246890075Sobrien case DW_OP_reg12: 246990075Sobrien return "DW_OP_reg12"; 247090075Sobrien case DW_OP_reg13: 247190075Sobrien return "DW_OP_reg13"; 247290075Sobrien case DW_OP_reg14: 247390075Sobrien return "DW_OP_reg14"; 247490075Sobrien case DW_OP_reg15: 247590075Sobrien return "DW_OP_reg15"; 247690075Sobrien case DW_OP_reg16: 247790075Sobrien return "DW_OP_reg16"; 247890075Sobrien case DW_OP_reg17: 247990075Sobrien return "DW_OP_reg17"; 248090075Sobrien case DW_OP_reg18: 248190075Sobrien return "DW_OP_reg18"; 248290075Sobrien case DW_OP_reg19: 248390075Sobrien return "DW_OP_reg19"; 248490075Sobrien case DW_OP_reg20: 248590075Sobrien return "DW_OP_reg20"; 248690075Sobrien case DW_OP_reg21: 248790075Sobrien return "DW_OP_reg21"; 248890075Sobrien case DW_OP_reg22: 248990075Sobrien return "DW_OP_reg22"; 249090075Sobrien case DW_OP_reg23: 249190075Sobrien return "DW_OP_reg23"; 249290075Sobrien case DW_OP_reg24: 249390075Sobrien return "DW_OP_reg24"; 249490075Sobrien case DW_OP_reg25: 249590075Sobrien return "DW_OP_reg25"; 249690075Sobrien case DW_OP_reg26: 249790075Sobrien return "DW_OP_reg26"; 249890075Sobrien case DW_OP_reg27: 249990075Sobrien return "DW_OP_reg27"; 250090075Sobrien case DW_OP_reg28: 250190075Sobrien return "DW_OP_reg28"; 250290075Sobrien case DW_OP_reg29: 250390075Sobrien return "DW_OP_reg29"; 250490075Sobrien case DW_OP_reg30: 250590075Sobrien return "DW_OP_reg30"; 250690075Sobrien case DW_OP_reg31: 250790075Sobrien return "DW_OP_reg31"; 250890075Sobrien case DW_OP_breg0: 250990075Sobrien return "DW_OP_breg0"; 251090075Sobrien case DW_OP_breg1: 251190075Sobrien return "DW_OP_breg1"; 251290075Sobrien case DW_OP_breg2: 251390075Sobrien return "DW_OP_breg2"; 251490075Sobrien case DW_OP_breg3: 251590075Sobrien return "DW_OP_breg3"; 251690075Sobrien case DW_OP_breg4: 251790075Sobrien return "DW_OP_breg4"; 251890075Sobrien case DW_OP_breg5: 251990075Sobrien return "DW_OP_breg5"; 252090075Sobrien case DW_OP_breg6: 252190075Sobrien return "DW_OP_breg6"; 252290075Sobrien case DW_OP_breg7: 252390075Sobrien return "DW_OP_breg7"; 252490075Sobrien case DW_OP_breg8: 252590075Sobrien return "DW_OP_breg8"; 252690075Sobrien case DW_OP_breg9: 252790075Sobrien return "DW_OP_breg9"; 252890075Sobrien case DW_OP_breg10: 252990075Sobrien return "DW_OP_breg10"; 253090075Sobrien case DW_OP_breg11: 253190075Sobrien return "DW_OP_breg11"; 253290075Sobrien case DW_OP_breg12: 253390075Sobrien return "DW_OP_breg12"; 253490075Sobrien case DW_OP_breg13: 253590075Sobrien return "DW_OP_breg13"; 253690075Sobrien case DW_OP_breg14: 253790075Sobrien return "DW_OP_breg14"; 253890075Sobrien case DW_OP_breg15: 253990075Sobrien return "DW_OP_breg15"; 254090075Sobrien case DW_OP_breg16: 254190075Sobrien return "DW_OP_breg16"; 254290075Sobrien case DW_OP_breg17: 254390075Sobrien return "DW_OP_breg17"; 254490075Sobrien case DW_OP_breg18: 254590075Sobrien return "DW_OP_breg18"; 254690075Sobrien case DW_OP_breg19: 254790075Sobrien return "DW_OP_breg19"; 254890075Sobrien case DW_OP_breg20: 254990075Sobrien return "DW_OP_breg20"; 255090075Sobrien case DW_OP_breg21: 255190075Sobrien return "DW_OP_breg21"; 255290075Sobrien case DW_OP_breg22: 255390075Sobrien return "DW_OP_breg22"; 255490075Sobrien case DW_OP_breg23: 255590075Sobrien return "DW_OP_breg23"; 255690075Sobrien case DW_OP_breg24: 255790075Sobrien return "DW_OP_breg24"; 255890075Sobrien case DW_OP_breg25: 255990075Sobrien return "DW_OP_breg25"; 256090075Sobrien case DW_OP_breg26: 256190075Sobrien return "DW_OP_breg26"; 256290075Sobrien case DW_OP_breg27: 256390075Sobrien return "DW_OP_breg27"; 256490075Sobrien case DW_OP_breg28: 256590075Sobrien return "DW_OP_breg28"; 256690075Sobrien case DW_OP_breg29: 256790075Sobrien return "DW_OP_breg29"; 256890075Sobrien case DW_OP_breg30: 256990075Sobrien return "DW_OP_breg30"; 257090075Sobrien case DW_OP_breg31: 257190075Sobrien return "DW_OP_breg31"; 257290075Sobrien case DW_OP_regx: 257390075Sobrien return "DW_OP_regx"; 257490075Sobrien case DW_OP_fbreg: 257590075Sobrien return "DW_OP_fbreg"; 257690075Sobrien case DW_OP_bregx: 257790075Sobrien return "DW_OP_bregx"; 257890075Sobrien case DW_OP_piece: 257990075Sobrien return "DW_OP_piece"; 258090075Sobrien case DW_OP_deref_size: 258190075Sobrien return "DW_OP_deref_size"; 258290075Sobrien case DW_OP_xderef_size: 258390075Sobrien return "DW_OP_xderef_size"; 258490075Sobrien case DW_OP_nop: 258590075Sobrien return "DW_OP_nop"; 258690075Sobrien default: 258790075Sobrien return "OP_<unknown>"; 258890075Sobrien } 258990075Sobrien} 259090075Sobrien 259190075Sobrien/* Return a pointer to a newly allocated location description. Location 259290075Sobrien descriptions are simple expression terms that can be strung 259390075Sobrien together to form more complicated location (address) descriptions. */ 259490075Sobrien 259590075Sobrienstatic inline dw_loc_descr_ref 259690075Sobriennew_loc_descr (op, oprnd1, oprnd2) 259790075Sobrien enum dwarf_location_atom op; 259890075Sobrien unsigned long oprnd1; 259990075Sobrien unsigned long oprnd2; 260090075Sobrien{ 260190075Sobrien /* Use xcalloc here so we clear out all of the long_long constant in 260290075Sobrien the union. */ 260390075Sobrien dw_loc_descr_ref descr 260490075Sobrien = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node)); 260590075Sobrien 260690075Sobrien descr->dw_loc_opc = op; 260790075Sobrien descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const; 260890075Sobrien descr->dw_loc_oprnd1.v.val_unsigned = oprnd1; 260990075Sobrien descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const; 261090075Sobrien descr->dw_loc_oprnd2.v.val_unsigned = oprnd2; 261190075Sobrien 261290075Sobrien return descr; 261390075Sobrien} 261490075Sobrien 261590075Sobrien 261690075Sobrien/* Add a location description term to a location description expression. */ 261790075Sobrien 261890075Sobrienstatic inline void 261990075Sobrienadd_loc_descr (list_head, descr) 262090075Sobrien dw_loc_descr_ref *list_head; 262190075Sobrien dw_loc_descr_ref descr; 262290075Sobrien{ 262390075Sobrien dw_loc_descr_ref *d; 262490075Sobrien 262590075Sobrien /* Find the end of the chain. */ 262690075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 262790075Sobrien ; 262890075Sobrien 262990075Sobrien *d = descr; 263090075Sobrien} 263190075Sobrien 263290075Sobrien/* Return the size of a location descriptor. */ 263390075Sobrien 263490075Sobrienstatic unsigned long 263590075Sobriensize_of_loc_descr (loc) 263690075Sobrien dw_loc_descr_ref loc; 263790075Sobrien{ 263890075Sobrien unsigned long size = 1; 263990075Sobrien 264090075Sobrien switch (loc->dw_loc_opc) 264190075Sobrien { 264290075Sobrien case DW_OP_addr: 264390075Sobrien size += DWARF2_ADDR_SIZE; 264490075Sobrien break; 264590075Sobrien case DW_OP_const1u: 264690075Sobrien case DW_OP_const1s: 264790075Sobrien size += 1; 264890075Sobrien break; 264990075Sobrien case DW_OP_const2u: 265090075Sobrien case DW_OP_const2s: 265190075Sobrien size += 2; 265290075Sobrien break; 265390075Sobrien case DW_OP_const4u: 265490075Sobrien case DW_OP_const4s: 265590075Sobrien size += 4; 265690075Sobrien break; 265790075Sobrien case DW_OP_const8u: 265890075Sobrien case DW_OP_const8s: 265990075Sobrien size += 8; 266090075Sobrien break; 266190075Sobrien case DW_OP_constu: 266290075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 266390075Sobrien break; 266490075Sobrien case DW_OP_consts: 266590075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 266690075Sobrien break; 266790075Sobrien case DW_OP_pick: 266890075Sobrien size += 1; 266990075Sobrien break; 267090075Sobrien case DW_OP_plus_uconst: 267190075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 267290075Sobrien break; 267390075Sobrien case DW_OP_skip: 267490075Sobrien case DW_OP_bra: 267590075Sobrien size += 2; 267690075Sobrien break; 267790075Sobrien case DW_OP_breg0: 267890075Sobrien case DW_OP_breg1: 267990075Sobrien case DW_OP_breg2: 268090075Sobrien case DW_OP_breg3: 268190075Sobrien case DW_OP_breg4: 268290075Sobrien case DW_OP_breg5: 268390075Sobrien case DW_OP_breg6: 268490075Sobrien case DW_OP_breg7: 268590075Sobrien case DW_OP_breg8: 268690075Sobrien case DW_OP_breg9: 268790075Sobrien case DW_OP_breg10: 268890075Sobrien case DW_OP_breg11: 268990075Sobrien case DW_OP_breg12: 269090075Sobrien case DW_OP_breg13: 269190075Sobrien case DW_OP_breg14: 269290075Sobrien case DW_OP_breg15: 269390075Sobrien case DW_OP_breg16: 269490075Sobrien case DW_OP_breg17: 269590075Sobrien case DW_OP_breg18: 269690075Sobrien case DW_OP_breg19: 269790075Sobrien case DW_OP_breg20: 269890075Sobrien case DW_OP_breg21: 269990075Sobrien case DW_OP_breg22: 270090075Sobrien case DW_OP_breg23: 270190075Sobrien case DW_OP_breg24: 270290075Sobrien case DW_OP_breg25: 270390075Sobrien case DW_OP_breg26: 270490075Sobrien case DW_OP_breg27: 270590075Sobrien case DW_OP_breg28: 270690075Sobrien case DW_OP_breg29: 270790075Sobrien case DW_OP_breg30: 270890075Sobrien case DW_OP_breg31: 270990075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 271090075Sobrien break; 271190075Sobrien case DW_OP_regx: 271290075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271390075Sobrien break; 271490075Sobrien case DW_OP_fbreg: 271590075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 271690075Sobrien break; 271790075Sobrien case DW_OP_bregx: 271890075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271990075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); 272090075Sobrien break; 272190075Sobrien case DW_OP_piece: 272290075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 272390075Sobrien break; 272490075Sobrien case DW_OP_deref_size: 272590075Sobrien case DW_OP_xderef_size: 272690075Sobrien size += 1; 272790075Sobrien break; 272890075Sobrien default: 272990075Sobrien break; 273090075Sobrien } 273190075Sobrien 273290075Sobrien return size; 273390075Sobrien} 273490075Sobrien 273590075Sobrien/* Return the size of a series of location descriptors. */ 273690075Sobrien 273790075Sobrienstatic unsigned long 273890075Sobriensize_of_locs (loc) 273990075Sobrien dw_loc_descr_ref loc; 274090075Sobrien{ 274190075Sobrien unsigned long size; 274290075Sobrien 274390075Sobrien for (size = 0; loc != NULL; loc = loc->dw_loc_next) 274490075Sobrien { 274590075Sobrien loc->dw_loc_addr = size; 274690075Sobrien size += size_of_loc_descr (loc); 274790075Sobrien } 274890075Sobrien 274990075Sobrien return size; 275090075Sobrien} 275190075Sobrien 275290075Sobrien/* Output location description stack opcode's operands (if any). */ 275390075Sobrien 275490075Sobrienstatic void 275590075Sobrienoutput_loc_operands (loc) 275690075Sobrien dw_loc_descr_ref loc; 275790075Sobrien{ 275890075Sobrien dw_val_ref val1 = &loc->dw_loc_oprnd1; 275990075Sobrien dw_val_ref val2 = &loc->dw_loc_oprnd2; 276090075Sobrien 276190075Sobrien switch (loc->dw_loc_opc) 276290075Sobrien { 276390075Sobrien#ifdef DWARF2_DEBUGGING_INFO 276490075Sobrien case DW_OP_addr: 276590075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val1->v.val_addr, NULL); 276690075Sobrien break; 276790075Sobrien case DW_OP_const2u: 276890075Sobrien case DW_OP_const2s: 276990075Sobrien dw2_asm_output_data (2, val1->v.val_int, NULL); 277090075Sobrien break; 277190075Sobrien case DW_OP_const4u: 277290075Sobrien case DW_OP_const4s: 277390075Sobrien dw2_asm_output_data (4, val1->v.val_int, NULL); 277490075Sobrien break; 277590075Sobrien case DW_OP_const8u: 277690075Sobrien case DW_OP_const8s: 277790075Sobrien if (HOST_BITS_PER_LONG < 64) 277890075Sobrien abort (); 277990075Sobrien dw2_asm_output_data (8, val1->v.val_int, NULL); 278090075Sobrien break; 278190075Sobrien case DW_OP_skip: 278290075Sobrien case DW_OP_bra: 278390075Sobrien { 278490075Sobrien int offset; 278590075Sobrien 278690075Sobrien if (val1->val_class == dw_val_class_loc) 278790075Sobrien offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3); 278890075Sobrien else 278990075Sobrien abort (); 279090075Sobrien 279190075Sobrien dw2_asm_output_data (2, offset, NULL); 279290075Sobrien } 279390075Sobrien break; 279490075Sobrien#else 279590075Sobrien case DW_OP_addr: 279690075Sobrien case DW_OP_const2u: 279790075Sobrien case DW_OP_const2s: 279890075Sobrien case DW_OP_const4u: 279990075Sobrien case DW_OP_const4s: 280090075Sobrien case DW_OP_const8u: 280190075Sobrien case DW_OP_const8s: 280290075Sobrien case DW_OP_skip: 280390075Sobrien case DW_OP_bra: 280490075Sobrien /* We currently don't make any attempt to make sure these are 280590075Sobrien aligned properly like we do for the main unwind info, so 280690075Sobrien don't support emitting things larger than a byte if we're 280790075Sobrien only doing unwinding. */ 280890075Sobrien abort (); 280990075Sobrien#endif 281090075Sobrien case DW_OP_const1u: 281190075Sobrien case DW_OP_const1s: 281290075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 281390075Sobrien break; 281490075Sobrien case DW_OP_constu: 281590075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 281690075Sobrien break; 281790075Sobrien case DW_OP_consts: 281890075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 281990075Sobrien break; 282090075Sobrien case DW_OP_pick: 282190075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 282290075Sobrien break; 282390075Sobrien case DW_OP_plus_uconst: 282490075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 282590075Sobrien break; 282690075Sobrien case DW_OP_breg0: 282790075Sobrien case DW_OP_breg1: 282890075Sobrien case DW_OP_breg2: 282990075Sobrien case DW_OP_breg3: 283090075Sobrien case DW_OP_breg4: 283190075Sobrien case DW_OP_breg5: 283290075Sobrien case DW_OP_breg6: 283390075Sobrien case DW_OP_breg7: 283490075Sobrien case DW_OP_breg8: 283590075Sobrien case DW_OP_breg9: 283690075Sobrien case DW_OP_breg10: 283790075Sobrien case DW_OP_breg11: 283890075Sobrien case DW_OP_breg12: 283990075Sobrien case DW_OP_breg13: 284090075Sobrien case DW_OP_breg14: 284190075Sobrien case DW_OP_breg15: 284290075Sobrien case DW_OP_breg16: 284390075Sobrien case DW_OP_breg17: 284490075Sobrien case DW_OP_breg18: 284590075Sobrien case DW_OP_breg19: 284690075Sobrien case DW_OP_breg20: 284790075Sobrien case DW_OP_breg21: 284890075Sobrien case DW_OP_breg22: 284990075Sobrien case DW_OP_breg23: 285090075Sobrien case DW_OP_breg24: 285190075Sobrien case DW_OP_breg25: 285290075Sobrien case DW_OP_breg26: 285390075Sobrien case DW_OP_breg27: 285490075Sobrien case DW_OP_breg28: 285590075Sobrien case DW_OP_breg29: 285690075Sobrien case DW_OP_breg30: 285790075Sobrien case DW_OP_breg31: 285890075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 285990075Sobrien break; 286090075Sobrien case DW_OP_regx: 286190075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286290075Sobrien break; 286390075Sobrien case DW_OP_fbreg: 286490075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 286590075Sobrien break; 286690075Sobrien case DW_OP_bregx: 286790075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286890075Sobrien dw2_asm_output_data_sleb128 (val2->v.val_int, NULL); 286990075Sobrien break; 287090075Sobrien case DW_OP_piece: 287190075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 287290075Sobrien break; 287390075Sobrien case DW_OP_deref_size: 287490075Sobrien case DW_OP_xderef_size: 287590075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 287690075Sobrien break; 287790075Sobrien default: 287890075Sobrien /* Other codes have no operands. */ 287990075Sobrien break; 288090075Sobrien } 288190075Sobrien} 288290075Sobrien 288390075Sobrien/* Output a sequence of location operations. */ 288490075Sobrien 288590075Sobrienstatic void 288690075Sobrienoutput_loc_sequence (loc) 288790075Sobrien dw_loc_descr_ref loc; 288890075Sobrien{ 288990075Sobrien for (; loc != NULL; loc = loc->dw_loc_next) 289090075Sobrien { 289190075Sobrien /* Output the opcode. */ 289290075Sobrien dw2_asm_output_data (1, loc->dw_loc_opc, 289390075Sobrien "%s", dwarf_stack_op_name (loc->dw_loc_opc)); 289490075Sobrien 289590075Sobrien /* Output the operand(s) (if any). */ 289690075Sobrien output_loc_operands (loc); 289790075Sobrien } 289890075Sobrien} 289990075Sobrien 290090075Sobrien/* This routine will generate the correct assembly data for a location 290190075Sobrien description based on a cfi entry with a complex address. */ 290290075Sobrien 290390075Sobrienstatic void 290490075Sobrienoutput_cfa_loc (cfi) 290590075Sobrien dw_cfi_ref cfi; 290690075Sobrien{ 290790075Sobrien dw_loc_descr_ref loc; 290890075Sobrien unsigned long size; 290990075Sobrien 291090075Sobrien /* Output the size of the block. */ 291190075Sobrien loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; 291290075Sobrien size = size_of_locs (loc); 291390075Sobrien dw2_asm_output_data_uleb128 (size, NULL); 291490075Sobrien 291590075Sobrien /* Now output the operations themselves. */ 291690075Sobrien output_loc_sequence (loc); 291790075Sobrien} 291890075Sobrien 291990075Sobrien/* This function builds a dwarf location descriptor sequence from 292090075Sobrien a dw_cfa_location. */ 292190075Sobrien 292290075Sobrienstatic struct dw_loc_descr_struct * 292390075Sobrienbuild_cfa_loc (cfa) 292490075Sobrien dw_cfa_location *cfa; 292590075Sobrien{ 292690075Sobrien struct dw_loc_descr_struct *head, *tmp; 292790075Sobrien 292890075Sobrien if (cfa->indirect == 0) 292990075Sobrien abort (); 293090075Sobrien 293190075Sobrien if (cfa->base_offset) 293290075Sobrien { 293390075Sobrien if (cfa->reg <= 31) 293490075Sobrien head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0); 293590075Sobrien else 293690075Sobrien head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset); 293790075Sobrien } 293890075Sobrien else if (cfa->reg <= 31) 293990075Sobrien head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); 294090075Sobrien else 294190075Sobrien head = new_loc_descr (DW_OP_regx, cfa->reg, 0); 294290075Sobrien 294390075Sobrien head->dw_loc_oprnd1.val_class = dw_val_class_const; 294490075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 294590075Sobrien add_loc_descr (&head, tmp); 294690075Sobrien if (cfa->offset != 0) 294790075Sobrien { 294890075Sobrien tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0); 294990075Sobrien add_loc_descr (&head, tmp); 295090075Sobrien } 295190075Sobrien 295290075Sobrien return head; 295390075Sobrien} 295490075Sobrien 295590075Sobrien/* This function fills in aa dw_cfa_location structure from a dwarf location 295690075Sobrien descriptor sequence. */ 295790075Sobrien 295890075Sobrienstatic void 295990075Sobrienget_cfa_from_loc_descr (cfa, loc) 296090075Sobrien dw_cfa_location *cfa; 296190075Sobrien struct dw_loc_descr_struct *loc; 296290075Sobrien{ 296390075Sobrien struct dw_loc_descr_struct *ptr; 296490075Sobrien cfa->offset = 0; 296590075Sobrien cfa->base_offset = 0; 296690075Sobrien cfa->indirect = 0; 296790075Sobrien cfa->reg = -1; 296890075Sobrien 296990075Sobrien for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next) 297090075Sobrien { 297190075Sobrien enum dwarf_location_atom op = ptr->dw_loc_opc; 297290075Sobrien 297390075Sobrien switch (op) 297490075Sobrien { 297590075Sobrien case DW_OP_reg0: 297690075Sobrien case DW_OP_reg1: 297790075Sobrien case DW_OP_reg2: 297890075Sobrien case DW_OP_reg3: 297990075Sobrien case DW_OP_reg4: 298090075Sobrien case DW_OP_reg5: 298190075Sobrien case DW_OP_reg6: 298290075Sobrien case DW_OP_reg7: 298390075Sobrien case DW_OP_reg8: 298490075Sobrien case DW_OP_reg9: 298590075Sobrien case DW_OP_reg10: 298690075Sobrien case DW_OP_reg11: 298790075Sobrien case DW_OP_reg12: 298890075Sobrien case DW_OP_reg13: 298990075Sobrien case DW_OP_reg14: 299090075Sobrien case DW_OP_reg15: 299190075Sobrien case DW_OP_reg16: 299290075Sobrien case DW_OP_reg17: 299390075Sobrien case DW_OP_reg18: 299490075Sobrien case DW_OP_reg19: 299590075Sobrien case DW_OP_reg20: 299690075Sobrien case DW_OP_reg21: 299790075Sobrien case DW_OP_reg22: 299890075Sobrien case DW_OP_reg23: 299990075Sobrien case DW_OP_reg24: 300090075Sobrien case DW_OP_reg25: 300190075Sobrien case DW_OP_reg26: 300290075Sobrien case DW_OP_reg27: 300390075Sobrien case DW_OP_reg28: 300490075Sobrien case DW_OP_reg29: 300590075Sobrien case DW_OP_reg30: 300690075Sobrien case DW_OP_reg31: 300790075Sobrien cfa->reg = op - DW_OP_reg0; 300890075Sobrien break; 300990075Sobrien case DW_OP_regx: 301090075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 301190075Sobrien break; 301290075Sobrien case DW_OP_breg0: 301390075Sobrien case DW_OP_breg1: 301490075Sobrien case DW_OP_breg2: 301590075Sobrien case DW_OP_breg3: 301690075Sobrien case DW_OP_breg4: 301790075Sobrien case DW_OP_breg5: 301890075Sobrien case DW_OP_breg6: 301990075Sobrien case DW_OP_breg7: 302090075Sobrien case DW_OP_breg8: 302190075Sobrien case DW_OP_breg9: 302290075Sobrien case DW_OP_breg10: 302390075Sobrien case DW_OP_breg11: 302490075Sobrien case DW_OP_breg12: 302590075Sobrien case DW_OP_breg13: 302690075Sobrien case DW_OP_breg14: 302790075Sobrien case DW_OP_breg15: 302890075Sobrien case DW_OP_breg16: 302990075Sobrien case DW_OP_breg17: 303090075Sobrien case DW_OP_breg18: 303190075Sobrien case DW_OP_breg19: 303290075Sobrien case DW_OP_breg20: 303390075Sobrien case DW_OP_breg21: 303490075Sobrien case DW_OP_breg22: 303590075Sobrien case DW_OP_breg23: 303690075Sobrien case DW_OP_breg24: 303790075Sobrien case DW_OP_breg25: 303890075Sobrien case DW_OP_breg26: 303990075Sobrien case DW_OP_breg27: 304090075Sobrien case DW_OP_breg28: 304190075Sobrien case DW_OP_breg29: 304290075Sobrien case DW_OP_breg30: 304390075Sobrien case DW_OP_breg31: 304490075Sobrien cfa->reg = op - DW_OP_breg0; 304590075Sobrien cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int; 304690075Sobrien break; 304790075Sobrien case DW_OP_bregx: 304890075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 304990075Sobrien cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int; 305090075Sobrien break; 305190075Sobrien case DW_OP_deref: 305290075Sobrien cfa->indirect = 1; 305390075Sobrien break; 305490075Sobrien case DW_OP_plus_uconst: 305590075Sobrien cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned; 305690075Sobrien break; 305790075Sobrien default: 305890075Sobrien internal_error ("DW_LOC_OP %s not implemented\n", 305990075Sobrien dwarf_stack_op_name (ptr->dw_loc_opc)); 306090075Sobrien } 306190075Sobrien } 306290075Sobrien} 306390075Sobrien#endif /* .debug_frame support */ 306490075Sobrien 306590075Sobrien/* And now, the support for symbolic debugging information. */ 306690075Sobrien#ifdef DWARF2_DEBUGGING_INFO 306790075Sobrien 306890075Sobrien/* .debug_str support. */ 306990075Sobrienstatic hashnode indirect_string_alloc PARAMS ((hash_table *)); 307090075Sobrienstatic int output_indirect_string PARAMS ((struct cpp_reader *, 307190075Sobrien hashnode, const PTR)); 307290075Sobrien 307390075Sobrien 307490075Sobrienstatic void dwarf2out_init PARAMS ((const char *)); 307590075Sobrienstatic void dwarf2out_finish PARAMS ((const char *)); 307690075Sobrienstatic void dwarf2out_define PARAMS ((unsigned int, const char *)); 307790075Sobrienstatic void dwarf2out_undef PARAMS ((unsigned int, const char *)); 307890075Sobrienstatic void dwarf2out_start_source_file PARAMS ((unsigned, const char *)); 307990075Sobrienstatic void dwarf2out_end_source_file PARAMS ((unsigned)); 308090075Sobrienstatic void dwarf2out_begin_block PARAMS ((unsigned, unsigned)); 308190075Sobrienstatic void dwarf2out_end_block PARAMS ((unsigned, unsigned)); 308290075Sobrienstatic bool dwarf2out_ignore_block PARAMS ((tree)); 308390075Sobrienstatic void dwarf2out_global_decl PARAMS ((tree)); 308490075Sobrienstatic void dwarf2out_abstract_function PARAMS ((tree)); 308590075Sobrien 308690075Sobrien/* The debug hooks structure. */ 308790075Sobrien 308890075Sobrienstruct gcc_debug_hooks dwarf2_debug_hooks = 308990075Sobrien{ 309090075Sobrien dwarf2out_init, 309190075Sobrien dwarf2out_finish, 309290075Sobrien dwarf2out_define, 309390075Sobrien dwarf2out_undef, 309490075Sobrien dwarf2out_start_source_file, 309590075Sobrien dwarf2out_end_source_file, 309690075Sobrien dwarf2out_begin_block, 309790075Sobrien dwarf2out_end_block, 309890075Sobrien dwarf2out_ignore_block, 309990075Sobrien dwarf2out_source_line, 310090075Sobrien dwarf2out_begin_prologue, 310190075Sobrien debug_nothing_int, /* end_prologue */ 310290075Sobrien dwarf2out_end_epilogue, 310390075Sobrien debug_nothing_tree, /* begin_function */ 310490075Sobrien debug_nothing_int, /* end_function */ 310590075Sobrien dwarf2out_decl, /* function_decl */ 310690075Sobrien dwarf2out_global_decl, 310790075Sobrien debug_nothing_tree, /* deferred_inline_function */ 310890075Sobrien /* The DWARF 2 backend tries to reduce debugging bloat by not 310990075Sobrien emitting the abstract description of inline functions until 311090075Sobrien something tries to reference them. */ 311190075Sobrien dwarf2out_abstract_function, /* outlining_inline_function */ 311290075Sobrien debug_nothing_rtx /* label */ 311390075Sobrien}; 311490075Sobrien 311590075Sobrien/* NOTE: In the comments in this file, many references are made to 311690075Sobrien "Debugging Information Entries". This term is abbreviated as `DIE' 311790075Sobrien throughout the remainder of this file. */ 311890075Sobrien 311990075Sobrien/* An internal representation of the DWARF output is built, and then 312090075Sobrien walked to generate the DWARF debugging info. The walk of the internal 312190075Sobrien representation is done after the entire program has been compiled. 312290075Sobrien The types below are used to describe the internal representation. */ 312390075Sobrien 312490075Sobrien/* Various DIE's use offsets relative to the beginning of the 312590075Sobrien .debug_info section to refer to each other. */ 312690075Sobrien 312790075Sobrientypedef long int dw_offset; 312890075Sobrien 312990075Sobrien/* Define typedefs here to avoid circular dependencies. */ 313090075Sobrien 313190075Sobrientypedef struct dw_attr_struct *dw_attr_ref; 313290075Sobrientypedef struct dw_line_info_struct *dw_line_info_ref; 313390075Sobrientypedef struct dw_separate_line_info_struct *dw_separate_line_info_ref; 313490075Sobrientypedef struct pubname_struct *pubname_ref; 313590075Sobrientypedef struct dw_ranges_struct *dw_ranges_ref; 313690075Sobrien 313790075Sobrien/* Each entry in the line_info_table maintains the file and 313890075Sobrien line number associated with the label generated for that 313990075Sobrien entry. The label gives the PC value associated with 314090075Sobrien the line number entry. */ 314190075Sobrien 314290075Sobrientypedef struct dw_line_info_struct 314390075Sobrien{ 314490075Sobrien unsigned long dw_file_num; 314590075Sobrien unsigned long dw_line_num; 314690075Sobrien} 314790075Sobriendw_line_info_entry; 314890075Sobrien 314990075Sobrien/* Line information for functions in separate sections; each one gets its 315090075Sobrien own sequence. */ 315190075Sobrientypedef struct dw_separate_line_info_struct 315290075Sobrien{ 315390075Sobrien unsigned long dw_file_num; 315490075Sobrien unsigned long dw_line_num; 315590075Sobrien unsigned long function; 315690075Sobrien} 315790075Sobriendw_separate_line_info_entry; 315890075Sobrien 315950397Sobrien/* Each DIE attribute has a field specifying the attribute kind, 316050397Sobrien a link to the next attribute in the chain, and an attribute value. 316150397Sobrien Attributes are typically linked below the DIE they modify. */ 316250397Sobrien 316350397Sobrientypedef struct dw_attr_struct 316450397Sobrien{ 316550397Sobrien enum dwarf_attribute dw_attr; 316650397Sobrien dw_attr_ref dw_attr_next; 316750397Sobrien dw_val_node dw_attr_val; 316850397Sobrien} 316950397Sobriendw_attr_node; 317050397Sobrien 317150397Sobrien/* The Debugging Information Entry (DIE) structure */ 317250397Sobrien 317350397Sobrientypedef struct die_struct 317450397Sobrien{ 317550397Sobrien enum dwarf_tag die_tag; 317690075Sobrien char *die_symbol; 317750397Sobrien dw_attr_ref die_attr; 317850397Sobrien dw_die_ref die_parent; 317950397Sobrien dw_die_ref die_child; 318050397Sobrien dw_die_ref die_sib; 318150397Sobrien dw_offset die_offset; 318250397Sobrien unsigned long die_abbrev; 318390075Sobrien int die_mark; 318450397Sobrien} 318550397Sobriendie_node; 318650397Sobrien 318750397Sobrien/* The pubname structure */ 318850397Sobrien 318950397Sobrientypedef struct pubname_struct 319050397Sobrien{ 319150397Sobrien dw_die_ref die; 319290075Sobrien char *name; 319350397Sobrien} 319450397Sobrienpubname_entry; 319550397Sobrien 319690075Sobrienstruct dw_ranges_struct 319790075Sobrien{ 319890075Sobrien int block_num; 319990075Sobrien}; 320090075Sobrien 320150397Sobrien/* The limbo die list structure. */ 320250397Sobrientypedef struct limbo_die_struct 320350397Sobrien{ 320450397Sobrien dw_die_ref die; 320590075Sobrien tree created_for; 320650397Sobrien struct limbo_die_struct *next; 320750397Sobrien} 320850397Sobrienlimbo_die_node; 320950397Sobrien 321050397Sobrien/* How to start an assembler comment. */ 321150397Sobrien#ifndef ASM_COMMENT_START 321250397Sobrien#define ASM_COMMENT_START ";#" 321350397Sobrien#endif 321450397Sobrien 321550397Sobrien/* Define a macro which returns non-zero for a TYPE_DECL which was 321650397Sobrien implicitly generated for a tagged type. 321750397Sobrien 321850397Sobrien Note that unlike the gcc front end (which generates a NULL named 321950397Sobrien TYPE_DECL node for each complete tagged type, each array type, and 322050397Sobrien each function type node created) the g++ front end generates a 322150397Sobrien _named_ TYPE_DECL node for each tagged type node created. 322250397Sobrien These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to 322350397Sobrien generate a DW_TAG_typedef DIE for them. */ 322450397Sobrien 322550397Sobrien#define TYPE_DECL_IS_STUB(decl) \ 322650397Sobrien (DECL_NAME (decl) == NULL_TREE \ 322750397Sobrien || (DECL_ARTIFICIAL (decl) \ 322850397Sobrien && is_tagged_type (TREE_TYPE (decl)) \ 322950397Sobrien && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \ 323050397Sobrien /* This is necessary for stub decls that \ 323150397Sobrien appear in nested inline functions. */ \ 323250397Sobrien || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \ 323350397Sobrien && (decl_ultimate_origin (decl) \ 323450397Sobrien == TYPE_STUB_DECL (TREE_TYPE (decl))))))) 323550397Sobrien 323650397Sobrien/* Information concerning the compilation unit's programming 323750397Sobrien language, and compiler version. */ 323850397Sobrien 323950397Sobrienextern int flag_traditional; 324050397Sobrien 324150397Sobrien/* Fixed size portion of the DWARF compilation unit header. */ 324250397Sobrien#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3) 324350397Sobrien 324450397Sobrien/* Fixed size portion of debugging line information prolog. */ 324550397Sobrien#define DWARF_LINE_PROLOG_HEADER_SIZE 5 324650397Sobrien 324750397Sobrien/* Fixed size portion of public names info. */ 324850397Sobrien#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2) 324950397Sobrien 325050397Sobrien/* Fixed size portion of the address range info. */ 325190075Sobrien#define DWARF_ARANGES_HEADER_SIZE \ 325290075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325390075Sobrien - DWARF_OFFSET_SIZE) 325450397Sobrien 325590075Sobrien/* Size of padding portion in the address range info. It must be 325690075Sobrien aligned to twice the pointer size. */ 325790075Sobrien#define DWARF_ARANGES_PAD_SIZE \ 325890075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325990075Sobrien - (2 * DWARF_OFFSET_SIZE + 4)) 326090075Sobrien 326190075Sobrien/* Use assembler line directives if available. */ 326290075Sobrien#ifndef DWARF2_ASM_LINE_DEBUG_INFO 326390075Sobrien#ifdef HAVE_AS_DWARF2_DEBUG_LINE 326490075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 1 326590075Sobrien#else 326690075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 0 326790075Sobrien#endif 326890075Sobrien#endif 326990075Sobrien 327050397Sobrien/* Minimum line offset in a special line info. opcode. 327150397Sobrien This value was chosen to give a reasonable range of values. */ 327250397Sobrien#define DWARF_LINE_BASE -10 327350397Sobrien 327490075Sobrien/* First special line opcode - leave room for the standard opcodes. */ 327550397Sobrien#define DWARF_LINE_OPCODE_BASE 10 327650397Sobrien 327750397Sobrien/* Range of line offsets in a special line info. opcode. */ 327850397Sobrien#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1) 327950397Sobrien 328050397Sobrien/* Flag that indicates the initial value of the is_stmt_start flag. 328150397Sobrien In the present implementation, we do not mark any lines as 328250397Sobrien the beginning of a source statement, because that information 328350397Sobrien is not made available by the GCC front-end. */ 328450397Sobrien#define DWARF_LINE_DEFAULT_IS_STMT_START 1 328550397Sobrien 328650397Sobrien/* This location is used by calc_die_sizes() to keep track 328750397Sobrien the offset of each DIE within the .debug_info section. */ 328850397Sobrienstatic unsigned long next_die_offset; 328950397Sobrien 329050397Sobrien/* Record the root of the DIE's built for the current compilation unit. */ 329150397Sobrienstatic dw_die_ref comp_unit_die; 329250397Sobrien 329350397Sobrien/* A list of DIEs with a NULL parent waiting to be relocated. */ 329450397Sobrienstatic limbo_die_node *limbo_die_list = 0; 329550397Sobrien 329690075Sobrien/* Structure used by lookup_filename to manage sets of filenames. */ 329790075Sobrienstruct file_table 329890075Sobrien{ 329990075Sobrien char **table; 330090075Sobrien unsigned allocated; 330190075Sobrien unsigned in_use; 330290075Sobrien unsigned last_lookup_index; 330390075Sobrien}; 330450397Sobrien 330550397Sobrien/* Size (in elements) of increments by which we may expand the filename 330650397Sobrien table. */ 330750397Sobrien#define FILE_TABLE_INCREMENT 64 330850397Sobrien 330990075Sobrien/* Filenames referenced by this compilation unit. */ 331090075Sobrienstatic struct file_table file_table; 331190075Sobrien 331250397Sobrien/* Local pointer to the name of the main input file. Initialized in 331350397Sobrien dwarf2out_init. */ 331490075Sobrienstatic const char *primary_filename; 331550397Sobrien 331650397Sobrien/* A pointer to the base of a table of references to DIE's that describe 331750397Sobrien declarations. The table is indexed by DECL_UID() which is a unique 331850397Sobrien number identifying each decl. */ 331950397Sobrienstatic dw_die_ref *decl_die_table; 332050397Sobrien 332150397Sobrien/* Number of elements currently allocated for the decl_die_table. */ 332250397Sobrienstatic unsigned decl_die_table_allocated; 332350397Sobrien 332450397Sobrien/* Number of elements in decl_die_table currently in use. */ 332550397Sobrienstatic unsigned decl_die_table_in_use; 332650397Sobrien 332750397Sobrien/* Size (in elements) of increments by which we may expand the 332850397Sobrien decl_die_table. */ 332950397Sobrien#define DECL_DIE_TABLE_INCREMENT 256 333050397Sobrien 333150397Sobrien/* A pointer to the base of a table of references to declaration 333250397Sobrien scopes. This table is a display which tracks the nesting 333350397Sobrien of declaration scopes at the current scope and containing 333450397Sobrien scopes. This table is used to find the proper place to 333550397Sobrien define type declaration DIE's. */ 333690075Sobrienvarray_type decl_scope_table; 333750397Sobrien 333850397Sobrien/* A pointer to the base of a list of references to DIE's that 333950397Sobrien are uniquely identified by their tag, presence/absence of 334050397Sobrien children DIE's, and list of attribute/value pairs. */ 334150397Sobrienstatic dw_die_ref *abbrev_die_table; 334250397Sobrien 334350397Sobrien/* Number of elements currently allocated for abbrev_die_table. */ 334450397Sobrienstatic unsigned abbrev_die_table_allocated; 334550397Sobrien 334650397Sobrien/* Number of elements in type_die_table currently in use. */ 334750397Sobrienstatic unsigned abbrev_die_table_in_use; 334850397Sobrien 334950397Sobrien/* Size (in elements) of increments by which we may expand the 335050397Sobrien abbrev_die_table. */ 335150397Sobrien#define ABBREV_DIE_TABLE_INCREMENT 256 335250397Sobrien 335350397Sobrien/* A pointer to the base of a table that contains line information 335450397Sobrien for each source code line in .text in the compilation unit. */ 335550397Sobrienstatic dw_line_info_ref line_info_table; 335650397Sobrien 335750397Sobrien/* Number of elements currently allocated for line_info_table. */ 335850397Sobrienstatic unsigned line_info_table_allocated; 335950397Sobrien 336050397Sobrien/* Number of elements in separate_line_info_table currently in use. */ 336150397Sobrienstatic unsigned separate_line_info_table_in_use; 336250397Sobrien 336350397Sobrien/* A pointer to the base of a table that contains line information 336450397Sobrien for each source code line outside of .text in the compilation unit. */ 336550397Sobrienstatic dw_separate_line_info_ref separate_line_info_table; 336650397Sobrien 336750397Sobrien/* Number of elements currently allocated for separate_line_info_table. */ 336850397Sobrienstatic unsigned separate_line_info_table_allocated; 336950397Sobrien 337050397Sobrien/* Number of elements in line_info_table currently in use. */ 337150397Sobrienstatic unsigned line_info_table_in_use; 337250397Sobrien 337350397Sobrien/* Size (in elements) of increments by which we may expand the 337450397Sobrien line_info_table. */ 337550397Sobrien#define LINE_INFO_TABLE_INCREMENT 1024 337650397Sobrien 337750397Sobrien/* A pointer to the base of a table that contains a list of publicly 337850397Sobrien accessible names. */ 337950397Sobrienstatic pubname_ref pubname_table; 338050397Sobrien 338150397Sobrien/* Number of elements currently allocated for pubname_table. */ 338250397Sobrienstatic unsigned pubname_table_allocated; 338350397Sobrien 338450397Sobrien/* Number of elements in pubname_table currently in use. */ 338550397Sobrienstatic unsigned pubname_table_in_use; 338650397Sobrien 338750397Sobrien/* Size (in elements) of increments by which we may expand the 338850397Sobrien pubname_table. */ 338950397Sobrien#define PUBNAME_TABLE_INCREMENT 64 339050397Sobrien 339190075Sobrien/* Array of dies for which we should generate .debug_arange info. */ 339290075Sobrienstatic dw_die_ref *arange_table; 339350397Sobrien 339450397Sobrien/* Number of elements currently allocated for arange_table. */ 339550397Sobrienstatic unsigned arange_table_allocated; 339650397Sobrien 339750397Sobrien/* Number of elements in arange_table currently in use. */ 339850397Sobrienstatic unsigned arange_table_in_use; 339950397Sobrien 340050397Sobrien/* Size (in elements) of increments by which we may expand the 340150397Sobrien arange_table. */ 340250397Sobrien#define ARANGE_TABLE_INCREMENT 64 340350397Sobrien 340490075Sobrien/* Array of dies for which we should generate .debug_ranges info. */ 340590075Sobrienstatic dw_ranges_ref ranges_table; 340650397Sobrien 340790075Sobrien/* Number of elements currently allocated for ranges_table. */ 340890075Sobrienstatic unsigned ranges_table_allocated; 340950397Sobrien 341090075Sobrien/* Number of elements in ranges_table currently in use. */ 341190075Sobrienstatic unsigned ranges_table_in_use; 341250397Sobrien 341390075Sobrien/* Size (in elements) of increments by which we may expand the 341490075Sobrien ranges_table. */ 341590075Sobrien#define RANGES_TABLE_INCREMENT 64 341650397Sobrien 341790075Sobrien/* Whether we have location lists that need outputting */ 341890075Sobrienstatic unsigned have_location_lists; 341950397Sobrien 342052284Sobrien/* A pointer to the base of a list of incomplete types which might be 342190075Sobrien completed at some later time. incomplete_types_list needs to be a VARRAY 342290075Sobrien because we want to tell the garbage collector about it. */ 342390075Sobrienvarray_type incomplete_types; 342452284Sobrien 342550397Sobrien/* Record whether the function being analyzed contains inlined functions. */ 342650397Sobrienstatic int current_function_has_inlines; 342750397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 342850397Sobrienstatic int comp_unit_has_inlines; 342950397Sobrien#endif 343050397Sobrien 343190075Sobrien/* Array of RTXes referenced by the debugging information, which therefore 343290075Sobrien must be kept around forever. This is a GC root. */ 343390075Sobrienstatic varray_type used_rtx_varray; 343450397Sobrien 343550397Sobrien/* Forward declarations for functions defined in this file. */ 343650397Sobrien 343790075Sobrienstatic int is_pseudo_reg PARAMS ((rtx)); 343890075Sobrienstatic tree type_main_variant PARAMS ((tree)); 343990075Sobrienstatic int is_tagged_type PARAMS ((tree)); 344090075Sobrienstatic const char *dwarf_tag_name PARAMS ((unsigned)); 344190075Sobrienstatic const char *dwarf_attr_name PARAMS ((unsigned)); 344290075Sobrienstatic const char *dwarf_form_name PARAMS ((unsigned)); 344350397Sobrien#if 0 344490075Sobrienstatic const char *dwarf_type_encoding_name PARAMS ((unsigned)); 344550397Sobrien#endif 344690075Sobrienstatic tree decl_ultimate_origin PARAMS ((tree)); 344790075Sobrienstatic tree block_ultimate_origin PARAMS ((tree)); 344890075Sobrienstatic tree decl_class_context PARAMS ((tree)); 344990075Sobrienstatic void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref)); 345090075Sobrienstatic inline dw_val_class AT_class PARAMS ((dw_attr_ref)); 345190075Sobrienstatic void add_AT_flag PARAMS ((dw_die_ref, 345290075Sobrien enum dwarf_attribute, 345390075Sobrien unsigned)); 345490075Sobrienstatic inline unsigned AT_flag PARAMS ((dw_attr_ref)); 345590075Sobrienstatic void add_AT_int PARAMS ((dw_die_ref, 345690075Sobrien enum dwarf_attribute, long)); 345790075Sobrienstatic inline long int AT_int PARAMS ((dw_attr_ref)); 345890075Sobrienstatic void add_AT_unsigned PARAMS ((dw_die_ref, 345990075Sobrien enum dwarf_attribute, 346090075Sobrien unsigned long)); 346190075Sobrienstatic inline unsigned long AT_unsigned PARAMS ((dw_attr_ref)); 346290075Sobrienstatic void add_AT_long_long PARAMS ((dw_die_ref, 346390075Sobrien enum dwarf_attribute, 346490075Sobrien unsigned long, 346590075Sobrien unsigned long)); 346690075Sobrienstatic void add_AT_float PARAMS ((dw_die_ref, 346790075Sobrien enum dwarf_attribute, 346890075Sobrien unsigned, long *)); 346990075Sobrienstatic void add_AT_string PARAMS ((dw_die_ref, 347090075Sobrien enum dwarf_attribute, 347190075Sobrien const char *)); 347290075Sobrienstatic inline const char *AT_string PARAMS ((dw_attr_ref)); 347390075Sobrienstatic int AT_string_form PARAMS ((dw_attr_ref)); 347490075Sobrienstatic void add_AT_die_ref PARAMS ((dw_die_ref, 347590075Sobrien enum dwarf_attribute, 347690075Sobrien dw_die_ref)); 347790075Sobrienstatic inline dw_die_ref AT_ref PARAMS ((dw_attr_ref)); 347890075Sobrienstatic inline int AT_ref_external PARAMS ((dw_attr_ref)); 347990075Sobrienstatic inline void set_AT_ref_external PARAMS ((dw_attr_ref, int)); 348090075Sobrienstatic void add_AT_fde_ref PARAMS ((dw_die_ref, 348190075Sobrien enum dwarf_attribute, 348290075Sobrien unsigned)); 348390075Sobrienstatic void add_AT_loc PARAMS ((dw_die_ref, 348490075Sobrien enum dwarf_attribute, 348590075Sobrien dw_loc_descr_ref)); 348690075Sobrienstatic inline dw_loc_descr_ref AT_loc PARAMS ((dw_attr_ref)); 348790075Sobrienstatic void add_AT_loc_list PARAMS ((dw_die_ref, 348890075Sobrien enum dwarf_attribute, 348990075Sobrien dw_loc_list_ref)); 349090075Sobrienstatic inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref)); 349190075Sobrienstatic void add_AT_addr PARAMS ((dw_die_ref, 349290075Sobrien enum dwarf_attribute, 349390075Sobrien rtx)); 349490075Sobrienstatic inline rtx AT_addr PARAMS ((dw_attr_ref)); 349590075Sobrienstatic void add_AT_lbl_id PARAMS ((dw_die_ref, 349690075Sobrien enum dwarf_attribute, 349790075Sobrien const char *)); 349890075Sobrienstatic void add_AT_lbl_offset PARAMS ((dw_die_ref, 349990075Sobrien enum dwarf_attribute, 350090075Sobrien const char *)); 350190075Sobrienstatic void add_AT_offset PARAMS ((dw_die_ref, 350290075Sobrien enum dwarf_attribute, 350390075Sobrien unsigned long)); 350490075Sobrienstatic void add_AT_range_list PARAMS ((dw_die_ref, 350590075Sobrien enum dwarf_attribute, 350690075Sobrien unsigned long)); 350790075Sobrienstatic inline const char *AT_lbl PARAMS ((dw_attr_ref)); 350890075Sobrienstatic dw_attr_ref get_AT PARAMS ((dw_die_ref, 350990075Sobrien enum dwarf_attribute)); 351090075Sobrienstatic const char *get_AT_low_pc PARAMS ((dw_die_ref)); 351190075Sobrienstatic const char *get_AT_hi_pc PARAMS ((dw_die_ref)); 351290075Sobrienstatic const char *get_AT_string PARAMS ((dw_die_ref, 351390075Sobrien enum dwarf_attribute)); 351490075Sobrienstatic int get_AT_flag PARAMS ((dw_die_ref, 351590075Sobrien enum dwarf_attribute)); 351690075Sobrienstatic unsigned get_AT_unsigned PARAMS ((dw_die_ref, 351790075Sobrien enum dwarf_attribute)); 351890075Sobrienstatic inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref, 351990075Sobrien enum dwarf_attribute)); 352090075Sobrienstatic int is_c_family PARAMS ((void)); 352190075Sobrienstatic int is_cxx PARAMS ((void)); 352290075Sobrienstatic int is_java PARAMS ((void)); 352390075Sobrienstatic int is_fortran PARAMS ((void)); 352490075Sobrienstatic void remove_AT PARAMS ((dw_die_ref, 352590075Sobrien enum dwarf_attribute)); 352690075Sobrienstatic inline void free_die PARAMS ((dw_die_ref)); 352790075Sobrienstatic void remove_children PARAMS ((dw_die_ref)); 352890075Sobrienstatic void add_child_die PARAMS ((dw_die_ref, dw_die_ref)); 352990075Sobrienstatic dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref, 353090075Sobrien tree)); 353190075Sobrienstatic dw_die_ref lookup_type_die PARAMS ((tree)); 353290075Sobrienstatic void equate_type_number_to_die PARAMS ((tree, dw_die_ref)); 353390075Sobrienstatic dw_die_ref lookup_decl_die PARAMS ((tree)); 353490075Sobrienstatic void equate_decl_number_to_die PARAMS ((tree, dw_die_ref)); 353590075Sobrienstatic void print_spaces PARAMS ((FILE *)); 353690075Sobrienstatic void print_die PARAMS ((dw_die_ref, FILE *)); 353790075Sobrienstatic void print_dwarf_line_table PARAMS ((FILE *)); 353890075Sobrienstatic void reverse_die_lists PARAMS ((dw_die_ref)); 353990075Sobrienstatic void reverse_all_dies PARAMS ((dw_die_ref)); 354090075Sobrienstatic dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref)); 354190075Sobrienstatic dw_die_ref pop_compile_unit PARAMS ((dw_die_ref)); 354290075Sobrienstatic void loc_checksum PARAMS ((dw_loc_descr_ref, 354390075Sobrien struct md5_ctx *)); 354490075Sobrienstatic void attr_checksum PARAMS ((dw_attr_ref, 354590075Sobrien struct md5_ctx *)); 354690075Sobrienstatic void die_checksum PARAMS ((dw_die_ref, 354790075Sobrien struct md5_ctx *)); 354890075Sobrienstatic void compute_section_prefix PARAMS ((dw_die_ref)); 354990075Sobrienstatic int is_type_die PARAMS ((dw_die_ref)); 355090075Sobrienstatic int is_comdat_die PARAMS ((dw_die_ref)); 355190075Sobrienstatic int is_symbol_die PARAMS ((dw_die_ref)); 355290075Sobrienstatic void assign_symbol_names PARAMS ((dw_die_ref)); 355390075Sobrienstatic void break_out_includes PARAMS ((dw_die_ref)); 355490075Sobrienstatic void add_sibling_attributes PARAMS ((dw_die_ref)); 355590075Sobrienstatic void build_abbrev_table PARAMS ((dw_die_ref)); 355690075Sobrienstatic void output_location_lists PARAMS ((dw_die_ref)); 355790075Sobrienstatic int constant_size PARAMS ((long unsigned)); 355890075Sobrienstatic unsigned long size_of_die PARAMS ((dw_die_ref)); 355990075Sobrienstatic void calc_die_sizes PARAMS ((dw_die_ref)); 356090075Sobrienstatic void mark_dies PARAMS ((dw_die_ref)); 356190075Sobrienstatic void unmark_dies PARAMS ((dw_die_ref)); 356290075Sobrienstatic unsigned long size_of_pubnames PARAMS ((void)); 356390075Sobrienstatic unsigned long size_of_aranges PARAMS ((void)); 356490075Sobrienstatic enum dwarf_form value_format PARAMS ((dw_attr_ref)); 356590075Sobrienstatic void output_value_format PARAMS ((dw_attr_ref)); 356690075Sobrienstatic void output_abbrev_section PARAMS ((void)); 356790075Sobrienstatic void output_die_symbol PARAMS ((dw_die_ref)); 356890075Sobrienstatic void output_die PARAMS ((dw_die_ref)); 356990075Sobrienstatic void output_compilation_unit_header PARAMS ((void)); 357090075Sobrienstatic void output_comp_unit PARAMS ((dw_die_ref)); 357190075Sobrienstatic const char *dwarf2_name PARAMS ((tree, int)); 357290075Sobrienstatic void add_pubname PARAMS ((tree, dw_die_ref)); 357390075Sobrienstatic void output_pubnames PARAMS ((void)); 357490075Sobrienstatic void add_arange PARAMS ((tree, dw_die_ref)); 357590075Sobrienstatic void output_aranges PARAMS ((void)); 357690075Sobrienstatic unsigned int add_ranges PARAMS ((tree)); 357790075Sobrienstatic void output_ranges PARAMS ((void)); 357890075Sobrienstatic void output_line_info PARAMS ((void)); 357990075Sobrienstatic void output_file_names PARAMS ((void)); 358090075Sobrienstatic dw_die_ref base_type_die PARAMS ((tree)); 358190075Sobrienstatic tree root_type PARAMS ((tree)); 358290075Sobrienstatic int is_base_type PARAMS ((tree)); 358390075Sobrienstatic dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref)); 358490075Sobrienstatic int type_is_enum PARAMS ((tree)); 358590075Sobrienstatic unsigned int reg_number PARAMS ((rtx)); 358690075Sobrienstatic dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx)); 358790075Sobrienstatic dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT)); 358890075Sobrienstatic dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long)); 358990075Sobrienstatic int is_based_loc PARAMS ((rtx)); 359090075Sobrienstatic dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode)); 359190075Sobrienstatic dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx)); 359290075Sobrienstatic dw_loc_descr_ref loc_descriptor PARAMS ((rtx)); 359390075Sobrienstatic dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int)); 359490075Sobrienstatic HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int)); 359590075Sobrienstatic tree field_type PARAMS ((tree)); 359690075Sobrienstatic unsigned int simple_type_align_in_bits PARAMS ((tree)); 359796263Sobrienstatic unsigned int simple_field_decl_align_in_bits PARAMS ((tree)); 359890075Sobrienstatic unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree)); 359990075Sobrienstatic HOST_WIDE_INT field_byte_offset PARAMS ((tree)); 360090075Sobrienstatic void add_AT_location_description PARAMS ((dw_die_ref, 360190075Sobrien enum dwarf_attribute, rtx)); 360290075Sobrienstatic void add_data_member_location_attribute PARAMS ((dw_die_ref, tree)); 360390075Sobrienstatic void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); 360490075Sobrienstatic rtx rtl_for_decl_location PARAMS ((tree)); 360590075Sobrienstatic void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree)); 360690075Sobrienstatic void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree)); 360790075Sobrienstatic void add_name_attribute PARAMS ((dw_die_ref, const char *)); 360890075Sobrienstatic void add_bound_info PARAMS ((dw_die_ref, 360990075Sobrien enum dwarf_attribute, tree)); 361090075Sobrienstatic void add_subscript_info PARAMS ((dw_die_ref, tree)); 361190075Sobrienstatic void add_byte_size_attribute PARAMS ((dw_die_ref, tree)); 361290075Sobrienstatic void add_bit_offset_attribute PARAMS ((dw_die_ref, tree)); 361390075Sobrienstatic void add_bit_size_attribute PARAMS ((dw_die_ref, tree)); 361490075Sobrienstatic void add_prototyped_attribute PARAMS ((dw_die_ref, tree)); 361590075Sobrienstatic void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree)); 361690075Sobrienstatic void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree)); 361790075Sobrienstatic void add_src_coords_attributes PARAMS ((dw_die_ref, tree)); 361890075Sobrienstatic void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree)); 361990075Sobrienstatic void push_decl_scope PARAMS ((tree)); 362090075Sobrienstatic void pop_decl_scope PARAMS ((void)); 362190075Sobrienstatic dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref)); 362290075Sobrienstatic inline int local_scope_p PARAMS ((dw_die_ref)); 362390075Sobrienstatic inline int class_scope_p PARAMS ((dw_die_ref)); 362490075Sobrienstatic void add_type_attribute PARAMS ((dw_die_ref, tree, int, int, 362590075Sobrien dw_die_ref)); 362690075Sobrienstatic const char *type_tag PARAMS ((tree)); 362790075Sobrienstatic tree member_declared_type PARAMS ((tree)); 362850397Sobrien#if 0 362990075Sobrienstatic const char *decl_start_label PARAMS ((tree)); 363050397Sobrien#endif 363190075Sobrienstatic void gen_array_type_die PARAMS ((tree, dw_die_ref)); 363290075Sobrienstatic void gen_set_type_die PARAMS ((tree, dw_die_ref)); 363350397Sobrien#if 0 363490075Sobrienstatic void gen_entry_point_die PARAMS ((tree, dw_die_ref)); 363550397Sobrien#endif 363690075Sobrienstatic void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref)); 363790075Sobrienstatic void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref)); 363890075Sobrienstatic void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref)); 363990075Sobrienstatic void gen_enumeration_type_die PARAMS ((tree, dw_die_ref)); 364090075Sobrienstatic dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref)); 364190075Sobrienstatic void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref)); 364290075Sobrienstatic void gen_formal_types_die PARAMS ((tree, dw_die_ref)); 364390075Sobrienstatic void gen_subprogram_die PARAMS ((tree, dw_die_ref)); 364490075Sobrienstatic void gen_variable_die PARAMS ((tree, dw_die_ref)); 364590075Sobrienstatic void gen_label_die PARAMS ((tree, dw_die_ref)); 364690075Sobrienstatic void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int)); 364790075Sobrienstatic void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int)); 364890075Sobrienstatic void gen_field_die PARAMS ((tree, dw_die_ref)); 364990075Sobrienstatic void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref)); 365090075Sobrienstatic dw_die_ref gen_compile_unit_die PARAMS ((const char *)); 365190075Sobrienstatic void gen_string_type_die PARAMS ((tree, dw_die_ref)); 365290075Sobrienstatic void gen_inheritance_die PARAMS ((tree, dw_die_ref)); 365390075Sobrienstatic void gen_member_die PARAMS ((tree, dw_die_ref)); 365490075Sobrienstatic void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref)); 365590075Sobrienstatic void gen_subroutine_type_die PARAMS ((tree, dw_die_ref)); 365690075Sobrienstatic void gen_typedef_die PARAMS ((tree, dw_die_ref)); 365790075Sobrienstatic void gen_type_die PARAMS ((tree, dw_die_ref)); 365890075Sobrienstatic void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref)); 365990075Sobrienstatic void gen_block_die PARAMS ((tree, dw_die_ref, int)); 366090075Sobrienstatic void decls_for_scope PARAMS ((tree, dw_die_ref, int)); 366190075Sobrienstatic int is_redundant_typedef PARAMS ((tree)); 366290075Sobrienstatic void gen_decl_die PARAMS ((tree, dw_die_ref)); 366390075Sobrienstatic unsigned lookup_filename PARAMS ((const char *)); 366490075Sobrienstatic void init_file_table PARAMS ((void)); 366590075Sobrienstatic void retry_incomplete_types PARAMS ((void)); 366690075Sobrienstatic void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); 366790075Sobrienstatic void splice_child_die PARAMS ((dw_die_ref, dw_die_ref)); 366890075Sobrienstatic int file_info_cmp PARAMS ((const void *, const void *)); 366990075Sobrienstatic dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref, 367090075Sobrien const char *, const char *, 367190075Sobrien const char *, unsigned)); 367290075Sobrienstatic void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *, 367390075Sobrien dw_loc_descr_ref, 367490075Sobrien const char *, const char *, const char *)); 367590075Sobrienstatic void output_loc_list PARAMS ((dw_loc_list_ref)); 367690075Sobrienstatic char *gen_internal_sym PARAMS ((const char *)); 367790075Sobrienstatic void mark_limbo_die_list PARAMS ((void *)); 367850397Sobrien 367950397Sobrien/* Section names used to hold DWARF debugging information. */ 368050397Sobrien#ifndef DEBUG_INFO_SECTION 368150397Sobrien#define DEBUG_INFO_SECTION ".debug_info" 368250397Sobrien#endif 368390075Sobrien#ifndef DEBUG_ABBREV_SECTION 368490075Sobrien#define DEBUG_ABBREV_SECTION ".debug_abbrev" 368550397Sobrien#endif 368690075Sobrien#ifndef DEBUG_ARANGES_SECTION 368790075Sobrien#define DEBUG_ARANGES_SECTION ".debug_aranges" 368850397Sobrien#endif 368990075Sobrien#ifndef DEBUG_MACINFO_SECTION 369090075Sobrien#define DEBUG_MACINFO_SECTION ".debug_macinfo" 369150397Sobrien#endif 369250397Sobrien#ifndef DEBUG_LINE_SECTION 369350397Sobrien#define DEBUG_LINE_SECTION ".debug_line" 369450397Sobrien#endif 369590075Sobrien#ifndef DEBUG_LOC_SECTION 369690075Sobrien#define DEBUG_LOC_SECTION ".debug_loc" 369750397Sobrien#endif 369890075Sobrien#ifndef DEBUG_PUBNAMES_SECTION 369990075Sobrien#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" 370050397Sobrien#endif 370190075Sobrien#ifndef DEBUG_STR_SECTION 370290075Sobrien#define DEBUG_STR_SECTION ".debug_str" 370350397Sobrien#endif 370490075Sobrien#ifndef DEBUG_RANGES_SECTION 370590075Sobrien#define DEBUG_RANGES_SECTION ".debug_ranges" 370690075Sobrien#endif 370750397Sobrien 370850397Sobrien/* Standard ELF section names for compiled code and data. */ 370990075Sobrien#ifndef TEXT_SECTION_NAME 371090075Sobrien#define TEXT_SECTION_NAME ".text" 371150397Sobrien#endif 371290075Sobrien 371390075Sobrien/* Section flags for .debug_str section. */ 371490075Sobrien#ifdef HAVE_GAS_SHF_MERGE 371590075Sobrien#define DEBUG_STR_SECTION_FLAGS \ 371690075Sobrien (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1) 371790075Sobrien#else 371890075Sobrien#define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG 371950397Sobrien#endif 372050397Sobrien 372152284Sobrien/* Labels we insert at beginning sections we can reference instead of 372290075Sobrien the section names themselves. */ 372350397Sobrien 372452284Sobrien#ifndef TEXT_SECTION_LABEL 372590075Sobrien#define TEXT_SECTION_LABEL "Ltext" 372652284Sobrien#endif 372752284Sobrien#ifndef DEBUG_LINE_SECTION_LABEL 372890075Sobrien#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" 372952284Sobrien#endif 373052284Sobrien#ifndef DEBUG_INFO_SECTION_LABEL 373190075Sobrien#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" 373252284Sobrien#endif 373390075Sobrien#ifndef DEBUG_ABBREV_SECTION_LABEL 373490075Sobrien#define DEBUG_ABBREV_SECTION_LABEL "Ldebug_abbrev" 373552284Sobrien#endif 373690075Sobrien#ifndef DEBUG_LOC_SECTION_LABEL 373790075Sobrien#define DEBUG_LOC_SECTION_LABEL "Ldebug_loc" 373890075Sobrien#endif 373990075Sobrien#ifndef DEBUG_RANGES_SECTION_LABEL 374090075Sobrien#define DEBUG_RANGES_SECTION_LABEL "Ldebug_ranges" 374190075Sobrien#endif 374290075Sobrien#ifndef DEBUG_MACINFO_SECTION_LABEL 374390075Sobrien#define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo" 374490075Sobrien#endif 374552284Sobrien 374650397Sobrien/* Definitions of defaults for formats and names of various special 374750397Sobrien (artificial) labels which may be generated within this file (when the -g 374850397Sobrien options is used and DWARF_DEBUGGING_INFO is in effect. 374950397Sobrien If necessary, these may be overridden from within the tm.h file, but 375050397Sobrien typically, overriding these defaults is unnecessary. */ 375150397Sobrien 375250397Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375352284Sobrienstatic char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375452284Sobrienstatic char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375552284Sobrienstatic char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375652284Sobrienstatic char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375790075Sobrienstatic char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375890075Sobrienstatic char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 375990075Sobrienstatic char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; 376050397Sobrien 376150397Sobrien#ifndef TEXT_END_LABEL 376250397Sobrien#define TEXT_END_LABEL "Letext" 376350397Sobrien#endif 376450397Sobrien#ifndef DATA_END_LABEL 376550397Sobrien#define DATA_END_LABEL "Ledata" 376650397Sobrien#endif 376750397Sobrien#ifndef BSS_END_LABEL 376850397Sobrien#define BSS_END_LABEL "Lebss" 376950397Sobrien#endif 377050397Sobrien#ifndef BLOCK_BEGIN_LABEL 377150397Sobrien#define BLOCK_BEGIN_LABEL "LBB" 377250397Sobrien#endif 377350397Sobrien#ifndef BLOCK_END_LABEL 377450397Sobrien#define BLOCK_END_LABEL "LBE" 377550397Sobrien#endif 377650397Sobrien#ifndef BODY_BEGIN_LABEL 377750397Sobrien#define BODY_BEGIN_LABEL "Lbb" 377850397Sobrien#endif 377950397Sobrien#ifndef BODY_END_LABEL 378050397Sobrien#define BODY_END_LABEL "Lbe" 378150397Sobrien#endif 378250397Sobrien#ifndef LINE_CODE_LABEL 378350397Sobrien#define LINE_CODE_LABEL "LM" 378450397Sobrien#endif 378550397Sobrien#ifndef SEPARATE_LINE_CODE_LABEL 378650397Sobrien#define SEPARATE_LINE_CODE_LABEL "LSM" 378750397Sobrien#endif 378850397Sobrien 378990075Sobrien/* We allow a language front-end to designate a function that is to be 379090075Sobrien called to "demangle" any name before it it put into a DIE. */ 379150397Sobrien 379290075Sobrienstatic const char *(*demangle_name_func) PARAMS ((const char *)); 379350397Sobrien 379490075Sobrienvoid 379590075Sobriendwarf2out_set_demangle_name_func (func) 379690075Sobrien const char *(*func) PARAMS ((const char *)); 379750397Sobrien{ 379890075Sobrien demangle_name_func = func; 379950397Sobrien} 380050397Sobrien 380150397Sobrien/* Test if rtl node points to a pseudo register. */ 380250397Sobrien 380350397Sobrienstatic inline int 380450397Sobrienis_pseudo_reg (rtl) 380590075Sobrien rtx rtl; 380650397Sobrien{ 380790075Sobrien return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 380890075Sobrien || (GET_CODE (rtl) == SUBREG 380990075Sobrien && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)); 381050397Sobrien} 381150397Sobrien 381250397Sobrien/* Return a reference to a type, with its const and volatile qualifiers 381350397Sobrien removed. */ 381450397Sobrien 381550397Sobrienstatic inline tree 381650397Sobrientype_main_variant (type) 381790075Sobrien tree type; 381850397Sobrien{ 381950397Sobrien type = TYPE_MAIN_VARIANT (type); 382050397Sobrien 382190075Sobrien /* ??? There really should be only one main variant among any group of 382290075Sobrien variants of a given type (and all of the MAIN_VARIANT values for all 382390075Sobrien members of the group should point to that one type) but sometimes the C 382490075Sobrien front-end messes this up for array types, so we work around that bug 382590075Sobrien here. */ 382650397Sobrien if (TREE_CODE (type) == ARRAY_TYPE) 382750397Sobrien while (type != TYPE_MAIN_VARIANT (type)) 382850397Sobrien type = TYPE_MAIN_VARIANT (type); 382950397Sobrien 383050397Sobrien return type; 383150397Sobrien} 383250397Sobrien 383350397Sobrien/* Return non-zero if the given type node represents a tagged type. */ 383450397Sobrien 383550397Sobrienstatic inline int 383650397Sobrienis_tagged_type (type) 383790075Sobrien tree type; 383850397Sobrien{ 383990075Sobrien enum tree_code code = TREE_CODE (type); 384050397Sobrien 384150397Sobrien return (code == RECORD_TYPE || code == UNION_TYPE 384250397Sobrien || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE); 384350397Sobrien} 384450397Sobrien 384550397Sobrien/* Convert a DIE tag into its string name. */ 384650397Sobrien 384790075Sobrienstatic const char * 384850397Sobriendwarf_tag_name (tag) 384990075Sobrien unsigned tag; 385050397Sobrien{ 385150397Sobrien switch (tag) 385250397Sobrien { 385350397Sobrien case DW_TAG_padding: 385450397Sobrien return "DW_TAG_padding"; 385550397Sobrien case DW_TAG_array_type: 385650397Sobrien return "DW_TAG_array_type"; 385750397Sobrien case DW_TAG_class_type: 385850397Sobrien return "DW_TAG_class_type"; 385950397Sobrien case DW_TAG_entry_point: 386050397Sobrien return "DW_TAG_entry_point"; 386150397Sobrien case DW_TAG_enumeration_type: 386250397Sobrien return "DW_TAG_enumeration_type"; 386350397Sobrien case DW_TAG_formal_parameter: 386450397Sobrien return "DW_TAG_formal_parameter"; 386550397Sobrien case DW_TAG_imported_declaration: 386650397Sobrien return "DW_TAG_imported_declaration"; 386750397Sobrien case DW_TAG_label: 386850397Sobrien return "DW_TAG_label"; 386950397Sobrien case DW_TAG_lexical_block: 387050397Sobrien return "DW_TAG_lexical_block"; 387150397Sobrien case DW_TAG_member: 387250397Sobrien return "DW_TAG_member"; 387350397Sobrien case DW_TAG_pointer_type: 387450397Sobrien return "DW_TAG_pointer_type"; 387550397Sobrien case DW_TAG_reference_type: 387650397Sobrien return "DW_TAG_reference_type"; 387750397Sobrien case DW_TAG_compile_unit: 387850397Sobrien return "DW_TAG_compile_unit"; 387950397Sobrien case DW_TAG_string_type: 388050397Sobrien return "DW_TAG_string_type"; 388150397Sobrien case DW_TAG_structure_type: 388250397Sobrien return "DW_TAG_structure_type"; 388350397Sobrien case DW_TAG_subroutine_type: 388450397Sobrien return "DW_TAG_subroutine_type"; 388550397Sobrien case DW_TAG_typedef: 388650397Sobrien return "DW_TAG_typedef"; 388750397Sobrien case DW_TAG_union_type: 388850397Sobrien return "DW_TAG_union_type"; 388950397Sobrien case DW_TAG_unspecified_parameters: 389050397Sobrien return "DW_TAG_unspecified_parameters"; 389150397Sobrien case DW_TAG_variant: 389250397Sobrien return "DW_TAG_variant"; 389350397Sobrien case DW_TAG_common_block: 389450397Sobrien return "DW_TAG_common_block"; 389550397Sobrien case DW_TAG_common_inclusion: 389650397Sobrien return "DW_TAG_common_inclusion"; 389750397Sobrien case DW_TAG_inheritance: 389850397Sobrien return "DW_TAG_inheritance"; 389950397Sobrien case DW_TAG_inlined_subroutine: 390050397Sobrien return "DW_TAG_inlined_subroutine"; 390150397Sobrien case DW_TAG_module: 390250397Sobrien return "DW_TAG_module"; 390350397Sobrien case DW_TAG_ptr_to_member_type: 390450397Sobrien return "DW_TAG_ptr_to_member_type"; 390550397Sobrien case DW_TAG_set_type: 390650397Sobrien return "DW_TAG_set_type"; 390750397Sobrien case DW_TAG_subrange_type: 390850397Sobrien return "DW_TAG_subrange_type"; 390950397Sobrien case DW_TAG_with_stmt: 391050397Sobrien return "DW_TAG_with_stmt"; 391150397Sobrien case DW_TAG_access_declaration: 391250397Sobrien return "DW_TAG_access_declaration"; 391350397Sobrien case DW_TAG_base_type: 391450397Sobrien return "DW_TAG_base_type"; 391550397Sobrien case DW_TAG_catch_block: 391650397Sobrien return "DW_TAG_catch_block"; 391750397Sobrien case DW_TAG_const_type: 391850397Sobrien return "DW_TAG_const_type"; 391950397Sobrien case DW_TAG_constant: 392050397Sobrien return "DW_TAG_constant"; 392150397Sobrien case DW_TAG_enumerator: 392250397Sobrien return "DW_TAG_enumerator"; 392350397Sobrien case DW_TAG_file_type: 392450397Sobrien return "DW_TAG_file_type"; 392550397Sobrien case DW_TAG_friend: 392650397Sobrien return "DW_TAG_friend"; 392750397Sobrien case DW_TAG_namelist: 392850397Sobrien return "DW_TAG_namelist"; 392950397Sobrien case DW_TAG_namelist_item: 393050397Sobrien return "DW_TAG_namelist_item"; 393150397Sobrien case DW_TAG_packed_type: 393250397Sobrien return "DW_TAG_packed_type"; 393350397Sobrien case DW_TAG_subprogram: 393450397Sobrien return "DW_TAG_subprogram"; 393550397Sobrien case DW_TAG_template_type_param: 393650397Sobrien return "DW_TAG_template_type_param"; 393750397Sobrien case DW_TAG_template_value_param: 393850397Sobrien return "DW_TAG_template_value_param"; 393950397Sobrien case DW_TAG_thrown_type: 394050397Sobrien return "DW_TAG_thrown_type"; 394150397Sobrien case DW_TAG_try_block: 394250397Sobrien return "DW_TAG_try_block"; 394350397Sobrien case DW_TAG_variant_part: 394450397Sobrien return "DW_TAG_variant_part"; 394550397Sobrien case DW_TAG_variable: 394650397Sobrien return "DW_TAG_variable"; 394750397Sobrien case DW_TAG_volatile_type: 394850397Sobrien return "DW_TAG_volatile_type"; 394950397Sobrien case DW_TAG_MIPS_loop: 395050397Sobrien return "DW_TAG_MIPS_loop"; 395150397Sobrien case DW_TAG_format_label: 395250397Sobrien return "DW_TAG_format_label"; 395350397Sobrien case DW_TAG_function_template: 395450397Sobrien return "DW_TAG_function_template"; 395550397Sobrien case DW_TAG_class_template: 395650397Sobrien return "DW_TAG_class_template"; 395790075Sobrien case DW_TAG_GNU_BINCL: 395890075Sobrien return "DW_TAG_GNU_BINCL"; 395990075Sobrien case DW_TAG_GNU_EINCL: 396090075Sobrien return "DW_TAG_GNU_EINCL"; 396150397Sobrien default: 396250397Sobrien return "DW_TAG_<unknown>"; 396350397Sobrien } 396450397Sobrien} 396550397Sobrien 396650397Sobrien/* Convert a DWARF attribute code into its string name. */ 396750397Sobrien 396890075Sobrienstatic const char * 396950397Sobriendwarf_attr_name (attr) 397090075Sobrien unsigned attr; 397150397Sobrien{ 397250397Sobrien switch (attr) 397350397Sobrien { 397450397Sobrien case DW_AT_sibling: 397550397Sobrien return "DW_AT_sibling"; 397650397Sobrien case DW_AT_location: 397750397Sobrien return "DW_AT_location"; 397850397Sobrien case DW_AT_name: 397950397Sobrien return "DW_AT_name"; 398050397Sobrien case DW_AT_ordering: 398150397Sobrien return "DW_AT_ordering"; 398250397Sobrien case DW_AT_subscr_data: 398350397Sobrien return "DW_AT_subscr_data"; 398450397Sobrien case DW_AT_byte_size: 398550397Sobrien return "DW_AT_byte_size"; 398650397Sobrien case DW_AT_bit_offset: 398750397Sobrien return "DW_AT_bit_offset"; 398850397Sobrien case DW_AT_bit_size: 398950397Sobrien return "DW_AT_bit_size"; 399050397Sobrien case DW_AT_element_list: 399150397Sobrien return "DW_AT_element_list"; 399250397Sobrien case DW_AT_stmt_list: 399350397Sobrien return "DW_AT_stmt_list"; 399450397Sobrien case DW_AT_low_pc: 399550397Sobrien return "DW_AT_low_pc"; 399650397Sobrien case DW_AT_high_pc: 399750397Sobrien return "DW_AT_high_pc"; 399850397Sobrien case DW_AT_language: 399950397Sobrien return "DW_AT_language"; 400050397Sobrien case DW_AT_member: 400150397Sobrien return "DW_AT_member"; 400250397Sobrien case DW_AT_discr: 400350397Sobrien return "DW_AT_discr"; 400450397Sobrien case DW_AT_discr_value: 400550397Sobrien return "DW_AT_discr_value"; 400650397Sobrien case DW_AT_visibility: 400750397Sobrien return "DW_AT_visibility"; 400850397Sobrien case DW_AT_import: 400950397Sobrien return "DW_AT_import"; 401050397Sobrien case DW_AT_string_length: 401150397Sobrien return "DW_AT_string_length"; 401250397Sobrien case DW_AT_common_reference: 401350397Sobrien return "DW_AT_common_reference"; 401450397Sobrien case DW_AT_comp_dir: 401550397Sobrien return "DW_AT_comp_dir"; 401650397Sobrien case DW_AT_const_value: 401750397Sobrien return "DW_AT_const_value"; 401850397Sobrien case DW_AT_containing_type: 401950397Sobrien return "DW_AT_containing_type"; 402050397Sobrien case DW_AT_default_value: 402150397Sobrien return "DW_AT_default_value"; 402250397Sobrien case DW_AT_inline: 402350397Sobrien return "DW_AT_inline"; 402450397Sobrien case DW_AT_is_optional: 402550397Sobrien return "DW_AT_is_optional"; 402650397Sobrien case DW_AT_lower_bound: 402750397Sobrien return "DW_AT_lower_bound"; 402850397Sobrien case DW_AT_producer: 402950397Sobrien return "DW_AT_producer"; 403050397Sobrien case DW_AT_prototyped: 403150397Sobrien return "DW_AT_prototyped"; 403250397Sobrien case DW_AT_return_addr: 403350397Sobrien return "DW_AT_return_addr"; 403450397Sobrien case DW_AT_start_scope: 403550397Sobrien return "DW_AT_start_scope"; 403650397Sobrien case DW_AT_stride_size: 403750397Sobrien return "DW_AT_stride_size"; 403850397Sobrien case DW_AT_upper_bound: 403950397Sobrien return "DW_AT_upper_bound"; 404050397Sobrien case DW_AT_abstract_origin: 404150397Sobrien return "DW_AT_abstract_origin"; 404250397Sobrien case DW_AT_accessibility: 404350397Sobrien return "DW_AT_accessibility"; 404450397Sobrien case DW_AT_address_class: 404550397Sobrien return "DW_AT_address_class"; 404650397Sobrien case DW_AT_artificial: 404750397Sobrien return "DW_AT_artificial"; 404850397Sobrien case DW_AT_base_types: 404950397Sobrien return "DW_AT_base_types"; 405050397Sobrien case DW_AT_calling_convention: 405150397Sobrien return "DW_AT_calling_convention"; 405250397Sobrien case DW_AT_count: 405350397Sobrien return "DW_AT_count"; 405450397Sobrien case DW_AT_data_member_location: 405550397Sobrien return "DW_AT_data_member_location"; 405650397Sobrien case DW_AT_decl_column: 405750397Sobrien return "DW_AT_decl_column"; 405850397Sobrien case DW_AT_decl_file: 405950397Sobrien return "DW_AT_decl_file"; 406050397Sobrien case DW_AT_decl_line: 406150397Sobrien return "DW_AT_decl_line"; 406250397Sobrien case DW_AT_declaration: 406350397Sobrien return "DW_AT_declaration"; 406450397Sobrien case DW_AT_discr_list: 406550397Sobrien return "DW_AT_discr_list"; 406650397Sobrien case DW_AT_encoding: 406750397Sobrien return "DW_AT_encoding"; 406850397Sobrien case DW_AT_external: 406950397Sobrien return "DW_AT_external"; 407050397Sobrien case DW_AT_frame_base: 407150397Sobrien return "DW_AT_frame_base"; 407250397Sobrien case DW_AT_friend: 407350397Sobrien return "DW_AT_friend"; 407450397Sobrien case DW_AT_identifier_case: 407550397Sobrien return "DW_AT_identifier_case"; 407650397Sobrien case DW_AT_macro_info: 407750397Sobrien return "DW_AT_macro_info"; 407850397Sobrien case DW_AT_namelist_items: 407950397Sobrien return "DW_AT_namelist_items"; 408050397Sobrien case DW_AT_priority: 408150397Sobrien return "DW_AT_priority"; 408250397Sobrien case DW_AT_segment: 408350397Sobrien return "DW_AT_segment"; 408450397Sobrien case DW_AT_specification: 408550397Sobrien return "DW_AT_specification"; 408650397Sobrien case DW_AT_static_link: 408750397Sobrien return "DW_AT_static_link"; 408850397Sobrien case DW_AT_type: 408950397Sobrien return "DW_AT_type"; 409050397Sobrien case DW_AT_use_location: 409150397Sobrien return "DW_AT_use_location"; 409250397Sobrien case DW_AT_variable_parameter: 409350397Sobrien return "DW_AT_variable_parameter"; 409450397Sobrien case DW_AT_virtuality: 409550397Sobrien return "DW_AT_virtuality"; 409650397Sobrien case DW_AT_vtable_elem_location: 409750397Sobrien return "DW_AT_vtable_elem_location"; 409850397Sobrien 409990075Sobrien case DW_AT_allocated: 410090075Sobrien return "DW_AT_allocated"; 410190075Sobrien case DW_AT_associated: 410290075Sobrien return "DW_AT_associated"; 410390075Sobrien case DW_AT_data_location: 410490075Sobrien return "DW_AT_data_location"; 410590075Sobrien case DW_AT_stride: 410690075Sobrien return "DW_AT_stride"; 410790075Sobrien case DW_AT_entry_pc: 410890075Sobrien return "DW_AT_entry_pc"; 410990075Sobrien case DW_AT_use_UTF8: 411090075Sobrien return "DW_AT_use_UTF8"; 411190075Sobrien case DW_AT_extension: 411290075Sobrien return "DW_AT_extension"; 411390075Sobrien case DW_AT_ranges: 411490075Sobrien return "DW_AT_ranges"; 411590075Sobrien case DW_AT_trampoline: 411690075Sobrien return "DW_AT_trampoline"; 411790075Sobrien case DW_AT_call_column: 411890075Sobrien return "DW_AT_call_column"; 411990075Sobrien case DW_AT_call_file: 412090075Sobrien return "DW_AT_call_file"; 412190075Sobrien case DW_AT_call_line: 412290075Sobrien return "DW_AT_call_line"; 412390075Sobrien 412450397Sobrien case DW_AT_MIPS_fde: 412550397Sobrien return "DW_AT_MIPS_fde"; 412650397Sobrien case DW_AT_MIPS_loop_begin: 412750397Sobrien return "DW_AT_MIPS_loop_begin"; 412850397Sobrien case DW_AT_MIPS_tail_loop_begin: 412950397Sobrien return "DW_AT_MIPS_tail_loop_begin"; 413050397Sobrien case DW_AT_MIPS_epilog_begin: 413150397Sobrien return "DW_AT_MIPS_epilog_begin"; 413250397Sobrien case DW_AT_MIPS_loop_unroll_factor: 413350397Sobrien return "DW_AT_MIPS_loop_unroll_factor"; 413450397Sobrien case DW_AT_MIPS_software_pipeline_depth: 413550397Sobrien return "DW_AT_MIPS_software_pipeline_depth"; 413650397Sobrien case DW_AT_MIPS_linkage_name: 413750397Sobrien return "DW_AT_MIPS_linkage_name"; 413850397Sobrien case DW_AT_MIPS_stride: 413950397Sobrien return "DW_AT_MIPS_stride"; 414050397Sobrien case DW_AT_MIPS_abstract_name: 414150397Sobrien return "DW_AT_MIPS_abstract_name"; 414250397Sobrien case DW_AT_MIPS_clone_origin: 414350397Sobrien return "DW_AT_MIPS_clone_origin"; 414450397Sobrien case DW_AT_MIPS_has_inlines: 414550397Sobrien return "DW_AT_MIPS_has_inlines"; 414650397Sobrien 414750397Sobrien case DW_AT_sf_names: 414850397Sobrien return "DW_AT_sf_names"; 414950397Sobrien case DW_AT_src_info: 415050397Sobrien return "DW_AT_src_info"; 415150397Sobrien case DW_AT_mac_info: 415250397Sobrien return "DW_AT_mac_info"; 415350397Sobrien case DW_AT_src_coords: 415450397Sobrien return "DW_AT_src_coords"; 415550397Sobrien case DW_AT_body_begin: 415650397Sobrien return "DW_AT_body_begin"; 415750397Sobrien case DW_AT_body_end: 415850397Sobrien return "DW_AT_body_end"; 415996263Sobrien case DW_AT_GNU_vector: 416096263Sobrien return "DW_AT_GNU_vector"; 416196263Sobrien 416290075Sobrien case DW_AT_VMS_rtnbeg_pd_address: 416390075Sobrien return "DW_AT_VMS_rtnbeg_pd_address"; 416490075Sobrien 416550397Sobrien default: 416650397Sobrien return "DW_AT_<unknown>"; 416750397Sobrien } 416850397Sobrien} 416950397Sobrien 417050397Sobrien/* Convert a DWARF value form code into its string name. */ 417150397Sobrien 417290075Sobrienstatic const char * 417350397Sobriendwarf_form_name (form) 417490075Sobrien unsigned form; 417550397Sobrien{ 417650397Sobrien switch (form) 417750397Sobrien { 417850397Sobrien case DW_FORM_addr: 417950397Sobrien return "DW_FORM_addr"; 418050397Sobrien case DW_FORM_block2: 418150397Sobrien return "DW_FORM_block2"; 418250397Sobrien case DW_FORM_block4: 418350397Sobrien return "DW_FORM_block4"; 418450397Sobrien case DW_FORM_data2: 418550397Sobrien return "DW_FORM_data2"; 418650397Sobrien case DW_FORM_data4: 418750397Sobrien return "DW_FORM_data4"; 418850397Sobrien case DW_FORM_data8: 418950397Sobrien return "DW_FORM_data8"; 419050397Sobrien case DW_FORM_string: 419150397Sobrien return "DW_FORM_string"; 419250397Sobrien case DW_FORM_block: 419350397Sobrien return "DW_FORM_block"; 419450397Sobrien case DW_FORM_block1: 419550397Sobrien return "DW_FORM_block1"; 419650397Sobrien case DW_FORM_data1: 419750397Sobrien return "DW_FORM_data1"; 419850397Sobrien case DW_FORM_flag: 419950397Sobrien return "DW_FORM_flag"; 420050397Sobrien case DW_FORM_sdata: 420150397Sobrien return "DW_FORM_sdata"; 420250397Sobrien case DW_FORM_strp: 420350397Sobrien return "DW_FORM_strp"; 420450397Sobrien case DW_FORM_udata: 420550397Sobrien return "DW_FORM_udata"; 420650397Sobrien case DW_FORM_ref_addr: 420750397Sobrien return "DW_FORM_ref_addr"; 420850397Sobrien case DW_FORM_ref1: 420950397Sobrien return "DW_FORM_ref1"; 421050397Sobrien case DW_FORM_ref2: 421150397Sobrien return "DW_FORM_ref2"; 421250397Sobrien case DW_FORM_ref4: 421350397Sobrien return "DW_FORM_ref4"; 421450397Sobrien case DW_FORM_ref8: 421550397Sobrien return "DW_FORM_ref8"; 421650397Sobrien case DW_FORM_ref_udata: 421750397Sobrien return "DW_FORM_ref_udata"; 421850397Sobrien case DW_FORM_indirect: 421950397Sobrien return "DW_FORM_indirect"; 422050397Sobrien default: 422150397Sobrien return "DW_FORM_<unknown>"; 422250397Sobrien } 422350397Sobrien} 422450397Sobrien 422550397Sobrien/* Convert a DWARF type code into its string name. */ 422650397Sobrien 422750397Sobrien#if 0 422890075Sobrienstatic const char * 422950397Sobriendwarf_type_encoding_name (enc) 423090075Sobrien unsigned enc; 423150397Sobrien{ 423250397Sobrien switch (enc) 423350397Sobrien { 423450397Sobrien case DW_ATE_address: 423550397Sobrien return "DW_ATE_address"; 423650397Sobrien case DW_ATE_boolean: 423750397Sobrien return "DW_ATE_boolean"; 423850397Sobrien case DW_ATE_complex_float: 423950397Sobrien return "DW_ATE_complex_float"; 424050397Sobrien case DW_ATE_float: 424150397Sobrien return "DW_ATE_float"; 424250397Sobrien case DW_ATE_signed: 424350397Sobrien return "DW_ATE_signed"; 424450397Sobrien case DW_ATE_signed_char: 424550397Sobrien return "DW_ATE_signed_char"; 424650397Sobrien case DW_ATE_unsigned: 424750397Sobrien return "DW_ATE_unsigned"; 424850397Sobrien case DW_ATE_unsigned_char: 424950397Sobrien return "DW_ATE_unsigned_char"; 425050397Sobrien default: 425150397Sobrien return "DW_ATE_<unknown>"; 425250397Sobrien } 425350397Sobrien} 425450397Sobrien#endif 425550397Sobrien 425650397Sobrien/* Determine the "ultimate origin" of a decl. The decl may be an inlined 425750397Sobrien instance of an inlined instance of a decl which is local to an inline 425850397Sobrien function, so we have to trace all of the way back through the origin chain 425950397Sobrien to find out what sort of node actually served as the original seed for the 426050397Sobrien given block. */ 426150397Sobrien 426250397Sobrienstatic tree 426350397Sobriendecl_ultimate_origin (decl) 426490075Sobrien tree decl; 426550397Sobrien{ 426690075Sobrien /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the 426790075Sobrien nodes in the function to point to themselves; ignore that if 426890075Sobrien we're trying to output the abstract instance of this function. */ 426990075Sobrien if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl) 427090075Sobrien return NULL_TREE; 427190075Sobrien 427290075Sobrien#ifdef ENABLE_CHECKING 427352284Sobrien if (DECL_FROM_INLINE (DECL_ORIGIN (decl))) 427452284Sobrien /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the 427552284Sobrien most distant ancestor, this should never happen. */ 427652284Sobrien abort (); 427752284Sobrien#endif 427850397Sobrien 427952284Sobrien return DECL_ABSTRACT_ORIGIN (decl); 428050397Sobrien} 428150397Sobrien 428250397Sobrien/* Determine the "ultimate origin" of a block. The block may be an inlined 428350397Sobrien instance of an inlined instance of a block which is local to an inline 428450397Sobrien function, so we have to trace all of the way back through the origin chain 428550397Sobrien to find out what sort of node actually served as the original seed for the 428650397Sobrien given block. */ 428750397Sobrien 428850397Sobrienstatic tree 428950397Sobrienblock_ultimate_origin (block) 429090075Sobrien tree block; 429150397Sobrien{ 429290075Sobrien tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); 429350397Sobrien 429490075Sobrien /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the 429590075Sobrien nodes in the function to point to themselves; ignore that if 429690075Sobrien we're trying to output the abstract instance of this function. */ 429790075Sobrien if (BLOCK_ABSTRACT (block) && immediate_origin == block) 429890075Sobrien return NULL_TREE; 429990075Sobrien 430050397Sobrien if (immediate_origin == NULL_TREE) 430150397Sobrien return NULL_TREE; 430250397Sobrien else 430350397Sobrien { 430490075Sobrien tree ret_val; 430590075Sobrien tree lookahead = immediate_origin; 430650397Sobrien 430750397Sobrien do 430850397Sobrien { 430950397Sobrien ret_val = lookahead; 431090075Sobrien lookahead = (TREE_CODE (ret_val) == BLOCK 431190075Sobrien ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL); 431250397Sobrien } 431350397Sobrien while (lookahead != NULL && lookahead != ret_val); 431450397Sobrien 431550397Sobrien return ret_val; 431650397Sobrien } 431750397Sobrien} 431850397Sobrien 431950397Sobrien/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT 432050397Sobrien of a virtual function may refer to a base class, so we check the 'this' 432150397Sobrien parameter. */ 432250397Sobrien 432350397Sobrienstatic tree 432450397Sobriendecl_class_context (decl) 432550397Sobrien tree decl; 432650397Sobrien{ 432750397Sobrien tree context = NULL_TREE; 432850397Sobrien 432950397Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl)) 433050397Sobrien context = DECL_CONTEXT (decl); 433150397Sobrien else 433250397Sobrien context = TYPE_MAIN_VARIANT 433350397Sobrien (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); 433450397Sobrien 433590075Sobrien if (context && !TYPE_P (context)) 433650397Sobrien context = NULL_TREE; 433750397Sobrien 433850397Sobrien return context; 433950397Sobrien} 434050397Sobrien 434190075Sobrien/* Add an attribute/value pair to a DIE. We build the lists up in reverse 434290075Sobrien addition order, and correct that in reverse_all_dies. */ 434350397Sobrien 434450397Sobrienstatic inline void 434550397Sobrienadd_dwarf_attr (die, attr) 434690075Sobrien dw_die_ref die; 434790075Sobrien dw_attr_ref attr; 434850397Sobrien{ 434950397Sobrien if (die != NULL && attr != NULL) 435050397Sobrien { 435190075Sobrien attr->dw_attr_next = die->die_attr; 435290075Sobrien die->die_attr = attr; 435350397Sobrien } 435450397Sobrien} 435550397Sobrien 435690075Sobrienstatic inline dw_val_class 435790075SobrienAT_class (a) 435890075Sobrien dw_attr_ref a; 435990075Sobrien{ 436090075Sobrien return a->dw_attr_val.val_class; 436190075Sobrien} 436290075Sobrien 436350397Sobrien/* Add a flag value attribute to a DIE. */ 436450397Sobrien 436550397Sobrienstatic inline void 436650397Sobrienadd_AT_flag (die, attr_kind, flag) 436790075Sobrien dw_die_ref die; 436890075Sobrien enum dwarf_attribute attr_kind; 436990075Sobrien unsigned flag; 437050397Sobrien{ 437190075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 437250397Sobrien 437350397Sobrien attr->dw_attr_next = NULL; 437450397Sobrien attr->dw_attr = attr_kind; 437550397Sobrien attr->dw_attr_val.val_class = dw_val_class_flag; 437650397Sobrien attr->dw_attr_val.v.val_flag = flag; 437750397Sobrien add_dwarf_attr (die, attr); 437850397Sobrien} 437950397Sobrien 438090075Sobrienstatic inline unsigned 438190075SobrienAT_flag (a) 438290075Sobrien dw_attr_ref a; 438390075Sobrien{ 438490075Sobrien if (a && AT_class (a) == dw_val_class_flag) 438590075Sobrien return a->dw_attr_val.v.val_flag; 438690075Sobrien 438790075Sobrien abort (); 438890075Sobrien} 438990075Sobrien 439050397Sobrien/* Add a signed integer attribute value to a DIE. */ 439150397Sobrien 439250397Sobrienstatic inline void 439350397Sobrienadd_AT_int (die, attr_kind, int_val) 439490075Sobrien dw_die_ref die; 439590075Sobrien enum dwarf_attribute attr_kind; 439690075Sobrien long int int_val; 439750397Sobrien{ 439890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 439950397Sobrien 440050397Sobrien attr->dw_attr_next = NULL; 440150397Sobrien attr->dw_attr = attr_kind; 440250397Sobrien attr->dw_attr_val.val_class = dw_val_class_const; 440350397Sobrien attr->dw_attr_val.v.val_int = int_val; 440450397Sobrien add_dwarf_attr (die, attr); 440550397Sobrien} 440650397Sobrien 440790075Sobrienstatic inline long int 440890075SobrienAT_int (a) 440990075Sobrien dw_attr_ref a; 441090075Sobrien{ 441190075Sobrien if (a && AT_class (a) == dw_val_class_const) 441290075Sobrien return a->dw_attr_val.v.val_int; 441390075Sobrien 441490075Sobrien abort (); 441590075Sobrien} 441690075Sobrien 441750397Sobrien/* Add an unsigned integer attribute value to a DIE. */ 441850397Sobrien 441950397Sobrienstatic inline void 442050397Sobrienadd_AT_unsigned (die, attr_kind, unsigned_val) 442190075Sobrien dw_die_ref die; 442290075Sobrien enum dwarf_attribute attr_kind; 442390075Sobrien unsigned long unsigned_val; 442450397Sobrien{ 442590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 442650397Sobrien 442750397Sobrien attr->dw_attr_next = NULL; 442850397Sobrien attr->dw_attr = attr_kind; 442950397Sobrien attr->dw_attr_val.val_class = dw_val_class_unsigned_const; 443050397Sobrien attr->dw_attr_val.v.val_unsigned = unsigned_val; 443150397Sobrien add_dwarf_attr (die, attr); 443250397Sobrien} 443350397Sobrien 443490075Sobrienstatic inline unsigned long 443590075SobrienAT_unsigned (a) 443690075Sobrien dw_attr_ref a; 443790075Sobrien{ 443890075Sobrien if (a && AT_class (a) == dw_val_class_unsigned_const) 443990075Sobrien return a->dw_attr_val.v.val_unsigned; 444090075Sobrien 444190075Sobrien abort (); 444290075Sobrien} 444390075Sobrien 444450397Sobrien/* Add an unsigned double integer attribute value to a DIE. */ 444550397Sobrien 444650397Sobrienstatic inline void 444750397Sobrienadd_AT_long_long (die, attr_kind, val_hi, val_low) 444890075Sobrien dw_die_ref die; 444990075Sobrien enum dwarf_attribute attr_kind; 445090075Sobrien unsigned long val_hi; 445190075Sobrien unsigned long val_low; 445250397Sobrien{ 445390075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 445450397Sobrien 445550397Sobrien attr->dw_attr_next = NULL; 445650397Sobrien attr->dw_attr = attr_kind; 445750397Sobrien attr->dw_attr_val.val_class = dw_val_class_long_long; 445850397Sobrien attr->dw_attr_val.v.val_long_long.hi = val_hi; 445950397Sobrien attr->dw_attr_val.v.val_long_long.low = val_low; 446050397Sobrien add_dwarf_attr (die, attr); 446150397Sobrien} 446250397Sobrien 446350397Sobrien/* Add a floating point attribute value to a DIE and return it. */ 446450397Sobrien 446550397Sobrienstatic inline void 446650397Sobrienadd_AT_float (die, attr_kind, length, array) 446790075Sobrien dw_die_ref die; 446890075Sobrien enum dwarf_attribute attr_kind; 446990075Sobrien unsigned length; 447090075Sobrien long *array; 447150397Sobrien{ 447290075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 447350397Sobrien 447450397Sobrien attr->dw_attr_next = NULL; 447550397Sobrien attr->dw_attr = attr_kind; 447650397Sobrien attr->dw_attr_val.val_class = dw_val_class_float; 447750397Sobrien attr->dw_attr_val.v.val_float.length = length; 447850397Sobrien attr->dw_attr_val.v.val_float.array = array; 447950397Sobrien add_dwarf_attr (die, attr); 448050397Sobrien} 448150397Sobrien 448250397Sobrien/* Add a string attribute value to a DIE. */ 448350397Sobrien 448450397Sobrienstatic inline void 448550397Sobrienadd_AT_string (die, attr_kind, str) 448690075Sobrien dw_die_ref die; 448790075Sobrien enum dwarf_attribute attr_kind; 448890075Sobrien const char *str; 448950397Sobrien{ 449090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 449190075Sobrien struct indirect_string_node *node; 449290075Sobrien 449390075Sobrien if (! debug_str_hash) 449490075Sobrien { 449590075Sobrien debug_str_hash = ht_create (10); 449690075Sobrien debug_str_hash->alloc_node = indirect_string_alloc; 449790075Sobrien } 449850397Sobrien 449990075Sobrien node = (struct indirect_string_node *) 450090075Sobrien ht_lookup (debug_str_hash, (const unsigned char *) str, 450190075Sobrien strlen (str), HT_ALLOC); 450290075Sobrien node->refcount++; 450390075Sobrien 450450397Sobrien attr->dw_attr_next = NULL; 450550397Sobrien attr->dw_attr = attr_kind; 450650397Sobrien attr->dw_attr_val.val_class = dw_val_class_str; 450790075Sobrien attr->dw_attr_val.v.val_str = node; 450850397Sobrien add_dwarf_attr (die, attr); 450950397Sobrien} 451050397Sobrien 451190075Sobrienstatic inline const char * 451290075SobrienAT_string (a) 451390075Sobrien dw_attr_ref a; 451490075Sobrien{ 451590075Sobrien if (a && AT_class (a) == dw_val_class_str) 451690075Sobrien return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id); 451790075Sobrien 451890075Sobrien abort (); 451990075Sobrien} 452090075Sobrien 452190075Sobrien/* Find out whether a string should be output inline in DIE 452290075Sobrien or out-of-line in .debug_str section. */ 452390075Sobrien 452490075Sobrienstatic int 452590075SobrienAT_string_form (a) 452690075Sobrien dw_attr_ref a; 452790075Sobrien{ 452890075Sobrien if (a && AT_class (a) == dw_val_class_str) 452990075Sobrien { 453090075Sobrien struct indirect_string_node *node; 453190075Sobrien unsigned int len; 453290075Sobrien extern int const_labelno; 453390075Sobrien char label[32]; 453490075Sobrien 453590075Sobrien node = a->dw_attr_val.v.val_str; 453690075Sobrien if (node->form) 453790075Sobrien return node->form; 453890075Sobrien 453990075Sobrien len = HT_LEN (&node->id) + 1; 454090075Sobrien 454190075Sobrien /* If the string is shorter or equal to the size of the reference, it is 454290075Sobrien always better to put it inline. */ 454390075Sobrien if (len <= DWARF_OFFSET_SIZE || node->refcount == 0) 454490075Sobrien return node->form = DW_FORM_string; 454590075Sobrien 454690075Sobrien /* If we cannot expect the linker to merge strings in .debug_str 454790075Sobrien section, only put it into .debug_str if it is worth even in this 454890075Sobrien single module. */ 454990075Sobrien if ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0 455090075Sobrien && (len - DWARF_OFFSET_SIZE) * node->refcount <= len) 455190075Sobrien return node->form = DW_FORM_string; 455290075Sobrien 455390075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); 455490075Sobrien ++const_labelno; 455590075Sobrien node->label = xstrdup (label); 455690075Sobrien 455790075Sobrien return node->form = DW_FORM_strp; 455890075Sobrien } 455990075Sobrien 456090075Sobrien abort (); 456190075Sobrien} 456290075Sobrien 456350397Sobrien/* Add a DIE reference attribute value to a DIE. */ 456450397Sobrien 456550397Sobrienstatic inline void 456650397Sobrienadd_AT_die_ref (die, attr_kind, targ_die) 456790075Sobrien dw_die_ref die; 456890075Sobrien enum dwarf_attribute attr_kind; 456990075Sobrien dw_die_ref targ_die; 457050397Sobrien{ 457190075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 457250397Sobrien 457350397Sobrien attr->dw_attr_next = NULL; 457450397Sobrien attr->dw_attr = attr_kind; 457550397Sobrien attr->dw_attr_val.val_class = dw_val_class_die_ref; 457690075Sobrien attr->dw_attr_val.v.val_die_ref.die = targ_die; 457790075Sobrien attr->dw_attr_val.v.val_die_ref.external = 0; 457850397Sobrien add_dwarf_attr (die, attr); 457950397Sobrien} 458050397Sobrien 458190075Sobrienstatic inline dw_die_ref 458290075SobrienAT_ref (a) 458390075Sobrien dw_attr_ref a; 458490075Sobrien{ 458590075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 458690075Sobrien return a->dw_attr_val.v.val_die_ref.die; 458790075Sobrien 458890075Sobrien abort (); 458990075Sobrien} 459090075Sobrien 459190075Sobrienstatic inline int 459290075SobrienAT_ref_external (a) 459390075Sobrien dw_attr_ref a; 459490075Sobrien{ 459590075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 459690075Sobrien return a->dw_attr_val.v.val_die_ref.external; 459790075Sobrien 459890075Sobrien return 0; 459990075Sobrien} 460090075Sobrien 460190075Sobrienstatic inline void 460290075Sobrienset_AT_ref_external (a, i) 460390075Sobrien dw_attr_ref a; 460490075Sobrien int i; 460590075Sobrien{ 460690075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 460790075Sobrien a->dw_attr_val.v.val_die_ref.external = i; 460890075Sobrien else 460990075Sobrien abort (); 461090075Sobrien} 461190075Sobrien 461250397Sobrien/* Add an FDE reference attribute value to a DIE. */ 461350397Sobrien 461450397Sobrienstatic inline void 461550397Sobrienadd_AT_fde_ref (die, attr_kind, targ_fde) 461690075Sobrien dw_die_ref die; 461790075Sobrien enum dwarf_attribute attr_kind; 461890075Sobrien unsigned targ_fde; 461950397Sobrien{ 462090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 462150397Sobrien 462250397Sobrien attr->dw_attr_next = NULL; 462350397Sobrien attr->dw_attr = attr_kind; 462450397Sobrien attr->dw_attr_val.val_class = dw_val_class_fde_ref; 462550397Sobrien attr->dw_attr_val.v.val_fde_index = targ_fde; 462650397Sobrien add_dwarf_attr (die, attr); 462750397Sobrien} 462850397Sobrien 462950397Sobrien/* Add a location description attribute value to a DIE. */ 463050397Sobrien 463150397Sobrienstatic inline void 463250397Sobrienadd_AT_loc (die, attr_kind, loc) 463390075Sobrien dw_die_ref die; 463490075Sobrien enum dwarf_attribute attr_kind; 463590075Sobrien dw_loc_descr_ref loc; 463650397Sobrien{ 463790075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 463850397Sobrien 463950397Sobrien attr->dw_attr_next = NULL; 464050397Sobrien attr->dw_attr = attr_kind; 464150397Sobrien attr->dw_attr_val.val_class = dw_val_class_loc; 464250397Sobrien attr->dw_attr_val.v.val_loc = loc; 464350397Sobrien add_dwarf_attr (die, attr); 464450397Sobrien} 464550397Sobrien 464690075Sobrienstatic inline dw_loc_descr_ref 464790075SobrienAT_loc (a) 464890075Sobrien dw_attr_ref a; 464990075Sobrien{ 465090075Sobrien if (a && AT_class (a) == dw_val_class_loc) 465190075Sobrien return a->dw_attr_val.v.val_loc; 465290075Sobrien 465390075Sobrien abort (); 465490075Sobrien} 465590075Sobrien 465690075Sobrienstatic inline void 465790075Sobrienadd_AT_loc_list (die, attr_kind, loc_list) 465890075Sobrien dw_die_ref die; 465990075Sobrien enum dwarf_attribute attr_kind; 466090075Sobrien dw_loc_list_ref loc_list; 466190075Sobrien{ 466290075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 466390075Sobrien 466490075Sobrien attr->dw_attr_next = NULL; 466590075Sobrien attr->dw_attr = attr_kind; 466690075Sobrien attr->dw_attr_val.val_class = dw_val_class_loc_list; 466790075Sobrien attr->dw_attr_val.v.val_loc_list = loc_list; 466890075Sobrien add_dwarf_attr (die, attr); 466990075Sobrien have_location_lists = 1; 467090075Sobrien} 467190075Sobrien 467290075Sobrienstatic inline dw_loc_list_ref 467390075SobrienAT_loc_list (a) 467490075Sobrien dw_attr_ref a; 467590075Sobrien{ 467690075Sobrien if (a && AT_class (a) == dw_val_class_loc_list) 467790075Sobrien return a->dw_attr_val.v.val_loc_list; 467890075Sobrien 467990075Sobrien abort (); 468090075Sobrien} 468190075Sobrien 468250397Sobrien/* Add an address constant attribute value to a DIE. */ 468350397Sobrien 468450397Sobrienstatic inline void 468550397Sobrienadd_AT_addr (die, attr_kind, addr) 468690075Sobrien dw_die_ref die; 468790075Sobrien enum dwarf_attribute attr_kind; 468890075Sobrien rtx addr; 468950397Sobrien{ 469090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 469150397Sobrien 469250397Sobrien attr->dw_attr_next = NULL; 469350397Sobrien attr->dw_attr = attr_kind; 469450397Sobrien attr->dw_attr_val.val_class = dw_val_class_addr; 469550397Sobrien attr->dw_attr_val.v.val_addr = addr; 469650397Sobrien add_dwarf_attr (die, attr); 469750397Sobrien} 469850397Sobrien 469990075Sobrienstatic inline rtx 470090075SobrienAT_addr (a) 470190075Sobrien dw_attr_ref a; 470290075Sobrien{ 470390075Sobrien if (a && AT_class (a) == dw_val_class_addr) 470490075Sobrien return a->dw_attr_val.v.val_addr; 470590075Sobrien 470690075Sobrien abort (); 470790075Sobrien} 470890075Sobrien 470950397Sobrien/* Add a label identifier attribute value to a DIE. */ 471050397Sobrien 471150397Sobrienstatic inline void 471250397Sobrienadd_AT_lbl_id (die, attr_kind, lbl_id) 471390075Sobrien dw_die_ref die; 471490075Sobrien enum dwarf_attribute attr_kind; 471590075Sobrien const char *lbl_id; 471650397Sobrien{ 471790075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 471850397Sobrien 471950397Sobrien attr->dw_attr_next = NULL; 472050397Sobrien attr->dw_attr = attr_kind; 472150397Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_id; 472250397Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); 472350397Sobrien add_dwarf_attr (die, attr); 472450397Sobrien} 472550397Sobrien 472650397Sobrien/* Add a section offset attribute value to a DIE. */ 472750397Sobrien 472850397Sobrienstatic inline void 472952284Sobrienadd_AT_lbl_offset (die, attr_kind, label) 473090075Sobrien dw_die_ref die; 473190075Sobrien enum dwarf_attribute attr_kind; 473290075Sobrien const char *label; 473350397Sobrien{ 473490075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 473550397Sobrien 473650397Sobrien attr->dw_attr_next = NULL; 473750397Sobrien attr->dw_attr = attr_kind; 473852284Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_offset; 473990075Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (label); 474050397Sobrien add_dwarf_attr (die, attr); 474150397Sobrien} 474250397Sobrien 474390075Sobrien/* Add an offset attribute value to a DIE. */ 474450397Sobrien 474590075Sobrienstatic inline void 474690075Sobrienadd_AT_offset (die, attr_kind, offset) 474790075Sobrien dw_die_ref die; 474890075Sobrien enum dwarf_attribute attr_kind; 474990075Sobrien unsigned long offset; 475050397Sobrien{ 475190075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 475250397Sobrien 475390075Sobrien attr->dw_attr_next = NULL; 475490075Sobrien attr->dw_attr = attr_kind; 475590075Sobrien attr->dw_attr_val.val_class = dw_val_class_offset; 475690075Sobrien attr->dw_attr_val.v.val_offset = offset; 475790075Sobrien add_dwarf_attr (die, attr); 475890075Sobrien} 475950397Sobrien 476090075Sobrien/* Add an range_list attribute value to a DIE. */ 476190075Sobrien 476290075Sobrienstatic void 476390075Sobrienadd_AT_range_list (die, attr_kind, offset) 476490075Sobrien dw_die_ref die; 476590075Sobrien enum dwarf_attribute attr_kind; 476690075Sobrien unsigned long offset; 476790075Sobrien{ 476890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 476990075Sobrien 477090075Sobrien attr->dw_attr_next = NULL; 477190075Sobrien attr->dw_attr = attr_kind; 477290075Sobrien attr->dw_attr_val.val_class = dw_val_class_range_list; 477390075Sobrien attr->dw_attr_val.v.val_offset = offset; 477490075Sobrien add_dwarf_attr (die, attr); 477550397Sobrien} 477650397Sobrien 477790075Sobrienstatic inline const char * 477890075SobrienAT_lbl (a) 477990075Sobrien dw_attr_ref a; 478090075Sobrien{ 478190075Sobrien if (a && (AT_class (a) == dw_val_class_lbl_id 478290075Sobrien || AT_class (a) == dw_val_class_lbl_offset)) 478390075Sobrien return a->dw_attr_val.v.val_lbl_id; 478490075Sobrien 478590075Sobrien abort (); 478690075Sobrien} 478790075Sobrien 478850397Sobrien/* Get the attribute of type attr_kind. */ 478950397Sobrien 479050397Sobrienstatic inline dw_attr_ref 479150397Sobrienget_AT (die, attr_kind) 479290075Sobrien dw_die_ref die; 479390075Sobrien enum dwarf_attribute attr_kind; 479450397Sobrien{ 479590075Sobrien dw_attr_ref a; 479690075Sobrien dw_die_ref spec = NULL; 479790075Sobrien 479850397Sobrien if (die != NULL) 479950397Sobrien { 480050397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 480190075Sobrien if (a->dw_attr == attr_kind) 480290075Sobrien return a; 480390075Sobrien else if (a->dw_attr == DW_AT_specification 480490075Sobrien || a->dw_attr == DW_AT_abstract_origin) 480590075Sobrien spec = AT_ref (a); 480650397Sobrien 480750397Sobrien if (spec) 480850397Sobrien return get_AT (spec, attr_kind); 480950397Sobrien } 481050397Sobrien 481150397Sobrien return NULL; 481250397Sobrien} 481350397Sobrien 481490075Sobrien/* Return the "low pc" attribute value, typically associated with a subprogram 481590075Sobrien DIE. Return null if the "low pc" attribute is either not present, or if it 481690075Sobrien cannot be represented as an assembler label identifier. */ 481750397Sobrien 481890075Sobrienstatic inline const char * 481950397Sobrienget_AT_low_pc (die) 482090075Sobrien dw_die_ref die; 482150397Sobrien{ 482290075Sobrien dw_attr_ref a = get_AT (die, DW_AT_low_pc); 482350397Sobrien 482490075Sobrien return a ? AT_lbl (a) : NULL; 482550397Sobrien} 482650397Sobrien 482790075Sobrien/* Return the "high pc" attribute value, typically associated with a subprogram 482890075Sobrien DIE. Return null if the "high pc" attribute is either not present, or if it 482990075Sobrien cannot be represented as an assembler label identifier. */ 483050397Sobrien 483190075Sobrienstatic inline const char * 483250397Sobrienget_AT_hi_pc (die) 483390075Sobrien dw_die_ref die; 483450397Sobrien{ 483590075Sobrien dw_attr_ref a = get_AT (die, DW_AT_high_pc); 483650397Sobrien 483790075Sobrien return a ? AT_lbl (a) : NULL; 483850397Sobrien} 483950397Sobrien 484050397Sobrien/* Return the value of the string attribute designated by ATTR_KIND, or 484150397Sobrien NULL if it is not present. */ 484250397Sobrien 484390075Sobrienstatic inline const char * 484450397Sobrienget_AT_string (die, attr_kind) 484590075Sobrien dw_die_ref die; 484690075Sobrien enum dwarf_attribute attr_kind; 484750397Sobrien{ 484890075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 484950397Sobrien 485090075Sobrien return a ? AT_string (a) : NULL; 485150397Sobrien} 485250397Sobrien 485350397Sobrien/* Return the value of the flag attribute designated by ATTR_KIND, or -1 485450397Sobrien if it is not present. */ 485550397Sobrien 485650397Sobrienstatic inline int 485750397Sobrienget_AT_flag (die, attr_kind) 485890075Sobrien dw_die_ref die; 485990075Sobrien enum dwarf_attribute attr_kind; 486050397Sobrien{ 486190075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 486250397Sobrien 486390075Sobrien return a ? AT_flag (a) : 0; 486450397Sobrien} 486550397Sobrien 486650397Sobrien/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0 486750397Sobrien if it is not present. */ 486850397Sobrien 486950397Sobrienstatic inline unsigned 487050397Sobrienget_AT_unsigned (die, attr_kind) 487190075Sobrien dw_die_ref die; 487290075Sobrien enum dwarf_attribute attr_kind; 487350397Sobrien{ 487490075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 487550397Sobrien 487690075Sobrien return a ? AT_unsigned (a) : 0; 487790075Sobrien} 487850397Sobrien 487990075Sobrienstatic inline dw_die_ref 488090075Sobrienget_AT_ref (die, attr_kind) 488190075Sobrien dw_die_ref die; 488290075Sobrien enum dwarf_attribute attr_kind; 488390075Sobrien{ 488490075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 488590075Sobrien 488690075Sobrien return a ? AT_ref (a) : NULL; 488750397Sobrien} 488850397Sobrien 488950397Sobrienstatic inline int 489050397Sobrienis_c_family () 489150397Sobrien{ 489290075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 489350397Sobrien 489450397Sobrien return (lang == DW_LANG_C || lang == DW_LANG_C89 489550397Sobrien || lang == DW_LANG_C_plus_plus); 489690075Sobrien} 489750397Sobrien 489850397Sobrienstatic inline int 489990075Sobrienis_cxx () 490090075Sobrien{ 490190075Sobrien return (get_AT_unsigned (comp_unit_die, DW_AT_language) 490290075Sobrien == DW_LANG_C_plus_plus); 490390075Sobrien} 490490075Sobrien 490590075Sobrienstatic inline int 490650397Sobrienis_fortran () 490750397Sobrien{ 490890075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 490950397Sobrien 491050397Sobrien return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90); 491190075Sobrien} 491250397Sobrien 491390075Sobrienstatic inline int 491490075Sobrienis_java () 491590075Sobrien{ 491690075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 491790075Sobrien 491890075Sobrien return (lang == DW_LANG_Java); 491990075Sobrien} 492090075Sobrien 492190075Sobrien/* Free up the memory used by A. */ 492290075Sobrien 492390075Sobrienstatic inline void free_AT PARAMS ((dw_attr_ref)); 492490075Sobrienstatic inline void 492590075Sobrienfree_AT (a) 492690075Sobrien dw_attr_ref a; 492790075Sobrien{ 492890075Sobrien switch (AT_class (a)) 492990075Sobrien { 493090075Sobrien case dw_val_class_str: 493190075Sobrien if (a->dw_attr_val.v.val_str->refcount) 493290075Sobrien a->dw_attr_val.v.val_str->refcount--; 493390075Sobrien break; 493490075Sobrien 493590075Sobrien case dw_val_class_lbl_id: 493690075Sobrien case dw_val_class_lbl_offset: 493790075Sobrien free (a->dw_attr_val.v.val_lbl_id); 493890075Sobrien break; 493990075Sobrien 494090075Sobrien case dw_val_class_float: 494190075Sobrien free (a->dw_attr_val.v.val_float.array); 494290075Sobrien break; 494390075Sobrien 494490075Sobrien default: 494590075Sobrien break; 494690075Sobrien } 494790075Sobrien 494890075Sobrien free (a); 494990075Sobrien} 495090075Sobrien 495150397Sobrien/* Remove the specified attribute if present. */ 495250397Sobrien 495390075Sobrienstatic void 495450397Sobrienremove_AT (die, attr_kind) 495590075Sobrien dw_die_ref die; 495690075Sobrien enum dwarf_attribute attr_kind; 495750397Sobrien{ 495890075Sobrien dw_attr_ref *p; 495990075Sobrien dw_attr_ref removed = NULL; 496050397Sobrien 496150397Sobrien if (die != NULL) 496250397Sobrien { 496390075Sobrien for (p = &(die->die_attr); *p; p = &((*p)->dw_attr_next)) 496490075Sobrien if ((*p)->dw_attr == attr_kind) 496590075Sobrien { 496690075Sobrien removed = *p; 496790075Sobrien *p = (*p)->dw_attr_next; 496890075Sobrien break; 496990075Sobrien } 497050397Sobrien 497150397Sobrien if (removed != 0) 497290075Sobrien free_AT (removed); 497350397Sobrien } 497450397Sobrien} 497550397Sobrien 497690075Sobrien/* Free up the memory used by DIE. */ 497790075Sobrien 497890075Sobrienstatic inline void 497990075Sobrienfree_die (die) 498090075Sobrien dw_die_ref die; 498190075Sobrien{ 498290075Sobrien remove_children (die); 498390075Sobrien free (die); 498490075Sobrien} 498590075Sobrien 498650397Sobrien/* Discard the children of this DIE. */ 498750397Sobrien 498890075Sobrienstatic void 498950397Sobrienremove_children (die) 499090075Sobrien dw_die_ref die; 499150397Sobrien{ 499290075Sobrien dw_die_ref child_die = die->die_child; 499350397Sobrien 499450397Sobrien die->die_child = NULL; 499550397Sobrien 499650397Sobrien while (child_die != NULL) 499750397Sobrien { 499890075Sobrien dw_die_ref tmp_die = child_die; 499990075Sobrien dw_attr_ref a; 500050397Sobrien 500150397Sobrien child_die = child_die->die_sib; 500290075Sobrien 500390075Sobrien for (a = tmp_die->die_attr; a != NULL;) 500450397Sobrien { 500590075Sobrien dw_attr_ref tmp_a = a; 500650397Sobrien 500750397Sobrien a = a->dw_attr_next; 500890075Sobrien free_AT (tmp_a); 500950397Sobrien } 501050397Sobrien 501190075Sobrien free_die (tmp_die); 501250397Sobrien } 501350397Sobrien} 501450397Sobrien 501590075Sobrien/* Add a child DIE below its parent. We build the lists up in reverse 501690075Sobrien addition order, and correct that in reverse_all_dies. */ 501750397Sobrien 501850397Sobrienstatic inline void 501950397Sobrienadd_child_die (die, child_die) 502090075Sobrien dw_die_ref die; 502190075Sobrien dw_die_ref child_die; 502250397Sobrien{ 502350397Sobrien if (die != NULL && child_die != NULL) 502450397Sobrien { 502550397Sobrien if (die == child_die) 502650397Sobrien abort (); 502790075Sobrien 502850397Sobrien child_die->die_parent = die; 502990075Sobrien child_die->die_sib = die->die_child; 503090075Sobrien die->die_child = child_die; 503190075Sobrien } 503290075Sobrien} 503350397Sobrien 503490075Sobrien/* Move CHILD, which must be a child of PARENT or the DIE for which PARENT 503590075Sobrien is the specification, to the front of PARENT's list of children. */ 503690075Sobrien 503790075Sobrienstatic void 503890075Sobriensplice_child_die (parent, child) 503990075Sobrien dw_die_ref parent, child; 504090075Sobrien{ 504190075Sobrien dw_die_ref *p; 504290075Sobrien 504390075Sobrien /* We want the declaration DIE from inside the class, not the 504490075Sobrien specification DIE at toplevel. */ 504590075Sobrien if (child->die_parent != parent) 504690075Sobrien { 504790075Sobrien dw_die_ref tmp = get_AT_ref (child, DW_AT_specification); 504890075Sobrien 504990075Sobrien if (tmp) 505090075Sobrien child = tmp; 505150397Sobrien } 505290075Sobrien 505390075Sobrien if (child->die_parent != parent 505490075Sobrien && child->die_parent != get_AT_ref (parent, DW_AT_specification)) 505590075Sobrien abort (); 505690075Sobrien 505790075Sobrien for (p = &(child->die_parent->die_child); *p; p = &((*p)->die_sib)) 505890075Sobrien if (*p == child) 505990075Sobrien { 506090075Sobrien *p = child->die_sib; 506190075Sobrien break; 506290075Sobrien } 506390075Sobrien 506490075Sobrien child->die_sib = parent->die_child; 506590075Sobrien parent->die_child = child; 506650397Sobrien} 506750397Sobrien 506850397Sobrien/* Return a pointer to a newly created DIE node. */ 506950397Sobrien 507050397Sobrienstatic inline dw_die_ref 507190075Sobriennew_die (tag_value, parent_die, t) 507290075Sobrien enum dwarf_tag tag_value; 507390075Sobrien dw_die_ref parent_die; 507490075Sobrien tree t; 507550397Sobrien{ 507690075Sobrien dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node)); 507750397Sobrien 507850397Sobrien die->die_tag = tag_value; 507950397Sobrien 508050397Sobrien if (parent_die != NULL) 508150397Sobrien add_child_die (parent_die, die); 508250397Sobrien else 508350397Sobrien { 508450397Sobrien limbo_die_node *limbo_node; 508550397Sobrien 508650397Sobrien limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node)); 508750397Sobrien limbo_node->die = die; 508890075Sobrien limbo_node->created_for = t; 508950397Sobrien limbo_node->next = limbo_die_list; 509050397Sobrien limbo_die_list = limbo_node; 509150397Sobrien } 509250397Sobrien 509350397Sobrien return die; 509450397Sobrien} 509550397Sobrien 509650397Sobrien/* Return the DIE associated with the given type specifier. */ 509750397Sobrien 509850397Sobrienstatic inline dw_die_ref 509950397Sobrienlookup_type_die (type) 510090075Sobrien tree type; 510150397Sobrien{ 510250397Sobrien return (dw_die_ref) TYPE_SYMTAB_POINTER (type); 510350397Sobrien} 510450397Sobrien 510550397Sobrien/* Equate a DIE to a given type specifier. */ 510650397Sobrien 510790075Sobrienstatic inline void 510850397Sobrienequate_type_number_to_die (type, type_die) 510990075Sobrien tree type; 511090075Sobrien dw_die_ref type_die; 511150397Sobrien{ 511250397Sobrien TYPE_SYMTAB_POINTER (type) = (char *) type_die; 511350397Sobrien} 511450397Sobrien 511550397Sobrien/* Return the DIE associated with a given declaration. */ 511650397Sobrien 511750397Sobrienstatic inline dw_die_ref 511850397Sobrienlookup_decl_die (decl) 511990075Sobrien tree decl; 512050397Sobrien{ 512190075Sobrien unsigned decl_id = DECL_UID (decl); 512250397Sobrien 512390075Sobrien return (decl_id < decl_die_table_in_use ? decl_die_table[decl_id] : NULL); 512450397Sobrien} 512550397Sobrien 512650397Sobrien/* Equate a DIE to a particular declaration. */ 512750397Sobrien 512850397Sobrienstatic void 512950397Sobrienequate_decl_number_to_die (decl, decl_die) 513090075Sobrien tree decl; 513190075Sobrien dw_die_ref decl_die; 513250397Sobrien{ 513390075Sobrien unsigned int decl_id = DECL_UID (decl); 513490075Sobrien unsigned int num_allocated; 513550397Sobrien 513650397Sobrien if (decl_id >= decl_die_table_allocated) 513750397Sobrien { 513850397Sobrien num_allocated 513950397Sobrien = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1) 514050397Sobrien / DECL_DIE_TABLE_INCREMENT) 514150397Sobrien * DECL_DIE_TABLE_INCREMENT; 514250397Sobrien 514350397Sobrien decl_die_table 514450397Sobrien = (dw_die_ref *) xrealloc (decl_die_table, 514550397Sobrien sizeof (dw_die_ref) * num_allocated); 514650397Sobrien 514790075Sobrien memset ((char *) &decl_die_table[decl_die_table_allocated], 0, 514850397Sobrien (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref)); 514950397Sobrien decl_die_table_allocated = num_allocated; 515050397Sobrien } 515150397Sobrien 515250397Sobrien if (decl_id >= decl_die_table_in_use) 515350397Sobrien decl_die_table_in_use = (decl_id + 1); 515450397Sobrien 515550397Sobrien decl_die_table[decl_id] = decl_die; 515650397Sobrien} 515750397Sobrien 515850397Sobrien/* Keep track of the number of spaces used to indent the 515950397Sobrien output of the debugging routines that print the structure of 516050397Sobrien the DIE internal representation. */ 516150397Sobrienstatic int print_indent; 516250397Sobrien 516350397Sobrien/* Indent the line the number of spaces given by print_indent. */ 516450397Sobrien 516550397Sobrienstatic inline void 516650397Sobrienprint_spaces (outfile) 516750397Sobrien FILE *outfile; 516850397Sobrien{ 516950397Sobrien fprintf (outfile, "%*s", print_indent, ""); 517050397Sobrien} 517150397Sobrien 517250397Sobrien/* Print the information associated with a given DIE, and its children. 517350397Sobrien This routine is a debugging aid only. */ 517450397Sobrien 517550397Sobrienstatic void 517650397Sobrienprint_die (die, outfile) 517750397Sobrien dw_die_ref die; 517850397Sobrien FILE *outfile; 517950397Sobrien{ 518090075Sobrien dw_attr_ref a; 518190075Sobrien dw_die_ref c; 518250397Sobrien 518350397Sobrien print_spaces (outfile); 518450397Sobrien fprintf (outfile, "DIE %4lu: %s\n", 518550397Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 518650397Sobrien print_spaces (outfile); 518750397Sobrien fprintf (outfile, " abbrev id: %lu", die->die_abbrev); 518850397Sobrien fprintf (outfile, " offset: %lu\n", die->die_offset); 518950397Sobrien 519050397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 519150397Sobrien { 519250397Sobrien print_spaces (outfile); 519350397Sobrien fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr)); 519450397Sobrien 519590075Sobrien switch (AT_class (a)) 519650397Sobrien { 519750397Sobrien case dw_val_class_addr: 519850397Sobrien fprintf (outfile, "address"); 519950397Sobrien break; 520090075Sobrien case dw_val_class_offset: 520190075Sobrien fprintf (outfile, "offset"); 520290075Sobrien break; 520350397Sobrien case dw_val_class_loc: 520450397Sobrien fprintf (outfile, "location descriptor"); 520550397Sobrien break; 520690075Sobrien case dw_val_class_loc_list: 520790075Sobrien fprintf (outfile, "location list -> label:%s", 520890075Sobrien AT_loc_list (a)->ll_symbol); 520990075Sobrien break; 521090075Sobrien case dw_val_class_range_list: 521190075Sobrien fprintf (outfile, "range list"); 521290075Sobrien break; 521350397Sobrien case dw_val_class_const: 521490075Sobrien fprintf (outfile, "%ld", AT_int (a)); 521550397Sobrien break; 521650397Sobrien case dw_val_class_unsigned_const: 521790075Sobrien fprintf (outfile, "%lu", AT_unsigned (a)); 521850397Sobrien break; 521950397Sobrien case dw_val_class_long_long: 522050397Sobrien fprintf (outfile, "constant (%lu,%lu)", 522190075Sobrien a->dw_attr_val.v.val_long_long.hi, 522290075Sobrien a->dw_attr_val.v.val_long_long.low); 522350397Sobrien break; 522450397Sobrien case dw_val_class_float: 522550397Sobrien fprintf (outfile, "floating-point constant"); 522650397Sobrien break; 522750397Sobrien case dw_val_class_flag: 522890075Sobrien fprintf (outfile, "%u", AT_flag (a)); 522950397Sobrien break; 523050397Sobrien case dw_val_class_die_ref: 523190075Sobrien if (AT_ref (a) != NULL) 523290075Sobrien { 523390075Sobrien if (AT_ref (a)->die_symbol) 523490075Sobrien fprintf (outfile, "die -> label: %s", AT_ref (a)->die_symbol); 523590075Sobrien else 523690075Sobrien fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset); 523790075Sobrien } 523850397Sobrien else 523950397Sobrien fprintf (outfile, "die -> <null>"); 524050397Sobrien break; 524150397Sobrien case dw_val_class_lbl_id: 524252284Sobrien case dw_val_class_lbl_offset: 524390075Sobrien fprintf (outfile, "label: %s", AT_lbl (a)); 524450397Sobrien break; 524550397Sobrien case dw_val_class_str: 524690075Sobrien if (AT_string (a) != NULL) 524790075Sobrien fprintf (outfile, "\"%s\"", AT_string (a)); 524850397Sobrien else 524950397Sobrien fprintf (outfile, "<null>"); 525050397Sobrien break; 525150397Sobrien default: 525250397Sobrien break; 525350397Sobrien } 525450397Sobrien 525550397Sobrien fprintf (outfile, "\n"); 525650397Sobrien } 525750397Sobrien 525850397Sobrien if (die->die_child != NULL) 525950397Sobrien { 526050397Sobrien print_indent += 4; 526150397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 526250397Sobrien print_die (c, outfile); 526350397Sobrien 526450397Sobrien print_indent -= 4; 526550397Sobrien } 526690075Sobrien if (print_indent == 0) 526790075Sobrien fprintf (outfile, "\n"); 526850397Sobrien} 526950397Sobrien 527050397Sobrien/* Print the contents of the source code line number correspondence table. 527150397Sobrien This routine is a debugging aid only. */ 527250397Sobrien 527350397Sobrienstatic void 527450397Sobrienprint_dwarf_line_table (outfile) 527550397Sobrien FILE *outfile; 527650397Sobrien{ 527790075Sobrien unsigned i; 527890075Sobrien dw_line_info_ref line_info; 527950397Sobrien 528050397Sobrien fprintf (outfile, "\n\nDWARF source line information\n"); 528190075Sobrien for (i = 1; i < line_info_table_in_use; i++) 528250397Sobrien { 528350397Sobrien line_info = &line_info_table[i]; 528450397Sobrien fprintf (outfile, "%5d: ", i); 528590075Sobrien fprintf (outfile, "%-20s", file_table.table[line_info->dw_file_num]); 528650397Sobrien fprintf (outfile, "%6ld", line_info->dw_line_num); 528750397Sobrien fprintf (outfile, "\n"); 528850397Sobrien } 528950397Sobrien 529050397Sobrien fprintf (outfile, "\n\n"); 529150397Sobrien} 529250397Sobrien 529350397Sobrien/* Print the information collected for a given DIE. */ 529450397Sobrien 529550397Sobrienvoid 529650397Sobriendebug_dwarf_die (die) 529750397Sobrien dw_die_ref die; 529850397Sobrien{ 529950397Sobrien print_die (die, stderr); 530050397Sobrien} 530150397Sobrien 530250397Sobrien/* Print all DWARF information collected for the compilation unit. 530350397Sobrien This routine is a debugging aid only. */ 530450397Sobrien 530550397Sobrienvoid 530650397Sobriendebug_dwarf () 530750397Sobrien{ 530850397Sobrien print_indent = 0; 530950397Sobrien print_die (comp_unit_die, stderr); 531090075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 531190075Sobrien print_dwarf_line_table (stderr); 531250397Sobrien} 531350397Sobrien 531490075Sobrien/* We build up the lists of children and attributes by pushing new ones 531590075Sobrien onto the beginning of the list. Reverse the lists for DIE so that 531690075Sobrien they are in order of addition. */ 531750397Sobrien 531850397Sobrienstatic void 531990075Sobrienreverse_die_lists (die) 532090075Sobrien dw_die_ref die; 532150397Sobrien{ 532290075Sobrien dw_die_ref c, cp, cn; 532390075Sobrien dw_attr_ref a, ap, an; 532490075Sobrien 532590075Sobrien for (a = die->die_attr, ap = 0; a; a = an) 532650397Sobrien { 532790075Sobrien an = a->dw_attr_next; 532890075Sobrien a->dw_attr_next = ap; 532990075Sobrien ap = a; 533090075Sobrien } 533150397Sobrien 533290075Sobrien die->die_attr = ap; 533350397Sobrien 533490075Sobrien for (c = die->die_child, cp = 0; c; c = cn) 533590075Sobrien { 533690075Sobrien cn = c->die_sib; 533790075Sobrien c->die_sib = cp; 533890075Sobrien cp = c; 533950397Sobrien } 534050397Sobrien 534190075Sobrien die->die_child = cp; 534290075Sobrien} 534390075Sobrien 534490075Sobrien/* reverse_die_lists only reverses the single die you pass it. Since we used to 534590075Sobrien reverse all dies in add_sibling_attributes, which runs through all the dies, 534690075Sobrien it would reverse all the dies. Now, however, since we don't call 534790075Sobrien reverse_die_lists in add_sibling_attributes, we need a routine to 534890075Sobrien recursively reverse all the dies. This is that routine. */ 534990075Sobrien 535090075Sobrienstatic void 535190075Sobrienreverse_all_dies (die) 535290075Sobrien dw_die_ref die; 535390075Sobrien{ 535490075Sobrien dw_die_ref c; 535590075Sobrien 535690075Sobrien reverse_die_lists (die); 535790075Sobrien 535890075Sobrien for (c = die->die_child; c; c = c->die_sib) 535990075Sobrien reverse_all_dies (c); 536090075Sobrien} 536190075Sobrien 536290075Sobrien/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU 536390075Sobrien for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL 536490075Sobrien DIE that marks the start of the DIEs for this include file. */ 536590075Sobrien 536690075Sobrienstatic dw_die_ref 536790075Sobrienpush_new_compile_unit (old_unit, bincl_die) 536890075Sobrien dw_die_ref old_unit, bincl_die; 536990075Sobrien{ 537090075Sobrien const char *filename = get_AT_string (bincl_die, DW_AT_name); 537190075Sobrien dw_die_ref new_unit = gen_compile_unit_die (filename); 537290075Sobrien 537390075Sobrien new_unit->die_sib = old_unit; 537490075Sobrien return new_unit; 537590075Sobrien} 537690075Sobrien 537790075Sobrien/* Close an include-file CU and reopen the enclosing one. */ 537890075Sobrien 537990075Sobrienstatic dw_die_ref 538090075Sobrienpop_compile_unit (old_unit) 538190075Sobrien dw_die_ref old_unit; 538290075Sobrien{ 538390075Sobrien dw_die_ref new_unit = old_unit->die_sib; 538490075Sobrien 538590075Sobrien old_unit->die_sib = NULL; 538690075Sobrien return new_unit; 538790075Sobrien} 538890075Sobrien 538990075Sobrien#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx) 539090075Sobrien#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO), ctx) 539190075Sobrien 539290075Sobrien/* Calculate the checksum of a location expression. */ 539390075Sobrien 539490075Sobrienstatic inline void 539590075Sobrienloc_checksum (loc, ctx) 539690075Sobrien dw_loc_descr_ref loc; 539790075Sobrien struct md5_ctx *ctx; 539890075Sobrien{ 539990075Sobrien CHECKSUM (loc->dw_loc_opc); 540090075Sobrien CHECKSUM (loc->dw_loc_oprnd1); 540190075Sobrien CHECKSUM (loc->dw_loc_oprnd2); 540290075Sobrien} 540390075Sobrien 540490075Sobrien/* Calculate the checksum of an attribute. */ 540590075Sobrien 540690075Sobrienstatic void 540790075Sobrienattr_checksum (at, ctx) 540890075Sobrien dw_attr_ref at; 540990075Sobrien struct md5_ctx *ctx; 541090075Sobrien{ 541190075Sobrien dw_loc_descr_ref loc; 541290075Sobrien rtx r; 541390075Sobrien 541490075Sobrien CHECKSUM (at->dw_attr); 541590075Sobrien 541690075Sobrien /* We don't care about differences in file numbering. */ 541790075Sobrien if (at->dw_attr == DW_AT_decl_file 541890075Sobrien /* Or that this was compiled with a different compiler snapshot; if 541990075Sobrien the output is the same, that's what matters. */ 542090075Sobrien || at->dw_attr == DW_AT_producer) 542190075Sobrien return; 542290075Sobrien 542390075Sobrien switch (AT_class (at)) 542490075Sobrien { 542590075Sobrien case dw_val_class_const: 542690075Sobrien CHECKSUM (at->dw_attr_val.v.val_int); 542790075Sobrien break; 542890075Sobrien case dw_val_class_unsigned_const: 542990075Sobrien CHECKSUM (at->dw_attr_val.v.val_unsigned); 543090075Sobrien break; 543190075Sobrien case dw_val_class_long_long: 543290075Sobrien CHECKSUM (at->dw_attr_val.v.val_long_long); 543390075Sobrien break; 543490075Sobrien case dw_val_class_float: 543590075Sobrien CHECKSUM (at->dw_attr_val.v.val_float); 543690075Sobrien break; 543790075Sobrien case dw_val_class_flag: 543890075Sobrien CHECKSUM (at->dw_attr_val.v.val_flag); 543990075Sobrien break; 544090075Sobrien case dw_val_class_str: 544190075Sobrien CHECKSUM_STRING (AT_string (at)); 544290075Sobrien break; 544390075Sobrien 544490075Sobrien case dw_val_class_addr: 544590075Sobrien r = AT_addr (at); 544690075Sobrien switch (GET_CODE (r)) 544790075Sobrien { 544890075Sobrien case SYMBOL_REF: 544990075Sobrien CHECKSUM_STRING (XSTR (r, 0)); 545090075Sobrien break; 545190075Sobrien 545290075Sobrien default: 545390075Sobrien abort (); 545490075Sobrien } 545590075Sobrien break; 545690075Sobrien 545790075Sobrien case dw_val_class_offset: 545890075Sobrien CHECKSUM (at->dw_attr_val.v.val_offset); 545990075Sobrien break; 546090075Sobrien 546190075Sobrien case dw_val_class_loc: 546290075Sobrien for (loc = AT_loc (at); loc; loc = loc->dw_loc_next) 546390075Sobrien loc_checksum (loc, ctx); 546490075Sobrien break; 546590075Sobrien 546690075Sobrien case dw_val_class_die_ref: 546790075Sobrien if (AT_ref (at)->die_offset) 546890075Sobrien CHECKSUM (AT_ref (at)->die_offset); 546990075Sobrien /* FIXME else use target die name or something. */ 547090075Sobrien 547190075Sobrien case dw_val_class_fde_ref: 547290075Sobrien case dw_val_class_lbl_id: 547390075Sobrien case dw_val_class_lbl_offset: 547490075Sobrien break; 547590075Sobrien 547690075Sobrien default: 547790075Sobrien break; 547890075Sobrien } 547990075Sobrien} 548090075Sobrien 548190075Sobrien/* Calculate the checksum of a DIE. */ 548290075Sobrien 548390075Sobrienstatic void 548490075Sobriendie_checksum (die, ctx) 548590075Sobrien dw_die_ref die; 548690075Sobrien struct md5_ctx *ctx; 548790075Sobrien{ 548890075Sobrien dw_die_ref c; 548990075Sobrien dw_attr_ref a; 549090075Sobrien 549190075Sobrien CHECKSUM (die->die_tag); 549290075Sobrien 549390075Sobrien for (a = die->die_attr; a; a = a->dw_attr_next) 549490075Sobrien attr_checksum (a, ctx); 549590075Sobrien 549690075Sobrien for (c = die->die_child; c; c = c->die_sib) 549790075Sobrien die_checksum (c, ctx); 549890075Sobrien} 549990075Sobrien 550090075Sobrien#undef CHECKSUM 550190075Sobrien#undef CHECKSUM_STRING 550290075Sobrien 550390075Sobrien/* The prefix to attach to symbols on DIEs in the current comdat debug 550490075Sobrien info section. */ 550590075Sobrienstatic char *comdat_symbol_id; 550690075Sobrien 550790075Sobrien/* The index of the current symbol within the current comdat CU. */ 550890075Sobrienstatic unsigned int comdat_symbol_number; 550990075Sobrien 551090075Sobrien/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its 551190075Sobrien children, and set comdat_symbol_id accordingly. */ 551290075Sobrien 551390075Sobrienstatic void 551490075Sobriencompute_section_prefix (unit_die) 551590075Sobrien dw_die_ref unit_die; 551690075Sobrien{ 551790075Sobrien const char *base = lbasename (get_AT_string (unit_die, DW_AT_name)); 551890075Sobrien char *name = (char *) alloca (strlen (base) + 64); 551990075Sobrien char *p; 552090075Sobrien int i; 552190075Sobrien unsigned char checksum[16]; 552290075Sobrien struct md5_ctx ctx; 552390075Sobrien 552490075Sobrien /* Compute the checksum of the DIE, then append part of it as hex digits to 552590075Sobrien the name filename of the unit. */ 552690075Sobrien 552790075Sobrien md5_init_ctx (&ctx); 552890075Sobrien die_checksum (unit_die, &ctx); 552990075Sobrien md5_finish_ctx (&ctx, checksum); 553090075Sobrien 553190075Sobrien sprintf (name, "%s.", base); 553290075Sobrien clean_symbol_name (name); 553390075Sobrien 553490075Sobrien p = name + strlen (name); 553590075Sobrien for (i = 0; i < 4; i++) 553690075Sobrien { 553790075Sobrien sprintf (p, "%.2x", checksum[i]); 553890075Sobrien p += 2; 553990075Sobrien } 554090075Sobrien 554190075Sobrien comdat_symbol_id = unit_die->die_symbol = xstrdup (name); 554290075Sobrien comdat_symbol_number = 0; 554390075Sobrien} 554490075Sobrien 554590075Sobrien/* Returns nonzero if DIE represents a type, in the sense of TYPE_P. */ 554690075Sobrien 554790075Sobrienstatic int 554890075Sobrienis_type_die (die) 554990075Sobrien dw_die_ref die; 555090075Sobrien{ 555190075Sobrien switch (die->die_tag) 555290075Sobrien { 555390075Sobrien case DW_TAG_array_type: 555490075Sobrien case DW_TAG_class_type: 555590075Sobrien case DW_TAG_enumeration_type: 555690075Sobrien case DW_TAG_pointer_type: 555790075Sobrien case DW_TAG_reference_type: 555890075Sobrien case DW_TAG_string_type: 555990075Sobrien case DW_TAG_structure_type: 556090075Sobrien case DW_TAG_subroutine_type: 556190075Sobrien case DW_TAG_union_type: 556290075Sobrien case DW_TAG_ptr_to_member_type: 556390075Sobrien case DW_TAG_set_type: 556490075Sobrien case DW_TAG_subrange_type: 556590075Sobrien case DW_TAG_base_type: 556690075Sobrien case DW_TAG_const_type: 556790075Sobrien case DW_TAG_file_type: 556890075Sobrien case DW_TAG_packed_type: 556990075Sobrien case DW_TAG_volatile_type: 557090075Sobrien return 1; 557190075Sobrien default: 557290075Sobrien return 0; 557390075Sobrien } 557490075Sobrien} 557590075Sobrien 557690075Sobrien/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU. 557790075Sobrien Basically, we want to choose the bits that are likely to be shared between 557890075Sobrien compilations (types) and leave out the bits that are specific to individual 557990075Sobrien compilations (functions). */ 558090075Sobrien 558190075Sobrienstatic int 558290075Sobrienis_comdat_die (c) 558390075Sobrien dw_die_ref c; 558490075Sobrien{ 558590075Sobrien /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as 558690075Sobrien we do for stabs. The advantage is a greater likelihood of sharing between 558790075Sobrien objects that don't include headers in the same order (and therefore would 558890075Sobrien put the base types in a different comdat). jason 8/28/00 */ 558990075Sobrien 559090075Sobrien if (c->die_tag == DW_TAG_base_type) 559190075Sobrien return 0; 559290075Sobrien 559390075Sobrien if (c->die_tag == DW_TAG_pointer_type 559490075Sobrien || c->die_tag == DW_TAG_reference_type 559590075Sobrien || c->die_tag == DW_TAG_const_type 559690075Sobrien || c->die_tag == DW_TAG_volatile_type) 559790075Sobrien { 559890075Sobrien dw_die_ref t = get_AT_ref (c, DW_AT_type); 559990075Sobrien 560090075Sobrien return t ? is_comdat_die (t) : 0; 560190075Sobrien } 560290075Sobrien 560390075Sobrien return is_type_die (c); 560490075Sobrien} 560590075Sobrien 560690075Sobrien/* Returns 1 iff C is the sort of DIE that might be referred to from another 560790075Sobrien compilation unit. */ 560890075Sobrien 560990075Sobrienstatic int 561090075Sobrienis_symbol_die (c) 561190075Sobrien dw_die_ref c; 561290075Sobrien{ 561390075Sobrien return (is_type_die (c) 561490075Sobrien || (get_AT (c, DW_AT_declaration) 561590075Sobrien && !get_AT (c, DW_AT_specification))); 561690075Sobrien} 561790075Sobrien 561890075Sobrienstatic char * 561990075Sobriengen_internal_sym (prefix) 562090075Sobrien const char *prefix; 562190075Sobrien{ 562290075Sobrien char buf[256]; 562390075Sobrien static int label_num; 562490075Sobrien 562590075Sobrien ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++); 562690075Sobrien return xstrdup (buf); 562790075Sobrien} 562890075Sobrien 562990075Sobrien/* Assign symbols to all worthy DIEs under DIE. */ 563090075Sobrien 563190075Sobrienstatic void 563290075Sobrienassign_symbol_names (die) 563390075Sobrien dw_die_ref die; 563490075Sobrien{ 563590075Sobrien dw_die_ref c; 563690075Sobrien 563790075Sobrien if (is_symbol_die (die)) 563890075Sobrien { 563990075Sobrien if (comdat_symbol_id) 564090075Sobrien { 564190075Sobrien char *p = alloca (strlen (comdat_symbol_id) + 64); 564290075Sobrien 564390075Sobrien sprintf (p, "%s.%s.%x", DIE_LABEL_PREFIX, 564490075Sobrien comdat_symbol_id, comdat_symbol_number++); 564590075Sobrien die->die_symbol = xstrdup (p); 564690075Sobrien } 564790075Sobrien else 564890075Sobrien die->die_symbol = gen_internal_sym ("LDIE"); 564990075Sobrien } 565090075Sobrien 565150397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 565290075Sobrien assign_symbol_names (c); 565390075Sobrien} 565490075Sobrien 565590075Sobrien/* Traverse the DIE (which is always comp_unit_die), and set up 565690075Sobrien additional compilation units for each of the include files we see 565790075Sobrien bracketed by BINCL/EINCL. */ 565890075Sobrien 565990075Sobrienstatic void 566090075Sobrienbreak_out_includes (die) 566190075Sobrien dw_die_ref die; 566290075Sobrien{ 566390075Sobrien dw_die_ref *ptr; 566490075Sobrien dw_die_ref unit = NULL; 566590075Sobrien limbo_die_node *node; 566690075Sobrien 566790075Sobrien for (ptr = &(die->die_child); *ptr; ) 566890075Sobrien { 566990075Sobrien dw_die_ref c = *ptr; 567090075Sobrien 567190075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL 567290075Sobrien || (unit && is_comdat_die (c))) 567390075Sobrien { 567490075Sobrien /* This DIE is for a secondary CU; remove it from the main one. */ 567590075Sobrien *ptr = c->die_sib; 567690075Sobrien 567790075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL) 567890075Sobrien { 567990075Sobrien unit = push_new_compile_unit (unit, c); 568090075Sobrien free_die (c); 568190075Sobrien } 568290075Sobrien else if (c->die_tag == DW_TAG_GNU_EINCL) 568390075Sobrien { 568490075Sobrien unit = pop_compile_unit (unit); 568590075Sobrien free_die (c); 568690075Sobrien } 568790075Sobrien else 568890075Sobrien add_child_die (unit, c); 568990075Sobrien } 569090075Sobrien else 569190075Sobrien { 569290075Sobrien /* Leave this DIE in the main CU. */ 569390075Sobrien ptr = &(c->die_sib); 569490075Sobrien continue; 569590075Sobrien } 569690075Sobrien } 569790075Sobrien 569890075Sobrien#if 0 569990075Sobrien /* We can only use this in debugging, since the frontend doesn't check 570090075Sobrien to make sure that we leave every include file we enter. */ 570190075Sobrien if (unit != NULL) 570290075Sobrien abort (); 570390075Sobrien#endif 570490075Sobrien 570590075Sobrien assign_symbol_names (die); 570690075Sobrien for (node = limbo_die_list; node; node = node->next) 570790075Sobrien { 570890075Sobrien compute_section_prefix (node->die); 570990075Sobrien assign_symbol_names (node->die); 571090075Sobrien } 571190075Sobrien} 571290075Sobrien 571390075Sobrien/* Traverse the DIE and add a sibling attribute if it may have the 571490075Sobrien effect of speeding up access to siblings. To save some space, 571590075Sobrien avoid generating sibling attributes for DIE's without children. */ 571690075Sobrien 571790075Sobrienstatic void 571890075Sobrienadd_sibling_attributes (die) 571990075Sobrien dw_die_ref die; 572090075Sobrien{ 572190075Sobrien dw_die_ref c; 572290075Sobrien 572390075Sobrien if (die->die_tag != DW_TAG_compile_unit 572490075Sobrien && die->die_sib && die->die_child != NULL) 572590075Sobrien /* Add the sibling link to the front of the attribute list. */ 572690075Sobrien add_AT_die_ref (die, DW_AT_sibling, die->die_sib); 572790075Sobrien 572890075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 572950397Sobrien add_sibling_attributes (c); 573050397Sobrien} 573150397Sobrien 573290075Sobrien/* Output all location lists for the DIE and its children. */ 573350397Sobrien 573450397Sobrienstatic void 573590075Sobrienoutput_location_lists (die) 573690075Sobrien dw_die_ref die; 573790075Sobrien{ 573890075Sobrien dw_die_ref c; 573990075Sobrien dw_attr_ref d_attr; 574090075Sobrien 574190075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 574290075Sobrien if (AT_class (d_attr) == dw_val_class_loc_list) 574390075Sobrien output_loc_list (AT_loc_list (d_attr)); 574490075Sobrien 574590075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 574690075Sobrien output_location_lists (c); 574790075Sobrien 574890075Sobrien} 574990075Sobrien/* The format of each DIE (and its attribute value pairs) is encoded in an 575090075Sobrien abbreviation table. This routine builds the abbreviation table and assigns 575190075Sobrien a unique abbreviation id for each abbreviation entry. The children of each 575290075Sobrien die are visited recursively. */ 575390075Sobrien 575490075Sobrienstatic void 575550397Sobrienbuild_abbrev_table (die) 575690075Sobrien dw_die_ref die; 575750397Sobrien{ 575890075Sobrien unsigned long abbrev_id; 575990075Sobrien unsigned int n_alloc; 576090075Sobrien dw_die_ref c; 576190075Sobrien dw_attr_ref d_attr, a_attr; 576290075Sobrien 576390075Sobrien /* Scan the DIE references, and mark as external any that refer to 576490075Sobrien DIEs from other CUs (i.e. those which are not marked). */ 576590075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 576690075Sobrien if (AT_class (d_attr) == dw_val_class_die_ref 576790075Sobrien && AT_ref (d_attr)->die_mark == 0) 576890075Sobrien { 576990075Sobrien if (AT_ref (d_attr)->die_symbol == 0) 577090075Sobrien abort (); 577190075Sobrien 577290075Sobrien set_AT_ref_external (d_attr, 1); 577390075Sobrien } 577490075Sobrien 577550397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 577650397Sobrien { 577790075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 577850397Sobrien 577950397Sobrien if (abbrev->die_tag == die->die_tag) 578050397Sobrien { 578150397Sobrien if ((abbrev->die_child != NULL) == (die->die_child != NULL)) 578250397Sobrien { 578350397Sobrien a_attr = abbrev->die_attr; 578450397Sobrien d_attr = die->die_attr; 578550397Sobrien 578650397Sobrien while (a_attr != NULL && d_attr != NULL) 578750397Sobrien { 578850397Sobrien if ((a_attr->dw_attr != d_attr->dw_attr) 578990075Sobrien || (value_format (a_attr) != value_format (d_attr))) 579050397Sobrien break; 579150397Sobrien 579250397Sobrien a_attr = a_attr->dw_attr_next; 579350397Sobrien d_attr = d_attr->dw_attr_next; 579450397Sobrien } 579550397Sobrien 579650397Sobrien if (a_attr == NULL && d_attr == NULL) 579750397Sobrien break; 579850397Sobrien } 579950397Sobrien } 580050397Sobrien } 580150397Sobrien 580250397Sobrien if (abbrev_id >= abbrev_die_table_in_use) 580350397Sobrien { 580450397Sobrien if (abbrev_die_table_in_use >= abbrev_die_table_allocated) 580550397Sobrien { 580650397Sobrien n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; 580790075Sobrien abbrev_die_table 580850397Sobrien = (dw_die_ref *) xrealloc (abbrev_die_table, 580950397Sobrien sizeof (dw_die_ref) * n_alloc); 581050397Sobrien 581190075Sobrien memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0, 581250397Sobrien (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); 581350397Sobrien abbrev_die_table_allocated = n_alloc; 581450397Sobrien } 581550397Sobrien 581650397Sobrien ++abbrev_die_table_in_use; 581750397Sobrien abbrev_die_table[abbrev_id] = die; 581850397Sobrien } 581950397Sobrien 582050397Sobrien die->die_abbrev = abbrev_id; 582150397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 582250397Sobrien build_abbrev_table (c); 582350397Sobrien} 582450397Sobrien 582550397Sobrien/* Return the power-of-two number of bytes necessary to represent VALUE. */ 582650397Sobrien 582750397Sobrienstatic int 582850397Sobrienconstant_size (value) 582950397Sobrien long unsigned value; 583050397Sobrien{ 583150397Sobrien int log; 583250397Sobrien 583350397Sobrien if (value == 0) 583450397Sobrien log = 0; 583550397Sobrien else 583650397Sobrien log = floor_log2 (value); 583750397Sobrien 583850397Sobrien log = log / 8; 583950397Sobrien log = 1 << (floor_log2 (log) + 1); 584050397Sobrien 584150397Sobrien return log; 584250397Sobrien} 584350397Sobrien 584490075Sobrien/* Return the size of a DIE as it is represented in the 584550397Sobrien .debug_info section. */ 584650397Sobrien 584750397Sobrienstatic unsigned long 584850397Sobriensize_of_die (die) 584990075Sobrien dw_die_ref die; 585050397Sobrien{ 585190075Sobrien unsigned long size = 0; 585290075Sobrien dw_attr_ref a; 585350397Sobrien 585450397Sobrien size += size_of_uleb128 (die->die_abbrev); 585550397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 585650397Sobrien { 585790075Sobrien switch (AT_class (a)) 585850397Sobrien { 585950397Sobrien case dw_val_class_addr: 586090075Sobrien size += DWARF2_ADDR_SIZE; 586150397Sobrien break; 586290075Sobrien case dw_val_class_offset: 586390075Sobrien size += DWARF_OFFSET_SIZE; 586490075Sobrien break; 586550397Sobrien case dw_val_class_loc: 586650397Sobrien { 586790075Sobrien unsigned long lsize = size_of_locs (AT_loc (a)); 586850397Sobrien 586950397Sobrien /* Block length. */ 587050397Sobrien size += constant_size (lsize); 587150397Sobrien size += lsize; 587250397Sobrien } 587350397Sobrien break; 587490075Sobrien case dw_val_class_loc_list: 587590075Sobrien size += DWARF_OFFSET_SIZE; 587690075Sobrien break; 587790075Sobrien case dw_val_class_range_list: 587890075Sobrien size += DWARF_OFFSET_SIZE; 587990075Sobrien break; 588050397Sobrien case dw_val_class_const: 588190075Sobrien size += size_of_sleb128 (AT_int (a)); 588250397Sobrien break; 588350397Sobrien case dw_val_class_unsigned_const: 588490075Sobrien size += constant_size (AT_unsigned (a)); 588550397Sobrien break; 588650397Sobrien case dw_val_class_long_long: 588790075Sobrien size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */ 588850397Sobrien break; 588950397Sobrien case dw_val_class_float: 589050397Sobrien size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ 589150397Sobrien break; 589250397Sobrien case dw_val_class_flag: 589350397Sobrien size += 1; 589450397Sobrien break; 589550397Sobrien case dw_val_class_die_ref: 589650397Sobrien size += DWARF_OFFSET_SIZE; 589750397Sobrien break; 589850397Sobrien case dw_val_class_fde_ref: 589950397Sobrien size += DWARF_OFFSET_SIZE; 590050397Sobrien break; 590150397Sobrien case dw_val_class_lbl_id: 590290075Sobrien size += DWARF2_ADDR_SIZE; 590350397Sobrien break; 590452284Sobrien case dw_val_class_lbl_offset: 590550397Sobrien size += DWARF_OFFSET_SIZE; 590650397Sobrien break; 590750397Sobrien case dw_val_class_str: 590890075Sobrien if (AT_string_form (a) == DW_FORM_strp) 590990075Sobrien size += DWARF_OFFSET_SIZE; 591090075Sobrien else 591190075Sobrien size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1; 591250397Sobrien break; 591350397Sobrien default: 591450397Sobrien abort (); 591550397Sobrien } 591650397Sobrien } 591750397Sobrien 591850397Sobrien return size; 591950397Sobrien} 592050397Sobrien 592190075Sobrien/* Size the debugging information associated with a given DIE. Visits the 592290075Sobrien DIE's children recursively. Updates the global variable next_die_offset, on 592390075Sobrien each time through. Uses the current value of next_die_offset to update the 592490075Sobrien die_offset field in each DIE. */ 592550397Sobrien 592650397Sobrienstatic void 592750397Sobriencalc_die_sizes (die) 592850397Sobrien dw_die_ref die; 592950397Sobrien{ 593090075Sobrien dw_die_ref c; 593190075Sobrien 593250397Sobrien die->die_offset = next_die_offset; 593350397Sobrien next_die_offset += size_of_die (die); 593450397Sobrien 593550397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 593650397Sobrien calc_die_sizes (c); 593750397Sobrien 593850397Sobrien if (die->die_child != NULL) 593950397Sobrien /* Count the null byte used to terminate sibling lists. */ 594050397Sobrien next_die_offset += 1; 594150397Sobrien} 594250397Sobrien 594390075Sobrien/* Set the marks for a die and its children. We do this so 594490075Sobrien that we know whether or not a reference needs to use FORM_ref_addr; only 594590075Sobrien DIEs in the same CU will be marked. We used to clear out the offset 594690075Sobrien and use that as the flag, but ran into ordering problems. */ 594750397Sobrien 594890075Sobrienstatic void 594990075Sobrienmark_dies (die) 595090075Sobrien dw_die_ref die; 595150397Sobrien{ 595290075Sobrien dw_die_ref c; 595350397Sobrien 595490075Sobrien die->die_mark = 1; 595590075Sobrien for (c = die->die_child; c; c = c->die_sib) 595690075Sobrien mark_dies (c); 595750397Sobrien} 595850397Sobrien 595990075Sobrien/* Clear the marks for a die and its children. */ 596050397Sobrien 596190075Sobrienstatic void 596290075Sobrienunmark_dies (die) 596390075Sobrien dw_die_ref die; 596450397Sobrien{ 596590075Sobrien dw_die_ref c; 596650397Sobrien 596790075Sobrien die->die_mark = 0; 596890075Sobrien for (c = die->die_child; c; c = c->die_sib) 596990075Sobrien unmark_dies (c); 597050397Sobrien} 597150397Sobrien 597250397Sobrien/* Return the size of the .debug_pubnames table generated for the 597350397Sobrien compilation unit. */ 597450397Sobrien 597550397Sobrienstatic unsigned long 597650397Sobriensize_of_pubnames () 597750397Sobrien{ 597890075Sobrien unsigned long size; 597990075Sobrien unsigned i; 598050397Sobrien 598150397Sobrien size = DWARF_PUBNAMES_HEADER_SIZE; 598290075Sobrien for (i = 0; i < pubname_table_in_use; i++) 598350397Sobrien { 598490075Sobrien pubname_ref p = &pubname_table[i]; 598590075Sobrien size += DWARF_OFFSET_SIZE + strlen (p->name) + 1; 598650397Sobrien } 598750397Sobrien 598850397Sobrien size += DWARF_OFFSET_SIZE; 598950397Sobrien return size; 599050397Sobrien} 599150397Sobrien 599250397Sobrien/* Return the size of the information in the .debug_aranges section. */ 599350397Sobrien 599450397Sobrienstatic unsigned long 599550397Sobriensize_of_aranges () 599650397Sobrien{ 599790075Sobrien unsigned long size; 599850397Sobrien 599950397Sobrien size = DWARF_ARANGES_HEADER_SIZE; 600050397Sobrien 600150397Sobrien /* Count the address/length pair for this compilation unit. */ 600290075Sobrien size += 2 * DWARF2_ADDR_SIZE; 600390075Sobrien size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use; 600450397Sobrien 600550397Sobrien /* Count the two zero words used to terminated the address range table. */ 600690075Sobrien size += 2 * DWARF2_ADDR_SIZE; 600750397Sobrien return size; 600850397Sobrien} 600950397Sobrien 601050397Sobrien/* Select the encoding of an attribute value. */ 601150397Sobrien 601250397Sobrienstatic enum dwarf_form 601390075Sobrienvalue_format (a) 601490075Sobrien dw_attr_ref a; 601550397Sobrien{ 601690075Sobrien switch (a->dw_attr_val.val_class) 601750397Sobrien { 601850397Sobrien case dw_val_class_addr: 601950397Sobrien return DW_FORM_addr; 602090075Sobrien case dw_val_class_range_list: 602190075Sobrien case dw_val_class_offset: 602290075Sobrien if (DWARF_OFFSET_SIZE == 4) 602390075Sobrien return DW_FORM_data4; 602490075Sobrien if (DWARF_OFFSET_SIZE == 8) 602590075Sobrien return DW_FORM_data8; 602690075Sobrien abort (); 602790075Sobrien case dw_val_class_loc_list: 602890075Sobrien /* FIXME: Could be DW_FORM_data8, with a > 32 bit size 602990075Sobrien .debug_loc section */ 603090075Sobrien return DW_FORM_data4; 603150397Sobrien case dw_val_class_loc: 603290075Sobrien switch (constant_size (size_of_locs (AT_loc (a)))) 603350397Sobrien { 603450397Sobrien case 1: 603550397Sobrien return DW_FORM_block1; 603650397Sobrien case 2: 603750397Sobrien return DW_FORM_block2; 603850397Sobrien default: 603950397Sobrien abort (); 604050397Sobrien } 604150397Sobrien case dw_val_class_const: 604290075Sobrien return DW_FORM_sdata; 604350397Sobrien case dw_val_class_unsigned_const: 604490075Sobrien switch (constant_size (AT_unsigned (a))) 604550397Sobrien { 604650397Sobrien case 1: 604750397Sobrien return DW_FORM_data1; 604850397Sobrien case 2: 604950397Sobrien return DW_FORM_data2; 605050397Sobrien case 4: 605150397Sobrien return DW_FORM_data4; 605250397Sobrien case 8: 605350397Sobrien return DW_FORM_data8; 605450397Sobrien default: 605550397Sobrien abort (); 605650397Sobrien } 605750397Sobrien case dw_val_class_long_long: 605850397Sobrien return DW_FORM_block1; 605950397Sobrien case dw_val_class_float: 606050397Sobrien return DW_FORM_block1; 606150397Sobrien case dw_val_class_flag: 606250397Sobrien return DW_FORM_flag; 606350397Sobrien case dw_val_class_die_ref: 606490075Sobrien if (AT_ref_external (a)) 606590075Sobrien return DW_FORM_ref_addr; 606690075Sobrien else 606790075Sobrien return DW_FORM_ref; 606850397Sobrien case dw_val_class_fde_ref: 606950397Sobrien return DW_FORM_data; 607050397Sobrien case dw_val_class_lbl_id: 607150397Sobrien return DW_FORM_addr; 607252284Sobrien case dw_val_class_lbl_offset: 607350397Sobrien return DW_FORM_data; 607450397Sobrien case dw_val_class_str: 607590075Sobrien return AT_string_form (a); 607690075Sobrien 607750397Sobrien default: 607850397Sobrien abort (); 607950397Sobrien } 608050397Sobrien} 608150397Sobrien 608250397Sobrien/* Output the encoding of an attribute value. */ 608350397Sobrien 608450397Sobrienstatic void 608590075Sobrienoutput_value_format (a) 608690075Sobrien dw_attr_ref a; 608750397Sobrien{ 608890075Sobrien enum dwarf_form form = value_format (a); 608950397Sobrien 609090075Sobrien dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form)); 609150397Sobrien} 609250397Sobrien 609350397Sobrien/* Output the .debug_abbrev section which defines the DIE abbreviation 609450397Sobrien table. */ 609550397Sobrien 609650397Sobrienstatic void 609750397Sobrienoutput_abbrev_section () 609850397Sobrien{ 609950397Sobrien unsigned long abbrev_id; 610050397Sobrien 610150397Sobrien dw_attr_ref a_attr; 610290075Sobrien 610350397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 610450397Sobrien { 610590075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 610650397Sobrien 610790075Sobrien dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)"); 610890075Sobrien dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)", 610990075Sobrien dwarf_tag_name (abbrev->die_tag)); 611050397Sobrien 611190075Sobrien if (abbrev->die_child != NULL) 611290075Sobrien dw2_asm_output_data (1, DW_children_yes, "DW_children_yes"); 611390075Sobrien else 611490075Sobrien dw2_asm_output_data (1, DW_children_no, "DW_children_no"); 611550397Sobrien 611650397Sobrien for (a_attr = abbrev->die_attr; a_attr != NULL; 611750397Sobrien a_attr = a_attr->dw_attr_next) 611850397Sobrien { 611990075Sobrien dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", 612090075Sobrien dwarf_attr_name (a_attr->dw_attr)); 612190075Sobrien output_value_format (a_attr); 612250397Sobrien } 612350397Sobrien 612490075Sobrien dw2_asm_output_data (1, 0, NULL); 612590075Sobrien dw2_asm_output_data (1, 0, NULL); 612650397Sobrien } 612752284Sobrien 612890075Sobrien /* Terminate the table. */ 612990075Sobrien dw2_asm_output_data (1, 0, NULL); 613050397Sobrien} 613150397Sobrien 613290075Sobrien/* Output a symbol we can use to refer to this DIE from another CU. */ 613350397Sobrien 613490075Sobrienstatic inline void 613590075Sobrienoutput_die_symbol (die) 613690075Sobrien dw_die_ref die; 613790075Sobrien{ 613890075Sobrien char *sym = die->die_symbol; 613990075Sobrien 614090075Sobrien if (sym == 0) 614190075Sobrien return; 614290075Sobrien 614390075Sobrien if (strncmp (sym, DIE_LABEL_PREFIX, sizeof (DIE_LABEL_PREFIX) - 1) == 0) 614490075Sobrien /* We make these global, not weak; if the target doesn't support 614590075Sobrien .linkonce, it doesn't support combining the sections, so debugging 614690075Sobrien will break. */ 614790075Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, sym); 614890075Sobrien 614990075Sobrien ASM_OUTPUT_LABEL (asm_out_file, sym); 615090075Sobrien} 615190075Sobrien 615290075Sobrien/* Return a new location list, given the begin and end range, and the 615390075Sobrien expression. gensym tells us whether to generate a new internal symbol for 615490075Sobrien this location list node, which is done for the head of the list only. */ 615590075Sobrien 615690075Sobrienstatic inline dw_loc_list_ref 615790075Sobriennew_loc_list (expr, begin, end, section, gensym) 615890075Sobrien dw_loc_descr_ref expr; 615990075Sobrien const char *begin; 616090075Sobrien const char *end; 616190075Sobrien const char *section; 616290075Sobrien unsigned gensym; 616390075Sobrien{ 616490075Sobrien dw_loc_list_ref retlist 616590075Sobrien = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node)); 616690075Sobrien 616790075Sobrien retlist->begin = begin; 616890075Sobrien retlist->end = end; 616990075Sobrien retlist->expr = expr; 617090075Sobrien retlist->section = section; 617190075Sobrien if (gensym) 617290075Sobrien retlist->ll_symbol = gen_internal_sym ("LLST"); 617390075Sobrien 617490075Sobrien return retlist; 617590075Sobrien} 617690075Sobrien 617790075Sobrien/* Add a location description expression to a location list */ 617890075Sobrien 617990075Sobrienstatic inline void 618090075Sobrienadd_loc_descr_to_loc_list (list_head, descr, begin, end, section) 618190075Sobrien dw_loc_list_ref *list_head; 618290075Sobrien dw_loc_descr_ref descr; 618390075Sobrien const char *begin; 618490075Sobrien const char *end; 618590075Sobrien const char *section; 618690075Sobrien{ 618790075Sobrien dw_loc_list_ref *d; 618890075Sobrien 618990075Sobrien /* Find the end of the chain. */ 619090075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 619190075Sobrien ; 619290075Sobrien 619390075Sobrien /* Add a new location list node to the list */ 619490075Sobrien *d = new_loc_list (descr, begin, end, section, 0); 619590075Sobrien} 619690075Sobrien 619790075Sobrien/* Output the location list given to us */ 619890075Sobrien 619950397Sobrienstatic void 620090075Sobrienoutput_loc_list (list_head) 620190075Sobrien dw_loc_list_ref list_head; 620250397Sobrien{ 620390075Sobrien dw_loc_list_ref curr = list_head; 620450397Sobrien 620590075Sobrien ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); 620690075Sobrien 620790075Sobrien /* ??? This shouldn't be needed now that we've forced the 620890075Sobrien compilation unit base address to zero when there is code 620990075Sobrien in more than one section. */ 621090075Sobrien if (strcmp (curr->section, ".text") == 0) 621150397Sobrien { 621290075Sobrien /* dw2_asm_output_data will mask off any extra bits in the ~0. */ 621390075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0, 621490075Sobrien "Location list base address specifier fake entry"); 621590075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section, 621690075Sobrien "Location list base address specifier base"); 621750397Sobrien } 621850397Sobrien 621990075Sobrien for (curr = list_head; curr != NULL; curr=curr->dw_loc_next) 622090075Sobrien { 622190075Sobrien unsigned long size; 622250397Sobrien 622390075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, 622490075Sobrien "Location list begin address (%s)", 622590075Sobrien list_head->ll_symbol); 622690075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section, 622790075Sobrien "Location list end address (%s)", 622890075Sobrien list_head->ll_symbol); 622990075Sobrien size = size_of_locs (curr->expr); 623090075Sobrien 623190075Sobrien /* Output the block length for this list of location operations. */ 623290075Sobrien if (size > 0xffff) 623390075Sobrien abort (); 623490075Sobrien dw2_asm_output_data (2, size, "%s", "Location expression size"); 623550397Sobrien 623690075Sobrien output_loc_sequence (curr->expr); 623790075Sobrien } 623850397Sobrien 623990075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 624090075Sobrien "Location list terminator begin (%s)", 624190075Sobrien list_head->ll_symbol); 624290075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 624390075Sobrien "Location list terminator end (%s)", 624490075Sobrien list_head->ll_symbol); 624550397Sobrien} 624650397Sobrien 624750397Sobrien/* Output the DIE and its attributes. Called recursively to generate 624850397Sobrien the definitions of each child DIE. */ 624950397Sobrien 625050397Sobrienstatic void 625150397Sobrienoutput_die (die) 625290075Sobrien dw_die_ref die; 625350397Sobrien{ 625490075Sobrien dw_attr_ref a; 625590075Sobrien dw_die_ref c; 625690075Sobrien unsigned long size; 625750397Sobrien 625890075Sobrien /* If someone in another CU might refer to us, set up a symbol for 625990075Sobrien them to point to. */ 626090075Sobrien if (die->die_symbol) 626190075Sobrien output_die_symbol (die); 626250397Sobrien 626390075Sobrien dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)", 626490075Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 626550397Sobrien 626650397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 626750397Sobrien { 626890075Sobrien const char *name = dwarf_attr_name (a->dw_attr); 626990075Sobrien 627090075Sobrien switch (AT_class (a)) 627150397Sobrien { 627250397Sobrien case dw_val_class_addr: 627390075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); 627450397Sobrien break; 627550397Sobrien 627690075Sobrien case dw_val_class_offset: 627790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset, 627890075Sobrien "%s", name); 627990075Sobrien break; 628050397Sobrien 628190075Sobrien case dw_val_class_range_list: 628290075Sobrien { 628390075Sobrien char *p = strchr (ranges_section_label, '\0'); 628450397Sobrien 628590075Sobrien sprintf (p, "+0x%lx", a->dw_attr_val.v.val_offset); 628690075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label, 628790075Sobrien "%s", name); 628890075Sobrien *p = '\0'; 628990075Sobrien } 629090075Sobrien break; 629150397Sobrien 629290075Sobrien case dw_val_class_loc: 629390075Sobrien size = size_of_locs (AT_loc (a)); 629450397Sobrien 629590075Sobrien /* Output the block length for this list of location operations. */ 629690075Sobrien dw2_asm_output_data (constant_size (size), size, "%s", name); 629750397Sobrien 629890075Sobrien output_loc_sequence (AT_loc (a)); 629950397Sobrien break; 630050397Sobrien 630150397Sobrien case dw_val_class_const: 630290075Sobrien /* ??? It would be slightly more efficient to use a scheme like is 630390075Sobrien used for unsigned constants below, but gdb 4.x does not sign 630490075Sobrien extend. Gdb 5.x does sign extend. */ 630590075Sobrien dw2_asm_output_data_sleb128 (AT_int (a), "%s", name); 630650397Sobrien break; 630750397Sobrien 630850397Sobrien case dw_val_class_unsigned_const: 630990075Sobrien dw2_asm_output_data (constant_size (AT_unsigned (a)), 631090075Sobrien AT_unsigned (a), "%s", name); 631150397Sobrien break; 631250397Sobrien 631350397Sobrien case dw_val_class_long_long: 631490075Sobrien { 631590075Sobrien unsigned HOST_WIDE_INT first, second; 631650397Sobrien 631790075Sobrien dw2_asm_output_data (1, 631890075Sobrien 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 631990075Sobrien "%s", name); 632050397Sobrien 632190075Sobrien if (WORDS_BIG_ENDIAN) 632290075Sobrien { 632390075Sobrien first = a->dw_attr_val.v.val_long_long.hi; 632490075Sobrien second = a->dw_attr_val.v.val_long_long.low; 632590075Sobrien } 632690075Sobrien else 632790075Sobrien { 632890075Sobrien first = a->dw_attr_val.v.val_long_long.low; 632990075Sobrien second = a->dw_attr_val.v.val_long_long.hi; 633090075Sobrien } 633190075Sobrien 633290075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 633390075Sobrien first, "long long constant"); 633490075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 633590075Sobrien second, NULL); 633690075Sobrien } 633750397Sobrien break; 633850397Sobrien 633950397Sobrien case dw_val_class_float: 634052284Sobrien { 634190075Sobrien unsigned int i; 634250397Sobrien 634390075Sobrien dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4, 634490075Sobrien "%s", name); 634550397Sobrien 634690075Sobrien for (i = 0; i < a->dw_attr_val.v.val_float.length; i++) 634790075Sobrien dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i], 634890075Sobrien "fp constant word %u", i); 634990075Sobrien break; 635052284Sobrien } 635150397Sobrien 635250397Sobrien case dw_val_class_flag: 635390075Sobrien dw2_asm_output_data (1, AT_flag (a), "%s", name); 635450397Sobrien break; 635550397Sobrien 635690075Sobrien case dw_val_class_loc_list: 635790075Sobrien { 635890075Sobrien char *sym = AT_loc_list (a)->ll_symbol; 635990075Sobrien 636090075Sobrien if (sym == 0) 636190075Sobrien abort (); 636290075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, 636390075Sobrien loc_section_label, "%s", name); 636490075Sobrien } 636590075Sobrien break; 636690075Sobrien 636750397Sobrien case dw_val_class_die_ref: 636890075Sobrien if (AT_ref_external (a)) 636990075Sobrien { 637090075Sobrien char *sym = AT_ref (a)->die_symbol; 637190075Sobrien 637290075Sobrien if (sym == 0) 637390075Sobrien abort (); 637490075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, sym, "%s", name); 637590075Sobrien } 637690075Sobrien else if (AT_ref (a)->die_offset == 0) 637790075Sobrien abort (); 637850397Sobrien else 637990075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset, 638090075Sobrien "%s", name); 638150397Sobrien break; 638250397Sobrien 638350397Sobrien case dw_val_class_fde_ref: 638450397Sobrien { 638550397Sobrien char l1[20]; 638690075Sobrien 638790075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL, 638890075Sobrien a->dw_attr_val.v.val_fde_index * 2); 638990075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, "%s", name); 639050397Sobrien } 639150397Sobrien break; 639250397Sobrien 639350397Sobrien case dw_val_class_lbl_id: 639490075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name); 639550397Sobrien break; 639650397Sobrien 639752284Sobrien case dw_val_class_lbl_offset: 639890075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a), "%s", name); 639950397Sobrien break; 640050397Sobrien 640150397Sobrien case dw_val_class_str: 640290075Sobrien if (AT_string_form (a) == DW_FORM_strp) 640390075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, 640490075Sobrien a->dw_attr_val.v.val_str->label, 640590075Sobrien "%s: \"%s\"", name, AT_string (a)); 640650397Sobrien else 640790075Sobrien dw2_asm_output_nstring (AT_string (a), -1, "%s", name); 640850397Sobrien break; 640950397Sobrien 641050397Sobrien default: 641150397Sobrien abort (); 641250397Sobrien } 641350397Sobrien } 641450397Sobrien 641550397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 641650397Sobrien output_die (c); 641750397Sobrien 641890075Sobrien /* Add null byte to terminate sibling list. */ 641950397Sobrien if (die->die_child != NULL) 642090075Sobrien dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx", 642190075Sobrien die->die_offset); 642250397Sobrien} 642350397Sobrien 642450397Sobrien/* Output the compilation unit that appears at the beginning of the 642550397Sobrien .debug_info section, and precedes the DIE descriptions. */ 642650397Sobrien 642750397Sobrienstatic void 642850397Sobrienoutput_compilation_unit_header () 642950397Sobrien{ 643090075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset - DWARF_OFFSET_SIZE, 643190075Sobrien "Length of Compilation Unit Info"); 643290075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number"); 643390075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label, 643490075Sobrien "Offset Into Abbrev. Section"); 643590075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); 643690075Sobrien} 643750397Sobrien 643890075Sobrien/* Output the compilation unit DIE and its children. */ 643950397Sobrien 644090075Sobrienstatic void 644190075Sobrienoutput_comp_unit (die) 644290075Sobrien dw_die_ref die; 644390075Sobrien{ 644490075Sobrien const char *secname; 644550397Sobrien 644690075Sobrien /* Even if there are no children of this DIE, we must output the information 644790075Sobrien about the compilation unit. Otherwise, on an empty translation unit, we 644890075Sobrien will generate a present, but empty, .debug_info section. IRIX 6.5 `nm' 644990075Sobrien will then complain when examining the file. First mark all the DIEs in 645090075Sobrien this CU so we know which get local refs. */ 645190075Sobrien mark_dies (die); 645250397Sobrien 645390075Sobrien build_abbrev_table (die); 645490075Sobrien 645590075Sobrien /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ 645690075Sobrien next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; 645790075Sobrien calc_die_sizes (die); 645890075Sobrien 645990075Sobrien if (die->die_symbol) 646090075Sobrien { 646190075Sobrien char *tmp = (char *) alloca (strlen (die->die_symbol) + 24); 646290075Sobrien 646390075Sobrien sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol); 646490075Sobrien secname = tmp; 646590075Sobrien die->die_symbol = NULL; 646690075Sobrien } 646790075Sobrien else 646890075Sobrien secname = (const char *) DEBUG_INFO_SECTION; 646990075Sobrien 647090075Sobrien /* Output debugging information. */ 647190075Sobrien named_section_flags (secname, SECTION_DEBUG); 647290075Sobrien output_compilation_unit_header (); 647390075Sobrien output_die (die); 647490075Sobrien 647590075Sobrien /* Leave the marks on the main CU, so we can check them in 647690075Sobrien output_pubnames. */ 647790075Sobrien if (die->die_symbol) 647890075Sobrien unmark_dies (die); 647950397Sobrien} 648050397Sobrien 648150397Sobrien/* The DWARF2 pubname for a nested thingy looks like "A::f". The output 648250397Sobrien of decl_printable_name for C++ looks like "A::f(int)". Let's drop the 648350397Sobrien argument list, and maybe the scope. */ 648450397Sobrien 648590075Sobrienstatic const char * 648650397Sobriendwarf2_name (decl, scope) 648750397Sobrien tree decl; 648850397Sobrien int scope; 648950397Sobrien{ 649050397Sobrien return (*decl_printable_name) (decl, scope ? 1 : 0); 649150397Sobrien} 649250397Sobrien 649350397Sobrien/* Add a new entry to .debug_pubnames if appropriate. */ 649450397Sobrien 649550397Sobrienstatic void 649650397Sobrienadd_pubname (decl, die) 649750397Sobrien tree decl; 649850397Sobrien dw_die_ref die; 649950397Sobrien{ 650050397Sobrien pubname_ref p; 650150397Sobrien 650250397Sobrien if (! TREE_PUBLIC (decl)) 650350397Sobrien return; 650450397Sobrien 650550397Sobrien if (pubname_table_in_use == pubname_table_allocated) 650650397Sobrien { 650750397Sobrien pubname_table_allocated += PUBNAME_TABLE_INCREMENT; 650890075Sobrien pubname_table 650990075Sobrien = (pubname_ref) xrealloc (pubname_table, 651090075Sobrien (pubname_table_allocated 651190075Sobrien * sizeof (pubname_entry))); 651250397Sobrien } 651350397Sobrien 651450397Sobrien p = &pubname_table[pubname_table_in_use++]; 651550397Sobrien p->die = die; 651650397Sobrien p->name = xstrdup (dwarf2_name (decl, 1)); 651750397Sobrien} 651850397Sobrien 651950397Sobrien/* Output the public names table used to speed up access to externally 652050397Sobrien visible names. For now, only generate entries for externally 652150397Sobrien visible procedures. */ 652250397Sobrien 652350397Sobrienstatic void 652450397Sobrienoutput_pubnames () 652550397Sobrien{ 652690075Sobrien unsigned i; 652790075Sobrien unsigned long pubnames_length = size_of_pubnames (); 652850397Sobrien 652990075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, 653090075Sobrien "Length of Public Names Info"); 653190075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 653290075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 653390075Sobrien "Offset of Compilation Unit Info"); 653490075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset, 653590075Sobrien "Compilation Unit Length"); 653650397Sobrien 653790075Sobrien for (i = 0; i < pubname_table_in_use; i++) 653850397Sobrien { 653990075Sobrien pubname_ref pub = &pubname_table[i]; 654050397Sobrien 654190075Sobrien /* We shouldn't see pubnames for DIEs outside of the main CU. */ 654290075Sobrien if (pub->die->die_mark == 0) 654390075Sobrien abort (); 654450397Sobrien 654590075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset, 654690075Sobrien "DIE offset"); 654750397Sobrien 654890075Sobrien dw2_asm_output_nstring (pub->name, -1, "external name"); 654950397Sobrien } 655050397Sobrien 655190075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); 655250397Sobrien} 655350397Sobrien 655450397Sobrien/* Add a new entry to .debug_aranges if appropriate. */ 655550397Sobrien 655650397Sobrienstatic void 655750397Sobrienadd_arange (decl, die) 655850397Sobrien tree decl; 655950397Sobrien dw_die_ref die; 656050397Sobrien{ 656150397Sobrien if (! DECL_SECTION_NAME (decl)) 656250397Sobrien return; 656350397Sobrien 656450397Sobrien if (arange_table_in_use == arange_table_allocated) 656550397Sobrien { 656650397Sobrien arange_table_allocated += ARANGE_TABLE_INCREMENT; 656790075Sobrien arange_table = (dw_die_ref *) 656890075Sobrien xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref)); 656950397Sobrien } 657050397Sobrien 657150397Sobrien arange_table[arange_table_in_use++] = die; 657250397Sobrien} 657350397Sobrien 657450397Sobrien/* Output the information that goes into the .debug_aranges table. 657550397Sobrien Namely, define the beginning and ending address range of the 657650397Sobrien text section generated for this compilation unit. */ 657750397Sobrien 657850397Sobrienstatic void 657950397Sobrienoutput_aranges () 658050397Sobrien{ 658190075Sobrien unsigned i; 658290075Sobrien unsigned long aranges_length = size_of_aranges (); 658350397Sobrien 658490075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length, 658590075Sobrien "Length of Address Ranges Info"); 658690075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 658790075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 658890075Sobrien "Offset of Compilation Unit Info"); 658990075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address"); 659090075Sobrien dw2_asm_output_data (1, 0, "Size of Segment Descriptor"); 659150397Sobrien 659290075Sobrien /* We need to align to twice the pointer size here. */ 659390075Sobrien if (DWARF_ARANGES_PAD_SIZE) 659490075Sobrien { 659590075Sobrien /* Pad using a 2 byte words so that padding is correct for any 659690075Sobrien pointer size. */ 659790075Sobrien dw2_asm_output_data (2, 0, "Pad to %d byte boundary", 659890075Sobrien 2 * DWARF2_ADDR_SIZE); 659990075Sobrien for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2) 660090075Sobrien dw2_asm_output_data (2, 0, NULL); 660190075Sobrien } 660250397Sobrien 660390075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); 660490075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, 660590075Sobrien text_section_label, "Length"); 660650397Sobrien 660790075Sobrien for (i = 0; i < arange_table_in_use; i++) 660890075Sobrien { 660990075Sobrien dw_die_ref die = arange_table[i]; 661050397Sobrien 661190075Sobrien /* We shouldn't see aranges for DIEs outside of the main CU. */ 661290075Sobrien if (die->die_mark == 0) 661390075Sobrien abort (); 661450397Sobrien 661590075Sobrien if (die->die_tag == DW_TAG_subprogram) 661690075Sobrien { 661790075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die), 661890075Sobrien "Address"); 661990075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die), 662090075Sobrien get_AT_low_pc (die), "Length"); 662190075Sobrien } 662290075Sobrien else 662390075Sobrien { 662490075Sobrien /* A static variable; extract the symbol from DW_AT_location. 662590075Sobrien Note that this code isn't currently hit, as we only emit 662690075Sobrien aranges for functions (jason 9/23/99). */ 662790075Sobrien dw_attr_ref a = get_AT (die, DW_AT_location); 662890075Sobrien dw_loc_descr_ref loc; 662950397Sobrien 663090075Sobrien if (! a || AT_class (a) != dw_val_class_loc) 663190075Sobrien abort (); 663250397Sobrien 663390075Sobrien loc = AT_loc (a); 663490075Sobrien if (loc->dw_loc_opc != DW_OP_addr) 663590075Sobrien abort (); 663650397Sobrien 663790075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, 663890075Sobrien loc->dw_loc_oprnd1.v.val_addr, "Address"); 663990075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 664090075Sobrien get_AT_unsigned (die, DW_AT_byte_size), 664190075Sobrien "Length"); 664290075Sobrien } 664390075Sobrien } 664450397Sobrien 664590075Sobrien /* Output the terminator words. */ 664690075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 664790075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 664890075Sobrien} 664990075Sobrien 665090075Sobrien/* Add a new entry to .debug_ranges. Return the offset at which it 665190075Sobrien was placed. */ 665290075Sobrien 665390075Sobrienstatic unsigned int 665490075Sobrienadd_ranges (block) 665590075Sobrien tree block; 665690075Sobrien{ 665790075Sobrien unsigned int in_use = ranges_table_in_use; 665890075Sobrien 665990075Sobrien if (in_use == ranges_table_allocated) 666050397Sobrien { 666190075Sobrien ranges_table_allocated += RANGES_TABLE_INCREMENT; 666290075Sobrien ranges_table = (dw_ranges_ref) 666390075Sobrien xrealloc (ranges_table, (ranges_table_allocated 666490075Sobrien * sizeof (struct dw_ranges_struct))); 666590075Sobrien } 666650397Sobrien 666790075Sobrien ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0); 666890075Sobrien ranges_table_in_use = in_use + 1; 666990075Sobrien 667090075Sobrien return in_use * 2 * DWARF2_ADDR_SIZE; 667190075Sobrien} 667290075Sobrien 667390075Sobrienstatic void 667490075Sobrienoutput_ranges () 667590075Sobrien{ 667690075Sobrien unsigned i; 667790075Sobrien static const char *const start_fmt = "Offset 0x%x"; 667890075Sobrien const char *fmt = start_fmt; 667990075Sobrien 668090075Sobrien for (i = 0; i < ranges_table_in_use; i++) 668190075Sobrien { 668290075Sobrien int block_num = ranges_table[i].block_num; 668390075Sobrien 668490075Sobrien if (block_num) 668590075Sobrien { 668690075Sobrien char blabel[MAX_ARTIFICIAL_LABEL_BYTES]; 668790075Sobrien char elabel[MAX_ARTIFICIAL_LABEL_BYTES]; 668890075Sobrien 668990075Sobrien ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num); 669090075Sobrien ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num); 669190075Sobrien 669290075Sobrien /* If all code is in the text section, then the compilation 669390075Sobrien unit base address defaults to DW_AT_low_pc, which is the 669490075Sobrien base of the text section. */ 669590075Sobrien if (separate_line_info_table_in_use == 0) 669690075Sobrien { 669790075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, 669890075Sobrien text_section_label, 669990075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 670090075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, 670190075Sobrien text_section_label, NULL); 670290075Sobrien } 670390075Sobrien 670490075Sobrien /* Otherwise, we add a DW_AT_entry_pc attribute to force the 670590075Sobrien compilation unit base address to zero, which allows us to 670690075Sobrien use absolute addresses, and not worry about whether the 670790075Sobrien target supports cross-section arithmetic. */ 670890075Sobrien else 670990075Sobrien { 671090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, 671190075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 671290075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL); 671390075Sobrien } 671490075Sobrien 671590075Sobrien fmt = NULL; 671690075Sobrien } 671750397Sobrien else 671850397Sobrien { 671990075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 672090075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 672190075Sobrien fmt = start_fmt; 672290075Sobrien } 672390075Sobrien } 672490075Sobrien} 672550397Sobrien 672690075Sobrien/* Data structure containing information about input files. */ 672790075Sobrienstruct file_info 672890075Sobrien{ 672990075Sobrien char *path; /* Complete file name. */ 673090075Sobrien char *fname; /* File name part. */ 673190075Sobrien int length; /* Length of entire string. */ 673290075Sobrien int file_idx; /* Index in input file table. */ 673390075Sobrien int dir_idx; /* Index in directory table. */ 673490075Sobrien}; 673590075Sobrien 673690075Sobrien/* Data structure containing information about directories with source 673790075Sobrien files. */ 673890075Sobrienstruct dir_info 673990075Sobrien{ 674090075Sobrien char *path; /* Path including directory name. */ 674190075Sobrien int length; /* Path length. */ 674290075Sobrien int prefix; /* Index of directory entry which is a prefix. */ 674390075Sobrien int count; /* Number of files in this directory. */ 674490075Sobrien int dir_idx; /* Index of directory used as base. */ 674590075Sobrien int used; /* Used in the end? */ 674690075Sobrien}; 674790075Sobrien 674890075Sobrien/* Callback function for file_info comparison. We sort by looking at 674990075Sobrien the directories in the path. */ 675090075Sobrien 675190075Sobrienstatic int 675290075Sobrienfile_info_cmp (p1, p2) 675390075Sobrien const void *p1; 675490075Sobrien const void *p2; 675590075Sobrien{ 675690075Sobrien const struct file_info *s1 = p1; 675790075Sobrien const struct file_info *s2 = p2; 675890075Sobrien unsigned char *cp1; 675990075Sobrien unsigned char *cp2; 676090075Sobrien 676190075Sobrien /* Take care of file names without directories. We need to make sure that 676290075Sobrien we return consistent values to qsort since some will get confused if 676390075Sobrien we return the same value when identical operands are passed in opposite 676490075Sobrien orders. So if neither has a directory, return 0 and otherwise return 676590075Sobrien 1 or -1 depending on which one has the directory. */ 676690075Sobrien if ((s1->path == s1->fname || s2->path == s2->fname)) 676790075Sobrien return (s2->path == s2->fname) - (s1->path == s1->fname); 676890075Sobrien 676990075Sobrien cp1 = (unsigned char *) s1->path; 677090075Sobrien cp2 = (unsigned char *) s2->path; 677190075Sobrien 677290075Sobrien while (1) 677390075Sobrien { 677490075Sobrien ++cp1; 677590075Sobrien ++cp2; 677690075Sobrien /* Reached the end of the first path? If so, handle like above. */ 677790075Sobrien if ((cp1 == (unsigned char *) s1->fname) 677890075Sobrien || (cp2 == (unsigned char *) s2->fname)) 677990075Sobrien return ((cp2 == (unsigned char *) s2->fname) 678090075Sobrien - (cp1 == (unsigned char *) s1->fname)); 678190075Sobrien 678290075Sobrien /* Character of current path component the same? */ 678390075Sobrien else if (*cp1 != *cp2) 678490075Sobrien return *cp1 - *cp2; 678590075Sobrien } 678690075Sobrien} 678790075Sobrien 678890075Sobrien/* Output the directory table and the file name table. We try to minimize 678990075Sobrien the total amount of memory needed. A heuristic is used to avoid large 679090075Sobrien slowdowns with many input files. */ 679190075Sobrien 679290075Sobrienstatic void 679390075Sobrienoutput_file_names () 679490075Sobrien{ 679590075Sobrien struct file_info *files; 679690075Sobrien struct dir_info *dirs; 679790075Sobrien int *saved; 679890075Sobrien int *savehere; 679990075Sobrien int *backmap; 680090075Sobrien int ndirs; 680190075Sobrien int idx_offset; 680290075Sobrien int i; 680390075Sobrien int idx; 680490075Sobrien 680590075Sobrien /* Allocate the various arrays we need. */ 680690075Sobrien files = (struct file_info *) alloca (file_table.in_use 680790075Sobrien * sizeof (struct file_info)); 680890075Sobrien dirs = (struct dir_info *) alloca (file_table.in_use 680990075Sobrien * sizeof (struct dir_info)); 681090075Sobrien 681190075Sobrien /* Sort the file names. */ 681290075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 681390075Sobrien { 681490075Sobrien char *f; 681590075Sobrien 681690075Sobrien /* Skip all leading "./". */ 681790075Sobrien f = file_table.table[i]; 681890075Sobrien while (f[0] == '.' && f[1] == '/') 681990075Sobrien f += 2; 682090075Sobrien 682190075Sobrien /* Create a new array entry. */ 682290075Sobrien files[i].path = f; 682390075Sobrien files[i].length = strlen (f); 682490075Sobrien files[i].file_idx = i; 682590075Sobrien 682690075Sobrien /* Search for the file name part. */ 682790075Sobrien f = strrchr (f, '/'); 682890075Sobrien files[i].fname = f == NULL ? files[i].path : f + 1; 682990075Sobrien } 683090075Sobrien 683190075Sobrien qsort (files + 1, file_table.in_use - 1, sizeof (files[0]), file_info_cmp); 683290075Sobrien 683390075Sobrien /* Find all the different directories used. */ 683490075Sobrien dirs[0].path = files[1].path; 683590075Sobrien dirs[0].length = files[1].fname - files[1].path; 683690075Sobrien dirs[0].prefix = -1; 683790075Sobrien dirs[0].count = 1; 683890075Sobrien dirs[0].dir_idx = 0; 683990075Sobrien dirs[0].used = 0; 684090075Sobrien files[1].dir_idx = 0; 684190075Sobrien ndirs = 1; 684290075Sobrien 684390075Sobrien for (i = 2; i < (int) file_table.in_use; i++) 684490075Sobrien if (files[i].fname - files[i].path == dirs[ndirs - 1].length 684590075Sobrien && memcmp (dirs[ndirs - 1].path, files[i].path, 684690075Sobrien dirs[ndirs - 1].length) == 0) 684790075Sobrien { 684890075Sobrien /* Same directory as last entry. */ 684990075Sobrien files[i].dir_idx = ndirs - 1; 685090075Sobrien ++dirs[ndirs - 1].count; 685190075Sobrien } 685290075Sobrien else 685390075Sobrien { 685490075Sobrien int j; 685590075Sobrien 685690075Sobrien /* This is a new directory. */ 685790075Sobrien dirs[ndirs].path = files[i].path; 685890075Sobrien dirs[ndirs].length = files[i].fname - files[i].path; 685990075Sobrien dirs[ndirs].count = 1; 686090075Sobrien dirs[ndirs].dir_idx = ndirs; 686190075Sobrien dirs[ndirs].used = 0; 686290075Sobrien files[i].dir_idx = ndirs; 686390075Sobrien 686490075Sobrien /* Search for a prefix. */ 686590075Sobrien dirs[ndirs].prefix = -1; 686690075Sobrien for (j = 0; j < ndirs; j++) 686790075Sobrien if (dirs[j].length < dirs[ndirs].length 686890075Sobrien && dirs[j].length > 1 686990075Sobrien && (dirs[ndirs].prefix == -1 687090075Sobrien || dirs[j].length > dirs[dirs[ndirs].prefix].length) 687190075Sobrien && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0) 687290075Sobrien dirs[ndirs].prefix = j; 687390075Sobrien 687490075Sobrien ++ndirs; 687590075Sobrien } 687690075Sobrien 687790075Sobrien /* Now to the actual work. We have to find a subset of the directories which 687890075Sobrien allow expressing the file name using references to the directory table 687990075Sobrien with the least amount of characters. We do not do an exhaustive search 688090075Sobrien where we would have to check out every combination of every single 688190075Sobrien possible prefix. Instead we use a heuristic which provides nearly optimal 688290075Sobrien results in most cases and never is much off. */ 688390075Sobrien saved = (int *) alloca (ndirs * sizeof (int)); 688490075Sobrien savehere = (int *) alloca (ndirs * sizeof (int)); 688590075Sobrien 688690075Sobrien memset (saved, '\0', ndirs * sizeof (saved[0])); 688790075Sobrien for (i = 0; i < ndirs; i++) 688890075Sobrien { 688990075Sobrien int j; 689090075Sobrien int total; 689190075Sobrien 689290075Sobrien /* We can always save some space for the current directory. But this 689390075Sobrien does not mean it will be enough to justify adding the directory. */ 689490075Sobrien savehere[i] = dirs[i].length; 689590075Sobrien total = (savehere[i] - saved[i]) * dirs[i].count; 689690075Sobrien 689790075Sobrien for (j = i + 1; j < ndirs; j++) 689890075Sobrien { 689990075Sobrien savehere[j] = 0; 690090075Sobrien if (saved[j] < dirs[i].length) 690190075Sobrien { 690290075Sobrien /* Determine whether the dirs[i] path is a prefix of the 690390075Sobrien dirs[j] path. */ 690490075Sobrien int k; 690590075Sobrien 690690075Sobrien k = dirs[j].prefix; 690790075Sobrien while (k != -1 && k != i) 690890075Sobrien k = dirs[k].prefix; 690990075Sobrien 691090075Sobrien if (k == i) 691190075Sobrien { 691290075Sobrien /* Yes it is. We can possibly safe some memory but 691390075Sobrien writing the filenames in dirs[j] relative to 691490075Sobrien dirs[i]. */ 691590075Sobrien savehere[j] = dirs[i].length; 691690075Sobrien total += (savehere[j] - saved[j]) * dirs[j].count; 691790075Sobrien } 691890075Sobrien } 691950397Sobrien } 692050397Sobrien 692190075Sobrien /* Check whether we can safe enough to justify adding the dirs[i] 692290075Sobrien directory. */ 692390075Sobrien if (total > dirs[i].length + 1) 692490075Sobrien { 692590075Sobrien /* It's worthwhile adding. */ 692690075Sobrien for (j = i; j < ndirs; j++) 692790075Sobrien if (savehere[j] > 0) 692890075Sobrien { 692990075Sobrien /* Remember how much we saved for this directory so far. */ 693090075Sobrien saved[j] = savehere[j]; 693150397Sobrien 693290075Sobrien /* Remember the prefix directory. */ 693390075Sobrien dirs[j].dir_idx = i; 693490075Sobrien } 693590075Sobrien } 693690075Sobrien } 693750397Sobrien 693890075Sobrien /* We have to emit them in the order they appear in the file_table array 693990075Sobrien since the index is used in the debug info generation. To do this 694090075Sobrien efficiently we generate a back-mapping of the indices first. */ 694190075Sobrien backmap = (int *) alloca (file_table.in_use * sizeof (int)); 694290075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 694390075Sobrien { 694490075Sobrien backmap[files[i].file_idx] = i; 694550397Sobrien 694690075Sobrien /* Mark this directory as used. */ 694790075Sobrien dirs[dirs[files[i].dir_idx].dir_idx].used = 1; 694850397Sobrien } 694950397Sobrien 695090075Sobrien /* That was it. We are ready to emit the information. First emit the 695190075Sobrien directory name table. We have to make sure the first actually emitted 695290075Sobrien directory name has index one; zero is reserved for the current working 695390075Sobrien directory. Make sure we do not confuse these indices with the one for the 695490075Sobrien constructed table (even though most of the time they are identical). */ 695590075Sobrien idx = 1; 695690075Sobrien idx_offset = dirs[0].length > 0 ? 1 : 0; 695790075Sobrien for (i = 1 - idx_offset; i < ndirs; i++) 695890075Sobrien if (dirs[i].used != 0) 695990075Sobrien { 696090075Sobrien dirs[i].used = idx++; 696190075Sobrien dw2_asm_output_nstring (dirs[i].path, dirs[i].length - 1, 696290075Sobrien "Directory Entry: 0x%x", dirs[i].used); 696390075Sobrien } 696490075Sobrien 696590075Sobrien dw2_asm_output_data (1, 0, "End directory table"); 696690075Sobrien 696790075Sobrien /* Correct the index for the current working directory entry if it 696890075Sobrien exists. */ 696990075Sobrien if (idx_offset == 0) 697090075Sobrien dirs[0].used = 0; 697190075Sobrien 697290075Sobrien /* Now write all the file names. */ 697390075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 697490075Sobrien { 697590075Sobrien int file_idx = backmap[i]; 697690075Sobrien int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; 697790075Sobrien 697890075Sobrien dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, 697990075Sobrien "File Entry: 0x%x", i); 698090075Sobrien 698190075Sobrien /* Include directory index. */ 698290075Sobrien dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL); 698390075Sobrien 698490075Sobrien /* Modification time. */ 698590075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 698690075Sobrien 698790075Sobrien /* File length in bytes. */ 698890075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 698990075Sobrien } 699090075Sobrien 699190075Sobrien dw2_asm_output_data (1, 0, "End file name table"); 699250397Sobrien} 699350397Sobrien 699490075Sobrien 699550397Sobrien/* Output the source line number correspondence information. This 699690075Sobrien information goes into the .debug_line section. */ 699750397Sobrien 699850397Sobrienstatic void 699950397Sobrienoutput_line_info () 700050397Sobrien{ 700190075Sobrien char l1[20], l2[20], p1[20], p2[20]; 700250397Sobrien char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 700350397Sobrien char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 700490075Sobrien unsigned opc; 700590075Sobrien unsigned n_op_args; 700690075Sobrien unsigned long lt_index; 700790075Sobrien unsigned long current_line; 700890075Sobrien long line_offset; 700990075Sobrien long line_delta; 701090075Sobrien unsigned long current_file; 701190075Sobrien unsigned long function; 701250397Sobrien 701390075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0); 701490075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0); 701590075Sobrien ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0); 701690075Sobrien ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0); 701750397Sobrien 701890075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, 701990075Sobrien "Length of Source Line Info"); 702090075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 702150397Sobrien 702290075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 702390075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length"); 702490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p1); 702550397Sobrien 702696263Sobrien /* Define the architecture-dependent minimum instruction length (in 702796263Sobrien bytes). In this implementation of DWARF, this field is used for 702896263Sobrien information purposes only. Since GCC generates assembly language, 702996263Sobrien we have no a priori knowledge of how many instruction bytes are 703096263Sobrien generated for each source line, and therefore can use only the 703196263Sobrien DW_LNE_set_address and DW_LNS_fixed_advance_pc line information 703296263Sobrien commands. Accordingly, we fix this as `1', which is "correct 703396263Sobrien enough" for all architectures, and don't let the target override. */ 703496263Sobrien dw2_asm_output_data (1, 1, 703590075Sobrien "Minimum Instruction Length"); 703696263Sobrien 703790075Sobrien dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, 703890075Sobrien "Default is_stmt_start flag"); 703990075Sobrien dw2_asm_output_data (1, DWARF_LINE_BASE, 704090075Sobrien "Line Base Value (Special Opcodes)"); 704190075Sobrien dw2_asm_output_data (1, DWARF_LINE_RANGE, 704290075Sobrien "Line Range Value (Special Opcodes)"); 704390075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE, 704490075Sobrien "Special Opcode Base"); 704550397Sobrien 704690075Sobrien for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++) 704750397Sobrien { 704850397Sobrien switch (opc) 704950397Sobrien { 705050397Sobrien case DW_LNS_advance_pc: 705150397Sobrien case DW_LNS_advance_line: 705250397Sobrien case DW_LNS_set_file: 705350397Sobrien case DW_LNS_set_column: 705450397Sobrien case DW_LNS_fixed_advance_pc: 705550397Sobrien n_op_args = 1; 705650397Sobrien break; 705750397Sobrien default: 705850397Sobrien n_op_args = 0; 705950397Sobrien break; 706050397Sobrien } 706150397Sobrien 706290075Sobrien dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args", 706390075Sobrien opc, n_op_args); 706450397Sobrien } 706550397Sobrien 706690075Sobrien /* Write out the information about the files we use. */ 706790075Sobrien output_file_names (); 706890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p2); 706950397Sobrien 707052284Sobrien /* We used to set the address register to the first location in the text 707152284Sobrien section here, but that didn't accomplish anything since we already 707252284Sobrien have a line note for the opening brace of the first function. */ 707350397Sobrien 707450397Sobrien /* Generate the line number to PC correspondence table, encoded as 707550397Sobrien a series of state machine operations. */ 707650397Sobrien current_file = 1; 707750397Sobrien current_line = 1; 707852284Sobrien strcpy (prev_line_label, text_section_label); 707950397Sobrien for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) 708050397Sobrien { 708190075Sobrien dw_line_info_ref line_info = &line_info_table[lt_index]; 708250397Sobrien 708390075Sobrien#if 0 708490075Sobrien /* Disable this optimization for now; GDB wants to see two line notes 708590075Sobrien at the beginning of a function so it can find the end of the 708690075Sobrien prologue. */ 708790075Sobrien 708852284Sobrien /* Don't emit anything for redundant notes. Just updating the 708952284Sobrien address doesn't accomplish anything, because we already assume 709052284Sobrien that anything after the last address is this line. */ 709152284Sobrien if (line_info->dw_line_num == current_line 709252284Sobrien && line_info->dw_file_num == current_file) 709352284Sobrien continue; 709490075Sobrien#endif 709552284Sobrien 709690075Sobrien /* Emit debug info for the address of the current line. 709790075Sobrien 709890075Sobrien Unfortunately, we have little choice here currently, and must always 709990075Sobrien use the most general form. GCC does not know the address delta 710090075Sobrien itself, so we can't use DW_LNS_advance_pc. Many ports do have length 710190075Sobrien attributes which will give an upper bound on the address range. We 710290075Sobrien could perhaps use length attributes to determine when it is safe to 710390075Sobrien use DW_LNS_fixed_advance_pc. */ 710490075Sobrien 710550397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index); 710650397Sobrien if (0) 710750397Sobrien { 710850397Sobrien /* This can handle deltas up to 0xffff. This takes 3 bytes. */ 710990075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 711090075Sobrien "DW_LNS_fixed_advance_pc"); 711190075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 711250397Sobrien } 711350397Sobrien else 711450397Sobrien { 711590075Sobrien /* This can handle any delta. This takes 711690075Sobrien 4+DWARF2_ADDR_SIZE bytes. */ 711790075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 711890075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 711990075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 712090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 712150397Sobrien } 712290075Sobrien 712350397Sobrien strcpy (prev_line_label, line_label); 712450397Sobrien 712550397Sobrien /* Emit debug info for the source file of the current line, if 712650397Sobrien different from the previous line. */ 712750397Sobrien if (line_info->dw_file_num != current_file) 712850397Sobrien { 712950397Sobrien current_file = line_info->dw_file_num; 713090075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 713190075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 713290075Sobrien file_table.table[current_file]); 713350397Sobrien } 713450397Sobrien 713550397Sobrien /* Emit debug info for the current line number, choosing the encoding 713650397Sobrien that uses the least amount of space. */ 713752284Sobrien if (line_info->dw_line_num != current_line) 713850397Sobrien { 713952284Sobrien line_offset = line_info->dw_line_num - current_line; 714052284Sobrien line_delta = line_offset - DWARF_LINE_BASE; 714152284Sobrien current_line = line_info->dw_line_num; 714252284Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 714390075Sobrien /* This can handle deltas from -10 to 234, using the current 714490075Sobrien definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This 714590075Sobrien takes 1 byte. */ 714690075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 714790075Sobrien "line %lu", current_line); 714852284Sobrien else 714952284Sobrien { 715052284Sobrien /* This can handle any delta. This takes at least 4 bytes, 715152284Sobrien depending on the value being encoded. */ 715290075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 715390075Sobrien "advance to line %lu", current_line); 715490075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 715590075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 715652284Sobrien } 715750397Sobrien } 715850397Sobrien else 715990075Sobrien /* We still need to start a new row, so output a copy insn. */ 716090075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 716150397Sobrien } 716250397Sobrien 716350397Sobrien /* Emit debug info for the address of the end of the function. */ 716450397Sobrien if (0) 716550397Sobrien { 716690075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 716790075Sobrien "DW_LNS_fixed_advance_pc"); 716890075Sobrien dw2_asm_output_delta (2, text_end_label, prev_line_label, NULL); 716950397Sobrien } 717050397Sobrien else 717150397Sobrien { 717290075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 717390075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 717490075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 717590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_end_label, NULL); 717650397Sobrien } 717750397Sobrien 717890075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 717990075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 718090075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 718150397Sobrien 718250397Sobrien function = 0; 718350397Sobrien current_file = 1; 718450397Sobrien current_line = 1; 718590075Sobrien for (lt_index = 0; lt_index < separate_line_info_table_in_use;) 718650397Sobrien { 718790075Sobrien dw_separate_line_info_ref line_info 718850397Sobrien = &separate_line_info_table[lt_index]; 718950397Sobrien 719090075Sobrien#if 0 719152284Sobrien /* Don't emit anything for redundant notes. */ 719252284Sobrien if (line_info->dw_line_num == current_line 719352284Sobrien && line_info->dw_file_num == current_file 719452284Sobrien && line_info->function == function) 719552284Sobrien goto cont; 719690075Sobrien#endif 719752284Sobrien 719850397Sobrien /* Emit debug info for the address of the current line. If this is 719950397Sobrien a new function, or the first line of a function, then we need 720050397Sobrien to handle it differently. */ 720150397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL, 720250397Sobrien lt_index); 720350397Sobrien if (function != line_info->function) 720450397Sobrien { 720550397Sobrien function = line_info->function; 720650397Sobrien 720750397Sobrien /* Set the address register to the first line in the function */ 720890075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 720990075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 721090075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 721190075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 721250397Sobrien } 721350397Sobrien else 721450397Sobrien { 721550397Sobrien /* ??? See the DW_LNS_advance_pc comment above. */ 721650397Sobrien if (0) 721750397Sobrien { 721890075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 721990075Sobrien "DW_LNS_fixed_advance_pc"); 722090075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 722150397Sobrien } 722250397Sobrien else 722350397Sobrien { 722490075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 722590075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 722690075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 722790075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 722850397Sobrien } 722950397Sobrien } 723090075Sobrien 723150397Sobrien strcpy (prev_line_label, line_label); 723250397Sobrien 723350397Sobrien /* Emit debug info for the source file of the current line, if 723450397Sobrien different from the previous line. */ 723550397Sobrien if (line_info->dw_file_num != current_file) 723650397Sobrien { 723750397Sobrien current_file = line_info->dw_file_num; 723890075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 723990075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 724090075Sobrien file_table.table[current_file]); 724150397Sobrien } 724250397Sobrien 724350397Sobrien /* Emit debug info for the current line number, choosing the encoding 724450397Sobrien that uses the least amount of space. */ 724550397Sobrien if (line_info->dw_line_num != current_line) 724650397Sobrien { 724750397Sobrien line_offset = line_info->dw_line_num - current_line; 724850397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 724950397Sobrien current_line = line_info->dw_line_num; 725050397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 725190075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 725290075Sobrien "line %lu", current_line); 725350397Sobrien else 725450397Sobrien { 725590075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 725690075Sobrien "advance to line %lu", current_line); 725790075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 725890075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 725950397Sobrien } 726050397Sobrien } 726152284Sobrien else 726290075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 726350397Sobrien 726490075Sobrien#if 0 726552284Sobrien cont: 726690075Sobrien#endif 726750397Sobrien 726890075Sobrien lt_index++; 726990075Sobrien 727050397Sobrien /* If we're done with a function, end its sequence. */ 727150397Sobrien if (lt_index == separate_line_info_table_in_use 727250397Sobrien || separate_line_info_table[lt_index].function != function) 727350397Sobrien { 727450397Sobrien current_file = 1; 727550397Sobrien current_line = 1; 727650397Sobrien 727750397Sobrien /* Emit debug info for the address of the end of the function. */ 727850397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function); 727950397Sobrien if (0) 728050397Sobrien { 728190075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 728290075Sobrien "DW_LNS_fixed_advance_pc"); 728390075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 728450397Sobrien } 728550397Sobrien else 728650397Sobrien { 728790075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 728890075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 728990075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 729090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 729150397Sobrien } 729250397Sobrien 729350397Sobrien /* Output the marker for the end of this sequence. */ 729490075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 729590075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 729690075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 729750397Sobrien } 729850397Sobrien } 729990075Sobrien 730090075Sobrien /* Output the marker for the end of the line number info. */ 730190075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 730250397Sobrien} 730350397Sobrien 730450397Sobrien/* Given a pointer to a tree node for some base type, return a pointer to 730550397Sobrien a DIE that describes the given type. 730650397Sobrien 730750397Sobrien This routine must only be called for GCC type nodes that correspond to 730850397Sobrien Dwarf base (fundamental) types. */ 730950397Sobrien 731050397Sobrienstatic dw_die_ref 731150397Sobrienbase_type_die (type) 731290075Sobrien tree type; 731350397Sobrien{ 731490075Sobrien dw_die_ref base_type_result; 731590075Sobrien const char *type_name; 731690075Sobrien enum dwarf_type encoding; 731790075Sobrien tree name = TYPE_NAME (type); 731850397Sobrien 731990075Sobrien if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE) 732050397Sobrien return 0; 732150397Sobrien 732290075Sobrien if (name) 732390075Sobrien { 732490075Sobrien if (TREE_CODE (name) == TYPE_DECL) 732590075Sobrien name = DECL_NAME (name); 732650397Sobrien 732790075Sobrien type_name = IDENTIFIER_POINTER (name); 732890075Sobrien } 732990075Sobrien else 733090075Sobrien type_name = "__unknown__"; 733190075Sobrien 733250397Sobrien switch (TREE_CODE (type)) 733350397Sobrien { 733450397Sobrien case INTEGER_TYPE: 733550397Sobrien /* Carefully distinguish the C character types, without messing 733650397Sobrien up if the language is not C. Note that we check only for the names 733790075Sobrien that contain spaces; other names might occur by coincidence in other 733850397Sobrien languages. */ 733950397Sobrien if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE 734050397Sobrien && (type == char_type_node 734150397Sobrien || ! strcmp (type_name, "signed char") 734250397Sobrien || ! strcmp (type_name, "unsigned char")))) 734350397Sobrien { 734450397Sobrien if (TREE_UNSIGNED (type)) 734550397Sobrien encoding = DW_ATE_unsigned; 734650397Sobrien else 734750397Sobrien encoding = DW_ATE_signed; 734850397Sobrien break; 734950397Sobrien } 735090075Sobrien /* else fall through. */ 735150397Sobrien 735250397Sobrien case CHAR_TYPE: 735350397Sobrien /* GNU Pascal/Ada CHAR type. Not used in C. */ 735450397Sobrien if (TREE_UNSIGNED (type)) 735550397Sobrien encoding = DW_ATE_unsigned_char; 735650397Sobrien else 735750397Sobrien encoding = DW_ATE_signed_char; 735850397Sobrien break; 735950397Sobrien 736050397Sobrien case REAL_TYPE: 736150397Sobrien encoding = DW_ATE_float; 736250397Sobrien break; 736350397Sobrien 736490075Sobrien /* Dwarf2 doesn't know anything about complex ints, so use 736590075Sobrien a user defined type for it. */ 736650397Sobrien case COMPLEX_TYPE: 736790075Sobrien if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) 736890075Sobrien encoding = DW_ATE_complex_float; 736990075Sobrien else 737090075Sobrien encoding = DW_ATE_lo_user; 737150397Sobrien break; 737250397Sobrien 737350397Sobrien case BOOLEAN_TYPE: 737450397Sobrien /* GNU FORTRAN/Ada/C++ BOOLEAN type. */ 737550397Sobrien encoding = DW_ATE_boolean; 737650397Sobrien break; 737750397Sobrien 737850397Sobrien default: 737990075Sobrien /* No other TREE_CODEs are Dwarf fundamental types. */ 738090075Sobrien abort (); 738150397Sobrien } 738250397Sobrien 738390075Sobrien base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type); 738490075Sobrien if (demangle_name_func) 738590075Sobrien type_name = (*demangle_name_func) (type_name); 738690075Sobrien 738750397Sobrien add_AT_string (base_type_result, DW_AT_name, type_name); 738850397Sobrien add_AT_unsigned (base_type_result, DW_AT_byte_size, 738950397Sobrien int_size_in_bytes (type)); 739050397Sobrien add_AT_unsigned (base_type_result, DW_AT_encoding, encoding); 739150397Sobrien 739250397Sobrien return base_type_result; 739350397Sobrien} 739450397Sobrien 739550397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to 739650397Sobrien the Dwarf "root" type for the given input type. The Dwarf "root" type of 739750397Sobrien a given type is generally the same as the given type, except that if the 739850397Sobrien given type is a pointer or reference type, then the root type of the given 739950397Sobrien type is the root type of the "basis" type for the pointer or reference 740050397Sobrien type. (This definition of the "root" type is recursive.) Also, the root 740150397Sobrien type of a `const' qualified type or a `volatile' qualified type is the 740250397Sobrien root type of the given type without the qualifiers. */ 740350397Sobrien 740450397Sobrienstatic tree 740550397Sobrienroot_type (type) 740690075Sobrien tree type; 740750397Sobrien{ 740850397Sobrien if (TREE_CODE (type) == ERROR_MARK) 740950397Sobrien return error_mark_node; 741050397Sobrien 741150397Sobrien switch (TREE_CODE (type)) 741250397Sobrien { 741350397Sobrien case ERROR_MARK: 741450397Sobrien return error_mark_node; 741550397Sobrien 741650397Sobrien case POINTER_TYPE: 741750397Sobrien case REFERENCE_TYPE: 741850397Sobrien return type_main_variant (root_type (TREE_TYPE (type))); 741950397Sobrien 742050397Sobrien default: 742150397Sobrien return type_main_variant (type); 742250397Sobrien } 742350397Sobrien} 742450397Sobrien 742550397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the 742650397Sobrien given input type is a Dwarf "fundamental" type. Otherwise return null. */ 742750397Sobrien 742850397Sobrienstatic inline int 742950397Sobrienis_base_type (type) 743090075Sobrien tree type; 743150397Sobrien{ 743250397Sobrien switch (TREE_CODE (type)) 743350397Sobrien { 743450397Sobrien case ERROR_MARK: 743550397Sobrien case VOID_TYPE: 743650397Sobrien case INTEGER_TYPE: 743750397Sobrien case REAL_TYPE: 743850397Sobrien case COMPLEX_TYPE: 743950397Sobrien case BOOLEAN_TYPE: 744050397Sobrien case CHAR_TYPE: 744150397Sobrien return 1; 744250397Sobrien 744350397Sobrien case SET_TYPE: 744450397Sobrien case ARRAY_TYPE: 744550397Sobrien case RECORD_TYPE: 744650397Sobrien case UNION_TYPE: 744750397Sobrien case QUAL_UNION_TYPE: 744850397Sobrien case ENUMERAL_TYPE: 744950397Sobrien case FUNCTION_TYPE: 745050397Sobrien case METHOD_TYPE: 745150397Sobrien case POINTER_TYPE: 745250397Sobrien case REFERENCE_TYPE: 745350397Sobrien case FILE_TYPE: 745450397Sobrien case OFFSET_TYPE: 745550397Sobrien case LANG_TYPE: 745690075Sobrien case VECTOR_TYPE: 745750397Sobrien return 0; 745850397Sobrien 745950397Sobrien default: 746050397Sobrien abort (); 746150397Sobrien } 746250397Sobrien 746350397Sobrien return 0; 746450397Sobrien} 746550397Sobrien 746650397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging 746750397Sobrien entry that chains various modifiers in front of the given type. */ 746850397Sobrien 746950397Sobrienstatic dw_die_ref 747050397Sobrienmodified_type_die (type, is_const_type, is_volatile_type, context_die) 747190075Sobrien tree type; 747290075Sobrien int is_const_type; 747390075Sobrien int is_volatile_type; 747490075Sobrien dw_die_ref context_die; 747550397Sobrien{ 747690075Sobrien enum tree_code code = TREE_CODE (type); 747790075Sobrien dw_die_ref mod_type_die = NULL; 747890075Sobrien dw_die_ref sub_die = NULL; 747990075Sobrien tree item_type = NULL; 748050397Sobrien 748150397Sobrien if (code != ERROR_MARK) 748250397Sobrien { 748390075Sobrien tree qualified_type; 748450397Sobrien 748590075Sobrien /* See if we already have the appropriately qualified variant of 748690075Sobrien this type. */ 748790075Sobrien qualified_type 748890075Sobrien = get_qualified_type (type, 748990075Sobrien ((is_const_type ? TYPE_QUAL_CONST : 0) 749090075Sobrien | (is_volatile_type 749190075Sobrien ? TYPE_QUAL_VOLATILE : 0))); 749250397Sobrien 749390075Sobrien /* If we do, then we can just use its DIE, if it exists. */ 749490075Sobrien if (qualified_type) 749550397Sobrien { 749690075Sobrien mod_type_die = lookup_type_die (qualified_type); 749790075Sobrien if (mod_type_die) 749890075Sobrien return mod_type_die; 749990075Sobrien } 750090075Sobrien 750190075Sobrien /* Handle C typedef types. */ 750290075Sobrien if (qualified_type && TYPE_NAME (qualified_type) 750390075Sobrien && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL 750490075Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type))) 750590075Sobrien { 750690075Sobrien tree type_name = TYPE_NAME (qualified_type); 750790075Sobrien tree dtype = TREE_TYPE (type_name); 750890075Sobrien 750990075Sobrien if (qualified_type == dtype) 751050397Sobrien { 751150397Sobrien /* For a named type, use the typedef. */ 751290075Sobrien gen_type_die (qualified_type, context_die); 751390075Sobrien mod_type_die = lookup_type_die (qualified_type); 751450397Sobrien } 751550397Sobrien else if (is_const_type < TYPE_READONLY (dtype) 751650397Sobrien || is_volatile_type < TYPE_VOLATILE (dtype)) 751750397Sobrien /* cv-unqualified version of named type. Just use the unnamed 751850397Sobrien type to which it refers. */ 751950397Sobrien mod_type_die 752090075Sobrien = modified_type_die (DECL_ORIGINAL_TYPE (type_name), 752150397Sobrien is_const_type, is_volatile_type, 752250397Sobrien context_die); 752390075Sobrien 752450397Sobrien /* Else cv-qualified version of named type; fall through. */ 752550397Sobrien } 752650397Sobrien 752750397Sobrien if (mod_type_die) 752890075Sobrien /* OK. */ 752990075Sobrien ; 753050397Sobrien else if (is_const_type) 753150397Sobrien { 753290075Sobrien mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type); 753350397Sobrien sub_die = modified_type_die (type, 0, is_volatile_type, context_die); 753450397Sobrien } 753550397Sobrien else if (is_volatile_type) 753650397Sobrien { 753790075Sobrien mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type); 753850397Sobrien sub_die = modified_type_die (type, 0, 0, context_die); 753950397Sobrien } 754050397Sobrien else if (code == POINTER_TYPE) 754150397Sobrien { 754290075Sobrien mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); 754350397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 754450397Sobrien#if 0 754550397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 754650397Sobrien#endif 754750397Sobrien item_type = TREE_TYPE (type); 754850397Sobrien } 754950397Sobrien else if (code == REFERENCE_TYPE) 755050397Sobrien { 755190075Sobrien mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); 755250397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 755350397Sobrien#if 0 755450397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 755590075Sobrien#endif 755650397Sobrien item_type = TREE_TYPE (type); 755750397Sobrien } 755850397Sobrien else if (is_base_type (type)) 755950397Sobrien mod_type_die = base_type_die (type); 756050397Sobrien else 756150397Sobrien { 756250397Sobrien gen_type_die (type, context_die); 756350397Sobrien 756450397Sobrien /* We have to get the type_main_variant here (and pass that to the 756550397Sobrien `lookup_type_die' routine) because the ..._TYPE node we have 756650397Sobrien might simply be a *copy* of some original type node (where the 756750397Sobrien copy was created to help us keep track of typedef names) and 756850397Sobrien that copy might have a different TYPE_UID from the original 756950397Sobrien ..._TYPE node. */ 757050397Sobrien mod_type_die = lookup_type_die (type_main_variant (type)); 757150397Sobrien if (mod_type_die == NULL) 757250397Sobrien abort (); 757350397Sobrien } 757490075Sobrien 757590075Sobrien /* We want to equate the qualified type to the die below. */ 7576102780Skan type = qualified_type; 757750397Sobrien } 757850397Sobrien 7579102780Skan if (type) 7580102780Skan equate_type_number_to_die (type, mod_type_die); 758150397Sobrien if (item_type) 758250397Sobrien /* We must do this after the equate_type_number_to_die call, in case 758350397Sobrien this is a recursive type. This ensures that the modified_type_die 758450397Sobrien recursion will terminate even if the type is recursive. Recursive 758550397Sobrien types are possible in Ada. */ 758650397Sobrien sub_die = modified_type_die (item_type, 758750397Sobrien TYPE_READONLY (item_type), 758850397Sobrien TYPE_VOLATILE (item_type), 758950397Sobrien context_die); 759050397Sobrien 759150397Sobrien if (sub_die != NULL) 759250397Sobrien add_AT_die_ref (mod_type_die, DW_AT_type, sub_die); 759350397Sobrien 759450397Sobrien return mod_type_die; 759550397Sobrien} 759650397Sobrien 759750397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is 759890075Sobrien an enumerated type. */ 759950397Sobrien 760050397Sobrienstatic inline int 760150397Sobrientype_is_enum (type) 760290075Sobrien tree type; 760350397Sobrien{ 760450397Sobrien return TREE_CODE (type) == ENUMERAL_TYPE; 760550397Sobrien} 760650397Sobrien 760790075Sobrien/* Return the register number described by a given RTL node. */ 760850397Sobrien 760990075Sobrienstatic unsigned int 761090075Sobrienreg_number (rtl) 761190075Sobrien rtx rtl; 761290075Sobrien{ 761390075Sobrien unsigned regno = REGNO (rtl); 761490075Sobrien 761590075Sobrien if (regno >= FIRST_PSEUDO_REGISTER) 761690075Sobrien abort (); 761790075Sobrien 761890075Sobrien return DBX_REGISTER_NUMBER (regno); 761990075Sobrien} 762090075Sobrien 762190075Sobrien/* Return a location descriptor that designates a machine register or 762290075Sobrien zero if there is no such. */ 762390075Sobrien 762450397Sobrienstatic dw_loc_descr_ref 762550397Sobrienreg_loc_descriptor (rtl) 762690075Sobrien rtx rtl; 762750397Sobrien{ 762890075Sobrien dw_loc_descr_ref loc_result = NULL; 762990075Sobrien unsigned reg; 763050397Sobrien 763190075Sobrien if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 763290075Sobrien return 0; 763390075Sobrien 763490075Sobrien reg = reg_number (rtl); 763550397Sobrien if (reg <= 31) 763650397Sobrien loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0); 763750397Sobrien else 763850397Sobrien loc_result = new_loc_descr (DW_OP_regx, reg, 0); 763950397Sobrien 764050397Sobrien return loc_result; 764150397Sobrien} 764250397Sobrien 764390075Sobrien/* Return a location descriptor that designates a constant. */ 764490075Sobrien 764590075Sobrienstatic dw_loc_descr_ref 764690075Sobrienint_loc_descriptor (i) 764790075Sobrien HOST_WIDE_INT i; 764890075Sobrien{ 764990075Sobrien enum dwarf_location_atom op; 765090075Sobrien 765190075Sobrien /* Pick the smallest representation of a constant, rather than just 765290075Sobrien defaulting to the LEB encoding. */ 765390075Sobrien if (i >= 0) 765490075Sobrien { 765590075Sobrien if (i <= 31) 765690075Sobrien op = DW_OP_lit0 + i; 765790075Sobrien else if (i <= 0xff) 765890075Sobrien op = DW_OP_const1u; 765990075Sobrien else if (i <= 0xffff) 766090075Sobrien op = DW_OP_const2u; 766190075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 766290075Sobrien || i <= 0xffffffff) 766390075Sobrien op = DW_OP_const4u; 766490075Sobrien else 766590075Sobrien op = DW_OP_constu; 766690075Sobrien } 766790075Sobrien else 766890075Sobrien { 766990075Sobrien if (i >= -0x80) 767090075Sobrien op = DW_OP_const1s; 767190075Sobrien else if (i >= -0x8000) 767290075Sobrien op = DW_OP_const2s; 767390075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 767490075Sobrien || i >= -0x80000000) 767590075Sobrien op = DW_OP_const4s; 767690075Sobrien else 767790075Sobrien op = DW_OP_consts; 767890075Sobrien } 767990075Sobrien 768090075Sobrien return new_loc_descr (op, i, 0); 768190075Sobrien} 768290075Sobrien 768350397Sobrien/* Return a location descriptor that designates a base+offset location. */ 768450397Sobrien 768550397Sobrienstatic dw_loc_descr_ref 768650397Sobrienbased_loc_descr (reg, offset) 768750397Sobrien unsigned reg; 768850397Sobrien long int offset; 768950397Sobrien{ 769090075Sobrien dw_loc_descr_ref loc_result; 769150397Sobrien /* For the "frame base", we use the frame pointer or stack pointer 769250397Sobrien registers, since the RTL for local variables is relative to one of 769350397Sobrien them. */ 769490075Sobrien unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed 769590075Sobrien ? HARD_FRAME_POINTER_REGNUM 769690075Sobrien : STACK_POINTER_REGNUM); 769750397Sobrien 769850397Sobrien if (reg == fp_reg) 769950397Sobrien loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); 770050397Sobrien else if (reg <= 31) 770150397Sobrien loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); 770250397Sobrien else 770350397Sobrien loc_result = new_loc_descr (DW_OP_bregx, reg, offset); 770450397Sobrien 770550397Sobrien return loc_result; 770650397Sobrien} 770750397Sobrien 770850397Sobrien/* Return true if this RTL expression describes a base+offset calculation. */ 770950397Sobrien 771050397Sobrienstatic inline int 771150397Sobrienis_based_loc (rtl) 771290075Sobrien rtx rtl; 771350397Sobrien{ 771490075Sobrien return (GET_CODE (rtl) == PLUS 771590075Sobrien && ((GET_CODE (XEXP (rtl, 0)) == REG 771690075Sobrien && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER 771790075Sobrien && GET_CODE (XEXP (rtl, 1)) == CONST_INT))); 771850397Sobrien} 771950397Sobrien 772050397Sobrien/* The following routine converts the RTL for a variable or parameter 772150397Sobrien (resident in memory) into an equivalent Dwarf representation of a 772250397Sobrien mechanism for getting the address of that same variable onto the top of a 772350397Sobrien hypothetical "address evaluation" stack. 772450397Sobrien 772550397Sobrien When creating memory location descriptors, we are effectively transforming 772650397Sobrien the RTL for a memory-resident object into its Dwarf postfix expression 772750397Sobrien equivalent. This routine recursively descends an RTL tree, turning 772890075Sobrien it into Dwarf postfix code as it goes. 772950397Sobrien 773090075Sobrien MODE is the mode of the memory reference, needed to handle some 773190075Sobrien autoincrement addressing modes. 773290075Sobrien 773390075Sobrien Return 0 if we can't represent the location. */ 773490075Sobrien 773550397Sobrienstatic dw_loc_descr_ref 773690075Sobrienmem_loc_descriptor (rtl, mode) 773790075Sobrien rtx rtl; 773890075Sobrien enum machine_mode mode; 773950397Sobrien{ 774050397Sobrien dw_loc_descr_ref mem_loc_result = NULL; 774190075Sobrien 774290075Sobrien /* Note that for a dynamically sized array, the location we will generate a 774350397Sobrien description of here will be the lowest numbered location which is 774450397Sobrien actually within the array. That's *not* necessarily the same as the 774550397Sobrien zeroth element of the array. */ 774650397Sobrien 774790075Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 774890075Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 774990075Sobrien#endif 775090075Sobrien 775150397Sobrien switch (GET_CODE (rtl)) 775250397Sobrien { 775390075Sobrien case POST_INC: 775490075Sobrien case POST_DEC: 775590075Sobrien case POST_MODIFY: 775690075Sobrien /* POST_INC and POST_DEC can be handled just like a SUBREG. So we 775790075Sobrien just fall into the SUBREG code. */ 775890075Sobrien 775990075Sobrien /* ... fall through ... */ 776090075Sobrien 776150397Sobrien case SUBREG: 776250397Sobrien /* The case of a subreg may arise when we have a local (register) 776350397Sobrien variable or a formal (register) parameter which doesn't quite fill 776450397Sobrien up an entire register. For now, just assume that it is 776550397Sobrien legitimate to make the Dwarf info refer to the whole register which 776650397Sobrien contains the given subreg. */ 776790075Sobrien rtl = SUBREG_REG (rtl); 776850397Sobrien 776990075Sobrien /* ... fall through ... */ 777050397Sobrien 777150397Sobrien case REG: 777250397Sobrien /* Whenever a register number forms a part of the description of the 777350397Sobrien method for calculating the (dynamic) address of a memory resident 777490075Sobrien object, DWARF rules require the register number be referred to as 777550397Sobrien a "base register". This distinction is not based in any way upon 777650397Sobrien what category of register the hardware believes the given register 777750397Sobrien belongs to. This is strictly DWARF terminology we're dealing with 777850397Sobrien here. Note that in cases where the location of a memory-resident 777950397Sobrien data object could be expressed as: OP_ADD (OP_BASEREG (basereg), 778050397Sobrien OP_CONST (0)) the actual DWARF location descriptor that we generate 778150397Sobrien may just be OP_BASEREG (basereg). This may look deceptively like 778250397Sobrien the object in question was allocated to a register (rather than in 778350397Sobrien memory) so DWARF consumers need to be aware of the subtle 778450397Sobrien distinction between OP_REG and OP_BASEREG. */ 778590075Sobrien if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) 778690075Sobrien mem_loc_result = based_loc_descr (reg_number (rtl), 0); 778750397Sobrien break; 778850397Sobrien 778950397Sobrien case MEM: 779090075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 779190075Sobrien if (mem_loc_result != 0) 779290075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); 779350397Sobrien break; 779450397Sobrien 779590075Sobrien case LABEL_REF: 779690075Sobrien /* Some ports can transform a symbol ref into a label ref, because 779790075Sobrien the symbol ref is too far away and has to be dumped into a constant 779890075Sobrien pool. */ 779950397Sobrien case CONST: 780050397Sobrien case SYMBOL_REF: 780190075Sobrien /* Alternatively, the symbol in the constant pool might be referenced 780290075Sobrien by a different symbol. */ 780390075Sobrien if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl)) 780490075Sobrien { 780596263Sobrien bool marked; 780696263Sobrien rtx tmp = get_pool_constant_mark (rtl, &marked); 780790075Sobrien 780890075Sobrien if (GET_CODE (tmp) == SYMBOL_REF) 780996263Sobrien { 781096263Sobrien rtl = tmp; 781196263Sobrien if (CONSTANT_POOL_ADDRESS_P (tmp)) 781296263Sobrien get_pool_constant_mark (tmp, &marked); 781396263Sobrien else 781496263Sobrien marked = true; 781596263Sobrien } 781696263Sobrien 781796263Sobrien /* If all references to this pool constant were optimized away, 781896263Sobrien it was not output and thus we can't represent it. 781996263Sobrien FIXME: might try to use DW_OP_const_value here, though 782096263Sobrien DW_OP_piece complicates it. */ 782196263Sobrien if (!marked) 782296263Sobrien return 0; 782390075Sobrien } 782490075Sobrien 782550397Sobrien mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); 782650397Sobrien mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; 782790075Sobrien mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl; 782890075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 782950397Sobrien break; 783050397Sobrien 783190075Sobrien case PRE_MODIFY: 783290075Sobrien /* Extract the PLUS expression nested inside and fall into 783390075Sobrien PLUS code below. */ 783490075Sobrien rtl = XEXP (rtl, 1); 783590075Sobrien goto plus; 783690075Sobrien 783790075Sobrien case PRE_INC: 783890075Sobrien case PRE_DEC: 783990075Sobrien /* Turn these into a PLUS expression and fall into the PLUS code 784090075Sobrien below. */ 784190075Sobrien rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0), 784290075Sobrien GEN_INT (GET_CODE (rtl) == PRE_INC 784390075Sobrien ? GET_MODE_UNIT_SIZE (mode) 784490075Sobrien : -GET_MODE_UNIT_SIZE (mode))); 784590075Sobrien 784690075Sobrien /* ... fall through ... */ 784790075Sobrien 784850397Sobrien case PLUS: 784990075Sobrien plus: 785050397Sobrien if (is_based_loc (rtl)) 785150397Sobrien mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), 785250397Sobrien INTVAL (XEXP (rtl, 1))); 785350397Sobrien else 785450397Sobrien { 785590075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode); 785690075Sobrien if (mem_loc_result == 0) 785790075Sobrien break; 785890075Sobrien 785990075Sobrien if (GET_CODE (XEXP (rtl, 1)) == CONST_INT 786090075Sobrien && INTVAL (XEXP (rtl, 1)) >= 0) 786190075Sobrien add_loc_descr (&mem_loc_result, 786290075Sobrien new_loc_descr (DW_OP_plus_uconst, 786390075Sobrien INTVAL (XEXP (rtl, 1)), 0)); 786490075Sobrien else 786590075Sobrien { 786690075Sobrien add_loc_descr (&mem_loc_result, 786790075Sobrien mem_loc_descriptor (XEXP (rtl, 1), mode)); 786890075Sobrien add_loc_descr (&mem_loc_result, 786990075Sobrien new_loc_descr (DW_OP_plus, 0, 0)); 787090075Sobrien } 787150397Sobrien } 787250397Sobrien break; 787350397Sobrien 787450397Sobrien case MULT: 787590075Sobrien { 787690075Sobrien /* If a pseudo-reg is optimized away, it is possible for it to 787790075Sobrien be replaced with a MEM containing a multiply. */ 787890075Sobrien dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); 787990075Sobrien dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); 788050397Sobrien 788190075Sobrien if (op0 == 0 || op1 == 0) 788290075Sobrien break; 788390075Sobrien 788490075Sobrien mem_loc_result = op0; 788590075Sobrien add_loc_descr (&mem_loc_result, op1); 788690075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); 788790075Sobrien break; 788890075Sobrien } 788990075Sobrien 789050397Sobrien case CONST_INT: 789190075Sobrien mem_loc_result = int_loc_descriptor (INTVAL (rtl)); 789250397Sobrien break; 789350397Sobrien 789490075Sobrien case ADDRESSOF: 789590075Sobrien /* If this is a MEM, return its address. Otherwise, we can't 789690075Sobrien represent this. */ 789790075Sobrien if (GET_CODE (XEXP (rtl, 0)) == MEM) 789890075Sobrien return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode); 789990075Sobrien else 790090075Sobrien return 0; 790190075Sobrien 790250397Sobrien default: 790350397Sobrien abort (); 790450397Sobrien } 790550397Sobrien 790650397Sobrien return mem_loc_result; 790750397Sobrien} 790850397Sobrien 790950397Sobrien/* Return a descriptor that describes the concatenation of two locations. 791050397Sobrien This is typically a complex variable. */ 791150397Sobrien 791250397Sobrienstatic dw_loc_descr_ref 791350397Sobrienconcat_loc_descriptor (x0, x1) 791490075Sobrien rtx x0, x1; 791550397Sobrien{ 791650397Sobrien dw_loc_descr_ref cc_loc_result = NULL; 791790075Sobrien dw_loc_descr_ref x0_ref = loc_descriptor (x0); 791890075Sobrien dw_loc_descr_ref x1_ref = loc_descriptor (x1); 791950397Sobrien 792090075Sobrien if (x0_ref == 0 || x1_ref == 0) 792190075Sobrien return 0; 792290075Sobrien 792390075Sobrien cc_loc_result = x0_ref; 792450397Sobrien add_loc_descr (&cc_loc_result, 792590075Sobrien new_loc_descr (DW_OP_piece, 792690075Sobrien GET_MODE_SIZE (GET_MODE (x0)), 0)); 792750397Sobrien 792890075Sobrien add_loc_descr (&cc_loc_result, x1_ref); 792950397Sobrien add_loc_descr (&cc_loc_result, 793090075Sobrien new_loc_descr (DW_OP_piece, 793190075Sobrien GET_MODE_SIZE (GET_MODE (x1)), 0)); 793250397Sobrien 793350397Sobrien return cc_loc_result; 793450397Sobrien} 793550397Sobrien 793650397Sobrien/* Output a proper Dwarf location descriptor for a variable or parameter 793750397Sobrien which is either allocated in a register or in a memory location. For a 793850397Sobrien register, we just generate an OP_REG and the register number. For a 793950397Sobrien memory location we provide a Dwarf postfix expression describing how to 794090075Sobrien generate the (dynamic) address of the object onto the address stack. 794150397Sobrien 794290075Sobrien If we don't know how to describe it, return 0. */ 794390075Sobrien 794450397Sobrienstatic dw_loc_descr_ref 794550397Sobrienloc_descriptor (rtl) 794690075Sobrien rtx rtl; 794750397Sobrien{ 794850397Sobrien dw_loc_descr_ref loc_result = NULL; 794990075Sobrien 795050397Sobrien switch (GET_CODE (rtl)) 795150397Sobrien { 795250397Sobrien case SUBREG: 795350397Sobrien /* The case of a subreg may arise when we have a local (register) 795450397Sobrien variable or a formal (register) parameter which doesn't quite fill 795550397Sobrien up an entire register. For now, just assume that it is 795650397Sobrien legitimate to make the Dwarf info refer to the whole register which 795750397Sobrien contains the given subreg. */ 795890075Sobrien rtl = SUBREG_REG (rtl); 795950397Sobrien 796090075Sobrien /* ... fall through ... */ 796150397Sobrien 796250397Sobrien case REG: 796350397Sobrien loc_result = reg_loc_descriptor (rtl); 796450397Sobrien break; 796550397Sobrien 796650397Sobrien case MEM: 796790075Sobrien loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 796850397Sobrien break; 796950397Sobrien 797050397Sobrien case CONCAT: 797150397Sobrien loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); 797250397Sobrien break; 797350397Sobrien 797450397Sobrien default: 797550397Sobrien abort (); 797650397Sobrien } 797750397Sobrien 797850397Sobrien return loc_result; 797950397Sobrien} 798050397Sobrien 798190075Sobrien/* Similar, but generate the descriptor from trees instead of rtl. This comes 798290075Sobrien up particularly with variable length arrays. If ADDRESSP is nonzero, we are 798390075Sobrien looking for an address. Otherwise, we return a value. If we can't make a 798490075Sobrien descriptor, return 0. */ 798590075Sobrien 798690075Sobrienstatic dw_loc_descr_ref 798790075Sobrienloc_descriptor_from_tree (loc, addressp) 798890075Sobrien tree loc; 798990075Sobrien int addressp; 799090075Sobrien{ 799190075Sobrien dw_loc_descr_ref ret, ret1; 799290075Sobrien int indirect_p = 0; 799390075Sobrien int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc)); 799490075Sobrien enum dwarf_location_atom op; 799590075Sobrien 799690075Sobrien /* ??? Most of the time we do not take proper care for sign/zero 799790075Sobrien extending the values properly. Hopefully this won't be a real 799890075Sobrien problem... */ 799990075Sobrien 800090075Sobrien switch (TREE_CODE (loc)) 800190075Sobrien { 800290075Sobrien case ERROR_MARK: 800390075Sobrien return 0; 800490075Sobrien 800590075Sobrien case WITH_RECORD_EXPR: 800690075Sobrien case PLACEHOLDER_EXPR: 800790075Sobrien /* This case involves extracting fields from an object to determine the 800890075Sobrien position of other fields. We don't try to encode this here. The 800990075Sobrien only user of this is Ada, which encodes the needed information using 801090075Sobrien the names of types. */ 801190075Sobrien return 0; 801290075Sobrien 801390075Sobrien case CALL_EXPR: 801490075Sobrien return 0; 801590075Sobrien 801690075Sobrien case ADDR_EXPR: 801790075Sobrien /* We can support this only if we can look through conversions and 801890075Sobrien find an INDIRECT_EXPR. */ 801990075Sobrien for (loc = TREE_OPERAND (loc, 0); 802090075Sobrien TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR 802190075Sobrien || TREE_CODE (loc) == NON_LVALUE_EXPR 802290075Sobrien || TREE_CODE (loc) == VIEW_CONVERT_EXPR 802390075Sobrien || TREE_CODE (loc) == SAVE_EXPR; 802490075Sobrien loc = TREE_OPERAND (loc, 0)) 802590075Sobrien ; 802690075Sobrien 802790075Sobrien return (TREE_CODE (loc) == INDIRECT_REF 802890075Sobrien ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp) 802990075Sobrien : 0); 803090075Sobrien 803190075Sobrien case VAR_DECL: 803290075Sobrien case PARM_DECL: 803390075Sobrien { 803490075Sobrien rtx rtl = rtl_for_decl_location (loc); 803590075Sobrien 803690075Sobrien if (rtl == NULL_RTX) 803790075Sobrien return 0; 803890075Sobrien else if (CONSTANT_P (rtl)) 803990075Sobrien { 804090075Sobrien ret = new_loc_descr (DW_OP_addr, 0, 0); 804190075Sobrien ret->dw_loc_oprnd1.val_class = dw_val_class_addr; 804290075Sobrien ret->dw_loc_oprnd1.v.val_addr = rtl; 804390075Sobrien indirect_p = 1; 804490075Sobrien } 804590075Sobrien else 804690075Sobrien { 804790075Sobrien enum machine_mode mode = GET_MODE (rtl); 804890075Sobrien 804990075Sobrien if (GET_CODE (rtl) == MEM) 805090075Sobrien { 805190075Sobrien indirect_p = 1; 805290075Sobrien rtl = XEXP (rtl, 0); 805390075Sobrien } 805490075Sobrien 805590075Sobrien ret = mem_loc_descriptor (rtl, mode); 805690075Sobrien } 805790075Sobrien } 805890075Sobrien break; 805990075Sobrien 806090075Sobrien case INDIRECT_REF: 806190075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 806290075Sobrien indirect_p = 1; 806390075Sobrien break; 806490075Sobrien 806590075Sobrien case COMPOUND_EXPR: 806690075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp); 806790075Sobrien 806890075Sobrien case NOP_EXPR: 806990075Sobrien case CONVERT_EXPR: 807090075Sobrien case NON_LVALUE_EXPR: 807190075Sobrien case VIEW_CONVERT_EXPR: 807290075Sobrien case SAVE_EXPR: 807390075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); 807490075Sobrien 807590075Sobrien case COMPONENT_REF: 807690075Sobrien case BIT_FIELD_REF: 807790075Sobrien case ARRAY_REF: 807890075Sobrien case ARRAY_RANGE_REF: 807990075Sobrien { 808090075Sobrien tree obj, offset; 808190075Sobrien HOST_WIDE_INT bitsize, bitpos, bytepos; 808290075Sobrien enum machine_mode mode; 808390075Sobrien int volatilep; 808490075Sobrien 808590075Sobrien obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, 808690075Sobrien &unsignedp, &volatilep); 808790075Sobrien 808890075Sobrien if (obj == loc) 808990075Sobrien return 0; 809090075Sobrien 809190075Sobrien ret = loc_descriptor_from_tree (obj, 1); 809290075Sobrien if (ret == 0 809390075Sobrien || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0) 809490075Sobrien return 0; 809590075Sobrien 809690075Sobrien if (offset != NULL_TREE) 809790075Sobrien { 809890075Sobrien /* Variable offset. */ 809990075Sobrien add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0)); 810090075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 810190075Sobrien } 810290075Sobrien 810390075Sobrien if (!addressp) 810490075Sobrien indirect_p = 1; 810590075Sobrien 810690075Sobrien bytepos = bitpos / BITS_PER_UNIT; 810790075Sobrien if (bytepos > 0) 810890075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); 810990075Sobrien else if (bytepos < 0) 811090075Sobrien { 811190075Sobrien add_loc_descr (&ret, int_loc_descriptor (bytepos)); 811290075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 811390075Sobrien } 811490075Sobrien break; 811590075Sobrien } 811690075Sobrien 811790075Sobrien case INTEGER_CST: 811890075Sobrien if (host_integerp (loc, 0)) 811990075Sobrien ret = int_loc_descriptor (tree_low_cst (loc, 0)); 812090075Sobrien else 812190075Sobrien return 0; 812290075Sobrien break; 812390075Sobrien 812490075Sobrien case TRUTH_AND_EXPR: 812590075Sobrien case TRUTH_ANDIF_EXPR: 812690075Sobrien case BIT_AND_EXPR: 812790075Sobrien op = DW_OP_and; 812890075Sobrien goto do_binop; 812990075Sobrien 813090075Sobrien case TRUTH_XOR_EXPR: 813190075Sobrien case BIT_XOR_EXPR: 813290075Sobrien op = DW_OP_xor; 813390075Sobrien goto do_binop; 813490075Sobrien 813590075Sobrien case TRUTH_OR_EXPR: 813690075Sobrien case TRUTH_ORIF_EXPR: 813790075Sobrien case BIT_IOR_EXPR: 813890075Sobrien op = DW_OP_or; 813990075Sobrien goto do_binop; 814090075Sobrien 814190075Sobrien case TRUNC_DIV_EXPR: 814290075Sobrien op = DW_OP_div; 814390075Sobrien goto do_binop; 814490075Sobrien 814590075Sobrien case MINUS_EXPR: 814690075Sobrien op = DW_OP_minus; 814790075Sobrien goto do_binop; 814890075Sobrien 814990075Sobrien case TRUNC_MOD_EXPR: 815090075Sobrien op = DW_OP_mod; 815190075Sobrien goto do_binop; 815290075Sobrien 815390075Sobrien case MULT_EXPR: 815490075Sobrien op = DW_OP_mul; 815590075Sobrien goto do_binop; 815690075Sobrien 815790075Sobrien case LSHIFT_EXPR: 815890075Sobrien op = DW_OP_shl; 815990075Sobrien goto do_binop; 816090075Sobrien 816190075Sobrien case RSHIFT_EXPR: 816290075Sobrien op = (unsignedp ? DW_OP_shr : DW_OP_shra); 816390075Sobrien goto do_binop; 816490075Sobrien 816590075Sobrien case PLUS_EXPR: 816690075Sobrien if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST 816790075Sobrien && host_integerp (TREE_OPERAND (loc, 1), 0)) 816890075Sobrien { 816990075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 817090075Sobrien if (ret == 0) 817190075Sobrien return 0; 817290075Sobrien 817390075Sobrien add_loc_descr (&ret, 817490075Sobrien new_loc_descr (DW_OP_plus_uconst, 817590075Sobrien tree_low_cst (TREE_OPERAND (loc, 1), 817690075Sobrien 0), 817790075Sobrien 0)); 817890075Sobrien break; 817990075Sobrien } 818090075Sobrien 818190075Sobrien op = DW_OP_plus; 818290075Sobrien goto do_binop; 818390075Sobrien 818490075Sobrien case LE_EXPR: 818590075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 818690075Sobrien return 0; 818790075Sobrien 818890075Sobrien op = DW_OP_le; 818990075Sobrien goto do_binop; 819090075Sobrien 819190075Sobrien case GE_EXPR: 819290075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 819390075Sobrien return 0; 819490075Sobrien 819590075Sobrien op = DW_OP_ge; 819690075Sobrien goto do_binop; 819790075Sobrien 819890075Sobrien case LT_EXPR: 819990075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 820090075Sobrien return 0; 820190075Sobrien 820290075Sobrien op = DW_OP_lt; 820390075Sobrien goto do_binop; 820490075Sobrien 820590075Sobrien case GT_EXPR: 820690075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 820790075Sobrien return 0; 820890075Sobrien 820990075Sobrien op = DW_OP_gt; 821090075Sobrien goto do_binop; 821190075Sobrien 821290075Sobrien case EQ_EXPR: 821390075Sobrien op = DW_OP_eq; 821490075Sobrien goto do_binop; 821590075Sobrien 821690075Sobrien case NE_EXPR: 821790075Sobrien op = DW_OP_ne; 821890075Sobrien goto do_binop; 821990075Sobrien 822090075Sobrien do_binop: 822190075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 822290075Sobrien ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 822390075Sobrien if (ret == 0 || ret1 == 0) 822490075Sobrien return 0; 822590075Sobrien 822690075Sobrien add_loc_descr (&ret, ret1); 822790075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 822890075Sobrien break; 822990075Sobrien 823090075Sobrien case TRUTH_NOT_EXPR: 823190075Sobrien case BIT_NOT_EXPR: 823290075Sobrien op = DW_OP_not; 823390075Sobrien goto do_unop; 823490075Sobrien 823590075Sobrien case ABS_EXPR: 823690075Sobrien op = DW_OP_abs; 823790075Sobrien goto do_unop; 823890075Sobrien 823990075Sobrien case NEGATE_EXPR: 824090075Sobrien op = DW_OP_neg; 824190075Sobrien goto do_unop; 824290075Sobrien 824390075Sobrien do_unop: 824490075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 824590075Sobrien if (ret == 0) 824690075Sobrien return 0; 824790075Sobrien 824890075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 824990075Sobrien break; 825090075Sobrien 825190075Sobrien case MAX_EXPR: 825290075Sobrien loc = build (COND_EXPR, TREE_TYPE (loc), 825390075Sobrien build (LT_EXPR, integer_type_node, 825490075Sobrien TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)), 825590075Sobrien TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0)); 825690075Sobrien 825790075Sobrien /* ... fall through ... */ 825890075Sobrien 825990075Sobrien case COND_EXPR: 826090075Sobrien { 826190075Sobrien dw_loc_descr_ref lhs 826290075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 826390075Sobrien dw_loc_descr_ref rhs 826490075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0); 826590075Sobrien dw_loc_descr_ref bra_node, jump_node, tmp; 826690075Sobrien 826790075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 826890075Sobrien if (ret == 0 || lhs == 0 || rhs == 0) 826990075Sobrien return 0; 827090075Sobrien 827190075Sobrien bra_node = new_loc_descr (DW_OP_bra, 0, 0); 827290075Sobrien add_loc_descr (&ret, bra_node); 827390075Sobrien 827490075Sobrien add_loc_descr (&ret, rhs); 827590075Sobrien jump_node = new_loc_descr (DW_OP_skip, 0, 0); 827690075Sobrien add_loc_descr (&ret, jump_node); 827790075Sobrien 827890075Sobrien add_loc_descr (&ret, lhs); 827990075Sobrien bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 828090075Sobrien bra_node->dw_loc_oprnd1.v.val_loc = lhs; 828190075Sobrien 828290075Sobrien /* ??? Need a node to point the skip at. Use a nop. */ 828390075Sobrien tmp = new_loc_descr (DW_OP_nop, 0, 0); 828490075Sobrien add_loc_descr (&ret, tmp); 828590075Sobrien jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 828690075Sobrien jump_node->dw_loc_oprnd1.v.val_loc = tmp; 828790075Sobrien } 828890075Sobrien break; 828990075Sobrien 829090075Sobrien default: 829190075Sobrien abort (); 829290075Sobrien } 829390075Sobrien 829490075Sobrien /* Show if we can't fill the request for an address. */ 829590075Sobrien if (addressp && indirect_p == 0) 829690075Sobrien return 0; 829790075Sobrien 829890075Sobrien /* If we've got an address and don't want one, dereference. */ 829990075Sobrien if (!addressp && indirect_p > 0) 830090075Sobrien { 830190075Sobrien HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc)); 830290075Sobrien 830390075Sobrien if (size > DWARF2_ADDR_SIZE || size == -1) 830490075Sobrien return 0; 830590075Sobrien else if (size == DWARF2_ADDR_SIZE) 830690075Sobrien op = DW_OP_deref; 830790075Sobrien else 830890075Sobrien op = DW_OP_deref_size; 830990075Sobrien 831090075Sobrien add_loc_descr (&ret, new_loc_descr (op, size, 0)); 831190075Sobrien } 831290075Sobrien 831390075Sobrien return ret; 831490075Sobrien} 831590075Sobrien 831690075Sobrien/* Given a value, round it up to the lowest multiple of `boundary' 831750397Sobrien which is not less than the value itself. */ 831850397Sobrien 831990075Sobrienstatic inline HOST_WIDE_INT 832050397Sobrienceiling (value, boundary) 832190075Sobrien HOST_WIDE_INT value; 832290075Sobrien unsigned int boundary; 832350397Sobrien{ 832450397Sobrien return (((value + boundary - 1) / boundary) * boundary); 832550397Sobrien} 832650397Sobrien 832750397Sobrien/* Given a pointer to what is assumed to be a FIELD_DECL node, return a 832850397Sobrien pointer to the declared type for the relevant field variable, or return 832950397Sobrien `integer_type_node' if the given node turns out to be an 833050397Sobrien ERROR_MARK node. */ 833150397Sobrien 833250397Sobrienstatic inline tree 833350397Sobrienfield_type (decl) 833490075Sobrien tree decl; 833550397Sobrien{ 833690075Sobrien tree type; 833750397Sobrien 833850397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 833950397Sobrien return integer_type_node; 834050397Sobrien 834150397Sobrien type = DECL_BIT_FIELD_TYPE (decl); 834250397Sobrien if (type == NULL_TREE) 834350397Sobrien type = TREE_TYPE (decl); 834450397Sobrien 834550397Sobrien return type; 834650397Sobrien} 834750397Sobrien 834890075Sobrien/* Given a pointer to a tree node, return the alignment in bits for 834990075Sobrien it, or else return BITS_PER_WORD if the node actually turns out to 835090075Sobrien be an ERROR_MARK node. */ 835150397Sobrien 835250397Sobrienstatic inline unsigned 835350397Sobriensimple_type_align_in_bits (type) 835490075Sobrien tree type; 835550397Sobrien{ 835650397Sobrien return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; 835750397Sobrien} 835850397Sobrien 835990075Sobrienstatic inline unsigned 836096263Sobriensimple_field_decl_align_in_bits (field) 836196263Sobrien tree field; 836290075Sobrien{ 836396263Sobrien unsigned align; 836496263Sobrien 836596263Sobrien if (TREE_CODE (field) == ERROR_MARK) 836696263Sobrien return BITS_PER_WORD; 836796263Sobrien 836896263Sobrien align = DECL_ALIGN (field); 836996263Sobrien 837096263Sobrien#ifdef BIGGEST_FIELD_ALIGNMENT 837196263Sobrien /* Some targets (i.e. i386) limit union field alignment 837296263Sobrien to a lower boundary than alignment of variables unless 837396263Sobrien it was overridden by attribute aligned. */ 837496263Sobrien if (! DECL_USER_ALIGN (field)) 837596263Sobrien align = MIN (align, (unsigned) BIGGEST_FIELD_ALIGNMENT); 837696263Sobrien#endif 837796263Sobrien 837896263Sobrien#ifdef ADJUST_FIELD_ALIGN 837996263Sobrien align = ADJUST_FIELD_ALIGN (field, align); 838096263Sobrien#endif 838196263Sobrien return align; 838290075Sobrien} 838390075Sobrien 838450397Sobrien/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE 838550397Sobrien node, return the size in bits for the type if it is a constant, or else 838650397Sobrien return the alignment for the type if the type's size is not constant, or 838750397Sobrien else return BITS_PER_WORD if the type actually turns out to be an 838850397Sobrien ERROR_MARK node. */ 838950397Sobrien 839090075Sobrienstatic inline unsigned HOST_WIDE_INT 839150397Sobriensimple_type_size_in_bits (type) 839290075Sobrien tree type; 839350397Sobrien{ 839490075Sobrien 839550397Sobrien if (TREE_CODE (type) == ERROR_MARK) 839650397Sobrien return BITS_PER_WORD; 839790075Sobrien else if (TYPE_SIZE (type) == NULL_TREE) 839890075Sobrien return 0; 839990075Sobrien else if (host_integerp (TYPE_SIZE (type), 1)) 840090075Sobrien return tree_low_cst (TYPE_SIZE (type), 1); 840150397Sobrien else 840290075Sobrien return TYPE_ALIGN (type); 840350397Sobrien} 840450397Sobrien 840590075Sobrien/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the 840690075Sobrien lowest addressed byte of the "containing object" for the given FIELD_DECL, 840790075Sobrien or return 0 if we are unable to determine what that offset is, either 840890075Sobrien because the argument turns out to be a pointer to an ERROR_MARK node, or 840990075Sobrien because the offset is actually variable. (We can't handle the latter case 841090075Sobrien just yet). */ 841150397Sobrien 841290075Sobrienstatic HOST_WIDE_INT 841350397Sobrienfield_byte_offset (decl) 841490075Sobrien tree decl; 841550397Sobrien{ 841690075Sobrien unsigned int type_align_in_bits; 841790075Sobrien unsigned int decl_align_in_bits; 841890075Sobrien unsigned HOST_WIDE_INT type_size_in_bits; 841990075Sobrien HOST_WIDE_INT object_offset_in_bits; 842090075Sobrien tree type; 842190075Sobrien tree field_size_tree; 842290075Sobrien HOST_WIDE_INT bitpos_int; 842390075Sobrien HOST_WIDE_INT deepest_bitpos; 842490075Sobrien unsigned HOST_WIDE_INT field_size_in_bits; 842550397Sobrien 842650397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 842750397Sobrien return 0; 842890075Sobrien else if (TREE_CODE (decl) != FIELD_DECL) 842950397Sobrien abort (); 843050397Sobrien 843150397Sobrien type = field_type (decl); 843250397Sobrien field_size_tree = DECL_SIZE (decl); 843350397Sobrien 843490075Sobrien /* The size could be unspecified if there was an error, or for 843590075Sobrien a flexible array member. */ 843690075Sobrien if (! field_size_tree) 843790075Sobrien field_size_tree = bitsize_zero_node; 843890075Sobrien 843990075Sobrien /* We cannot yet cope with fields whose positions are variable, so 844050397Sobrien for now, when we see such things, we simply return 0. Someday, we may 844150397Sobrien be able to handle such cases, but it will be damn difficult. */ 844290075Sobrien if (! host_integerp (bit_position (decl), 0)) 844350397Sobrien return 0; 844450397Sobrien 844590075Sobrien bitpos_int = int_bit_position (decl); 844650397Sobrien 844790075Sobrien /* If we don't know the size of the field, pretend it's a full word. */ 844890075Sobrien if (host_integerp (field_size_tree, 1)) 844990075Sobrien field_size_in_bits = tree_low_cst (field_size_tree, 1); 845090075Sobrien else 845190075Sobrien field_size_in_bits = BITS_PER_WORD; 845290075Sobrien 845350397Sobrien type_size_in_bits = simple_type_size_in_bits (type); 845450397Sobrien type_align_in_bits = simple_type_align_in_bits (type); 845596263Sobrien decl_align_in_bits = simple_field_decl_align_in_bits (decl); 845650397Sobrien 845790075Sobrien /* The GCC front-end doesn't make any attempt to keep track of the starting 845890075Sobrien bit offset (relative to the start of the containing structure type) of the 845990075Sobrien hypothetical "containing object" for a bit-field. Thus, when computing 846090075Sobrien the byte offset value for the start of the "containing object" of a 846190075Sobrien bit-field, we must deduce this information on our own. This can be rather 846290075Sobrien tricky to do in some cases. For example, handling the following structure 846390075Sobrien type definition when compiling for an i386/i486 target (which only aligns 846490075Sobrien long long's to 32-bit boundaries) can be very tricky: 846550397Sobrien 846650397Sobrien struct S { int field1; long long field2:31; }; 846750397Sobrien 846890075Sobrien Fortunately, there is a simple rule-of-thumb which can be used in such 846990075Sobrien cases. When compiling for an i386/i486, GCC will allocate 8 bytes for the 847090075Sobrien structure shown above. It decides to do this based upon one simple rule 847190075Sobrien for bit-field allocation. GCC allocates each "containing object" for each 847290075Sobrien bit-field at the first (i.e. lowest addressed) legitimate alignment 847390075Sobrien boundary (based upon the required minimum alignment for the declared type 847490075Sobrien of the field) which it can possibly use, subject to the condition that 847590075Sobrien there is still enough available space remaining in the containing object 847690075Sobrien (when allocated at the selected point) to fully accommodate all of the 847790075Sobrien bits of the bit-field itself. 847850397Sobrien 847990075Sobrien This simple rule makes it obvious why GCC allocates 8 bytes for each 848090075Sobrien object of the structure type shown above. When looking for a place to 848190075Sobrien allocate the "containing object" for `field2', the compiler simply tries 848290075Sobrien to allocate a 64-bit "containing object" at each successive 32-bit 848390075Sobrien boundary (starting at zero) until it finds a place to allocate that 64- 848490075Sobrien bit field such that at least 31 contiguous (and previously unallocated) 848590075Sobrien bits remain within that selected 64 bit field. (As it turns out, for the 848690075Sobrien example above, the compiler finds it is OK to allocate the "containing 848790075Sobrien object" 64-bit field at bit-offset zero within the structure type.) 848890075Sobrien 848990075Sobrien Here we attempt to work backwards from the limited set of facts we're 849090075Sobrien given, and we try to deduce from those facts, where GCC must have believed 849190075Sobrien that the containing object started (within the structure type). The value 849290075Sobrien we deduce is then used (by the callers of this routine) to generate 849390075Sobrien DW_AT_location and DW_AT_bit_offset attributes for fields (both bit-fields 849490075Sobrien and, in the case of DW_AT_location, regular fields as well). */ 849590075Sobrien 849650397Sobrien /* Figure out the bit-distance from the start of the structure to the 849750397Sobrien "deepest" bit of the bit-field. */ 849850397Sobrien deepest_bitpos = bitpos_int + field_size_in_bits; 849950397Sobrien 850050397Sobrien /* This is the tricky part. Use some fancy footwork to deduce where the 850150397Sobrien lowest addressed bit of the containing object must be. */ 850290075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 850350397Sobrien 850490075Sobrien /* Round up to type_align by default. This works best for bitfields. */ 850590075Sobrien object_offset_in_bits += type_align_in_bits - 1; 850690075Sobrien object_offset_in_bits /= type_align_in_bits; 850790075Sobrien object_offset_in_bits *= type_align_in_bits; 850850397Sobrien 850990075Sobrien if (object_offset_in_bits > bitpos_int) 851090075Sobrien { 851190075Sobrien /* Sigh, the decl must be packed. */ 851290075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 851350397Sobrien 851490075Sobrien /* Round up to decl_align instead. */ 851590075Sobrien object_offset_in_bits += decl_align_in_bits - 1; 851690075Sobrien object_offset_in_bits /= decl_align_in_bits; 851790075Sobrien object_offset_in_bits *= decl_align_in_bits; 851890075Sobrien } 851990075Sobrien 852090075Sobrien return object_offset_in_bits / BITS_PER_UNIT; 852150397Sobrien} 852250397Sobrien 852350397Sobrien/* The following routines define various Dwarf attributes and any data 852450397Sobrien associated with them. */ 852550397Sobrien 852650397Sobrien/* Add a location description attribute value to a DIE. 852750397Sobrien 852850397Sobrien This emits location attributes suitable for whole variables and 852950397Sobrien whole parameters. Note that the location attributes for struct fields are 853050397Sobrien generated by the routine `data_member_location_attribute' below. */ 853150397Sobrien 853250397Sobrienstatic void 853350397Sobrienadd_AT_location_description (die, attr_kind, rtl) 853450397Sobrien dw_die_ref die; 853550397Sobrien enum dwarf_attribute attr_kind; 853690075Sobrien rtx rtl; 853750397Sobrien{ 853890075Sobrien dw_loc_descr_ref descr = loc_descriptor (rtl); 853950397Sobrien 854090075Sobrien if (descr != 0) 854190075Sobrien add_AT_loc (die, attr_kind, descr); 854250397Sobrien} 854350397Sobrien 854490075Sobrien/* Attach the specialized form of location attribute used for data members of 854590075Sobrien struct and union types. In the special case of a FIELD_DECL node which 854690075Sobrien represents a bit-field, the "offset" part of this special location 854790075Sobrien descriptor must indicate the distance in bytes from the lowest-addressed 854890075Sobrien byte of the containing struct or union type to the lowest-addressed byte of 854990075Sobrien the "containing object" for the bit-field. (See the `field_byte_offset' 855090075Sobrien function above). 855150397Sobrien 855290075Sobrien For any given bit-field, the "containing object" is a hypothetical object 855390075Sobrien (of some integral or enum type) within which the given bit-field lives. The 855490075Sobrien type of this hypothetical "containing object" is always the same as the 855590075Sobrien declared type of the individual bit-field itself (for GCC anyway... the 855690075Sobrien DWARF spec doesn't actually mandate this). Note that it is the size (in 855790075Sobrien bytes) of the hypothetical "containing object" which will be given in the 855890075Sobrien DW_AT_byte_size attribute for this bit-field. (See the 855990075Sobrien `byte_size_attribute' function below.) It is also used when calculating the 856090075Sobrien value of the DW_AT_bit_offset attribute. (See the `bit_offset_attribute' 856190075Sobrien function below.) */ 856290075Sobrien 856350397Sobrienstatic void 856450397Sobrienadd_data_member_location_attribute (die, decl) 856590075Sobrien dw_die_ref die; 856690075Sobrien tree decl; 856750397Sobrien{ 856890075Sobrien long offset; 856990075Sobrien dw_loc_descr_ref loc_descr = 0; 857050397Sobrien 857150397Sobrien if (TREE_CODE (decl) == TREE_VEC) 857290075Sobrien { 857390075Sobrien /* We're working on the TAG_inheritance for a base class. */ 857490075Sobrien if (TREE_VIA_VIRTUAL (decl) && is_cxx ()) 857590075Sobrien { 857690075Sobrien /* For C++ virtual bases we can't just use BINFO_OFFSET, as they 857790075Sobrien aren't at a fixed offset from all (sub)objects of the same 857890075Sobrien type. We need to extract the appropriate offset from our 857990075Sobrien vtable. The following dwarf expression means 858090075Sobrien 858190075Sobrien BaseAddr = ObAddr + *((*ObAddr) - Offset) 858290075Sobrien 858390075Sobrien This is specific to the V3 ABI, of course. */ 858490075Sobrien 858590075Sobrien dw_loc_descr_ref tmp; 858690075Sobrien 858790075Sobrien /* Make a copy of the object address. */ 858890075Sobrien tmp = new_loc_descr (DW_OP_dup, 0, 0); 858990075Sobrien add_loc_descr (&loc_descr, tmp); 859090075Sobrien 859190075Sobrien /* Extract the vtable address. */ 859290075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 859390075Sobrien add_loc_descr (&loc_descr, tmp); 859490075Sobrien 859590075Sobrien /* Calculate the address of the offset. */ 859690075Sobrien offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0); 859790075Sobrien if (offset >= 0) 859890075Sobrien abort (); 859990075Sobrien 860090075Sobrien tmp = int_loc_descriptor (-offset); 860190075Sobrien add_loc_descr (&loc_descr, tmp); 860290075Sobrien tmp = new_loc_descr (DW_OP_minus, 0, 0); 860390075Sobrien add_loc_descr (&loc_descr, tmp); 860490075Sobrien 860590075Sobrien /* Extract the offset. */ 860690075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 860790075Sobrien add_loc_descr (&loc_descr, tmp); 860890075Sobrien 860990075Sobrien /* Add it to the object address. */ 861090075Sobrien tmp = new_loc_descr (DW_OP_plus, 0, 0); 861190075Sobrien add_loc_descr (&loc_descr, tmp); 861290075Sobrien } 861390075Sobrien else 861490075Sobrien offset = tree_low_cst (BINFO_OFFSET (decl), 0); 861590075Sobrien } 861650397Sobrien else 861750397Sobrien offset = field_byte_offset (decl); 861850397Sobrien 861990075Sobrien if (! loc_descr) 862090075Sobrien { 862190075Sobrien enum dwarf_location_atom op; 862250397Sobrien 862390075Sobrien /* The DWARF2 standard says that we should assume that the structure 862490075Sobrien address is already on the stack, so we can specify a structure field 862590075Sobrien address by using DW_OP_plus_uconst. */ 862690075Sobrien 862750397Sobrien#ifdef MIPS_DEBUGGING_INFO 862890075Sobrien /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst 862990075Sobrien operator correctly. It works only if we leave the offset on the 863090075Sobrien stack. */ 863190075Sobrien op = DW_OP_constu; 863250397Sobrien#else 863390075Sobrien op = DW_OP_plus_uconst; 863450397Sobrien#endif 863550397Sobrien 863690075Sobrien loc_descr = new_loc_descr (op, offset, 0); 863790075Sobrien } 863890075Sobrien 863950397Sobrien add_AT_loc (die, DW_AT_data_member_location, loc_descr); 864050397Sobrien} 864150397Sobrien 864250397Sobrien/* Attach an DW_AT_const_value attribute for a variable or a parameter which 864350397Sobrien does not have a "location" either in memory or in a register. These 864450397Sobrien things can arise in GNU C when a constant is passed as an actual parameter 864550397Sobrien to an inlined function. They can also arise in C++ where declared 864650397Sobrien constants do not necessarily get memory "homes". */ 864750397Sobrien 864850397Sobrienstatic void 864950397Sobrienadd_const_value_attribute (die, rtl) 865090075Sobrien dw_die_ref die; 865190075Sobrien rtx rtl; 865250397Sobrien{ 865350397Sobrien switch (GET_CODE (rtl)) 865450397Sobrien { 865550397Sobrien case CONST_INT: 865690075Sobrien /* Note that a CONST_INT rtx could represent either an integer 865790075Sobrien or a floating-point constant. A CONST_INT is used whenever 865890075Sobrien the constant will fit into a single word. In all such 865990075Sobrien cases, the original mode of the constant value is wiped 866090075Sobrien out, and the CONST_INT rtx is assigned VOIDmode. */ 866190075Sobrien { 866290075Sobrien HOST_WIDE_INT val = INTVAL (rtl); 866390075Sobrien 866490075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 866590075Sobrien if (val < 0 && (long) val == val) 866690075Sobrien add_AT_int (die, DW_AT_const_value, (long) val); 866790075Sobrien else if ((unsigned long) val == (unsigned HOST_WIDE_INT) val) 866890075Sobrien add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val); 866990075Sobrien else 867090075Sobrien { 867190075Sobrien#if HOST_BITS_PER_LONG * 2 == HOST_BITS_PER_WIDE_INT 867290075Sobrien add_AT_long_long (die, DW_AT_const_value, 867390075Sobrien val >> HOST_BITS_PER_LONG, val); 867490075Sobrien#else 867590075Sobrien abort (); 867690075Sobrien#endif 867790075Sobrien } 867890075Sobrien } 867950397Sobrien break; 868050397Sobrien 868150397Sobrien case CONST_DOUBLE: 868250397Sobrien /* Note that a CONST_DOUBLE rtx could represent either an integer or a 868350397Sobrien floating-point constant. A CONST_DOUBLE is used whenever the 868450397Sobrien constant requires more than one word in order to be adequately 868550397Sobrien represented. We output CONST_DOUBLEs as blocks. */ 868650397Sobrien { 868790075Sobrien enum machine_mode mode = GET_MODE (rtl); 868850397Sobrien 868950397Sobrien if (GET_MODE_CLASS (mode) == MODE_FLOAT) 869050397Sobrien { 869190075Sobrien unsigned length = GET_MODE_SIZE (mode) / 4; 869290075Sobrien long *array = (long *) xmalloc (sizeof (long) * length); 869350397Sobrien REAL_VALUE_TYPE rv; 869450397Sobrien 869550397Sobrien REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); 869650397Sobrien switch (mode) 869750397Sobrien { 869850397Sobrien case SFmode: 869950397Sobrien REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); 870050397Sobrien break; 870150397Sobrien 870250397Sobrien case DFmode: 870350397Sobrien REAL_VALUE_TO_TARGET_DOUBLE (rv, array); 870450397Sobrien break; 870550397Sobrien 870650397Sobrien case XFmode: 870750397Sobrien case TFmode: 870850397Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); 870950397Sobrien break; 871050397Sobrien 871150397Sobrien default: 871250397Sobrien abort (); 871350397Sobrien } 871450397Sobrien 871550397Sobrien add_AT_float (die, DW_AT_const_value, length, array); 871650397Sobrien } 871750397Sobrien else 871890075Sobrien { 871990075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 872090075Sobrien if (HOST_BITS_PER_LONG != HOST_BITS_PER_WIDE_INT) 872190075Sobrien abort (); 872290075Sobrien 872390075Sobrien add_AT_long_long (die, DW_AT_const_value, 872490075Sobrien CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl)); 872590075Sobrien } 872650397Sobrien } 872750397Sobrien break; 872850397Sobrien 872950397Sobrien case CONST_STRING: 873050397Sobrien add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); 873150397Sobrien break; 873250397Sobrien 873350397Sobrien case SYMBOL_REF: 873450397Sobrien case LABEL_REF: 873550397Sobrien case CONST: 873690075Sobrien add_AT_addr (die, DW_AT_const_value, rtl); 873790075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 873850397Sobrien break; 873950397Sobrien 874050397Sobrien case PLUS: 874150397Sobrien /* In cases where an inlined instance of an inline function is passed 874250397Sobrien the address of an `auto' variable (which is local to the caller) we 874350397Sobrien can get a situation where the DECL_RTL of the artificial local 874450397Sobrien variable (for the inlining) which acts as a stand-in for the 874550397Sobrien corresponding formal parameter (of the inline function) will look 874650397Sobrien like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not 874790075Sobrien exactly a compile-time constant expression, but it isn't the address 874890075Sobrien of the (artificial) local variable either. Rather, it represents the 874950397Sobrien *value* which the artificial local variable always has during its 875090075Sobrien lifetime. We currently have no way to represent such quasi-constant 875150397Sobrien values in Dwarf, so for now we just punt and generate nothing. */ 875250397Sobrien break; 875350397Sobrien 875450397Sobrien default: 875550397Sobrien /* No other kinds of rtx should be possible here. */ 875650397Sobrien abort (); 875750397Sobrien } 875850397Sobrien 875950397Sobrien} 876050397Sobrien 876190075Sobrienstatic rtx 876290075Sobrienrtl_for_decl_location (decl) 876390075Sobrien tree decl; 876450397Sobrien{ 876590075Sobrien rtx rtl; 876650397Sobrien 876750397Sobrien /* Here we have to decide where we are going to say the parameter "lives" 876850397Sobrien (as far as the debugger is concerned). We only have a couple of 876950397Sobrien choices. GCC provides us with DECL_RTL and with DECL_INCOMING_RTL. 877050397Sobrien 877190075Sobrien DECL_RTL normally indicates where the parameter lives during most of the 877250397Sobrien activation of the function. If optimization is enabled however, this 877390075Sobrien could be either NULL or else a pseudo-reg. Both of those cases indicate 877450397Sobrien that the parameter doesn't really live anywhere (as far as the code 877550397Sobrien generation parts of GCC are concerned) during most of the function's 877650397Sobrien activation. That will happen (for example) if the parameter is never 877750397Sobrien referenced within the function. 877850397Sobrien 877950397Sobrien We could just generate a location descriptor here for all non-NULL 878050397Sobrien non-pseudo values of DECL_RTL and ignore all of the rest, but we can be 878150397Sobrien a little nicer than that if we also consider DECL_INCOMING_RTL in cases 878250397Sobrien where DECL_RTL is NULL or is a pseudo-reg. 878350397Sobrien 878450397Sobrien Note however that we can only get away with using DECL_INCOMING_RTL as 878550397Sobrien a backup substitute for DECL_RTL in certain limited cases. In cases 878650397Sobrien where DECL_ARG_TYPE (decl) indicates the same type as TREE_TYPE (decl), 878750397Sobrien we can be sure that the parameter was passed using the same type as it is 878850397Sobrien declared to have within the function, and that its DECL_INCOMING_RTL 878950397Sobrien points us to a place where a value of that type is passed. 879050397Sobrien 879150397Sobrien In cases where DECL_ARG_TYPE (decl) and TREE_TYPE (decl) are different, 879250397Sobrien we cannot (in general) use DECL_INCOMING_RTL as a substitute for DECL_RTL 879350397Sobrien because in these cases DECL_INCOMING_RTL points us to a value of some 879450397Sobrien type which is *different* from the type of the parameter itself. Thus, 879550397Sobrien if we tried to use DECL_INCOMING_RTL to generate a location attribute in 879650397Sobrien such cases, the debugger would end up (for example) trying to fetch a 879750397Sobrien `float' from a place which actually contains the first part of a 879850397Sobrien `double'. That would lead to really incorrect and confusing 879950397Sobrien output at debug-time. 880050397Sobrien 880150397Sobrien So, in general, we *do not* use DECL_INCOMING_RTL as a backup for DECL_RTL 880250397Sobrien in cases where DECL_ARG_TYPE (decl) != TREE_TYPE (decl). There 880350397Sobrien are a couple of exceptions however. On little-endian machines we can 880450397Sobrien get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE (decl) is 880550397Sobrien not the same as TREE_TYPE (decl), but only when DECL_ARG_TYPE (decl) is 880650397Sobrien an integral type that is smaller than TREE_TYPE (decl). These cases arise 880750397Sobrien when (on a little-endian machine) a non-prototyped function has a 880850397Sobrien parameter declared to be of type `short' or `char'. In such cases, 880950397Sobrien TREE_TYPE (decl) will be `short' or `char', DECL_ARG_TYPE (decl) will 881050397Sobrien be `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the 881150397Sobrien passed `int' value. If the debugger then uses that address to fetch 881250397Sobrien a `short' or a `char' (on a little-endian machine) the result will be 881350397Sobrien the correct data, so we allow for such exceptional cases below. 881450397Sobrien 881550397Sobrien Note that our goal here is to describe the place where the given formal 881690075Sobrien parameter lives during most of the function's activation (i.e. between the 881790075Sobrien end of the prologue and the start of the epilogue). We'll do that as best 881890075Sobrien as we can. Note however that if the given formal parameter is modified 881990075Sobrien sometime during the execution of the function, then a stack backtrace (at 882090075Sobrien debug-time) will show the function as having been called with the *new* 882190075Sobrien value rather than the value which was originally passed in. This happens 882290075Sobrien rarely enough that it is not a major problem, but it *is* a problem, and 882390075Sobrien I'd like to fix it. 882450397Sobrien 882590075Sobrien A future version of dwarf2out.c may generate two additional attributes for 882690075Sobrien any given DW_TAG_formal_parameter DIE which will describe the "passed 882790075Sobrien type" and the "passed location" for the given formal parameter in addition 882890075Sobrien to the attributes we now generate to indicate the "declared type" and the 882990075Sobrien "active location" for each parameter. This additional set of attributes 883090075Sobrien could be used by debuggers for stack backtraces. Separately, note that 883190075Sobrien sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL can be NULL also. 883290075Sobrien This happens (for example) for inlined-instances of inline function formal 883390075Sobrien parameters which are never referenced. This really shouldn't be 883490075Sobrien happening. All PARM_DECL nodes should get valid non-NULL 883590075Sobrien DECL_INCOMING_RTL values, but integrate.c doesn't currently generate these 883690075Sobrien values for inlined instances of inline function parameters, so when we see 883790075Sobrien such cases, we are just out-of-luck for the time being (until integrate.c 883850397Sobrien gets fixed). */ 883950397Sobrien 884050397Sobrien /* Use DECL_RTL as the "location" unless we find something better. */ 884190075Sobrien rtl = DECL_RTL_IF_SET (decl); 884250397Sobrien 884390075Sobrien /* When generating abstract instances, ignore everything except 884490075Sobrien constants and symbols living in memory. */ 884590075Sobrien if (! reload_completed) 884650397Sobrien { 884790075Sobrien if (rtl 884890075Sobrien && (CONSTANT_P (rtl) 884990075Sobrien || (GET_CODE (rtl) == MEM 885090075Sobrien && CONSTANT_P (XEXP (rtl, 0))))) 885196263Sobrien { 885296263Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 885396263Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 885496263Sobrien#endif 885596263Sobrien return rtl; 885696263Sobrien } 885790075Sobrien rtl = NULL_RTX; 885890075Sobrien } 885990075Sobrien else if (TREE_CODE (decl) == PARM_DECL) 886090075Sobrien { 886150397Sobrien if (rtl == NULL_RTX || is_pseudo_reg (rtl)) 886250397Sobrien { 886390075Sobrien tree declared_type = type_main_variant (TREE_TYPE (decl)); 886490075Sobrien tree passed_type = type_main_variant (DECL_ARG_TYPE (decl)); 886550397Sobrien 886650397Sobrien /* This decl represents a formal parameter which was optimized out. 886750397Sobrien Note that DECL_INCOMING_RTL may be NULL in here, but we handle 886890075Sobrien all cases where (rtl == NULL_RTX) just below. */ 886950397Sobrien if (declared_type == passed_type) 887050397Sobrien rtl = DECL_INCOMING_RTL (decl); 887150397Sobrien else if (! BYTES_BIG_ENDIAN 887250397Sobrien && TREE_CODE (declared_type) == INTEGER_TYPE 887352284Sobrien && (GET_MODE_SIZE (TYPE_MODE (declared_type)) 887452284Sobrien <= GET_MODE_SIZE (TYPE_MODE (passed_type)))) 887590075Sobrien rtl = DECL_INCOMING_RTL (decl); 887650397Sobrien } 887752284Sobrien 887852284Sobrien /* If the parm was passed in registers, but lives on the stack, then 887952284Sobrien make a big endian correction if the mode of the type of the 888052284Sobrien parameter is not the same as the mode of the rtl. */ 888152284Sobrien /* ??? This is the same series of checks that are made in dbxout.c before 888252284Sobrien we reach the big endian correction code there. It isn't clear if all 888352284Sobrien of these checks are necessary here, but keeping them all is the safe 888452284Sobrien thing to do. */ 888552284Sobrien else if (GET_CODE (rtl) == MEM 888652284Sobrien && XEXP (rtl, 0) != const0_rtx 888752284Sobrien && ! CONSTANT_P (XEXP (rtl, 0)) 888852284Sobrien /* Not passed in memory. */ 888952284Sobrien && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM 889052284Sobrien /* Not passed by invisible reference. */ 889152284Sobrien && (GET_CODE (XEXP (rtl, 0)) != REG 889252284Sobrien || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM 889352284Sobrien || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM 889452284Sobrien#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 889552284Sobrien || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM 889652284Sobrien#endif 889752284Sobrien ) 889852284Sobrien /* Big endian correction check. */ 889952284Sobrien && BYTES_BIG_ENDIAN 890052284Sobrien && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl) 890152284Sobrien && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))) 890252284Sobrien < UNITS_PER_WORD)) 890352284Sobrien { 890452284Sobrien int offset = (UNITS_PER_WORD 890552284Sobrien - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))); 890690075Sobrien 890752284Sobrien rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)), 890852284Sobrien plus_constant (XEXP (rtl, 0), offset)); 890952284Sobrien } 891050397Sobrien } 891150397Sobrien 891290075Sobrien if (rtl != NULL_RTX) 891390075Sobrien { 891490075Sobrien rtl = eliminate_regs (rtl, 0, NULL_RTX); 891590075Sobrien#ifdef LEAF_REG_REMAP 891690075Sobrien if (current_function_uses_only_leaf_regs) 891790075Sobrien leaf_renumber_regs_insn (rtl); 891890075Sobrien#endif 891990075Sobrien } 892090075Sobrien 892190075Sobrien /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant, 892290075Sobrien and will have been substituted directly into all expressions that use it. 892390075Sobrien C does not have such a concept, but C++ and other languages do. */ 892490075Sobrien else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) 892596263Sobrien { 892696263Sobrien /* If a variable is initialized with a string constant without embedded 892796263Sobrien zeros, build CONST_STRING. */ 892896263Sobrien if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST 892996263Sobrien && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) 893096263Sobrien { 893196263Sobrien tree arrtype = TREE_TYPE (decl); 893296263Sobrien tree enttype = TREE_TYPE (arrtype); 893396263Sobrien tree domain = TYPE_DOMAIN (arrtype); 893496263Sobrien tree init = DECL_INITIAL (decl); 893596263Sobrien enum machine_mode mode = TYPE_MODE (enttype); 893690075Sobrien 893796263Sobrien if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1 893896263Sobrien && domain 893996263Sobrien && integer_zerop (TYPE_MIN_VALUE (domain)) 894096263Sobrien && compare_tree_int (TYPE_MAX_VALUE (domain), 894196263Sobrien TREE_STRING_LENGTH (init) - 1) == 0 894296263Sobrien && ((size_t) TREE_STRING_LENGTH (init) 894396263Sobrien == strlen (TREE_STRING_POINTER (init)) + 1)) 894496263Sobrien rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init)); 894596263Sobrien } 8946102780Skan /* If the initializer is something that we know will expand into an 8947102780Skan immediate RTL constant, expand it now. Expanding anything else 8948102780Skan tends to produce unresolved symbols; see debug/5770 and c++/6381. */ 8949102780Skan else if (TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST 8950102780Skan || TREE_CODE (DECL_INITIAL (decl)) == REAL_CST) 895196263Sobrien { 895296263Sobrien rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode, 895396263Sobrien EXPAND_INITIALIZER); 8954102780Skan /* If expand_expr returns a MEM, it wasn't immediate. */ 895596263Sobrien if (rtl && GET_CODE (rtl) == MEM) 8956102780Skan abort (); 895796263Sobrien } 895896263Sobrien } 895996263Sobrien 896096263Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 896196263Sobrien if (rtl) 896296263Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 896396263Sobrien#endif 896490075Sobrien return rtl; 896590075Sobrien} 896690075Sobrien 896790075Sobrien/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value 896890075Sobrien data attribute for a variable or a parameter. We generate the 896990075Sobrien DW_AT_const_value attribute only in those cases where the given variable 897090075Sobrien or parameter does not have a true "location" either in memory or in a 897190075Sobrien register. This can happen (for example) when a constant is passed as an 897290075Sobrien actual argument in a call to an inline function. (It's possible that 897390075Sobrien these things can crop up in other ways also.) Note that one type of 897490075Sobrien constant value which can be passed into an inlined function is a constant 897590075Sobrien pointer. This can happen for example if an actual argument in an inlined 897690075Sobrien function call evaluates to a compile-time constant address. */ 897790075Sobrien 897890075Sobrienstatic void 897990075Sobrienadd_location_or_const_value_attribute (die, decl) 898090075Sobrien dw_die_ref die; 898190075Sobrien tree decl; 898290075Sobrien{ 898390075Sobrien rtx rtl; 898490075Sobrien 898590075Sobrien if (TREE_CODE (decl) == ERROR_MARK) 898690075Sobrien return; 898790075Sobrien else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 898890075Sobrien abort (); 898990075Sobrien 899090075Sobrien rtl = rtl_for_decl_location (decl); 899150397Sobrien if (rtl == NULL_RTX) 899250397Sobrien return; 899350397Sobrien 899490075Sobrien /* If we don't look past the constant pool, we risk emitting a 899590075Sobrien reference to a constant pool entry that isn't referenced from 899690075Sobrien code, and thus is not emitted. */ 899790075Sobrien rtl = avoid_constant_pool_reference (rtl); 899850397Sobrien 899950397Sobrien switch (GET_CODE (rtl)) 900050397Sobrien { 900150397Sobrien case ADDRESSOF: 900250397Sobrien /* The address of a variable that was optimized away; don't emit 900350397Sobrien anything. */ 900450397Sobrien break; 900550397Sobrien 900650397Sobrien case CONST_INT: 900750397Sobrien case CONST_DOUBLE: 900850397Sobrien case CONST_STRING: 900950397Sobrien case SYMBOL_REF: 901050397Sobrien case LABEL_REF: 901150397Sobrien case CONST: 901250397Sobrien case PLUS: 901350397Sobrien /* DECL_RTL could be (plus (reg ...) (const_int ...)) */ 901450397Sobrien add_const_value_attribute (die, rtl); 901550397Sobrien break; 901650397Sobrien 901750397Sobrien case MEM: 901850397Sobrien case REG: 901950397Sobrien case SUBREG: 902050397Sobrien case CONCAT: 902150397Sobrien add_AT_location_description (die, DW_AT_location, rtl); 902250397Sobrien break; 902350397Sobrien 902450397Sobrien default: 902550397Sobrien abort (); 902650397Sobrien } 902750397Sobrien} 902850397Sobrien 902990075Sobrien/* If we don't have a copy of this variable in memory for some reason (such 903090075Sobrien as a C++ member constant that doesn't have an out-of-line definition), 903190075Sobrien we should tell the debugger about the constant value. */ 903290075Sobrien 903390075Sobrienstatic void 903490075Sobrientree_add_const_value_attribute (var_die, decl) 903590075Sobrien dw_die_ref var_die; 903690075Sobrien tree decl; 903790075Sobrien{ 903890075Sobrien tree init = DECL_INITIAL (decl); 903990075Sobrien tree type = TREE_TYPE (decl); 904090075Sobrien 904190075Sobrien if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init 904290075Sobrien && initializer_constant_valid_p (init, type) == null_pointer_node) 904390075Sobrien /* OK */; 904490075Sobrien else 904590075Sobrien return; 904690075Sobrien 904790075Sobrien switch (TREE_CODE (type)) 904890075Sobrien { 904990075Sobrien case INTEGER_TYPE: 905090075Sobrien if (host_integerp (init, 0)) 905190075Sobrien add_AT_unsigned (var_die, DW_AT_const_value, 905290075Sobrien tree_low_cst (init, 0)); 905390075Sobrien else 905490075Sobrien add_AT_long_long (var_die, DW_AT_const_value, 905590075Sobrien TREE_INT_CST_HIGH (init), 905690075Sobrien TREE_INT_CST_LOW (init)); 905790075Sobrien break; 905890075Sobrien 905990075Sobrien default:; 906090075Sobrien } 906190075Sobrien} 906290075Sobrien 906350397Sobrien/* Generate an DW_AT_name attribute given some string value to be included as 906450397Sobrien the value of the attribute. */ 906550397Sobrien 906650397Sobrienstatic inline void 906750397Sobrienadd_name_attribute (die, name_string) 906890075Sobrien dw_die_ref die; 906990075Sobrien const char *name_string; 907050397Sobrien{ 907150397Sobrien if (name_string != NULL && *name_string != 0) 907290075Sobrien { 907390075Sobrien if (demangle_name_func) 907490075Sobrien name_string = (*demangle_name_func) (name_string); 907590075Sobrien 907690075Sobrien add_AT_string (die, DW_AT_name, name_string); 907790075Sobrien } 907850397Sobrien} 907950397Sobrien 908050397Sobrien/* Given a tree node describing an array bound (either lower or upper) output 908150397Sobrien a representation for that bound. */ 908250397Sobrien 908350397Sobrienstatic void 908450397Sobrienadd_bound_info (subrange_die, bound_attr, bound) 908590075Sobrien dw_die_ref subrange_die; 908690075Sobrien enum dwarf_attribute bound_attr; 908790075Sobrien tree bound; 908850397Sobrien{ 908950397Sobrien switch (TREE_CODE (bound)) 909050397Sobrien { 909150397Sobrien case ERROR_MARK: 909250397Sobrien return; 909350397Sobrien 909490075Sobrien /* All fixed-bounds are represented by INTEGER_CST nodes. */ 909550397Sobrien case INTEGER_CST: 909690075Sobrien if (! host_integerp (bound, 0) 909790075Sobrien || (bound_attr == DW_AT_lower_bound 909890075Sobrien && (((is_c_family () || is_java ()) && integer_zerop (bound)) 909990075Sobrien || (is_fortran () && integer_onep (bound))))) 910090075Sobrien /* use the default */ 910190075Sobrien ; 910250397Sobrien else 910390075Sobrien add_AT_unsigned (subrange_die, bound_attr, tree_low_cst (bound, 0)); 910450397Sobrien break; 910550397Sobrien 910650397Sobrien case CONVERT_EXPR: 910750397Sobrien case NOP_EXPR: 910850397Sobrien case NON_LVALUE_EXPR: 910990075Sobrien case VIEW_CONVERT_EXPR: 911050397Sobrien add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); 911150397Sobrien break; 911290075Sobrien 911350397Sobrien case SAVE_EXPR: 911450397Sobrien /* If optimization is turned on, the SAVE_EXPRs that describe how to 911550397Sobrien access the upper bound values may be bogus. If they refer to a 911650397Sobrien register, they may only describe how to get at these values at the 911750397Sobrien points in the generated code right after they have just been 911850397Sobrien computed. Worse yet, in the typical case, the upper bound values 911950397Sobrien will not even *be* computed in the optimized code (though the 912050397Sobrien number of elements will), so these SAVE_EXPRs are entirely 912150397Sobrien bogus. In order to compensate for this fact, we check here to see 912250397Sobrien if optimization is enabled, and if so, we don't add an attribute 912350397Sobrien for the (unknown and unknowable) upper bound. This should not 912450397Sobrien cause too much trouble for existing (stupid?) debuggers because 912550397Sobrien they have to deal with empty upper bounds location descriptions 912650397Sobrien anyway in order to be able to deal with incomplete array types. 912750397Sobrien Of course an intelligent debugger (GDB?) should be able to 912890075Sobrien comprehend that a missing upper bound specification in an array 912950397Sobrien type used for a storage class `auto' local array variable 913050397Sobrien indicates that the upper bound is both unknown (at compile- time) 913150397Sobrien and unknowable (at run-time) due to optimization. 913250397Sobrien 913350397Sobrien We assume that a MEM rtx is safe because gcc wouldn't put the 913450397Sobrien value there unless it was going to be used repeatedly in the 913550397Sobrien function, i.e. for cleanups. */ 913690075Sobrien if (SAVE_EXPR_RTL (bound) 913790075Sobrien && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM)) 913850397Sobrien { 913990075Sobrien dw_die_ref ctx = lookup_decl_die (current_function_decl); 914090075Sobrien dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound); 914190075Sobrien rtx loc = SAVE_EXPR_RTL (bound); 914250397Sobrien 914350397Sobrien /* If the RTL for the SAVE_EXPR is memory, handle the case where 914450397Sobrien it references an outer function's frame. */ 914550397Sobrien if (GET_CODE (loc) == MEM) 914650397Sobrien { 914750397Sobrien rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound); 914850397Sobrien 914950397Sobrien if (XEXP (loc, 0) != new_addr) 915090075Sobrien loc = gen_rtx_MEM (GET_MODE (loc), new_addr); 915150397Sobrien } 915250397Sobrien 915350397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 915450397Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 915550397Sobrien add_AT_location_description (decl_die, DW_AT_location, loc); 915650397Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 915750397Sobrien } 915850397Sobrien 915950397Sobrien /* Else leave out the attribute. */ 916050397Sobrien break; 916150397Sobrien 916250397Sobrien case VAR_DECL: 916390075Sobrien case PARM_DECL: 916490075Sobrien { 916590075Sobrien dw_die_ref decl_die = lookup_decl_die (bound); 916650397Sobrien 916790075Sobrien /* ??? Can this happen, or should the variable have been bound 916890075Sobrien first? Probably it can, since I imagine that we try to create 916990075Sobrien the types of parameters in the order in which they exist in 917090075Sobrien the list, and won't have created a forward reference to a 917190075Sobrien later parameter. */ 917290075Sobrien if (decl_die != NULL) 917390075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 917490075Sobrien break; 917590075Sobrien } 917690075Sobrien 917750397Sobrien default: 917890075Sobrien { 917990075Sobrien /* Otherwise try to create a stack operation procedure to 918090075Sobrien evaluate the value of the array bound. */ 918190075Sobrien 918290075Sobrien dw_die_ref ctx, decl_die; 918390075Sobrien dw_loc_descr_ref loc; 918490075Sobrien 918590075Sobrien loc = loc_descriptor_from_tree (bound, 0); 918690075Sobrien if (loc == NULL) 918790075Sobrien break; 918890075Sobrien 918990075Sobrien if (current_function_decl == 0) 919090075Sobrien ctx = comp_unit_die; 919190075Sobrien else 919290075Sobrien ctx = lookup_decl_die (current_function_decl); 919390075Sobrien 919490075Sobrien /* If we weren't able to find a context, it's most likely the case 919590075Sobrien that we are processing the return type of the function. So 919690075Sobrien make a SAVE_EXPR to point to it and have the limbo DIE code 919790075Sobrien find the proper die. The save_expr function doesn't always 919890075Sobrien make a SAVE_EXPR, so do it ourselves. */ 919990075Sobrien if (ctx == 0) 920090075Sobrien bound = build (SAVE_EXPR, TREE_TYPE (bound), bound, 920190075Sobrien current_function_decl, NULL_TREE); 920290075Sobrien 920390075Sobrien decl_die = new_die (DW_TAG_variable, ctx, bound); 920490075Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 920590075Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 920690075Sobrien add_AT_loc (decl_die, DW_AT_location, loc); 920790075Sobrien 920890075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 920990075Sobrien break; 921090075Sobrien } 921150397Sobrien } 921250397Sobrien} 921350397Sobrien 921450397Sobrien/* Note that the block of subscript information for an array type also 921550397Sobrien includes information about the element type of type given array type. */ 921650397Sobrien 921750397Sobrienstatic void 921850397Sobrienadd_subscript_info (type_die, type) 921990075Sobrien dw_die_ref type_die; 922090075Sobrien tree type; 922150397Sobrien{ 922250397Sobrien#ifndef MIPS_DEBUGGING_INFO 922390075Sobrien unsigned dimension_number; 922450397Sobrien#endif 922590075Sobrien tree lower, upper; 922690075Sobrien dw_die_ref subrange_die; 922750397Sobrien 922890075Sobrien /* The GNU compilers represent multidimensional array types as sequences of 922950397Sobrien one dimensional array types whose element types are themselves array 923050397Sobrien types. Here we squish that down, so that each multidimensional array 923190075Sobrien type gets only one array_type DIE in the Dwarf debugging info. The draft 923250397Sobrien Dwarf specification say that we are allowed to do this kind of 923350397Sobrien compression in C (because there is no difference between an array or 923490075Sobrien arrays and a multidimensional array in C) but for other source languages 923550397Sobrien (e.g. Ada) we probably shouldn't do this. */ 923650397Sobrien 923750397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 923850397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 923950397Sobrien We work around this by disabling this feature. See also 924050397Sobrien gen_array_type_die. */ 924150397Sobrien#ifndef MIPS_DEBUGGING_INFO 924250397Sobrien for (dimension_number = 0; 924350397Sobrien TREE_CODE (type) == ARRAY_TYPE; 924450397Sobrien type = TREE_TYPE (type), dimension_number++) 924590075Sobrien#endif 924650397Sobrien { 924790075Sobrien tree domain = TYPE_DOMAIN (type); 924850397Sobrien 924950397Sobrien /* Arrays come in three flavors: Unspecified bounds, fixed bounds, 925090075Sobrien and (in GNU C only) variable bounds. Handle all three forms 925150397Sobrien here. */ 925290075Sobrien subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL); 925350397Sobrien if (domain) 925450397Sobrien { 925550397Sobrien /* We have an array type with specified bounds. */ 925650397Sobrien lower = TYPE_MIN_VALUE (domain); 925750397Sobrien upper = TYPE_MAX_VALUE (domain); 925850397Sobrien 925950397Sobrien /* define the index type. */ 926050397Sobrien if (TREE_TYPE (domain)) 926150397Sobrien { 926250397Sobrien /* ??? This is probably an Ada unnamed subrange type. Ignore the 926350397Sobrien TREE_TYPE field. We can't emit debug info for this 926450397Sobrien because it is an unnamed integral type. */ 926550397Sobrien if (TREE_CODE (domain) == INTEGER_TYPE 926650397Sobrien && TYPE_NAME (domain) == NULL_TREE 926750397Sobrien && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE 926850397Sobrien && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE) 926990075Sobrien ; 927050397Sobrien else 927150397Sobrien add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0, 927250397Sobrien type_die); 927350397Sobrien } 927450397Sobrien 927550397Sobrien /* ??? If upper is NULL, the array has unspecified length, 927650397Sobrien but it does have a lower bound. This happens with Fortran 927750397Sobrien dimension arr(N:*) 927850397Sobrien Since the debugger is definitely going to need to know N 927950397Sobrien to produce useful results, go ahead and output the lower 928050397Sobrien bound solo, and hope the debugger can cope. */ 928150397Sobrien 928250397Sobrien add_bound_info (subrange_die, DW_AT_lower_bound, lower); 928350397Sobrien if (upper) 928450397Sobrien add_bound_info (subrange_die, DW_AT_upper_bound, upper); 928550397Sobrien } 928650397Sobrien 928790075Sobrien /* Otherwise we have an array type with an unspecified length. The 928890075Sobrien DWARF-2 spec does not say how to handle this; let's just leave out the 928990075Sobrien bounds. */ 929050397Sobrien } 929150397Sobrien} 929250397Sobrien 929350397Sobrienstatic void 929450397Sobrienadd_byte_size_attribute (die, tree_node) 929550397Sobrien dw_die_ref die; 929690075Sobrien tree tree_node; 929750397Sobrien{ 929890075Sobrien unsigned size; 929950397Sobrien 930050397Sobrien switch (TREE_CODE (tree_node)) 930150397Sobrien { 930250397Sobrien case ERROR_MARK: 930350397Sobrien size = 0; 930450397Sobrien break; 930550397Sobrien case ENUMERAL_TYPE: 930650397Sobrien case RECORD_TYPE: 930750397Sobrien case UNION_TYPE: 930850397Sobrien case QUAL_UNION_TYPE: 930950397Sobrien size = int_size_in_bytes (tree_node); 931050397Sobrien break; 931150397Sobrien case FIELD_DECL: 931250397Sobrien /* For a data member of a struct or union, the DW_AT_byte_size is 931350397Sobrien generally given as the number of bytes normally allocated for an 931450397Sobrien object of the *declared* type of the member itself. This is true 931550397Sobrien even for bit-fields. */ 931650397Sobrien size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT; 931750397Sobrien break; 931850397Sobrien default: 931950397Sobrien abort (); 932050397Sobrien } 932150397Sobrien 932250397Sobrien /* Note that `size' might be -1 when we get to this point. If it is, that 932350397Sobrien indicates that the byte size of the entity in question is variable. We 932450397Sobrien have no good way of expressing this fact in Dwarf at the present time, 932550397Sobrien so just let the -1 pass on through. */ 932650397Sobrien add_AT_unsigned (die, DW_AT_byte_size, size); 932750397Sobrien} 932850397Sobrien 932950397Sobrien/* For a FIELD_DECL node which represents a bit-field, output an attribute 933050397Sobrien which specifies the distance in bits from the highest order bit of the 933150397Sobrien "containing object" for the bit-field to the highest order bit of the 933250397Sobrien bit-field itself. 933350397Sobrien 933490075Sobrien For any given bit-field, the "containing object" is a hypothetical object 933590075Sobrien (of some integral or enum type) within which the given bit-field lives. The 933690075Sobrien type of this hypothetical "containing object" is always the same as the 933790075Sobrien declared type of the individual bit-field itself. The determination of the 933890075Sobrien exact location of the "containing object" for a bit-field is rather 933990075Sobrien complicated. It's handled by the `field_byte_offset' function (above). 934050397Sobrien 934150397Sobrien Note that it is the size (in bytes) of the hypothetical "containing object" 934250397Sobrien which will be given in the DW_AT_byte_size attribute for this bit-field. 934350397Sobrien (See `byte_size_attribute' above). */ 934450397Sobrien 934550397Sobrienstatic inline void 934650397Sobrienadd_bit_offset_attribute (die, decl) 934790075Sobrien dw_die_ref die; 934890075Sobrien tree decl; 934950397Sobrien{ 935090075Sobrien HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl); 935190075Sobrien tree type = DECL_BIT_FIELD_TYPE (decl); 935290075Sobrien HOST_WIDE_INT bitpos_int; 935390075Sobrien HOST_WIDE_INT highest_order_object_bit_offset; 935490075Sobrien HOST_WIDE_INT highest_order_field_bit_offset; 935590075Sobrien HOST_WIDE_INT unsigned bit_offset; 935650397Sobrien 935750397Sobrien /* Must be a field and a bit field. */ 935850397Sobrien if (!type 935950397Sobrien || TREE_CODE (decl) != FIELD_DECL) 936050397Sobrien abort (); 936150397Sobrien 936250397Sobrien /* We can't yet handle bit-fields whose offsets are variable, so if we 936350397Sobrien encounter such things, just return without generating any attribute 936490075Sobrien whatsoever. Likewise for variable or too large size. */ 936590075Sobrien if (! host_integerp (bit_position (decl), 0) 936690075Sobrien || ! host_integerp (DECL_SIZE (decl), 1)) 936750397Sobrien return; 936850397Sobrien 936990075Sobrien bitpos_int = int_bit_position (decl); 937050397Sobrien 937150397Sobrien /* Note that the bit offset is always the distance (in bits) from the 937290075Sobrien highest-order bit of the "containing object" to the highest-order bit of 937390075Sobrien the bit-field itself. Since the "high-order end" of any object or field 937450397Sobrien is different on big-endian and little-endian machines, the computation 937550397Sobrien below must take account of these differences. */ 937650397Sobrien highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT; 937750397Sobrien highest_order_field_bit_offset = bitpos_int; 937850397Sobrien 937950397Sobrien if (! BYTES_BIG_ENDIAN) 938050397Sobrien { 938190075Sobrien highest_order_field_bit_offset += tree_low_cst (DECL_SIZE (decl), 0); 938250397Sobrien highest_order_object_bit_offset += simple_type_size_in_bits (type); 938350397Sobrien } 938450397Sobrien 938550397Sobrien bit_offset 938650397Sobrien = (! BYTES_BIG_ENDIAN 938750397Sobrien ? highest_order_object_bit_offset - highest_order_field_bit_offset 938850397Sobrien : highest_order_field_bit_offset - highest_order_object_bit_offset); 938950397Sobrien 939050397Sobrien add_AT_unsigned (die, DW_AT_bit_offset, bit_offset); 939150397Sobrien} 939250397Sobrien 939350397Sobrien/* For a FIELD_DECL node which represents a bit field, output an attribute 939450397Sobrien which specifies the length in bits of the given field. */ 939550397Sobrien 939650397Sobrienstatic inline void 939750397Sobrienadd_bit_size_attribute (die, decl) 939890075Sobrien dw_die_ref die; 939990075Sobrien tree decl; 940050397Sobrien{ 940150397Sobrien /* Must be a field and a bit field. */ 940250397Sobrien if (TREE_CODE (decl) != FIELD_DECL 940350397Sobrien || ! DECL_BIT_FIELD_TYPE (decl)) 940450397Sobrien abort (); 940590075Sobrien 940690075Sobrien if (host_integerp (DECL_SIZE (decl), 1)) 940790075Sobrien add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1)); 940850397Sobrien} 940950397Sobrien 941050397Sobrien/* If the compiled language is ANSI C, then add a 'prototyped' 941150397Sobrien attribute, if arg types are given for the parameters of a function. */ 941250397Sobrien 941350397Sobrienstatic inline void 941450397Sobrienadd_prototyped_attribute (die, func_type) 941590075Sobrien dw_die_ref die; 941690075Sobrien tree func_type; 941750397Sobrien{ 941850397Sobrien if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 941950397Sobrien && TYPE_ARG_TYPES (func_type) != NULL) 942050397Sobrien add_AT_flag (die, DW_AT_prototyped, 1); 942150397Sobrien} 942250397Sobrien 942350397Sobrien/* Add an 'abstract_origin' attribute below a given DIE. The DIE is found 942450397Sobrien by looking in either the type declaration or object declaration 942550397Sobrien equate table. */ 942650397Sobrien 942750397Sobrienstatic inline void 942850397Sobrienadd_abstract_origin_attribute (die, origin) 942990075Sobrien dw_die_ref die; 943090075Sobrien tree origin; 943150397Sobrien{ 943250397Sobrien dw_die_ref origin_die = NULL; 943390075Sobrien 943490075Sobrien if (TREE_CODE (origin) != FUNCTION_DECL) 943590075Sobrien { 943690075Sobrien /* We may have gotten separated from the block for the inlined 943790075Sobrien function, if we're in an exception handler or some such; make 943890075Sobrien sure that the abstract function has been written out. 943990075Sobrien 944090075Sobrien Doing this for nested functions is wrong, however; functions are 944190075Sobrien distinct units, and our context might not even be inline. */ 944290075Sobrien tree fn = origin; 944390075Sobrien 944490075Sobrien if (TYPE_P (fn)) 944590075Sobrien fn = TYPE_STUB_DECL (fn); 944690075Sobrien 944790075Sobrien fn = decl_function_context (fn); 944890075Sobrien if (fn) 944990075Sobrien dwarf2out_abstract_function (fn); 945090075Sobrien } 945190075Sobrien 945290075Sobrien if (DECL_P (origin)) 945350397Sobrien origin_die = lookup_decl_die (origin); 945490075Sobrien else if (TYPE_P (origin)) 945550397Sobrien origin_die = lookup_type_die (origin); 945650397Sobrien 945790075Sobrien if (origin_die == NULL) 945890075Sobrien abort (); 945990075Sobrien 946050397Sobrien add_AT_die_ref (die, DW_AT_abstract_origin, origin_die); 946150397Sobrien} 946250397Sobrien 946350397Sobrien/* We do not currently support the pure_virtual attribute. */ 946450397Sobrien 946550397Sobrienstatic inline void 946650397Sobrienadd_pure_or_virtual_attribute (die, func_decl) 946790075Sobrien dw_die_ref die; 946890075Sobrien tree func_decl; 946950397Sobrien{ 947050397Sobrien if (DECL_VINDEX (func_decl)) 947150397Sobrien { 947250397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 947350397Sobrien 947490075Sobrien if (host_integerp (DECL_VINDEX (func_decl), 0)) 947590075Sobrien add_AT_loc (die, DW_AT_vtable_elem_location, 947690075Sobrien new_loc_descr (DW_OP_constu, 947790075Sobrien tree_low_cst (DECL_VINDEX (func_decl), 0), 947890075Sobrien 0)); 947990075Sobrien 948050397Sobrien /* GNU extension: Record what type this method came from originally. */ 948150397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 948250397Sobrien add_AT_die_ref (die, DW_AT_containing_type, 948350397Sobrien lookup_type_die (DECL_CONTEXT (func_decl))); 948450397Sobrien } 948550397Sobrien} 948650397Sobrien 948750397Sobrien/* Add source coordinate attributes for the given decl. */ 948850397Sobrien 948950397Sobrienstatic void 949050397Sobrienadd_src_coords_attributes (die, decl) 949190075Sobrien dw_die_ref die; 949290075Sobrien tree decl; 949350397Sobrien{ 949490075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 949550397Sobrien 949650397Sobrien add_AT_unsigned (die, DW_AT_decl_file, file_index); 949750397Sobrien add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 949850397Sobrien} 949950397Sobrien 950050397Sobrien/* Add an DW_AT_name attribute and source coordinate attribute for the 950150397Sobrien given decl, but only if it actually has a name. */ 950250397Sobrien 950350397Sobrienstatic void 950450397Sobrienadd_name_and_src_coords_attributes (die, decl) 950590075Sobrien dw_die_ref die; 950690075Sobrien tree decl; 950750397Sobrien{ 950890075Sobrien tree decl_name; 950950397Sobrien 951090075Sobrien decl_name = DECL_NAME (decl); 951150397Sobrien if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) 951250397Sobrien { 951350397Sobrien add_name_attribute (die, dwarf2_name (decl, 0)); 951490075Sobrien if (! DECL_ARTIFICIAL (decl)) 951590075Sobrien add_src_coords_attributes (die, decl); 951690075Sobrien 951750397Sobrien if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) 951890075Sobrien && TREE_PUBLIC (decl) 951990075Sobrien && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) 952090075Sobrien && !DECL_ABSTRACT (decl)) 952150397Sobrien add_AT_string (die, DW_AT_MIPS_linkage_name, 952250397Sobrien IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 952350397Sobrien } 952490075Sobrien 952590075Sobrien#ifdef VMS_DEBUGGING_INFO 952690075Sobrien /* Get the function's name, as described by its RTL. This may be different 952790075Sobrien from the DECL_NAME name used in the source file. */ 952890075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) 952990075Sobrien { 953090075Sobrien add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address, 953190075Sobrien XEXP (DECL_RTL (decl), 0)); 953290075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, XEXP (DECL_RTL (decl), 0)); 953390075Sobrien } 953490075Sobrien#endif 953550397Sobrien} 953650397Sobrien 953790075Sobrien/* Push a new declaration scope. */ 953850397Sobrien 953950397Sobrienstatic void 954050397Sobrienpush_decl_scope (scope) 954150397Sobrien tree scope; 954250397Sobrien{ 954390075Sobrien VARRAY_PUSH_TREE (decl_scope_table, scope); 954490075Sobrien} 954550397Sobrien 954690075Sobrien/* Pop a declaration scope. */ 954750397Sobrien 954890075Sobrienstatic inline void 954990075Sobrienpop_decl_scope () 955090075Sobrien{ 955190075Sobrien if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0) 955290075Sobrien abort (); 955350397Sobrien 955490075Sobrien VARRAY_POP (decl_scope_table); 955550397Sobrien} 955650397Sobrien 955790075Sobrien/* Return the DIE for the scope that immediately contains this type. 955890075Sobrien Non-named types get global scope. Named types nested in other 955990075Sobrien types get their containing scope if it's open, or global scope 956090075Sobrien otherwise. All other types (i.e. function-local named types) get 956190075Sobrien the current active scope. */ 956250397Sobrien 956350397Sobrienstatic dw_die_ref 956450397Sobrienscope_die_for (t, context_die) 956590075Sobrien tree t; 956690075Sobrien dw_die_ref context_die; 956750397Sobrien{ 956890075Sobrien dw_die_ref scope_die = NULL; 956990075Sobrien tree containing_scope; 957090075Sobrien int i; 957150397Sobrien 957290075Sobrien /* Non-types always go in the current scope. */ 957390075Sobrien if (! TYPE_P (t)) 957490075Sobrien abort (); 957550397Sobrien 957690075Sobrien containing_scope = TYPE_CONTEXT (t); 957790075Sobrien 957850397Sobrien /* Ignore namespaces for the moment. */ 957950397Sobrien if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL) 958050397Sobrien containing_scope = NULL_TREE; 958150397Sobrien 958252284Sobrien /* Ignore function type "scopes" from the C frontend. They mean that 958352284Sobrien a tagged type is local to a parmlist of a function declarator, but 958452284Sobrien that isn't useful to DWARF. */ 958552284Sobrien if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE) 958652284Sobrien containing_scope = NULL_TREE; 958752284Sobrien 958850397Sobrien if (containing_scope == NULL_TREE) 958950397Sobrien scope_die = comp_unit_die; 959090075Sobrien else if (TYPE_P (containing_scope)) 959150397Sobrien { 959290075Sobrien /* For types, we can just look up the appropriate DIE. But 959390075Sobrien first we check to see if we're in the middle of emitting it 959490075Sobrien so we know where the new DIE should go. */ 959590075Sobrien for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i) 959690075Sobrien if (VARRAY_TREE (decl_scope_table, i) == containing_scope) 959790075Sobrien break; 959850397Sobrien 959950397Sobrien if (i < 0) 960050397Sobrien { 960150397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE 960250397Sobrien && !TREE_ASM_WRITTEN (containing_scope)) 960350397Sobrien abort (); 960452284Sobrien 960552284Sobrien /* If none of the current dies are suitable, we get file scope. */ 960652284Sobrien scope_die = comp_unit_die; 960750397Sobrien } 960890075Sobrien else 960990075Sobrien scope_die = lookup_type_die (containing_scope); 961050397Sobrien } 961190075Sobrien else 961290075Sobrien scope_die = context_die; 961350397Sobrien 961450397Sobrien return scope_die; 961550397Sobrien} 961650397Sobrien 961790075Sobrien/* Returns nonzero if CONTEXT_DIE is internal to a function. */ 961890075Sobrien 961990075Sobrienstatic inline int 962090075Sobrienlocal_scope_p (context_die) 962190075Sobrien dw_die_ref context_die; 962250397Sobrien{ 962390075Sobrien for (; context_die; context_die = context_die->die_parent) 962490075Sobrien if (context_die->die_tag == DW_TAG_inlined_subroutine 962590075Sobrien || context_die->die_tag == DW_TAG_subprogram) 962690075Sobrien return 1; 962790075Sobrien 962890075Sobrien return 0; 962950397Sobrien} 963050397Sobrien 963190075Sobrien/* Returns nonzero if CONTEXT_DIE is a class. */ 963290075Sobrien 963390075Sobrienstatic inline int 963490075Sobrienclass_scope_p (context_die) 963590075Sobrien dw_die_ref context_die; 963690075Sobrien{ 963790075Sobrien return (context_die 963890075Sobrien && (context_die->die_tag == DW_TAG_structure_type 963990075Sobrien || context_die->die_tag == DW_TAG_union_type)); 964090075Sobrien} 964190075Sobrien 964250397Sobrien/* Many forms of DIEs require a "type description" attribute. This 964350397Sobrien routine locates the proper "type descriptor" die for the type given 964450397Sobrien by 'type', and adds an DW_AT_type attribute below the given die. */ 964550397Sobrien 964650397Sobrienstatic void 964750397Sobrienadd_type_attribute (object_die, type, decl_const, decl_volatile, context_die) 964890075Sobrien dw_die_ref object_die; 964990075Sobrien tree type; 965090075Sobrien int decl_const; 965190075Sobrien int decl_volatile; 965290075Sobrien dw_die_ref context_die; 965350397Sobrien{ 965490075Sobrien enum tree_code code = TREE_CODE (type); 965590075Sobrien dw_die_ref type_die = NULL; 965650397Sobrien 965750397Sobrien /* ??? If this type is an unnamed subrange type of an integral or 965850397Sobrien floating-point type, use the inner type. This is because we have no 965950397Sobrien support for unnamed types in base_type_die. This can happen if this is 966050397Sobrien an Ada subrange type. Correct solution is emit a subrange type die. */ 966150397Sobrien if ((code == INTEGER_TYPE || code == REAL_TYPE) 966250397Sobrien && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0) 966350397Sobrien type = TREE_TYPE (type), code = TREE_CODE (type); 966450397Sobrien 966590075Sobrien if (code == ERROR_MARK 966690075Sobrien /* Handle a special case. For functions whose return type is void, we 966790075Sobrien generate *no* type attribute. (Note that no object may have type 966890075Sobrien `void', so this only applies to function return types). */ 966990075Sobrien || code == VOID_TYPE) 967050397Sobrien return; 967150397Sobrien 967250397Sobrien type_die = modified_type_die (type, 967350397Sobrien decl_const || TYPE_READONLY (type), 967450397Sobrien decl_volatile || TYPE_VOLATILE (type), 967550397Sobrien context_die); 967690075Sobrien 967750397Sobrien if (type_die != NULL) 967850397Sobrien add_AT_die_ref (object_die, DW_AT_type, type_die); 967950397Sobrien} 968050397Sobrien 968150397Sobrien/* Given a tree pointer to a struct, class, union, or enum type node, return 968250397Sobrien a pointer to the (string) tag name for the given type, or zero if the type 968350397Sobrien was declared without a tag. */ 968450397Sobrien 968590075Sobrienstatic const char * 968650397Sobrientype_tag (type) 968790075Sobrien tree type; 968850397Sobrien{ 968990075Sobrien const char *name = 0; 969050397Sobrien 969150397Sobrien if (TYPE_NAME (type) != 0) 969250397Sobrien { 969390075Sobrien tree t = 0; 969450397Sobrien 969550397Sobrien /* Find the IDENTIFIER_NODE for the type name. */ 969650397Sobrien if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 969750397Sobrien t = TYPE_NAME (type); 969850397Sobrien 969990075Sobrien /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 970050397Sobrien a TYPE_DECL node, regardless of whether or not a `typedef' was 970150397Sobrien involved. */ 970250397Sobrien else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 970350397Sobrien && ! DECL_IGNORED_P (TYPE_NAME (type))) 970450397Sobrien t = DECL_NAME (TYPE_NAME (type)); 970550397Sobrien 970650397Sobrien /* Now get the name as a string, or invent one. */ 970750397Sobrien if (t != 0) 970850397Sobrien name = IDENTIFIER_POINTER (t); 970950397Sobrien } 971050397Sobrien 971150397Sobrien return (name == 0 || *name == '\0') ? 0 : name; 971250397Sobrien} 971350397Sobrien 971450397Sobrien/* Return the type associated with a data member, make a special check 971550397Sobrien for bit field types. */ 971650397Sobrien 971750397Sobrienstatic inline tree 971850397Sobrienmember_declared_type (member) 971990075Sobrien tree member; 972050397Sobrien{ 972150397Sobrien return (DECL_BIT_FIELD_TYPE (member) 972290075Sobrien ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member)); 972350397Sobrien} 972450397Sobrien 972550397Sobrien/* Get the decl's label, as described by its RTL. This may be different 972650397Sobrien from the DECL_NAME name used in the source file. */ 972750397Sobrien 972850397Sobrien#if 0 972990075Sobrienstatic const char * 973050397Sobriendecl_start_label (decl) 973190075Sobrien tree decl; 973250397Sobrien{ 973350397Sobrien rtx x; 973490075Sobrien const char *fnname; 973590075Sobrien 973650397Sobrien x = DECL_RTL (decl); 973750397Sobrien if (GET_CODE (x) != MEM) 973850397Sobrien abort (); 973950397Sobrien 974050397Sobrien x = XEXP (x, 0); 974150397Sobrien if (GET_CODE (x) != SYMBOL_REF) 974250397Sobrien abort (); 974350397Sobrien 974450397Sobrien fnname = XSTR (x, 0); 974550397Sobrien return fnname; 974650397Sobrien} 974750397Sobrien#endif 974850397Sobrien 974950397Sobrien/* These routines generate the internal representation of the DIE's for 975050397Sobrien the compilation unit. Debugging information is collected by walking 975150397Sobrien the declaration trees passed in from dwarf2out_decl(). */ 975250397Sobrien 975350397Sobrienstatic void 975450397Sobriengen_array_type_die (type, context_die) 975590075Sobrien tree type; 975690075Sobrien dw_die_ref context_die; 975750397Sobrien{ 975890075Sobrien dw_die_ref scope_die = scope_die_for (type, context_die); 975990075Sobrien dw_die_ref array_die; 976090075Sobrien tree element_type; 976150397Sobrien 976250397Sobrien /* ??? The SGI dwarf reader fails for array of array of enum types unless 976350397Sobrien the inner array type comes before the outer array type. Thus we must 976450397Sobrien call gen_type_die before we call new_die. See below also. */ 976550397Sobrien#ifdef MIPS_DEBUGGING_INFO 976650397Sobrien gen_type_die (TREE_TYPE (type), context_die); 976750397Sobrien#endif 976850397Sobrien 976990075Sobrien array_die = new_die (DW_TAG_array_type, scope_die, type); 977096263Sobrien add_name_attribute (array_die, type_tag (type)); 977196263Sobrien equate_type_number_to_die (type, array_die); 977250397Sobrien 977396263Sobrien if (TREE_CODE (type) == VECTOR_TYPE) 977496263Sobrien { 977596263Sobrien /* The frontend feeds us a representation for the vector as a struct 977696263Sobrien containing an array. Pull out the array type. */ 977796263Sobrien type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type))); 977896263Sobrien add_AT_flag (array_die, DW_AT_GNU_vector, 1); 977996263Sobrien } 978096263Sobrien 978150397Sobrien#if 0 978250397Sobrien /* We default the array ordering. SDB will probably do 978350397Sobrien the right things even if DW_AT_ordering is not present. It's not even 978450397Sobrien an issue until we start to get into multidimensional arrays anyway. If 978550397Sobrien SDB is ever caught doing the Wrong Thing for multi-dimensional arrays, 978650397Sobrien then we'll have to put the DW_AT_ordering attribute back in. (But if 978750397Sobrien and when we find out that we need to put these in, we will only do so 978850397Sobrien for multidimensional arrays. */ 978950397Sobrien add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major); 979050397Sobrien#endif 979150397Sobrien 979250397Sobrien#ifdef MIPS_DEBUGGING_INFO 979350397Sobrien /* The SGI compilers handle arrays of unknown bound by setting 979450397Sobrien AT_declaration and not emitting any subrange DIEs. */ 979550397Sobrien if (! TYPE_DOMAIN (type)) 979650397Sobrien add_AT_unsigned (array_die, DW_AT_declaration, 1); 979750397Sobrien else 979850397Sobrien#endif 979950397Sobrien add_subscript_info (array_die, type); 980050397Sobrien 980150397Sobrien /* Add representation of the type of the elements of this array type. */ 980250397Sobrien element_type = TREE_TYPE (type); 980350397Sobrien 980450397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 980550397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 980650397Sobrien We work around this by disabling this feature. See also 980750397Sobrien add_subscript_info. */ 980850397Sobrien#ifndef MIPS_DEBUGGING_INFO 980950397Sobrien while (TREE_CODE (element_type) == ARRAY_TYPE) 981050397Sobrien element_type = TREE_TYPE (element_type); 981150397Sobrien 981250397Sobrien gen_type_die (element_type, context_die); 981350397Sobrien#endif 981450397Sobrien 981550397Sobrien add_type_attribute (array_die, element_type, 0, 0, context_die); 981650397Sobrien} 981750397Sobrien 981850397Sobrienstatic void 981950397Sobriengen_set_type_die (type, context_die) 982090075Sobrien tree type; 982190075Sobrien dw_die_ref context_die; 982250397Sobrien{ 982390075Sobrien dw_die_ref type_die 982490075Sobrien = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type); 982550397Sobrien 982650397Sobrien equate_type_number_to_die (type, type_die); 982750397Sobrien add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die); 982850397Sobrien} 982950397Sobrien 983050397Sobrien#if 0 983150397Sobrienstatic void 983250397Sobriengen_entry_point_die (decl, context_die) 983390075Sobrien tree decl; 983490075Sobrien dw_die_ref context_die; 983550397Sobrien{ 983690075Sobrien tree origin = decl_ultimate_origin (decl); 983790075Sobrien dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl); 983890075Sobrien 983950397Sobrien if (origin != NULL) 984050397Sobrien add_abstract_origin_attribute (decl_die, origin); 984150397Sobrien else 984250397Sobrien { 984350397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 984450397Sobrien add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)), 984550397Sobrien 0, 0, context_die); 984650397Sobrien } 984750397Sobrien 984850397Sobrien if (DECL_ABSTRACT (decl)) 984950397Sobrien equate_decl_number_to_die (decl, decl_die); 985050397Sobrien else 985150397Sobrien add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl)); 985250397Sobrien} 985350397Sobrien#endif 985450397Sobrien 985552284Sobrien/* Walk through the list of incomplete types again, trying once more to 985652284Sobrien emit full debugging info for them. */ 985752284Sobrien 985852284Sobrienstatic void 985952284Sobrienretry_incomplete_types () 986052284Sobrien{ 986190075Sobrien int i; 986252284Sobrien 986390075Sobrien for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--) 986490075Sobrien gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die); 986552284Sobrien} 986652284Sobrien 986750397Sobrien/* Generate a DIE to represent an inlined instance of an enumeration type. */ 986850397Sobrien 986950397Sobrienstatic void 987050397Sobriengen_inlined_enumeration_type_die (type, context_die) 987190075Sobrien tree type; 987290075Sobrien dw_die_ref context_die; 987350397Sobrien{ 987490075Sobrien dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type); 987550397Sobrien 987690075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 987790075Sobrien be incomplete and such types are not marked. */ 987850397Sobrien add_abstract_origin_attribute (type_die, type); 987950397Sobrien} 988050397Sobrien 988150397Sobrien/* Generate a DIE to represent an inlined instance of a structure type. */ 988250397Sobrien 988350397Sobrienstatic void 988450397Sobriengen_inlined_structure_type_die (type, context_die) 988590075Sobrien tree type; 988690075Sobrien dw_die_ref context_die; 988750397Sobrien{ 988890075Sobrien dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type); 988950397Sobrien 989090075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 989190075Sobrien be incomplete and such types are not marked. */ 989250397Sobrien add_abstract_origin_attribute (type_die, type); 989350397Sobrien} 989450397Sobrien 989550397Sobrien/* Generate a DIE to represent an inlined instance of a union type. */ 989650397Sobrien 989750397Sobrienstatic void 989850397Sobriengen_inlined_union_type_die (type, context_die) 989990075Sobrien tree type; 990090075Sobrien dw_die_ref context_die; 990150397Sobrien{ 990290075Sobrien dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type); 990350397Sobrien 990490075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 990590075Sobrien be incomplete and such types are not marked. */ 990650397Sobrien add_abstract_origin_attribute (type_die, type); 990750397Sobrien} 990850397Sobrien 990950397Sobrien/* Generate a DIE to represent an enumeration type. Note that these DIEs 991050397Sobrien include all of the information about the enumeration values also. Each 991150397Sobrien enumerated type name/value is listed as a child of the enumerated type 991250397Sobrien DIE. */ 991350397Sobrien 991450397Sobrienstatic void 991550397Sobriengen_enumeration_type_die (type, context_die) 991690075Sobrien tree type; 991790075Sobrien dw_die_ref context_die; 991850397Sobrien{ 991990075Sobrien dw_die_ref type_die = lookup_type_die (type); 992050397Sobrien 992150397Sobrien if (type_die == NULL) 992250397Sobrien { 992350397Sobrien type_die = new_die (DW_TAG_enumeration_type, 992490075Sobrien scope_die_for (type, context_die), type); 992550397Sobrien equate_type_number_to_die (type, type_die); 992650397Sobrien add_name_attribute (type_die, type_tag (type)); 992750397Sobrien } 992850397Sobrien else if (! TYPE_SIZE (type)) 992950397Sobrien return; 993050397Sobrien else 993150397Sobrien remove_AT (type_die, DW_AT_declaration); 993250397Sobrien 993350397Sobrien /* Handle a GNU C/C++ extension, i.e. incomplete enum types. If the 993450397Sobrien given enum type is incomplete, do not generate the DW_AT_byte_size 993550397Sobrien attribute or the DW_AT_element_list attribute. */ 993650397Sobrien if (TYPE_SIZE (type)) 993750397Sobrien { 993890075Sobrien tree link; 993950397Sobrien 994050397Sobrien TREE_ASM_WRITTEN (type) = 1; 994150397Sobrien add_byte_size_attribute (type_die, type); 994250397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 994350397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 994450397Sobrien 994550397Sobrien /* If the first reference to this type was as the return type of an 994650397Sobrien inline function, then it may not have a parent. Fix this now. */ 994750397Sobrien if (type_die->die_parent == NULL) 994850397Sobrien add_child_die (scope_die_for (type, context_die), type_die); 994950397Sobrien 995050397Sobrien for (link = TYPE_FIELDS (type); 995150397Sobrien link != NULL; link = TREE_CHAIN (link)) 995250397Sobrien { 995390075Sobrien dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link); 995450397Sobrien 995550397Sobrien add_name_attribute (enum_die, 995650397Sobrien IDENTIFIER_POINTER (TREE_PURPOSE (link))); 995790075Sobrien 995890075Sobrien if (host_integerp (TREE_VALUE (link), 0)) 995990075Sobrien { 996090075Sobrien if (tree_int_cst_sgn (TREE_VALUE (link)) < 0) 996190075Sobrien add_AT_int (enum_die, DW_AT_const_value, 996290075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 996390075Sobrien else 996490075Sobrien add_AT_unsigned (enum_die, DW_AT_const_value, 996590075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 996690075Sobrien } 996750397Sobrien } 996850397Sobrien } 996950397Sobrien else 997050397Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 997150397Sobrien} 997250397Sobrien 997350397Sobrien/* Generate a DIE to represent either a real live formal parameter decl or to 997450397Sobrien represent just the type of some formal parameter position in some function 997550397Sobrien type. 997650397Sobrien 997750397Sobrien Note that this routine is a bit unusual because its argument may be a 997850397Sobrien ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which 997950397Sobrien represents an inlining of some PARM_DECL) or else some sort of a ..._TYPE 998050397Sobrien node. If it's the former then this function is being called to output a 998150397Sobrien DIE to represent a formal parameter object (or some inlining thereof). If 998250397Sobrien it's the latter, then this function is only being called to output a 998350397Sobrien DW_TAG_formal_parameter DIE to stand as a placeholder for some formal 998450397Sobrien argument type of some subprogram type. */ 998550397Sobrien 998650397Sobrienstatic dw_die_ref 998750397Sobriengen_formal_parameter_die (node, context_die) 998890075Sobrien tree node; 998990075Sobrien dw_die_ref context_die; 999050397Sobrien{ 999190075Sobrien dw_die_ref parm_die 999290075Sobrien = new_die (DW_TAG_formal_parameter, context_die, node); 999390075Sobrien tree origin; 999450397Sobrien 999550397Sobrien switch (TREE_CODE_CLASS (TREE_CODE (node))) 999650397Sobrien { 999750397Sobrien case 'd': 999850397Sobrien origin = decl_ultimate_origin (node); 999950397Sobrien if (origin != NULL) 1000050397Sobrien add_abstract_origin_attribute (parm_die, origin); 1000150397Sobrien else 1000250397Sobrien { 1000350397Sobrien add_name_and_src_coords_attributes (parm_die, node); 1000450397Sobrien add_type_attribute (parm_die, TREE_TYPE (node), 1000550397Sobrien TREE_READONLY (node), 1000650397Sobrien TREE_THIS_VOLATILE (node), 1000750397Sobrien context_die); 1000850397Sobrien if (DECL_ARTIFICIAL (node)) 1000950397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 1001050397Sobrien } 1001150397Sobrien 1001250397Sobrien equate_decl_number_to_die (node, parm_die); 1001350397Sobrien if (! DECL_ABSTRACT (node)) 1001450397Sobrien add_location_or_const_value_attribute (parm_die, node); 1001550397Sobrien 1001650397Sobrien break; 1001750397Sobrien 1001850397Sobrien case 't': 1001950397Sobrien /* We were called with some kind of a ..._TYPE node. */ 1002050397Sobrien add_type_attribute (parm_die, node, 0, 0, context_die); 1002150397Sobrien break; 1002250397Sobrien 1002350397Sobrien default: 1002450397Sobrien abort (); 1002550397Sobrien } 1002650397Sobrien 1002750397Sobrien return parm_die; 1002850397Sobrien} 1002950397Sobrien 1003050397Sobrien/* Generate a special type of DIE used as a stand-in for a trailing ellipsis 1003150397Sobrien at the end of an (ANSI prototyped) formal parameters list. */ 1003250397Sobrien 1003350397Sobrienstatic void 1003450397Sobriengen_unspecified_parameters_die (decl_or_type, context_die) 1003590075Sobrien tree decl_or_type; 1003690075Sobrien dw_die_ref context_die; 1003750397Sobrien{ 1003890075Sobrien new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type); 1003950397Sobrien} 1004050397Sobrien 1004150397Sobrien/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a 1004250397Sobrien DW_TAG_unspecified_parameters DIE) to represent the types of the formal 1004350397Sobrien parameters as specified in some function type specification (except for 1004490075Sobrien those which appear as part of a function *definition*). */ 1004550397Sobrien 1004650397Sobrienstatic void 1004750397Sobriengen_formal_types_die (function_or_method_type, context_die) 1004890075Sobrien tree function_or_method_type; 1004990075Sobrien dw_die_ref context_die; 1005050397Sobrien{ 1005190075Sobrien tree link; 1005290075Sobrien tree formal_type = NULL; 1005390075Sobrien tree first_parm_type; 1005490075Sobrien tree arg; 1005550397Sobrien 1005690075Sobrien if (TREE_CODE (function_or_method_type) == FUNCTION_DECL) 1005790075Sobrien { 1005890075Sobrien arg = DECL_ARGUMENTS (function_or_method_type); 1005990075Sobrien function_or_method_type = TREE_TYPE (function_or_method_type); 1006090075Sobrien } 1006190075Sobrien else 1006290075Sobrien arg = NULL_TREE; 1006390075Sobrien 1006490075Sobrien first_parm_type = TYPE_ARG_TYPES (function_or_method_type); 1006550397Sobrien 1006690075Sobrien /* Make our first pass over the list of formal parameter types and output a 1006750397Sobrien DW_TAG_formal_parameter DIE for each one. */ 1006890075Sobrien for (link = first_parm_type; link; ) 1006950397Sobrien { 1007090075Sobrien dw_die_ref parm_die; 1007190075Sobrien 1007250397Sobrien formal_type = TREE_VALUE (link); 1007350397Sobrien if (formal_type == void_type_node) 1007450397Sobrien break; 1007550397Sobrien 1007650397Sobrien /* Output a (nameless) DIE to represent the formal parameter itself. */ 1007750397Sobrien parm_die = gen_formal_parameter_die (formal_type, context_die); 1007890075Sobrien if ((TREE_CODE (function_or_method_type) == METHOD_TYPE 1007990075Sobrien && link == first_parm_type) 1008090075Sobrien || (arg && DECL_ARTIFICIAL (arg))) 1008150397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 1008290075Sobrien 1008390075Sobrien link = TREE_CHAIN (link); 1008490075Sobrien if (arg) 1008590075Sobrien arg = TREE_CHAIN (arg); 1008650397Sobrien } 1008750397Sobrien 1008850397Sobrien /* If this function type has an ellipsis, add a 1008950397Sobrien DW_TAG_unspecified_parameters DIE to the end of the parameter list. */ 1009050397Sobrien if (formal_type != void_type_node) 1009150397Sobrien gen_unspecified_parameters_die (function_or_method_type, context_die); 1009250397Sobrien 1009390075Sobrien /* Make our second (and final) pass over the list of formal parameter types 1009450397Sobrien and output DIEs to represent those types (as necessary). */ 1009550397Sobrien for (link = TYPE_ARG_TYPES (function_or_method_type); 1009690075Sobrien link && TREE_VALUE (link); 1009750397Sobrien link = TREE_CHAIN (link)) 1009890075Sobrien gen_type_die (TREE_VALUE (link), context_die); 1009990075Sobrien} 1010090075Sobrien 1010190075Sobrien/* We want to generate the DIE for TYPE so that we can generate the 1010290075Sobrien die for MEMBER, which has been defined; we will need to refer back 1010390075Sobrien to the member declaration nested within TYPE. If we're trying to 1010490075Sobrien generate minimal debug info for TYPE, processing TYPE won't do the 1010590075Sobrien trick; we need to attach the member declaration by hand. */ 1010690075Sobrien 1010790075Sobrienstatic void 1010890075Sobriengen_type_die_for_member (type, member, context_die) 1010990075Sobrien tree type, member; 1011090075Sobrien dw_die_ref context_die; 1011190075Sobrien{ 1011290075Sobrien gen_type_die (type, context_die); 1011390075Sobrien 1011490075Sobrien /* If we're trying to avoid duplicate debug info, we may not have 1011590075Sobrien emitted the member decl for this function. Emit it now. */ 1011690075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) 1011790075Sobrien && ! lookup_decl_die (member)) 1011850397Sobrien { 1011990075Sobrien if (decl_ultimate_origin (member)) 1012090075Sobrien abort (); 1012150397Sobrien 1012290075Sobrien push_decl_scope (type); 1012390075Sobrien if (TREE_CODE (member) == FUNCTION_DECL) 1012490075Sobrien gen_subprogram_die (member, lookup_type_die (type)); 1012590075Sobrien else 1012690075Sobrien gen_variable_die (member, lookup_type_die (type)); 1012790075Sobrien 1012890075Sobrien pop_decl_scope (); 1012950397Sobrien } 1013050397Sobrien} 1013150397Sobrien 1013290075Sobrien/* Generate the DWARF2 info for the "abstract" instance of a function which we 1013390075Sobrien may later generate inlined and/or out-of-line instances of. */ 1013490075Sobrien 1013590075Sobrienstatic void 1013690075Sobriendwarf2out_abstract_function (decl) 1013790075Sobrien tree decl; 1013890075Sobrien{ 1013990075Sobrien dw_die_ref old_die; 1014090075Sobrien tree save_fn; 1014190075Sobrien tree context; 1014290075Sobrien int was_abstract = DECL_ABSTRACT (decl); 1014390075Sobrien 1014490075Sobrien /* Make sure we have the actual abstract inline, not a clone. */ 1014590075Sobrien decl = DECL_ORIGIN (decl); 1014690075Sobrien 1014790075Sobrien old_die = lookup_decl_die (decl); 1014890075Sobrien if (old_die && get_AT_unsigned (old_die, DW_AT_inline)) 1014990075Sobrien /* We've already generated the abstract instance. */ 1015090075Sobrien return; 1015190075Sobrien 1015290075Sobrien /* Be sure we've emitted the in-class declaration DIE (if any) first, so 1015390075Sobrien we don't get confused by DECL_ABSTRACT. */ 1015490075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1015590075Sobrien { 1015690075Sobrien context = decl_class_context (decl); 1015790075Sobrien if (context) 1015890075Sobrien gen_type_die_for_member 1015990075Sobrien (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); 1016090075Sobrien } 1016190075Sobrien 1016290075Sobrien /* Pretend we've just finished compiling this function. */ 1016390075Sobrien save_fn = current_function_decl; 1016490075Sobrien current_function_decl = decl; 1016590075Sobrien 1016690075Sobrien set_decl_abstract_flags (decl, 1); 1016790075Sobrien dwarf2out_decl (decl); 1016890075Sobrien if (! was_abstract) 1016990075Sobrien set_decl_abstract_flags (decl, 0); 1017090075Sobrien 1017190075Sobrien current_function_decl = save_fn; 1017290075Sobrien} 1017390075Sobrien 1017450397Sobrien/* Generate a DIE to represent a declared function (either file-scope or 1017550397Sobrien block-local). */ 1017650397Sobrien 1017750397Sobrienstatic void 1017850397Sobriengen_subprogram_die (decl, context_die) 1017990075Sobrien tree decl; 1018090075Sobrien dw_die_ref context_die; 1018150397Sobrien{ 1018250397Sobrien char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 1018390075Sobrien tree origin = decl_ultimate_origin (decl); 1018490075Sobrien dw_die_ref subr_die; 1018590075Sobrien rtx fp_reg; 1018690075Sobrien tree fn_arg_types; 1018790075Sobrien tree outer_scope; 1018890075Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1018990075Sobrien int declaration = (current_function_decl != decl 1019090075Sobrien || class_scope_p (context_die)); 1019150397Sobrien 1019290075Sobrien /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we 1019390075Sobrien started to generate the abstract instance of an inline, decided to output 1019490075Sobrien its containing class, and proceeded to emit the declaration of the inline 1019590075Sobrien from the member list for the class. If so, DECLARATION takes priority; 1019690075Sobrien we'll get back to the abstract instance when done with the class. */ 1019790075Sobrien 1019890075Sobrien /* The class-scope declaration DIE must be the primary DIE. */ 1019990075Sobrien if (origin && declaration && class_scope_p (context_die)) 1020050397Sobrien { 1020190075Sobrien origin = NULL; 1020290075Sobrien if (old_die) 1020390075Sobrien abort (); 1020450397Sobrien } 1020590075Sobrien 1020690075Sobrien if (origin != NULL) 1020750397Sobrien { 1020890075Sobrien if (declaration && ! local_scope_p (context_die)) 1020990075Sobrien abort (); 1021050397Sobrien 1021190075Sobrien /* Fixup die_parent for the abstract instance of a nested 1021290075Sobrien inline function. */ 1021390075Sobrien if (old_die && old_die->die_parent == NULL) 1021490075Sobrien add_child_die (context_die, old_die); 1021590075Sobrien 1021690075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1021790075Sobrien add_abstract_origin_attribute (subr_die, origin); 1021850397Sobrien } 1021950397Sobrien else if (old_die) 1022050397Sobrien { 1022190075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1022250397Sobrien 1022390075Sobrien if (!get_AT_flag (old_die, DW_AT_declaration) 1022490075Sobrien /* We can have a normal definition following an inline one in the 1022590075Sobrien case of redefinition of GNU C extern inlines. 1022690075Sobrien It seems reasonable to use AT_specification in this case. */ 1022790075Sobrien && !get_AT_unsigned (old_die, DW_AT_inline)) 1022852284Sobrien { 1022952284Sobrien /* ??? This can happen if there is a bug in the program, for 1023052284Sobrien instance, if it has duplicate function definitions. Ideally, 1023152284Sobrien we should detect this case and ignore it. For now, if we have 1023252284Sobrien already reported an error, any error at all, then assume that 1023390075Sobrien we got here because of an input error, not a dwarf2 bug. */ 1023452284Sobrien if (errorcount) 1023552284Sobrien return; 1023652284Sobrien abort (); 1023752284Sobrien } 1023850397Sobrien 1023950397Sobrien /* If the definition comes from the same place as the declaration, 1024050397Sobrien maybe use the old DIE. We always want the DIE for this function 1024150397Sobrien that has the *_pc attributes to be under comp_unit_die so the 1024290075Sobrien debugger can find it. We also need to do this for abstract 1024390075Sobrien instances of inlines, since the spec requires the out-of-line copy 1024490075Sobrien to have the same parent. For local class methods, this doesn't 1024590075Sobrien apply; we just use the old DIE. */ 1024690075Sobrien if ((old_die->die_parent == comp_unit_die || context_die == NULL) 1024790075Sobrien && (DECL_ARTIFICIAL (decl) 1024890075Sobrien || (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index 1024990075Sobrien && (get_AT_unsigned (old_die, DW_AT_decl_line) 1025090075Sobrien == (unsigned) DECL_SOURCE_LINE (decl))))) 1025150397Sobrien { 1025250397Sobrien subr_die = old_die; 1025350397Sobrien 1025450397Sobrien /* Clear out the declaration attribute and the parm types. */ 1025550397Sobrien remove_AT (subr_die, DW_AT_declaration); 1025650397Sobrien remove_children (subr_die); 1025750397Sobrien } 1025850397Sobrien else 1025950397Sobrien { 1026090075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1026150397Sobrien add_AT_die_ref (subr_die, DW_AT_specification, old_die); 1026250397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1026350397Sobrien add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); 1026450397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1026590075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1026650397Sobrien add_AT_unsigned 1026750397Sobrien (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 1026850397Sobrien } 1026950397Sobrien } 1027050397Sobrien else 1027150397Sobrien { 1027290075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1027350397Sobrien 1027450397Sobrien if (TREE_PUBLIC (decl)) 1027550397Sobrien add_AT_flag (subr_die, DW_AT_external, 1); 1027650397Sobrien 1027750397Sobrien add_name_and_src_coords_attributes (subr_die, decl); 1027850397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1027950397Sobrien { 1028090075Sobrien add_prototyped_attribute (subr_die, TREE_TYPE (decl)); 1028190075Sobrien add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)), 1028290075Sobrien 0, 0, context_die); 1028350397Sobrien } 1028450397Sobrien 1028550397Sobrien add_pure_or_virtual_attribute (subr_die, decl); 1028650397Sobrien if (DECL_ARTIFICIAL (decl)) 1028750397Sobrien add_AT_flag (subr_die, DW_AT_artificial, 1); 1028890075Sobrien 1028950397Sobrien if (TREE_PROTECTED (decl)) 1029050397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected); 1029150397Sobrien else if (TREE_PRIVATE (decl)) 1029250397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private); 1029350397Sobrien } 1029450397Sobrien 1029550397Sobrien if (declaration) 1029650397Sobrien { 1029790075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1029890075Sobrien { 1029990075Sobrien add_AT_flag (subr_die, DW_AT_declaration, 1); 1030050397Sobrien 1030190075Sobrien /* The first time we see a member function, it is in the context of 1030290075Sobrien the class to which it belongs. We make sure of this by emitting 1030390075Sobrien the class first. The next time is the definition, which is 1030490075Sobrien handled above. The two may come from the same source text. */ 1030590075Sobrien if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl)) 1030690075Sobrien equate_decl_number_to_die (decl, subr_die); 1030790075Sobrien } 1030850397Sobrien } 1030950397Sobrien else if (DECL_ABSTRACT (decl)) 1031050397Sobrien { 1031190075Sobrien if (DECL_INLINE (decl) && !flag_no_inline) 1031250397Sobrien { 1031390075Sobrien /* ??? Checking DECL_DEFER_OUTPUT is correct for static 1031490075Sobrien inline functions, but not for extern inline functions. 1031590075Sobrien We can't get this completely correct because information 1031690075Sobrien about whether the function was declared inline is not 1031790075Sobrien saved anywhere. */ 1031890075Sobrien if (DECL_DEFER_OUTPUT (decl)) 1031950397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined); 1032050397Sobrien else 1032190075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); 1032250397Sobrien } 1032350397Sobrien else 1032490075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined); 1032550397Sobrien 1032650397Sobrien equate_decl_number_to_die (decl, subr_die); 1032750397Sobrien } 1032850397Sobrien else if (!DECL_EXTERNAL (decl)) 1032950397Sobrien { 1033090075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1033150397Sobrien equate_decl_number_to_die (decl, subr_die); 1033250397Sobrien 1033350397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, 1033450397Sobrien current_funcdef_number); 1033550397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); 1033650397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, 1033750397Sobrien current_funcdef_number); 1033850397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); 1033950397Sobrien 1034050397Sobrien add_pubname (decl, subr_die); 1034150397Sobrien add_arange (decl, subr_die); 1034250397Sobrien 1034350397Sobrien#ifdef MIPS_DEBUGGING_INFO 1034450397Sobrien /* Add a reference to the FDE for this routine. */ 1034550397Sobrien add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); 1034650397Sobrien#endif 1034750397Sobrien 1034850397Sobrien /* Define the "frame base" location for this routine. We use the 1034950397Sobrien frame pointer or stack pointer registers, since the RTL for local 1035050397Sobrien variables is relative to one of them. */ 1035150397Sobrien fp_reg 1035250397Sobrien = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; 1035350397Sobrien add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); 1035450397Sobrien 1035550397Sobrien#if 0 1035650397Sobrien /* ??? This fails for nested inline functions, because context_display 1035750397Sobrien is not part of the state saved/restored for inline functions. */ 1035850397Sobrien if (current_function_needs_context) 1035950397Sobrien add_AT_location_description (subr_die, DW_AT_static_link, 1036050397Sobrien lookup_static_chain (decl)); 1036150397Sobrien#endif 1036250397Sobrien } 1036350397Sobrien 1036450397Sobrien /* Now output descriptions of the arguments for this function. This gets 1036590075Sobrien (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list 1036650397Sobrien for a FUNCTION_DECL doesn't indicate cases where there was a trailing 1036750397Sobrien `...' at the end of the formal parameter list. In order to find out if 1036850397Sobrien there was a trailing ellipsis or not, we must instead look at the type 1036950397Sobrien associated with the FUNCTION_DECL. This will be a node of type 1037050397Sobrien FUNCTION_TYPE. If the chain of type nodes hanging off of this 1037190075Sobrien FUNCTION_TYPE node ends with a void_type_node then there should *not* be 1037250397Sobrien an ellipsis at the end. */ 1037350397Sobrien 1037450397Sobrien /* In the case where we are describing a mere function declaration, all we 1037590075Sobrien need to do here (and all we *can* do here) is to describe the *types* of 1037650397Sobrien its formal parameters. */ 1037750397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1037850397Sobrien ; 1037950397Sobrien else if (declaration) 1038090075Sobrien gen_formal_types_die (decl, subr_die); 1038150397Sobrien else 1038250397Sobrien { 1038350397Sobrien /* Generate DIEs to represent all known formal parameters */ 1038490075Sobrien tree arg_decls = DECL_ARGUMENTS (decl); 1038590075Sobrien tree parm; 1038650397Sobrien 1038750397Sobrien /* When generating DIEs, generate the unspecified_parameters DIE 1038850397Sobrien instead if we come across the arg "__builtin_va_alist" */ 1038950397Sobrien for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) 1039050397Sobrien if (TREE_CODE (parm) == PARM_DECL) 1039150397Sobrien { 1039250397Sobrien if (DECL_NAME (parm) 1039350397Sobrien && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), 1039450397Sobrien "__builtin_va_alist")) 1039550397Sobrien gen_unspecified_parameters_die (parm, subr_die); 1039650397Sobrien else 1039750397Sobrien gen_decl_die (parm, subr_die); 1039850397Sobrien } 1039950397Sobrien 1040090075Sobrien /* Decide whether we need an unspecified_parameters DIE at the end. 1040190075Sobrien There are 2 more cases to do this for: 1) the ansi ... declaration - 1040250397Sobrien this is detectable when the end of the arg list is not a 1040350397Sobrien void_type_node 2) an unprototyped function declaration (not a 1040450397Sobrien definition). This just means that we have no info about the 1040550397Sobrien parameters at all. */ 1040650397Sobrien fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); 1040750397Sobrien if (fn_arg_types != NULL) 1040850397Sobrien { 1040950397Sobrien /* this is the prototyped case, check for ... */ 1041050397Sobrien if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) 1041150397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1041250397Sobrien } 1041350397Sobrien else if (DECL_INITIAL (decl) == NULL_TREE) 1041450397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1041550397Sobrien } 1041650397Sobrien 1041750397Sobrien /* Output Dwarf info for all of the stuff within the body of the function 1041850397Sobrien (if it has one - it may be just a declaration). */ 1041950397Sobrien outer_scope = DECL_INITIAL (decl); 1042050397Sobrien 1042190075Sobrien /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent 1042290075Sobrien a function. This BLOCK actually represents the outermost binding contour 1042390075Sobrien for the function, i.e. the contour in which the function's formal 1042490075Sobrien parameters and labels get declared. Curiously, it appears that the front 1042590075Sobrien end doesn't actually put the PARM_DECL nodes for the current function onto 1042690075Sobrien the BLOCK_VARS list for this outer scope, but are strung off of the 1042790075Sobrien DECL_ARGUMENTS list for the function instead. 1042890075Sobrien 1042990075Sobrien The BLOCK_VARS list for the `outer_scope' does provide us with a list of 1043090075Sobrien the LABEL_DECL nodes for the function however, and we output DWARF info 1043190075Sobrien for those in decls_for_scope. Just within the `outer_scope' there will be 1043290075Sobrien a BLOCK node representing the function's outermost pair of curly braces, 1043390075Sobrien and any blocks used for the base and member initializers of a C++ 1043450397Sobrien constructor function. */ 1043550397Sobrien if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK) 1043650397Sobrien { 1043750397Sobrien current_function_has_inlines = 0; 1043850397Sobrien decls_for_scope (outer_scope, subr_die, 0); 1043950397Sobrien 1044050397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 1044150397Sobrien if (current_function_has_inlines) 1044250397Sobrien { 1044350397Sobrien add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1); 1044450397Sobrien if (! comp_unit_has_inlines) 1044550397Sobrien { 1044650397Sobrien add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1); 1044750397Sobrien comp_unit_has_inlines = 1; 1044850397Sobrien } 1044950397Sobrien } 1045050397Sobrien#endif 1045150397Sobrien } 1045250397Sobrien} 1045350397Sobrien 1045450397Sobrien/* Generate a DIE to represent a declared data object. */ 1045550397Sobrien 1045650397Sobrienstatic void 1045750397Sobriengen_variable_die (decl, context_die) 1045890075Sobrien tree decl; 1045990075Sobrien dw_die_ref context_die; 1046050397Sobrien{ 1046190075Sobrien tree origin = decl_ultimate_origin (decl); 1046290075Sobrien dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl); 1046350397Sobrien 1046450397Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1046590075Sobrien int declaration = (DECL_EXTERNAL (decl) 1046690075Sobrien || class_scope_p (context_die)); 1046750397Sobrien 1046850397Sobrien if (origin != NULL) 1046950397Sobrien add_abstract_origin_attribute (var_die, origin); 1047090075Sobrien 1047150397Sobrien /* Loop unrolling can create multiple blocks that refer to the same 1047290075Sobrien static variable, so we must test for the DW_AT_declaration flag. 1047390075Sobrien 1047490075Sobrien ??? Loop unrolling/reorder_blocks should perhaps be rewritten to 1047550397Sobrien copy decls and set the DECL_ABSTRACT flag on them instead of 1047690075Sobrien sharing them. 1047790075Sobrien 1047890075Sobrien ??? Duplicated blocks have been rewritten to use .debug_ranges. */ 1047950397Sobrien else if (old_die && TREE_STATIC (decl) 1048050397Sobrien && get_AT_flag (old_die, DW_AT_declaration) == 1) 1048150397Sobrien { 1048290075Sobrien /* This is a definition of a C++ class level static. */ 1048350397Sobrien add_AT_die_ref (var_die, DW_AT_specification, old_die); 1048450397Sobrien if (DECL_NAME (decl)) 1048550397Sobrien { 1048690075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1048750397Sobrien 1048850397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1048950397Sobrien add_AT_unsigned (var_die, DW_AT_decl_file, file_index); 1049050397Sobrien 1049150397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1049290075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1049350397Sobrien 1049450397Sobrien add_AT_unsigned (var_die, DW_AT_decl_line, 1049550397Sobrien DECL_SOURCE_LINE (decl)); 1049650397Sobrien } 1049750397Sobrien } 1049850397Sobrien else 1049950397Sobrien { 1050050397Sobrien add_name_and_src_coords_attributes (var_die, decl); 1050190075Sobrien add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl), 1050250397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1050350397Sobrien 1050450397Sobrien if (TREE_PUBLIC (decl)) 1050550397Sobrien add_AT_flag (var_die, DW_AT_external, 1); 1050650397Sobrien 1050750397Sobrien if (DECL_ARTIFICIAL (decl)) 1050850397Sobrien add_AT_flag (var_die, DW_AT_artificial, 1); 1050950397Sobrien 1051050397Sobrien if (TREE_PROTECTED (decl)) 1051150397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); 1051250397Sobrien else if (TREE_PRIVATE (decl)) 1051350397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); 1051450397Sobrien } 1051550397Sobrien 1051650397Sobrien if (declaration) 1051750397Sobrien add_AT_flag (var_die, DW_AT_declaration, 1); 1051890075Sobrien 1051990075Sobrien if (class_scope_p (context_die) || DECL_ABSTRACT (decl)) 1052050397Sobrien equate_decl_number_to_die (decl, var_die); 1052150397Sobrien 1052250397Sobrien if (! declaration && ! DECL_ABSTRACT (decl)) 1052350397Sobrien { 1052450397Sobrien add_location_or_const_value_attribute (var_die, decl); 1052550397Sobrien add_pubname (decl, var_die); 1052650397Sobrien } 1052790075Sobrien else 1052890075Sobrien tree_add_const_value_attribute (var_die, decl); 1052950397Sobrien} 1053050397Sobrien 1053150397Sobrien/* Generate a DIE to represent a label identifier. */ 1053250397Sobrien 1053350397Sobrienstatic void 1053450397Sobriengen_label_die (decl, context_die) 1053590075Sobrien tree decl; 1053690075Sobrien dw_die_ref context_die; 1053750397Sobrien{ 1053890075Sobrien tree origin = decl_ultimate_origin (decl); 1053990075Sobrien dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl); 1054090075Sobrien rtx insn; 1054150397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1054250397Sobrien 1054350397Sobrien if (origin != NULL) 1054450397Sobrien add_abstract_origin_attribute (lbl_die, origin); 1054550397Sobrien else 1054650397Sobrien add_name_and_src_coords_attributes (lbl_die, decl); 1054750397Sobrien 1054850397Sobrien if (DECL_ABSTRACT (decl)) 1054950397Sobrien equate_decl_number_to_die (decl, lbl_die); 1055050397Sobrien else 1055150397Sobrien { 1055250397Sobrien insn = DECL_RTL (decl); 1055352284Sobrien 1055452284Sobrien /* Deleted labels are programmer specified labels which have been 1055552284Sobrien eliminated because of various optimisations. We still emit them 1055652284Sobrien here so that it is possible to put breakpoints on them. */ 1055752284Sobrien if (GET_CODE (insn) == CODE_LABEL 1055852284Sobrien || ((GET_CODE (insn) == NOTE 1055952284Sobrien && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))) 1056050397Sobrien { 1056190075Sobrien /* When optimization is enabled (via -O) some parts of the compiler 1056290075Sobrien (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which 1056350397Sobrien represent source-level labels which were explicitly declared by 1056450397Sobrien the user. This really shouldn't be happening though, so catch 1056550397Sobrien it if it ever does happen. */ 1056650397Sobrien if (INSN_DELETED_P (insn)) 1056750397Sobrien abort (); 1056850397Sobrien 1056990075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn)); 1057050397Sobrien add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); 1057150397Sobrien } 1057250397Sobrien } 1057350397Sobrien} 1057450397Sobrien 1057550397Sobrien/* Generate a DIE for a lexical block. */ 1057650397Sobrien 1057750397Sobrienstatic void 1057850397Sobriengen_lexical_block_die (stmt, context_die, depth) 1057990075Sobrien tree stmt; 1058090075Sobrien dw_die_ref context_die; 1058150397Sobrien int depth; 1058250397Sobrien{ 1058390075Sobrien dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); 1058450397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1058550397Sobrien 1058650397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1058750397Sobrien { 1058890075Sobrien if (BLOCK_FRAGMENT_CHAIN (stmt)) 1058990075Sobrien { 1059090075Sobrien tree chain; 1059190075Sobrien 1059290075Sobrien add_AT_range_list (stmt_die, DW_AT_ranges, add_ranges (stmt)); 1059390075Sobrien 1059490075Sobrien chain = BLOCK_FRAGMENT_CHAIN (stmt); 1059590075Sobrien do 1059690075Sobrien { 1059790075Sobrien add_ranges (chain); 1059890075Sobrien chain = BLOCK_FRAGMENT_CHAIN (chain); 1059990075Sobrien } 1060090075Sobrien while (chain); 1060190075Sobrien add_ranges (NULL); 1060290075Sobrien } 1060390075Sobrien else 1060490075Sobrien { 1060590075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1060690075Sobrien BLOCK_NUMBER (stmt)); 1060790075Sobrien add_AT_lbl_id (stmt_die, DW_AT_low_pc, label); 1060890075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1060990075Sobrien BLOCK_NUMBER (stmt)); 1061090075Sobrien add_AT_lbl_id (stmt_die, DW_AT_high_pc, label); 1061190075Sobrien } 1061250397Sobrien } 1061350397Sobrien 1061450397Sobrien decls_for_scope (stmt, stmt_die, depth); 1061550397Sobrien} 1061650397Sobrien 1061750397Sobrien/* Generate a DIE for an inlined subprogram. */ 1061850397Sobrien 1061950397Sobrienstatic void 1062050397Sobriengen_inlined_subroutine_die (stmt, context_die, depth) 1062190075Sobrien tree stmt; 1062290075Sobrien dw_die_ref context_die; 1062350397Sobrien int depth; 1062450397Sobrien{ 1062550397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1062650397Sobrien { 1062790075Sobrien dw_die_ref subr_die 1062890075Sobrien = new_die (DW_TAG_inlined_subroutine, context_die, stmt); 1062990075Sobrien tree decl = block_ultimate_origin (stmt); 1063050397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1063150397Sobrien 1063290075Sobrien /* Emit info for the abstract instance first, if we haven't yet. */ 1063390075Sobrien dwarf2out_abstract_function (decl); 1063490075Sobrien 1063550397Sobrien add_abstract_origin_attribute (subr_die, decl); 1063650397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1063790075Sobrien BLOCK_NUMBER (stmt)); 1063850397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label); 1063990075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1064090075Sobrien BLOCK_NUMBER (stmt)); 1064150397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label); 1064250397Sobrien decls_for_scope (stmt, subr_die, depth); 1064350397Sobrien current_function_has_inlines = 1; 1064450397Sobrien } 1064596263Sobrien else 1064696263Sobrien /* We may get here if we're the outer block of function A that was 1064796263Sobrien inlined into function B that was inlined into function C. When 1064896263Sobrien generating debugging info for C, dwarf2out_abstract_function(B) 1064996263Sobrien would mark all inlined blocks as abstract, including this one. 1065096263Sobrien So, we wouldn't (and shouldn't) expect labels to be generated 1065196263Sobrien for this one. Instead, just emit debugging info for 1065296263Sobrien declarations within the block. This is particularly important 1065396263Sobrien in the case of initializers of arguments passed from B to us: 1065496263Sobrien if they're statement expressions containing declarations, we 1065596263Sobrien wouldn't generate dies for their abstract variables, and then, 1065696263Sobrien when generating dies for the real variables, we'd die (pun 1065796263Sobrien intended :-) */ 1065896263Sobrien gen_lexical_block_die (stmt, context_die, depth); 1065950397Sobrien} 1066050397Sobrien 1066150397Sobrien/* Generate a DIE for a field in a record, or structure. */ 1066250397Sobrien 1066350397Sobrienstatic void 1066450397Sobriengen_field_die (decl, context_die) 1066590075Sobrien tree decl; 1066690075Sobrien dw_die_ref context_die; 1066750397Sobrien{ 1066890075Sobrien dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl); 1066950397Sobrien 1067050397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 1067150397Sobrien add_type_attribute (decl_die, member_declared_type (decl), 1067250397Sobrien TREE_READONLY (decl), TREE_THIS_VOLATILE (decl), 1067350397Sobrien context_die); 1067450397Sobrien 1067550397Sobrien if (DECL_BIT_FIELD_TYPE (decl)) 1067650397Sobrien { 1067750397Sobrien add_byte_size_attribute (decl_die, decl); 1067850397Sobrien add_bit_size_attribute (decl_die, decl); 1067950397Sobrien add_bit_offset_attribute (decl_die, decl); 1068050397Sobrien } 1068150397Sobrien 1068250397Sobrien if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE) 1068350397Sobrien add_data_member_location_attribute (decl_die, decl); 1068450397Sobrien 1068550397Sobrien if (DECL_ARTIFICIAL (decl)) 1068650397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 1068750397Sobrien 1068850397Sobrien if (TREE_PROTECTED (decl)) 1068950397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected); 1069050397Sobrien else if (TREE_PRIVATE (decl)) 1069150397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private); 1069250397Sobrien} 1069350397Sobrien 1069450397Sobrien#if 0 1069550397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1069650397Sobrien Use modified_type_die instead. 1069750397Sobrien We keep this code here just in case these types of DIEs may be needed to 1069850397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1069990075Sobrien 1070050397Sobrienstatic void 1070150397Sobriengen_pointer_type_die (type, context_die) 1070290075Sobrien tree type; 1070390075Sobrien dw_die_ref context_die; 1070450397Sobrien{ 1070590075Sobrien dw_die_ref ptr_die 1070690075Sobrien = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type); 1070750397Sobrien 1070850397Sobrien equate_type_number_to_die (type, ptr_die); 1070950397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1071050397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1071150397Sobrien} 1071250397Sobrien 1071350397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1071450397Sobrien Use modified_type_die instead. 1071550397Sobrien We keep this code here just in case these types of DIEs may be needed to 1071650397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1071790075Sobrien 1071850397Sobrienstatic void 1071950397Sobriengen_reference_type_die (type, context_die) 1072090075Sobrien tree type; 1072190075Sobrien dw_die_ref context_die; 1072250397Sobrien{ 1072390075Sobrien dw_die_ref ref_die 1072490075Sobrien = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type); 1072550397Sobrien 1072650397Sobrien equate_type_number_to_die (type, ref_die); 1072750397Sobrien add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die); 1072850397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1072950397Sobrien} 1073050397Sobrien#endif 1073150397Sobrien 1073250397Sobrien/* Generate a DIE for a pointer to a member type. */ 1073390075Sobrien 1073450397Sobrienstatic void 1073550397Sobriengen_ptr_to_mbr_type_die (type, context_die) 1073690075Sobrien tree type; 1073790075Sobrien dw_die_ref context_die; 1073850397Sobrien{ 1073990075Sobrien dw_die_ref ptr_die 1074090075Sobrien = new_die (DW_TAG_ptr_to_member_type, 1074190075Sobrien scope_die_for (type, context_die), type); 1074250397Sobrien 1074350397Sobrien equate_type_number_to_die (type, ptr_die); 1074450397Sobrien add_AT_die_ref (ptr_die, DW_AT_containing_type, 1074550397Sobrien lookup_type_die (TYPE_OFFSET_BASETYPE (type))); 1074650397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1074750397Sobrien} 1074850397Sobrien 1074950397Sobrien/* Generate the DIE for the compilation unit. */ 1075050397Sobrien 1075190075Sobrienstatic dw_die_ref 1075290075Sobriengen_compile_unit_die (filename) 1075390075Sobrien const char *filename; 1075450397Sobrien{ 1075590075Sobrien dw_die_ref die; 1075650397Sobrien char producer[250]; 1075790075Sobrien const char *wd = getpwd (); 1075890075Sobrien const char *language_string = lang_hooks.name; 1075990075Sobrien int language; 1076050397Sobrien 1076190075Sobrien die = new_die (DW_TAG_compile_unit, NULL, NULL); 1076290075Sobrien add_name_attribute (die, filename); 1076350397Sobrien 1076490075Sobrien if (wd != NULL && filename[0] != DIR_SEPARATOR) 1076590075Sobrien add_AT_string (die, DW_AT_comp_dir, wd); 1076650397Sobrien 1076750397Sobrien sprintf (producer, "%s %s", language_string, version_string); 1076850397Sobrien 1076950397Sobrien#ifdef MIPS_DEBUGGING_INFO 1077050397Sobrien /* The MIPS/SGI compilers place the 'cc' command line options in the producer 1077150397Sobrien string. The SGI debugger looks for -g, -g1, -g2, or -g3; if they do 1077250397Sobrien not appear in the producer string, the debugger reaches the conclusion 1077350397Sobrien that the object file is stripped and has no debugging information. 1077450397Sobrien To get the MIPS/SGI debugger to believe that there is debugging 1077550397Sobrien information in the object file, we add a -g to the producer string. */ 1077650397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1077750397Sobrien strcat (producer, " -g"); 1077850397Sobrien#endif 1077950397Sobrien 1078090075Sobrien add_AT_string (die, DW_AT_producer, producer); 1078150397Sobrien 1078250397Sobrien if (strcmp (language_string, "GNU C++") == 0) 1078390075Sobrien language = DW_LANG_C_plus_plus; 1078450397Sobrien else if (strcmp (language_string, "GNU Ada") == 0) 1078590075Sobrien language = DW_LANG_Ada83; 1078650397Sobrien else if (strcmp (language_string, "GNU F77") == 0) 1078790075Sobrien language = DW_LANG_Fortran77; 1078850397Sobrien else if (strcmp (language_string, "GNU Pascal") == 0) 1078990075Sobrien language = DW_LANG_Pascal83; 1079090075Sobrien else if (strcmp (language_string, "GNU Java") == 0) 1079190075Sobrien language = DW_LANG_Java; 1079250397Sobrien else if (flag_traditional) 1079390075Sobrien language = DW_LANG_C; 1079450397Sobrien else 1079590075Sobrien language = DW_LANG_C89; 1079650397Sobrien 1079790075Sobrien add_AT_unsigned (die, DW_AT_language, language); 1079890075Sobrien return die; 1079950397Sobrien} 1080050397Sobrien 1080150397Sobrien/* Generate a DIE for a string type. */ 1080250397Sobrien 1080350397Sobrienstatic void 1080450397Sobriengen_string_type_die (type, context_die) 1080590075Sobrien tree type; 1080690075Sobrien dw_die_ref context_die; 1080750397Sobrien{ 1080890075Sobrien dw_die_ref type_die 1080990075Sobrien = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type); 1081050397Sobrien 1081150397Sobrien equate_type_number_to_die (type, type_die); 1081250397Sobrien 1081390075Sobrien /* ??? Fudge the string length attribute for now. 1081490075Sobrien TODO: add string length info. */ 1081590075Sobrien#if 0 1081690075Sobrien string_length_attribute (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 1081790075Sobrien bound_representation (upper_bound, 0, 'u'); 1081890075Sobrien#endif 1081950397Sobrien} 1082050397Sobrien 1082150397Sobrien/* Generate the DIE for a base class. */ 1082250397Sobrien 1082350397Sobrienstatic void 1082450397Sobriengen_inheritance_die (binfo, context_die) 1082590075Sobrien tree binfo; 1082690075Sobrien dw_die_ref context_die; 1082750397Sobrien{ 1082890075Sobrien dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo); 1082950397Sobrien 1083050397Sobrien add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die); 1083150397Sobrien add_data_member_location_attribute (die, binfo); 1083250397Sobrien 1083350397Sobrien if (TREE_VIA_VIRTUAL (binfo)) 1083450397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 1083590075Sobrien 1083650397Sobrien if (TREE_VIA_PUBLIC (binfo)) 1083750397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); 1083850397Sobrien else if (TREE_VIA_PROTECTED (binfo)) 1083950397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); 1084050397Sobrien} 1084150397Sobrien 1084250397Sobrien/* Generate a DIE for a class member. */ 1084350397Sobrien 1084450397Sobrienstatic void 1084550397Sobriengen_member_die (type, context_die) 1084690075Sobrien tree type; 1084790075Sobrien dw_die_ref context_die; 1084850397Sobrien{ 1084990075Sobrien tree member; 1085090075Sobrien dw_die_ref child; 1085150397Sobrien 1085250397Sobrien /* If this is not an incomplete type, output descriptions of each of its 1085350397Sobrien members. Note that as we output the DIEs necessary to represent the 1085450397Sobrien members of this record or union type, we will also be trying to output 1085550397Sobrien DIEs to represent the *types* of those members. However the `type' 1085690075Sobrien function (above) will specifically avoid generating type DIEs for member 1085790075Sobrien types *within* the list of member DIEs for this (containing) type except 1085850397Sobrien for those types (of members) which are explicitly marked as also being 1085950397Sobrien members of this (containing) type themselves. The g++ front- end can 1086090075Sobrien force any given type to be treated as a member of some other (containing) 1086190075Sobrien type by setting the TYPE_CONTEXT of the given (member) type to point to 1086290075Sobrien the TREE node representing the appropriate (containing) type. */ 1086350397Sobrien 1086450397Sobrien /* First output info about the base classes. */ 1086550397Sobrien if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) 1086650397Sobrien { 1086790075Sobrien tree bases = TYPE_BINFO_BASETYPES (type); 1086890075Sobrien int n_bases = TREE_VEC_LENGTH (bases); 1086990075Sobrien int i; 1087050397Sobrien 1087150397Sobrien for (i = 0; i < n_bases; i++) 1087250397Sobrien gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die); 1087350397Sobrien } 1087450397Sobrien 1087550397Sobrien /* Now output info about the data members and type members. */ 1087650397Sobrien for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) 1087790075Sobrien { 1087890075Sobrien /* If we thought we were generating minimal debug info for TYPE 1087990075Sobrien and then changed our minds, some of the member declarations 1088090075Sobrien may have already been defined. Don't define them again, but 1088190075Sobrien do put them in the right order. */ 1088250397Sobrien 1088390075Sobrien child = lookup_decl_die (member); 1088490075Sobrien if (child) 1088590075Sobrien splice_child_die (context_die, child); 1088690075Sobrien else 1088790075Sobrien gen_decl_die (member, context_die); 1088890075Sobrien } 1088990075Sobrien 1089050397Sobrien /* Now output info about the function members (if any). */ 1089150397Sobrien for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member)) 1089290075Sobrien { 1089390075Sobrien /* Don't include clones in the member list. */ 1089490075Sobrien if (DECL_ABSTRACT_ORIGIN (member)) 1089590075Sobrien continue; 1089690075Sobrien 1089790075Sobrien child = lookup_decl_die (member); 1089890075Sobrien if (child) 1089990075Sobrien splice_child_die (context_die, child); 1090090075Sobrien else 1090190075Sobrien gen_decl_die (member, context_die); 1090290075Sobrien } 1090350397Sobrien} 1090450397Sobrien 1090590075Sobrien/* Generate a DIE for a structure or union type. If TYPE_DECL_SUPPRESS_DEBUG 1090690075Sobrien is set, we pretend that the type was never defined, so we only get the 1090790075Sobrien member DIEs needed by later specification DIEs. */ 1090850397Sobrien 1090950397Sobrienstatic void 1091050397Sobriengen_struct_or_union_type_die (type, context_die) 1091190075Sobrien tree type; 1091290075Sobrien dw_die_ref context_die; 1091350397Sobrien{ 1091490075Sobrien dw_die_ref type_die = lookup_type_die (type); 1091590075Sobrien dw_die_ref scope_die = 0; 1091690075Sobrien int nested = 0; 1091790075Sobrien int complete = (TYPE_SIZE (type) 1091890075Sobrien && (! TYPE_STUB_DECL (type) 1091990075Sobrien || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)))); 1092050397Sobrien 1092190075Sobrien if (type_die && ! complete) 1092250397Sobrien return; 1092350397Sobrien 1092450397Sobrien if (TYPE_CONTEXT (type) != NULL_TREE 1092552284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))) 1092650397Sobrien nested = 1; 1092750397Sobrien 1092850397Sobrien scope_die = scope_die_for (type, context_die); 1092950397Sobrien 1093050397Sobrien if (! type_die || (nested && scope_die == comp_unit_die)) 1093150397Sobrien /* First occurrence of type or toplevel definition of nested class. */ 1093250397Sobrien { 1093390075Sobrien dw_die_ref old_die = type_die; 1093450397Sobrien 1093550397Sobrien type_die = new_die (TREE_CODE (type) == RECORD_TYPE 1093650397Sobrien ? DW_TAG_structure_type : DW_TAG_union_type, 1093790075Sobrien scope_die, type); 1093850397Sobrien equate_type_number_to_die (type, type_die); 1093950397Sobrien if (old_die) 1094050397Sobrien add_AT_die_ref (type_die, DW_AT_specification, old_die); 1094190075Sobrien else 1094290075Sobrien add_name_attribute (type_die, type_tag (type)); 1094350397Sobrien } 1094450397Sobrien else 1094550397Sobrien remove_AT (type_die, DW_AT_declaration); 1094650397Sobrien 1094750397Sobrien /* If this type has been completed, then give it a byte_size attribute and 1094850397Sobrien then give a list of members. */ 1094990075Sobrien if (complete) 1095050397Sobrien { 1095190075Sobrien /* Prevent infinite recursion in cases where the type of some member of 1095250397Sobrien this type is expressed in terms of this type itself. */ 1095350397Sobrien TREE_ASM_WRITTEN (type) = 1; 1095450397Sobrien add_byte_size_attribute (type_die, type); 1095550397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 1095650397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 1095750397Sobrien 1095850397Sobrien /* If the first reference to this type was as the return type of an 1095950397Sobrien inline function, then it may not have a parent. Fix this now. */ 1096050397Sobrien if (type_die->die_parent == NULL) 1096150397Sobrien add_child_die (scope_die, type_die); 1096250397Sobrien 1096350397Sobrien push_decl_scope (type); 1096450397Sobrien gen_member_die (type, type_die); 1096550397Sobrien pop_decl_scope (); 1096650397Sobrien 1096750397Sobrien /* GNU extension: Record what type our vtable lives in. */ 1096850397Sobrien if (TYPE_VFIELD (type)) 1096950397Sobrien { 1097050397Sobrien tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type)); 1097150397Sobrien 1097250397Sobrien gen_type_die (vtype, context_die); 1097350397Sobrien add_AT_die_ref (type_die, DW_AT_containing_type, 1097450397Sobrien lookup_type_die (vtype)); 1097550397Sobrien } 1097650397Sobrien } 1097750397Sobrien else 1097852284Sobrien { 1097952284Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 1098052284Sobrien 1098190075Sobrien /* We don't need to do this for function-local types. */ 1098290075Sobrien if (TYPE_STUB_DECL (type) 1098390075Sobrien && ! decl_function_context (TYPE_STUB_DECL (type))) 1098490075Sobrien VARRAY_PUSH_TREE (incomplete_types, type); 1098552284Sobrien } 1098650397Sobrien} 1098750397Sobrien 1098850397Sobrien/* Generate a DIE for a subroutine _type_. */ 1098950397Sobrien 1099050397Sobrienstatic void 1099150397Sobriengen_subroutine_type_die (type, context_die) 1099290075Sobrien tree type; 1099390075Sobrien dw_die_ref context_die; 1099450397Sobrien{ 1099590075Sobrien tree return_type = TREE_TYPE (type); 1099690075Sobrien dw_die_ref subr_die 1099790075Sobrien = new_die (DW_TAG_subroutine_type, 1099890075Sobrien scope_die_for (type, context_die), type); 1099950397Sobrien 1100050397Sobrien equate_type_number_to_die (type, subr_die); 1100150397Sobrien add_prototyped_attribute (subr_die, type); 1100250397Sobrien add_type_attribute (subr_die, return_type, 0, 0, context_die); 1100350397Sobrien gen_formal_types_die (type, subr_die); 1100450397Sobrien} 1100550397Sobrien 1100650397Sobrien/* Generate a DIE for a type definition */ 1100750397Sobrien 1100850397Sobrienstatic void 1100950397Sobriengen_typedef_die (decl, context_die) 1101090075Sobrien tree decl; 1101190075Sobrien dw_die_ref context_die; 1101250397Sobrien{ 1101390075Sobrien dw_die_ref type_die; 1101490075Sobrien tree origin; 1101550397Sobrien 1101650397Sobrien if (TREE_ASM_WRITTEN (decl)) 1101750397Sobrien return; 1101890075Sobrien 1101950397Sobrien TREE_ASM_WRITTEN (decl) = 1; 1102090075Sobrien type_die = new_die (DW_TAG_typedef, context_die, decl); 1102150397Sobrien origin = decl_ultimate_origin (decl); 1102250397Sobrien if (origin != NULL) 1102350397Sobrien add_abstract_origin_attribute (type_die, origin); 1102450397Sobrien else 1102550397Sobrien { 1102690075Sobrien tree type; 1102790075Sobrien 1102850397Sobrien add_name_and_src_coords_attributes (type_die, decl); 1102950397Sobrien if (DECL_ORIGINAL_TYPE (decl)) 1103050397Sobrien { 1103150397Sobrien type = DECL_ORIGINAL_TYPE (decl); 1103290075Sobrien 1103390075Sobrien if (type == TREE_TYPE (decl)) 1103490075Sobrien abort (); 1103590075Sobrien else 1103690075Sobrien equate_type_number_to_die (TREE_TYPE (decl), type_die); 1103750397Sobrien } 1103850397Sobrien else 1103950397Sobrien type = TREE_TYPE (decl); 1104090075Sobrien 1104150397Sobrien add_type_attribute (type_die, type, TREE_READONLY (decl), 1104250397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1104350397Sobrien } 1104450397Sobrien 1104550397Sobrien if (DECL_ABSTRACT (decl)) 1104650397Sobrien equate_decl_number_to_die (decl, type_die); 1104750397Sobrien} 1104850397Sobrien 1104950397Sobrien/* Generate a type description DIE. */ 1105050397Sobrien 1105150397Sobrienstatic void 1105250397Sobriengen_type_die (type, context_die) 1105390075Sobrien tree type; 1105490075Sobrien dw_die_ref context_die; 1105550397Sobrien{ 1105690075Sobrien int need_pop; 1105790075Sobrien 1105850397Sobrien if (type == NULL_TREE || type == error_mark_node) 1105950397Sobrien return; 1106050397Sobrien 1106150397Sobrien /* We are going to output a DIE to represent the unqualified version of 1106250397Sobrien this type (i.e. without any const or volatile qualifiers) so get the 1106350397Sobrien main variant (i.e. the unqualified version) of this type now. */ 1106450397Sobrien type = type_main_variant (type); 1106550397Sobrien 1106650397Sobrien if (TREE_ASM_WRITTEN (type)) 1106750397Sobrien return; 1106850397Sobrien 1106950397Sobrien if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 1107050397Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 1107190075Sobrien { 1107250397Sobrien TREE_ASM_WRITTEN (type) = 1; 1107350397Sobrien gen_decl_die (TYPE_NAME (type), context_die); 1107450397Sobrien return; 1107550397Sobrien } 1107650397Sobrien 1107750397Sobrien switch (TREE_CODE (type)) 1107850397Sobrien { 1107950397Sobrien case ERROR_MARK: 1108050397Sobrien break; 1108150397Sobrien 1108250397Sobrien case POINTER_TYPE: 1108350397Sobrien case REFERENCE_TYPE: 1108450397Sobrien /* We must set TREE_ASM_WRITTEN in case this is a recursive type. This 1108550397Sobrien ensures that the gen_type_die recursion will terminate even if the 1108650397Sobrien type is recursive. Recursive types are possible in Ada. */ 1108750397Sobrien /* ??? We could perhaps do this for all types before the switch 1108850397Sobrien statement. */ 1108950397Sobrien TREE_ASM_WRITTEN (type) = 1; 1109050397Sobrien 1109150397Sobrien /* For these types, all that is required is that we output a DIE (or a 1109250397Sobrien set of DIEs) to represent the "basis" type. */ 1109350397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1109450397Sobrien break; 1109550397Sobrien 1109650397Sobrien case OFFSET_TYPE: 1109790075Sobrien /* This code is used for C++ pointer-to-data-member types. 1109850397Sobrien Output a description of the relevant class type. */ 1109950397Sobrien gen_type_die (TYPE_OFFSET_BASETYPE (type), context_die); 1110050397Sobrien 1110150397Sobrien /* Output a description of the type of the object pointed to. */ 1110250397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1110350397Sobrien 1110450397Sobrien /* Now output a DIE to represent this pointer-to-data-member type 1110550397Sobrien itself. */ 1110650397Sobrien gen_ptr_to_mbr_type_die (type, context_die); 1110750397Sobrien break; 1110850397Sobrien 1110950397Sobrien case SET_TYPE: 1111050397Sobrien gen_type_die (TYPE_DOMAIN (type), context_die); 1111150397Sobrien gen_set_type_die (type, context_die); 1111250397Sobrien break; 1111350397Sobrien 1111450397Sobrien case FILE_TYPE: 1111550397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1111650397Sobrien abort (); /* No way to represent these in Dwarf yet! */ 1111750397Sobrien break; 1111850397Sobrien 1111950397Sobrien case FUNCTION_TYPE: 1112050397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1112150397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1112250397Sobrien gen_subroutine_type_die (type, context_die); 1112350397Sobrien break; 1112450397Sobrien 1112550397Sobrien case METHOD_TYPE: 1112650397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1112750397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1112850397Sobrien gen_subroutine_type_die (type, context_die); 1112950397Sobrien break; 1113050397Sobrien 1113150397Sobrien case ARRAY_TYPE: 1113250397Sobrien if (TYPE_STRING_FLAG (type) && TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) 1113350397Sobrien { 1113450397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1113550397Sobrien gen_string_type_die (type, context_die); 1113650397Sobrien } 1113750397Sobrien else 1113850397Sobrien gen_array_type_die (type, context_die); 1113950397Sobrien break; 1114050397Sobrien 1114190075Sobrien case VECTOR_TYPE: 1114296263Sobrien gen_array_type_die (type, context_die); 1114390075Sobrien break; 1114490075Sobrien 1114550397Sobrien case ENUMERAL_TYPE: 1114650397Sobrien case RECORD_TYPE: 1114750397Sobrien case UNION_TYPE: 1114850397Sobrien case QUAL_UNION_TYPE: 1114990075Sobrien /* If this is a nested type whose containing class hasn't been written 1115090075Sobrien out yet, writing it out will cover this one, too. This does not apply 1115190075Sobrien to instantiations of member class templates; they need to be added to 1115290075Sobrien the containing class as they are generated. FIXME: This hurts the 1115390075Sobrien idea of combining type decls from multiple TUs, since we can't predict 1115490075Sobrien what set of template instantiations we'll get. */ 1115550397Sobrien if (TYPE_CONTEXT (type) 1115652284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) 1115750397Sobrien && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 1115850397Sobrien { 1115950397Sobrien gen_type_die (TYPE_CONTEXT (type), context_die); 1116050397Sobrien 1116190075Sobrien if (TREE_ASM_WRITTEN (type)) 1116250397Sobrien return; 1116350397Sobrien 1116450397Sobrien /* If that failed, attach ourselves to the stub. */ 1116550397Sobrien push_decl_scope (TYPE_CONTEXT (type)); 1116650397Sobrien context_die = lookup_type_die (TYPE_CONTEXT (type)); 1116790075Sobrien need_pop = 1; 1116850397Sobrien } 1116990075Sobrien else 1117090075Sobrien need_pop = 0; 1117150397Sobrien 1117250397Sobrien if (TREE_CODE (type) == ENUMERAL_TYPE) 1117350397Sobrien gen_enumeration_type_die (type, context_die); 1117450397Sobrien else 1117550397Sobrien gen_struct_or_union_type_die (type, context_die); 1117650397Sobrien 1117790075Sobrien if (need_pop) 1117850397Sobrien pop_decl_scope (); 1117950397Sobrien 1118050397Sobrien /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix 1118150397Sobrien it up if it is ever completed. gen_*_type_die will set it for us 1118250397Sobrien when appropriate. */ 1118350397Sobrien return; 1118450397Sobrien 1118550397Sobrien case VOID_TYPE: 1118650397Sobrien case INTEGER_TYPE: 1118750397Sobrien case REAL_TYPE: 1118850397Sobrien case COMPLEX_TYPE: 1118950397Sobrien case BOOLEAN_TYPE: 1119050397Sobrien case CHAR_TYPE: 1119150397Sobrien /* No DIEs needed for fundamental types. */ 1119250397Sobrien break; 1119350397Sobrien 1119450397Sobrien case LANG_TYPE: 1119550397Sobrien /* No Dwarf representation currently defined. */ 1119650397Sobrien break; 1119750397Sobrien 1119850397Sobrien default: 1119950397Sobrien abort (); 1120050397Sobrien } 1120150397Sobrien 1120250397Sobrien TREE_ASM_WRITTEN (type) = 1; 1120350397Sobrien} 1120450397Sobrien 1120550397Sobrien/* Generate a DIE for a tagged type instantiation. */ 1120650397Sobrien 1120750397Sobrienstatic void 1120850397Sobriengen_tagged_type_instantiation_die (type, context_die) 1120990075Sobrien tree type; 1121090075Sobrien dw_die_ref context_die; 1121150397Sobrien{ 1121250397Sobrien if (type == NULL_TREE || type == error_mark_node) 1121350397Sobrien return; 1121450397Sobrien 1121550397Sobrien /* We are going to output a DIE to represent the unqualified version of 1121650397Sobrien this type (i.e. without any const or volatile qualifiers) so make sure 1121750397Sobrien that we have the main variant (i.e. the unqualified version) of this 1121850397Sobrien type now. */ 1121990075Sobrien if (type != type_main_variant (type)) 1122050397Sobrien abort (); 1122150397Sobrien 1122290075Sobrien /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is 1122390075Sobrien an instance of an unresolved type. */ 1122490075Sobrien 1122550397Sobrien switch (TREE_CODE (type)) 1122650397Sobrien { 1122750397Sobrien case ERROR_MARK: 1122850397Sobrien break; 1122950397Sobrien 1123050397Sobrien case ENUMERAL_TYPE: 1123150397Sobrien gen_inlined_enumeration_type_die (type, context_die); 1123250397Sobrien break; 1123350397Sobrien 1123450397Sobrien case RECORD_TYPE: 1123550397Sobrien gen_inlined_structure_type_die (type, context_die); 1123650397Sobrien break; 1123750397Sobrien 1123850397Sobrien case UNION_TYPE: 1123950397Sobrien case QUAL_UNION_TYPE: 1124050397Sobrien gen_inlined_union_type_die (type, context_die); 1124150397Sobrien break; 1124250397Sobrien 1124350397Sobrien default: 1124450397Sobrien abort (); 1124550397Sobrien } 1124650397Sobrien} 1124750397Sobrien 1124850397Sobrien/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the 1124950397Sobrien things which are local to the given block. */ 1125050397Sobrien 1125150397Sobrienstatic void 1125250397Sobriengen_block_die (stmt, context_die, depth) 1125390075Sobrien tree stmt; 1125490075Sobrien dw_die_ref context_die; 1125550397Sobrien int depth; 1125650397Sobrien{ 1125790075Sobrien int must_output_die = 0; 1125890075Sobrien tree origin; 1125990075Sobrien tree decl; 1126090075Sobrien enum tree_code origin_code; 1126150397Sobrien 1126250397Sobrien /* Ignore blocks never really used to make RTL. */ 1126390075Sobrien if (stmt == NULL_TREE || !TREE_USED (stmt) 1126490075Sobrien || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt))) 1126550397Sobrien return; 1126650397Sobrien 1126790075Sobrien /* If the block is one fragment of a non-contiguous block, do not 1126890075Sobrien process the variables, since they will have been done by the 1126990075Sobrien origin block. Do process subblocks. */ 1127090075Sobrien if (BLOCK_FRAGMENT_ORIGIN (stmt)) 1127190075Sobrien { 1127290075Sobrien tree sub; 1127390075Sobrien 1127490075Sobrien for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub)) 1127590075Sobrien gen_block_die (sub, context_die, depth + 1); 1127690075Sobrien 1127790075Sobrien return; 1127890075Sobrien } 1127990075Sobrien 1128050397Sobrien /* Determine the "ultimate origin" of this block. This block may be an 1128150397Sobrien inlined instance of an inlined instance of inline function, so we have 1128250397Sobrien to trace all of the way back through the origin chain to find out what 1128350397Sobrien sort of node actually served as the original seed for the creation of 1128450397Sobrien the current block. */ 1128550397Sobrien origin = block_ultimate_origin (stmt); 1128650397Sobrien origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK; 1128750397Sobrien 1128850397Sobrien /* Determine if we need to output any Dwarf DIEs at all to represent this 1128950397Sobrien block. */ 1129050397Sobrien if (origin_code == FUNCTION_DECL) 1129150397Sobrien /* The outer scopes for inlinings *must* always be represented. We 1129250397Sobrien generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */ 1129350397Sobrien must_output_die = 1; 1129450397Sobrien else 1129550397Sobrien { 1129650397Sobrien /* In the case where the current block represents an inlining of the 1129790075Sobrien "body block" of an inline function, we must *NOT* output any DIE for 1129890075Sobrien this block because we have already output a DIE to represent the whole 1129990075Sobrien inlined function scope and the "body block" of any function doesn't 1130090075Sobrien really represent a different scope according to ANSI C rules. So we 1130190075Sobrien check here to make sure that this block does not represent a "body 1130290075Sobrien block inlining" before trying to set the MUST_OUTPUT_DIE flag. */ 1130350397Sobrien if (! is_body_block (origin ? origin : stmt)) 1130450397Sobrien { 1130550397Sobrien /* Determine if this block directly contains any "significant" 1130650397Sobrien local declarations which we will need to output DIEs for. */ 1130750397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1130850397Sobrien /* We are not in terse mode so *any* local declaration counts 1130950397Sobrien as being a "significant" one. */ 1131050397Sobrien must_output_die = (BLOCK_VARS (stmt) != NULL); 1131150397Sobrien else 1131250397Sobrien /* We are in terse mode, so only local (nested) function 1131350397Sobrien definitions count as "significant" local declarations. */ 1131450397Sobrien for (decl = BLOCK_VARS (stmt); 1131550397Sobrien decl != NULL; decl = TREE_CHAIN (decl)) 1131650397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1131750397Sobrien && DECL_INITIAL (decl)) 1131850397Sobrien { 1131950397Sobrien must_output_die = 1; 1132050397Sobrien break; 1132150397Sobrien } 1132250397Sobrien } 1132350397Sobrien } 1132450397Sobrien 1132550397Sobrien /* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block 1132650397Sobrien DIE for any block which contains no significant local declarations at 1132750397Sobrien all. Rather, in such cases we just call `decls_for_scope' so that any 1132850397Sobrien needed Dwarf info for any sub-blocks will get properly generated. Note 1132950397Sobrien that in terse mode, our definition of what constitutes a "significant" 1133050397Sobrien local declaration gets restricted to include only inlined function 1133150397Sobrien instances and local (nested) function definitions. */ 1133250397Sobrien if (must_output_die) 1133350397Sobrien { 1133450397Sobrien if (origin_code == FUNCTION_DECL) 1133550397Sobrien gen_inlined_subroutine_die (stmt, context_die, depth); 1133650397Sobrien else 1133750397Sobrien gen_lexical_block_die (stmt, context_die, depth); 1133850397Sobrien } 1133950397Sobrien else 1134050397Sobrien decls_for_scope (stmt, context_die, depth); 1134150397Sobrien} 1134250397Sobrien 1134350397Sobrien/* Generate all of the decls declared within a given scope and (recursively) 1134450397Sobrien all of its sub-blocks. */ 1134550397Sobrien 1134650397Sobrienstatic void 1134750397Sobriendecls_for_scope (stmt, context_die, depth) 1134890075Sobrien tree stmt; 1134990075Sobrien dw_die_ref context_die; 1135050397Sobrien int depth; 1135150397Sobrien{ 1135290075Sobrien tree decl; 1135390075Sobrien tree subblocks; 1135450397Sobrien 1135550397Sobrien /* Ignore blocks never really used to make RTL. */ 1135650397Sobrien if (stmt == NULL_TREE || ! TREE_USED (stmt)) 1135750397Sobrien return; 1135850397Sobrien 1135950397Sobrien /* Output the DIEs to represent all of the data objects and typedefs 1136050397Sobrien declared directly within this block but not within any nested 1136150397Sobrien sub-blocks. Also, nested function and tag DIEs have been 1136250397Sobrien generated with a parent of NULL; fix that up now. */ 1136390075Sobrien for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl)) 1136450397Sobrien { 1136590075Sobrien dw_die_ref die; 1136650397Sobrien 1136750397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 1136850397Sobrien die = lookup_decl_die (decl); 1136950397Sobrien else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)) 1137050397Sobrien die = lookup_type_die (TREE_TYPE (decl)); 1137150397Sobrien else 1137250397Sobrien die = NULL; 1137350397Sobrien 1137450397Sobrien if (die != NULL && die->die_parent == NULL) 1137550397Sobrien add_child_die (context_die, die); 1137650397Sobrien else 1137750397Sobrien gen_decl_die (decl, context_die); 1137850397Sobrien } 1137950397Sobrien 1138050397Sobrien /* Output the DIEs to represent all sub-blocks (and the items declared 1138150397Sobrien therein) of this block. */ 1138250397Sobrien for (subblocks = BLOCK_SUBBLOCKS (stmt); 1138350397Sobrien subblocks != NULL; 1138450397Sobrien subblocks = BLOCK_CHAIN (subblocks)) 1138550397Sobrien gen_block_die (subblocks, context_die, depth + 1); 1138650397Sobrien} 1138750397Sobrien 1138850397Sobrien/* Is this a typedef we can avoid emitting? */ 1138950397Sobrien 1139050397Sobrienstatic inline int 1139150397Sobrienis_redundant_typedef (decl) 1139290075Sobrien tree decl; 1139350397Sobrien{ 1139450397Sobrien if (TYPE_DECL_IS_STUB (decl)) 1139550397Sobrien return 1; 1139650397Sobrien 1139750397Sobrien if (DECL_ARTIFICIAL (decl) 1139850397Sobrien && DECL_CONTEXT (decl) 1139950397Sobrien && is_tagged_type (DECL_CONTEXT (decl)) 1140050397Sobrien && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL 1140150397Sobrien && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))) 1140250397Sobrien /* Also ignore the artificial member typedef for the class name. */ 1140350397Sobrien return 1; 1140450397Sobrien 1140550397Sobrien return 0; 1140650397Sobrien} 1140750397Sobrien 1140850397Sobrien/* Generate Dwarf debug information for a decl described by DECL. */ 1140950397Sobrien 1141050397Sobrienstatic void 1141150397Sobriengen_decl_die (decl, context_die) 1141290075Sobrien tree decl; 1141390075Sobrien dw_die_ref context_die; 1141450397Sobrien{ 1141590075Sobrien tree origin; 1141650397Sobrien 1141790075Sobrien if (DECL_P (decl) && DECL_IGNORED_P (decl)) 1141850397Sobrien return; 1141950397Sobrien 1142050397Sobrien switch (TREE_CODE (decl)) 1142150397Sobrien { 1142290075Sobrien case ERROR_MARK: 1142390075Sobrien break; 1142490075Sobrien 1142550397Sobrien case CONST_DECL: 1142690075Sobrien /* The individual enumerators of an enum type get output when we output 1142750397Sobrien the Dwarf representation of the relevant enum type itself. */ 1142850397Sobrien break; 1142950397Sobrien 1143050397Sobrien case FUNCTION_DECL: 1143150397Sobrien /* Don't output any DIEs to represent mere function declarations, 1143250397Sobrien unless they are class members or explicit block externs. */ 1143350397Sobrien if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE 1143490075Sobrien && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl))) 1143550397Sobrien break; 1143650397Sobrien 1143790075Sobrien /* If we're emitting a clone, emit info for the abstract instance. */ 1143890075Sobrien if (DECL_ORIGIN (decl) != decl) 1143990075Sobrien dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl)); 1144090075Sobrien 1144190075Sobrien /* If we're emitting an out-of-line copy of an inline function, 1144290075Sobrien emit info for the abstract instance and set up to refer to it. */ 1144390075Sobrien else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl) 1144490075Sobrien && ! class_scope_p (context_die) 1144590075Sobrien /* dwarf2out_abstract_function won't emit a die if this is just 1144690075Sobrien a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in 1144790075Sobrien that case, because that works only if we have a die. */ 1144890075Sobrien && DECL_INITIAL (decl) != NULL_TREE) 1144950397Sobrien { 1145090075Sobrien dwarf2out_abstract_function (decl); 1145190075Sobrien set_decl_origin_self (decl); 1145290075Sobrien } 1145390075Sobrien 1145490075Sobrien /* Otherwise we're emitting the primary DIE for this decl. */ 1145590075Sobrien else if (debug_info_level > DINFO_LEVEL_TERSE) 1145690075Sobrien { 1145750397Sobrien /* Before we describe the FUNCTION_DECL itself, make sure that we 1145850397Sobrien have described its return type. */ 1145950397Sobrien gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die); 1146050397Sobrien 1146190075Sobrien /* And its virtual context. */ 1146290075Sobrien if (DECL_VINDEX (decl) != NULL_TREE) 1146390075Sobrien gen_type_die (DECL_CONTEXT (decl), context_die); 1146490075Sobrien 1146550397Sobrien /* And its containing type. */ 1146650397Sobrien origin = decl_class_context (decl); 1146750397Sobrien if (origin != NULL_TREE) 1146890075Sobrien gen_type_die_for_member (origin, decl, context_die); 1146950397Sobrien } 1147050397Sobrien 1147150397Sobrien /* Now output a DIE to represent the function itself. */ 1147250397Sobrien gen_subprogram_die (decl, context_die); 1147350397Sobrien break; 1147450397Sobrien 1147550397Sobrien case TYPE_DECL: 1147650397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1147750397Sobrien actual typedefs. */ 1147850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1147950397Sobrien break; 1148050397Sobrien 1148190075Sobrien /* In the special case of a TYPE_DECL node representing the declaration 1148290075Sobrien of some type tag, if the given TYPE_DECL is marked as having been 1148390075Sobrien instantiated from some other (original) TYPE_DECL node (e.g. one which 1148490075Sobrien was generated within the original definition of an inline function) we 1148590075Sobrien have to generate a special (abbreviated) DW_TAG_structure_type, 1148690075Sobrien DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */ 1148790075Sobrien if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE) 1148850397Sobrien { 1148950397Sobrien gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die); 1149050397Sobrien break; 1149150397Sobrien } 1149250397Sobrien 1149350397Sobrien if (is_redundant_typedef (decl)) 1149450397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1149550397Sobrien else 1149650397Sobrien /* Output a DIE to represent the typedef itself. */ 1149750397Sobrien gen_typedef_die (decl, context_die); 1149850397Sobrien break; 1149950397Sobrien 1150050397Sobrien case LABEL_DECL: 1150150397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1150250397Sobrien gen_label_die (decl, context_die); 1150350397Sobrien break; 1150450397Sobrien 1150550397Sobrien case VAR_DECL: 1150650397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1150750397Sobrien variable declarations or definitions. */ 1150850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1150950397Sobrien break; 1151050397Sobrien 1151150397Sobrien /* Output any DIEs that are needed to specify the type of this data 1151250397Sobrien object. */ 1151350397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1151450397Sobrien 1151550397Sobrien /* And its containing type. */ 1151650397Sobrien origin = decl_class_context (decl); 1151750397Sobrien if (origin != NULL_TREE) 1151890075Sobrien gen_type_die_for_member (origin, decl, context_die); 1151950397Sobrien 1152050397Sobrien /* Now output the DIE to represent the data object itself. This gets 1152150397Sobrien complicated because of the possibility that the VAR_DECL really 1152250397Sobrien represents an inlined instance of a formal parameter for an inline 1152350397Sobrien function. */ 1152450397Sobrien origin = decl_ultimate_origin (decl); 1152550397Sobrien if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) 1152650397Sobrien gen_formal_parameter_die (decl, context_die); 1152750397Sobrien else 1152850397Sobrien gen_variable_die (decl, context_die); 1152950397Sobrien break; 1153050397Sobrien 1153150397Sobrien case FIELD_DECL: 1153290075Sobrien /* Ignore the nameless fields that are used to skip bits but handle C++ 1153390075Sobrien anonymous unions. */ 1153450397Sobrien if (DECL_NAME (decl) != NULL_TREE 1153550397Sobrien || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE) 1153650397Sobrien { 1153750397Sobrien gen_type_die (member_declared_type (decl), context_die); 1153850397Sobrien gen_field_die (decl, context_die); 1153950397Sobrien } 1154050397Sobrien break; 1154150397Sobrien 1154250397Sobrien case PARM_DECL: 1154350397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1154450397Sobrien gen_formal_parameter_die (decl, context_die); 1154550397Sobrien break; 1154650397Sobrien 1154790075Sobrien case NAMESPACE_DECL: 1154890075Sobrien /* Ignore for now. */ 1154990075Sobrien break; 1155090075Sobrien 1155150397Sobrien default: 1155250397Sobrien abort (); 1155350397Sobrien } 1155450397Sobrien} 1155590075Sobrien 1155690075Sobrienstatic void 1155790075Sobrienmark_limbo_die_list (ptr) 1155890075Sobrien void *ptr ATTRIBUTE_UNUSED; 1155990075Sobrien{ 1156090075Sobrien limbo_die_node *node; 1156190075Sobrien for (node = limbo_die_list; node ; node = node->next) 1156290075Sobrien ggc_mark_tree (node->created_for); 1156390075Sobrien} 1156450397Sobrien 1156590075Sobrien/* Add Ada "use" clause information for SGI Workshop debugger. */ 1156650397Sobrien 1156750397Sobrienvoid 1156890075Sobriendwarf2out_add_library_unit_info (filename, context_list) 1156990075Sobrien const char *filename; 1157090075Sobrien const char *context_list; 1157150397Sobrien{ 1157290075Sobrien unsigned int file_index; 1157350397Sobrien 1157490075Sobrien if (filename != NULL) 1157550397Sobrien { 1157690075Sobrien dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die, NULL); 1157790075Sobrien tree context_list_decl 1157890075Sobrien = build_decl (LABEL_DECL, get_identifier (context_list), 1157990075Sobrien void_type_node); 1158050397Sobrien 1158190075Sobrien TREE_PUBLIC (context_list_decl) = TRUE; 1158290075Sobrien add_name_attribute (unit_die, context_list); 1158390075Sobrien file_index = lookup_filename (filename); 1158490075Sobrien add_AT_unsigned (unit_die, DW_AT_decl_file, file_index); 1158590075Sobrien add_pubname (context_list_decl, unit_die); 1158650397Sobrien } 1158790075Sobrien} 1158850397Sobrien 1158990075Sobrien/* Output debug information for global decl DECL. Called from toplev.c after 1159090075Sobrien compilation proper has finished. */ 1159190075Sobrien 1159290075Sobrienstatic void 1159390075Sobriendwarf2out_global_decl (decl) 1159490075Sobrien tree decl; 1159590075Sobrien{ 1159690075Sobrien /* Output DWARF2 information for file-scope tentative data object 1159790075Sobrien declarations, file-scope (extern) function declarations (which had no 1159890075Sobrien corresponding body) and file-scope tagged type declarations and 1159990075Sobrien definitions which have not yet been forced out. */ 1160090075Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) 1160190075Sobrien dwarf2out_decl (decl); 1160290075Sobrien} 1160390075Sobrien 1160490075Sobrien/* Write the debugging output for DECL. */ 1160590075Sobrien 1160690075Sobrienvoid 1160790075Sobriendwarf2out_decl (decl) 1160890075Sobrien tree decl; 1160990075Sobrien{ 1161090075Sobrien dw_die_ref context_die = comp_unit_die; 1161190075Sobrien 1161250397Sobrien switch (TREE_CODE (decl)) 1161350397Sobrien { 1161490075Sobrien case ERROR_MARK: 1161590075Sobrien return; 1161690075Sobrien 1161750397Sobrien case FUNCTION_DECL: 1161890075Sobrien /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a 1161950397Sobrien builtin function. Explicit programmer-supplied declarations of 1162050397Sobrien these same functions should NOT be ignored however. */ 1162190075Sobrien if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl)) 1162250397Sobrien return; 1162350397Sobrien 1162450397Sobrien /* What we would really like to do here is to filter out all mere 1162550397Sobrien file-scope declarations of file-scope functions which are never 1162650397Sobrien referenced later within this translation unit (and keep all of ones 1162790075Sobrien that *are* referenced later on) but we aren't clairvoyant, so we have 1162890075Sobrien no idea which functions will be referenced in the future (i.e. later 1162950397Sobrien on within the current translation unit). So here we just ignore all 1163090075Sobrien file-scope function declarations which are not also definitions. If 1163150397Sobrien and when the debugger needs to know something about these functions, 1163290075Sobrien it will have to hunt around and find the DWARF information associated 1163390075Sobrien with the definition of the function. 1163490075Sobrien 1163590075Sobrien We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL 1163690075Sobrien nodes represent definitions and which ones represent mere 1163790075Sobrien declarations. We have to check DECL_INITIAL instead. That's because 1163890075Sobrien the C front-end supports some weird semantics for "extern inline" 1163990075Sobrien function definitions. These can get inlined within the current 1164090075Sobrien translation unit (an thus, we need to generate Dwarf info for their 1164190075Sobrien abstract instances so that the Dwarf info for the concrete inlined 1164290075Sobrien instances can have something to refer to) but the compiler never 1164390075Sobrien generates any out-of-lines instances of such things (despite the fact 1164490075Sobrien that they *are* definitions). 1164590075Sobrien 1164690075Sobrien The important point is that the C front-end marks these "extern 1164790075Sobrien inline" functions as DECL_EXTERNAL, but we need to generate DWARF for 1164890075Sobrien them anyway. Note that the C++ front-end also plays some similar games 1164990075Sobrien for inline function definitions appearing within include files which 1165090075Sobrien also contain `#pragma interface' pragmas. */ 1165150397Sobrien if (DECL_INITIAL (decl) == NULL_TREE) 1165250397Sobrien return; 1165350397Sobrien 1165450397Sobrien /* If we're a nested function, initially use a parent of NULL; if we're 1165550397Sobrien a plain function, this will be fixed up in decls_for_scope. If 1165650397Sobrien we're a method, it will be ignored, since we already have a DIE. */ 1165750397Sobrien if (decl_function_context (decl)) 1165850397Sobrien context_die = NULL; 1165950397Sobrien break; 1166050397Sobrien 1166150397Sobrien case VAR_DECL: 1166290075Sobrien /* Ignore this VAR_DECL if it refers to a file-scope extern data object 1166350397Sobrien declaration and if the declaration was never even referenced from 1166450397Sobrien within this entire compilation unit. We suppress these DIEs in 1166550397Sobrien order to save space in the .debug section (by eliminating entries 1166650397Sobrien which are probably useless). Note that we must not suppress 1166750397Sobrien block-local extern declarations (whether used or not) because that 1166850397Sobrien would screw-up the debugger's name lookup mechanism and cause it to 1166950397Sobrien miss things which really ought to be in scope at a given point. */ 1167050397Sobrien if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) 1167150397Sobrien return; 1167250397Sobrien 1167350397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1167450397Sobrien variable declarations or definitions. */ 1167550397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1167650397Sobrien return; 1167750397Sobrien break; 1167850397Sobrien 1167950397Sobrien case TYPE_DECL: 1168090075Sobrien /* Don't emit stubs for types unless they are needed by other DIEs. */ 1168190075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (decl)) 1168290075Sobrien return; 1168390075Sobrien 1168450397Sobrien /* Don't bother trying to generate any DIEs to represent any of the 1168550397Sobrien normal built-in types for the language we are compiling. */ 1168650397Sobrien if (DECL_SOURCE_LINE (decl) == 0) 1168750397Sobrien { 1168850397Sobrien /* OK, we need to generate one for `bool' so GDB knows what type 1168950397Sobrien comparisons have. */ 1169050397Sobrien if ((get_AT_unsigned (comp_unit_die, DW_AT_language) 1169150397Sobrien == DW_LANG_C_plus_plus) 1169290075Sobrien && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE 1169390075Sobrien && ! DECL_IGNORED_P (decl)) 1169450397Sobrien modified_type_die (TREE_TYPE (decl), 0, 0, NULL); 1169550397Sobrien 1169650397Sobrien return; 1169750397Sobrien } 1169850397Sobrien 1169950397Sobrien /* If we are in terse mode, don't generate any DIEs for types. */ 1170050397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1170150397Sobrien return; 1170250397Sobrien 1170350397Sobrien /* If we're a function-scope tag, initially use a parent of NULL; 1170450397Sobrien this will be fixed up in decls_for_scope. */ 1170550397Sobrien if (decl_function_context (decl)) 1170650397Sobrien context_die = NULL; 1170750397Sobrien 1170850397Sobrien break; 1170950397Sobrien 1171050397Sobrien default: 1171150397Sobrien return; 1171250397Sobrien } 1171350397Sobrien 1171450397Sobrien gen_decl_die (decl, context_die); 1171550397Sobrien} 1171650397Sobrien 1171750397Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for 1171850397Sobrien a lexical block. */ 1171950397Sobrien 1172090075Sobrienstatic void 1172190075Sobriendwarf2out_begin_block (line, blocknum) 1172290075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1172390075Sobrien unsigned int blocknum; 1172450397Sobrien{ 1172550397Sobrien function_section (current_function_decl); 1172690075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 1172750397Sobrien} 1172850397Sobrien 1172950397Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a 1173050397Sobrien lexical block. */ 1173150397Sobrien 1173290075Sobrienstatic void 1173390075Sobriendwarf2out_end_block (line, blocknum) 1173490075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1173590075Sobrien unsigned int blocknum; 1173650397Sobrien{ 1173750397Sobrien function_section (current_function_decl); 1173890075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); 1173950397Sobrien} 1174050397Sobrien 1174190075Sobrien/* Returns nonzero if it is appropriate not to emit any debugging 1174290075Sobrien information for BLOCK, because it doesn't contain any instructions. 1174350397Sobrien 1174490075Sobrien Don't allow this for blocks with nested functions or local classes 1174590075Sobrien as we would end up with orphans, and in the presence of scheduling 1174690075Sobrien we may end up calling them anyway. */ 1174790075Sobrien 1174890075Sobrienstatic bool 1174990075Sobriendwarf2out_ignore_block (block) 1175090075Sobrien tree block; 1175150397Sobrien{ 1175290075Sobrien tree decl; 1175350397Sobrien 1175490075Sobrien for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl)) 1175590075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1175690075Sobrien || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))) 1175790075Sobrien return 0; 1175890075Sobrien 1175990075Sobrien return 1; 1176050397Sobrien} 1176150397Sobrien 1176290075Sobrien/* Lookup FILE_NAME (in the list of filenames that we know about here in 1176350397Sobrien dwarf2out.c) and return its "index". The index of each (known) filename is 1176490075Sobrien just a unique number which is associated with only that one filename. We 1176590075Sobrien need such numbers for the sake of generating labels (in the .debug_sfnames 1176690075Sobrien section) and references to those files numbers (in the .debug_srcinfo 1176790075Sobrien and.debug_macinfo sections). If the filename given as an argument is not 1176890075Sobrien found in our current list, add it to the list and assign it the next 1176990075Sobrien available unique index number. In order to speed up searches, we remember 1177090075Sobrien the index of the filename was looked up last. This handles the majority of 1177190075Sobrien all searches. */ 1177250397Sobrien 1177350397Sobrienstatic unsigned 1177450397Sobrienlookup_filename (file_name) 1177590075Sobrien const char *file_name; 1177650397Sobrien{ 1177790075Sobrien unsigned i; 1177850397Sobrien 1177990075Sobrien /* ??? Why isn't DECL_SOURCE_FILE left null instead. */ 1178090075Sobrien if (strcmp (file_name, "<internal>") == 0 1178190075Sobrien || strcmp (file_name, "<built-in>") == 0) 1178290075Sobrien return 0; 1178350397Sobrien 1178490075Sobrien /* Check to see if the file name that was searched on the previous 1178590075Sobrien call matches this file name. If so, return the index. */ 1178690075Sobrien if (file_table.last_lookup_index != 0) 1178790075Sobrien if (0 == strcmp (file_name, 1178890075Sobrien file_table.table[file_table.last_lookup_index])) 1178990075Sobrien return file_table.last_lookup_index; 1179090075Sobrien 1179150397Sobrien /* Didn't match the previous lookup, search the table */ 1179290075Sobrien for (i = 1; i < file_table.in_use; i++) 1179390075Sobrien if (strcmp (file_name, file_table.table[i]) == 0) 1179450397Sobrien { 1179590075Sobrien file_table.last_lookup_index = i; 1179650397Sobrien return i; 1179750397Sobrien } 1179850397Sobrien 1179990075Sobrien /* Prepare to add a new table entry by making sure there is enough space in 1180050397Sobrien the table to do so. If not, expand the current table. */ 1180190075Sobrien if (i == file_table.allocated) 1180250397Sobrien { 1180390075Sobrien file_table.allocated = i + FILE_TABLE_INCREMENT; 1180490075Sobrien file_table.table = (char **) 1180590075Sobrien xrealloc (file_table.table, file_table.allocated * sizeof (char *)); 1180650397Sobrien } 1180750397Sobrien 1180850397Sobrien /* Add the new entry to the end of the filename table. */ 1180990075Sobrien file_table.table[i] = xstrdup (file_name); 1181090075Sobrien file_table.in_use = i + 1; 1181190075Sobrien file_table.last_lookup_index = i; 1181250397Sobrien 1181390075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1181490075Sobrien fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name); 1181590075Sobrien 1181690075Sobrien return i; 1181750397Sobrien} 1181850397Sobrien 1181990075Sobrienstatic void 1182090075Sobrieninit_file_table () 1182190075Sobrien{ 1182290075Sobrien /* Allocate the initial hunk of the file_table. */ 1182390075Sobrien file_table.table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *)); 1182490075Sobrien file_table.allocated = FILE_TABLE_INCREMENT; 1182590075Sobrien 1182690075Sobrien /* Skip the first entry - file numbers begin at 1. */ 1182790075Sobrien file_table.in_use = 1; 1182890075Sobrien file_table.last_lookup_index = 0; 1182990075Sobrien} 1183090075Sobrien 1183150397Sobrien/* Output a label to mark the beginning of a source code line entry 1183250397Sobrien and record information relating to this source line, in 1183350397Sobrien 'line_info_table' for later output of the .debug_line section. */ 1183450397Sobrien 1183590075Sobrienstatic void 1183690075Sobriendwarf2out_source_line (line, filename) 1183790075Sobrien unsigned int line; 1183890075Sobrien const char *filename; 1183950397Sobrien{ 1184050397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1184150397Sobrien { 1184250397Sobrien function_section (current_function_decl); 1184350397Sobrien 1184490075Sobrien /* If requested, emit something human-readable. */ 1184590075Sobrien if (flag_debug_asm) 1184690075Sobrien fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, 1184790075Sobrien filename, line); 1184890075Sobrien 1184990075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1185050397Sobrien { 1185190075Sobrien unsigned file_num = lookup_filename (filename); 1185290075Sobrien 1185390075Sobrien /* Emit the .loc directive understood by GNU as. */ 1185490075Sobrien fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); 1185590075Sobrien 1185690075Sobrien /* Indicate that line number info exists. */ 1185790075Sobrien line_info_table_in_use++; 1185890075Sobrien 1185990075Sobrien /* Indicate that multiple line number tables exist. */ 1186090075Sobrien if (DECL_SECTION_NAME (current_function_decl)) 1186190075Sobrien separate_line_info_table_in_use++; 1186290075Sobrien } 1186390075Sobrien else if (DECL_SECTION_NAME (current_function_decl)) 1186490075Sobrien { 1186590075Sobrien dw_separate_line_info_ref line_info; 1186650397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, 1186750397Sobrien separate_line_info_table_in_use); 1186850397Sobrien 1186950397Sobrien /* expand the line info table if necessary */ 1187050397Sobrien if (separate_line_info_table_in_use 1187150397Sobrien == separate_line_info_table_allocated) 1187250397Sobrien { 1187350397Sobrien separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1187450397Sobrien separate_line_info_table 1187550397Sobrien = (dw_separate_line_info_ref) 1187650397Sobrien xrealloc (separate_line_info_table, 1187750397Sobrien separate_line_info_table_allocated 1187850397Sobrien * sizeof (dw_separate_line_info_entry)); 1187950397Sobrien } 1188050397Sobrien 1188150397Sobrien /* Add the new entry at the end of the line_info_table. */ 1188250397Sobrien line_info 1188350397Sobrien = &separate_line_info_table[separate_line_info_table_in_use++]; 1188450397Sobrien line_info->dw_file_num = lookup_filename (filename); 1188550397Sobrien line_info->dw_line_num = line; 1188650397Sobrien line_info->function = current_funcdef_number; 1188750397Sobrien } 1188850397Sobrien else 1188950397Sobrien { 1189090075Sobrien dw_line_info_ref line_info; 1189150397Sobrien 1189250397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, 1189350397Sobrien line_info_table_in_use); 1189450397Sobrien 1189550397Sobrien /* Expand the line info table if necessary. */ 1189650397Sobrien if (line_info_table_in_use == line_info_table_allocated) 1189750397Sobrien { 1189850397Sobrien line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1189950397Sobrien line_info_table 1190050397Sobrien = (dw_line_info_ref) 1190150397Sobrien xrealloc (line_info_table, 1190250397Sobrien (line_info_table_allocated 1190350397Sobrien * sizeof (dw_line_info_entry))); 1190450397Sobrien } 1190550397Sobrien 1190650397Sobrien /* Add the new entry at the end of the line_info_table. */ 1190750397Sobrien line_info = &line_info_table[line_info_table_in_use++]; 1190850397Sobrien line_info->dw_file_num = lookup_filename (filename); 1190950397Sobrien line_info->dw_line_num = line; 1191050397Sobrien } 1191150397Sobrien } 1191250397Sobrien} 1191350397Sobrien 1191490075Sobrien/* Record the beginning of a new source file. */ 1191550397Sobrien 1191690075Sobrienstatic void 1191790075Sobriendwarf2out_start_source_file (lineno, filename) 1191890075Sobrien unsigned int lineno; 1191990075Sobrien const char *filename; 1192050397Sobrien{ 1192190075Sobrien if (flag_eliminate_dwarf2_dups) 1192290075Sobrien { 1192390075Sobrien /* Record the beginning of the file for break_out_includes. */ 1192490075Sobrien dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); 1192590075Sobrien add_AT_string (bincl_die, DW_AT_name, filename); 1192690075Sobrien } 1192790075Sobrien 1192890075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1192990075Sobrien { 1193090075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1193190075Sobrien dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); 1193290075Sobrien dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", 1193390075Sobrien lineno); 1193490075Sobrien dw2_asm_output_data_uleb128 (lookup_filename (filename), 1193590075Sobrien "Filename we just started"); 1193690075Sobrien } 1193750397Sobrien} 1193850397Sobrien 1193990075Sobrien/* Record the end of a source file. */ 1194050397Sobrien 1194190075Sobrienstatic void 1194290075Sobriendwarf2out_end_source_file (lineno) 1194390075Sobrien unsigned int lineno ATTRIBUTE_UNUSED; 1194450397Sobrien{ 1194590075Sobrien if (flag_eliminate_dwarf2_dups) 1194690075Sobrien /* Record the end of the file for break_out_includes. */ 1194790075Sobrien new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL); 1194890075Sobrien 1194990075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1195090075Sobrien { 1195190075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1195290075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1195390075Sobrien } 1195450397Sobrien} 1195550397Sobrien 1195690075Sobrien/* Called from debug_define in toplev.c. The `buffer' parameter contains 1195750397Sobrien the tail part of the directive line, i.e. the part which is past the 1195850397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1195950397Sobrien 1196090075Sobrienstatic void 1196150397Sobriendwarf2out_define (lineno, buffer) 1196290075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1196390075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1196450397Sobrien{ 1196590075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1196690075Sobrien { 1196790075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1196890075Sobrien dw2_asm_output_data (1, DW_MACINFO_define, "Define macro"); 1196990075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1197090075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1197190075Sobrien } 1197250397Sobrien} 1197350397Sobrien 1197490075Sobrien/* Called from debug_undef in toplev.c. The `buffer' parameter contains 1197550397Sobrien the tail part of the directive line, i.e. the part which is past the 1197650397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1197750397Sobrien 1197890075Sobrienstatic void 1197950397Sobriendwarf2out_undef (lineno, buffer) 1198090075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1198190075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1198250397Sobrien{ 1198390075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1198490075Sobrien { 1198590075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1198690075Sobrien dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro"); 1198790075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1198890075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1198990075Sobrien } 1199050397Sobrien} 1199150397Sobrien 1199250397Sobrien/* Set up for Dwarf output at the start of compilation. */ 1199350397Sobrien 1199490075Sobrienstatic void 1199590075Sobriendwarf2out_init (main_input_filename) 1199690075Sobrien const char *main_input_filename; 1199750397Sobrien{ 1199890075Sobrien init_file_table (); 1199990075Sobrien 1200050397Sobrien /* Remember the name of the primary input file. */ 1200150397Sobrien primary_filename = main_input_filename; 1200250397Sobrien 1200390075Sobrien /* Add it to the file table first, under the assumption that we'll 1200490075Sobrien be emitting line number data for it first, which avoids having 1200590075Sobrien to add an initial DW_LNS_set_file. */ 1200690075Sobrien lookup_filename (main_input_filename); 1200750397Sobrien 1200850397Sobrien /* Allocate the initial hunk of the decl_die_table. */ 1200950397Sobrien decl_die_table 1201090075Sobrien = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref)); 1201150397Sobrien decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT; 1201250397Sobrien decl_die_table_in_use = 0; 1201350397Sobrien 1201450397Sobrien /* Allocate the initial hunk of the decl_scope_table. */ 1201590075Sobrien VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table"); 1201690075Sobrien ggc_add_tree_varray_root (&decl_scope_table, 1); 1201750397Sobrien 1201850397Sobrien /* Allocate the initial hunk of the abbrev_die_table. */ 1201950397Sobrien abbrev_die_table 1202090075Sobrien = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT, 1202190075Sobrien sizeof (dw_die_ref)); 1202250397Sobrien abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; 1202350397Sobrien /* Zero-th entry is allocated, but unused */ 1202450397Sobrien abbrev_die_table_in_use = 1; 1202550397Sobrien 1202650397Sobrien /* Allocate the initial hunk of the line_info_table. */ 1202750397Sobrien line_info_table 1202890075Sobrien = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, 1202990075Sobrien sizeof (dw_line_info_entry)); 1203050397Sobrien line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 1203190075Sobrien 1203250397Sobrien /* Zero-th entry is allocated, but unused */ 1203350397Sobrien line_info_table_in_use = 1; 1203450397Sobrien 1203590075Sobrien /* Generate the initial DIE for the .debug section. Note that the (string) 1203650397Sobrien value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE 1203790075Sobrien will (typically) be a relative pathname and that this pathname should be 1203850397Sobrien taken as being relative to the directory from which the compiler was 1203950397Sobrien invoked when the given (base) source file was compiled. */ 1204090075Sobrien comp_unit_die = gen_compile_unit_die (main_input_filename); 1204150397Sobrien 1204290075Sobrien VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types"); 1204390075Sobrien ggc_add_tree_varray_root (&incomplete_types, 1); 1204490075Sobrien 1204590075Sobrien VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray"); 1204690075Sobrien ggc_add_rtx_varray_root (&used_rtx_varray, 1); 1204790075Sobrien 1204890075Sobrien ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list); 1204990075Sobrien 1205050397Sobrien ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1205190075Sobrien ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, 1205290075Sobrien DEBUG_ABBREV_SECTION_LABEL, 0); 1205390075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1205490075Sobrien ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0); 1205590075Sobrien else 1205690075Sobrien strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME)); 1205790075Sobrien 1205890075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, 1205952284Sobrien DEBUG_INFO_SECTION_LABEL, 0); 1206090075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, 1206152284Sobrien DEBUG_LINE_SECTION_LABEL, 0); 1206290075Sobrien ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, 1206390075Sobrien DEBUG_RANGES_SECTION_LABEL, 0); 1206490075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1206552284Sobrien ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); 1206690075Sobrien named_section_flags (DEBUG_INFO_SECTION, SECTION_DEBUG); 1206752284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label); 1206890075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1206952284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); 1207090075Sobrien 1207190075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1207290075Sobrien { 1207390075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1207490075Sobrien ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label, 1207590075Sobrien DEBUG_MACINFO_SECTION_LABEL, 0); 1207690075Sobrien ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label); 1207790075Sobrien } 1207890075Sobrien 1207990075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1208090075Sobrien { 1208190075Sobrien text_section (); 1208290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, text_section_label); 1208390075Sobrien } 1208450397Sobrien} 1208550397Sobrien 1208690075Sobrien/* Allocate a string in .debug_str hash table. */ 1208790075Sobrien 1208890075Sobrienstatic hashnode 1208990075Sobrienindirect_string_alloc (tab) 1209090075Sobrien hash_table *tab ATTRIBUTE_UNUSED; 1209190075Sobrien{ 1209290075Sobrien struct indirect_string_node *node; 1209390075Sobrien 1209490075Sobrien node = xmalloc (sizeof (struct indirect_string_node)); 1209590075Sobrien node->refcount = 0; 1209690075Sobrien node->form = 0; 1209790075Sobrien node->label = NULL; 1209890075Sobrien 1209990075Sobrien return (hashnode) node; 1210090075Sobrien} 1210190075Sobrien 1210290075Sobrien/* A helper function for dwarf2out_finish called through 1210390075Sobrien ht_forall. Emit one queued .debug_str string. */ 1210490075Sobrien 1210590075Sobrienstatic int 1210690075Sobrienoutput_indirect_string (pfile, h, v) 1210790075Sobrien struct cpp_reader *pfile ATTRIBUTE_UNUSED; 1210890075Sobrien hashnode h; 1210990075Sobrien const PTR v ATTRIBUTE_UNUSED; 1211090075Sobrien{ 1211190075Sobrien struct indirect_string_node *node = (struct indirect_string_node *) h; 1211290075Sobrien 1211390075Sobrien if (node->form == DW_FORM_strp) 1211490075Sobrien { 1211590075Sobrien named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS); 1211690075Sobrien ASM_OUTPUT_LABEL (asm_out_file, node->label); 1211790075Sobrien assemble_string ((const char *) HT_STR (&node->id), 1211890075Sobrien HT_LEN (&node->id) + 1); 1211990075Sobrien } 1212090075Sobrien 1212190075Sobrien return 1; 1212290075Sobrien} 1212390075Sobrien 1212450397Sobrien/* Output stuff that dwarf requires at the end of every file, 1212550397Sobrien and generate the DWARF-2 debugging info. */ 1212650397Sobrien 1212790075Sobrienstatic void 1212890075Sobriendwarf2out_finish (input_filename) 1212990075Sobrien const char *input_filename ATTRIBUTE_UNUSED; 1213050397Sobrien{ 1213150397Sobrien limbo_die_node *node, *next_node; 1213290075Sobrien dw_die_ref die = 0; 1213350397Sobrien 1213450397Sobrien /* Traverse the limbo die list, and add parent/child links. The only 1213550397Sobrien dies without parents that should be here are concrete instances of 1213650397Sobrien inline functions, and the comp_unit_die. We can ignore the comp_unit_die. 1213750397Sobrien For concrete instances, we can get the parent die from the abstract 1213850397Sobrien instance. */ 1213950397Sobrien for (node = limbo_die_list; node; node = next_node) 1214050397Sobrien { 1214150397Sobrien next_node = node->next; 1214250397Sobrien die = node->die; 1214350397Sobrien 1214450397Sobrien if (die->die_parent == NULL) 1214550397Sobrien { 1214690075Sobrien dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); 1214790075Sobrien tree context; 1214890075Sobrien 1214990075Sobrien if (origin) 1215090075Sobrien add_child_die (origin->die_parent, die); 1215150397Sobrien else if (die == comp_unit_die) 1215290075Sobrien ; 1215390075Sobrien /* If this was an expression for a bound involved in a function 1215490075Sobrien return type, it may be a SAVE_EXPR for which we weren't able 1215590075Sobrien to find a DIE previously. So try now. */ 1215690075Sobrien else if (node->created_for 1215790075Sobrien && TREE_CODE (node->created_for) == SAVE_EXPR 1215890075Sobrien && 0 != (origin = (lookup_decl_die 1215990075Sobrien (SAVE_EXPR_CONTEXT 1216090075Sobrien (node->created_for))))) 1216190075Sobrien add_child_die (origin, die); 1216290075Sobrien else if (errorcount > 0 || sorrycount > 0) 1216390075Sobrien /* It's OK to be confused by errors in the input. */ 1216490075Sobrien add_child_die (comp_unit_die, die); 1216590075Sobrien else if (node->created_for 1216690075Sobrien && ((DECL_P (node->created_for) 1216790075Sobrien && (context = DECL_CONTEXT (node->created_for))) 1216890075Sobrien || (TYPE_P (node->created_for) 1216990075Sobrien && (context = TYPE_CONTEXT (node->created_for)))) 1217090075Sobrien && TREE_CODE (context) == FUNCTION_DECL) 1217190075Sobrien { 1217290075Sobrien /* In certain situations, the lexical block containing a 1217390075Sobrien nested function can be optimized away, which results 1217490075Sobrien in the nested function die being orphaned. Likewise 1217590075Sobrien with the return type of that nested function. Force 1217690075Sobrien this to be a child of the containing function. */ 1217790075Sobrien origin = lookup_decl_die (context); 1217890075Sobrien if (! origin) 1217990075Sobrien abort (); 1218090075Sobrien add_child_die (origin, die); 1218190075Sobrien } 1218250397Sobrien else 1218350397Sobrien abort (); 1218450397Sobrien } 1218590075Sobrien 1218650397Sobrien free (node); 1218750397Sobrien } 1218850397Sobrien 1218990075Sobrien limbo_die_list = NULL; 1219090075Sobrien 1219152284Sobrien /* Walk through the list of incomplete types again, trying once more to 1219252284Sobrien emit full debugging info for them. */ 1219352284Sobrien retry_incomplete_types (); 1219452284Sobrien 1219590075Sobrien /* We need to reverse all the dies before break_out_includes, or 1219690075Sobrien we'll see the end of an include file before the beginning. */ 1219790075Sobrien reverse_all_dies (comp_unit_die); 1219890075Sobrien 1219990075Sobrien /* Generate separate CUs for each of the include files we've seen. 1220090075Sobrien They will go into limbo_die_list. */ 1220190075Sobrien if (flag_eliminate_dwarf2_dups) 1220290075Sobrien break_out_includes (comp_unit_die); 1220390075Sobrien 1220490075Sobrien /* Traverse the DIE's and add add sibling attributes to those DIE's 1220550397Sobrien that have children. */ 1220650397Sobrien add_sibling_attributes (comp_unit_die); 1220790075Sobrien for (node = limbo_die_list; node; node = node->next) 1220890075Sobrien add_sibling_attributes (node->die); 1220950397Sobrien 1221050397Sobrien /* Output a terminator label for the .text section. */ 1221190075Sobrien text_section (); 1221250397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); 1221350397Sobrien 1221490075Sobrien /* Output the source line correspondence table. We must do this 1221590075Sobrien even if there is no line information. Otherwise, on an empty 1221690075Sobrien translation unit, we will generate a present, but empty, 1221790075Sobrien .debug_info section. IRIX 6.5 `nm' will then complain when 1221890075Sobrien examining the file. */ 1221990075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 1222050397Sobrien { 1222190075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1222250397Sobrien output_line_info (); 1222390075Sobrien } 1222450397Sobrien 1222590075Sobrien /* Output location list section if necessary. */ 1222690075Sobrien if (have_location_lists) 1222790075Sobrien { 1222890075Sobrien /* Output the location lists info. */ 1222990075Sobrien named_section_flags (DEBUG_LOC_SECTION, SECTION_DEBUG); 1223090075Sobrien ASM_GENERATE_INTERNAL_LABEL (loc_section_label, 1223190075Sobrien DEBUG_LOC_SECTION_LABEL, 0); 1223290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); 1223390075Sobrien output_location_lists (die); 1223490075Sobrien have_location_lists = 0; 1223590075Sobrien } 1223650397Sobrien 1223790075Sobrien /* We can only use the low/high_pc attributes if all of the code was 1223890075Sobrien in .text. */ 1223990075Sobrien if (separate_line_info_table_in_use == 0) 1224090075Sobrien { 1224190075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); 1224290075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); 1224350397Sobrien } 1224450397Sobrien 1224590075Sobrien /* If it wasn't, we need to give .debug_loc and .debug_ranges an appropriate 1224690075Sobrien "base address". Use zero so that these addresses become absolute. */ 1224790075Sobrien else if (have_location_lists || ranges_table_in_use) 1224890075Sobrien add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); 1224990075Sobrien 1225090075Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1225190075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, 1225290075Sobrien debug_line_section_label); 1225390075Sobrien 1225490075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1225590075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_macro_info, macinfo_section_label); 1225690075Sobrien 1225790075Sobrien /* Output all of the compilation units. We put the main one last so that 1225890075Sobrien the offsets are available to output_pubnames. */ 1225990075Sobrien for (node = limbo_die_list; node; node = node->next) 1226090075Sobrien output_comp_unit (node->die); 1226190075Sobrien 1226290075Sobrien output_comp_unit (comp_unit_die); 1226390075Sobrien 1226450397Sobrien /* Output the abbreviation table. */ 1226590075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1226650397Sobrien output_abbrev_section (); 1226750397Sobrien 1226890075Sobrien /* Output public names table if necessary. */ 1226950397Sobrien if (pubname_table_in_use) 1227050397Sobrien { 1227190075Sobrien named_section_flags (DEBUG_PUBNAMES_SECTION, SECTION_DEBUG); 1227250397Sobrien output_pubnames (); 1227350397Sobrien } 1227450397Sobrien 1227590075Sobrien /* Output the address range information. We only put functions in the arange 1227690075Sobrien table, so don't write it out if we don't have any. */ 1227750397Sobrien if (fde_table_in_use) 1227850397Sobrien { 1227990075Sobrien named_section_flags (DEBUG_ARANGES_SECTION, SECTION_DEBUG); 1228050397Sobrien output_aranges (); 1228150397Sobrien } 1228290075Sobrien 1228390075Sobrien /* Output ranges section if necessary. */ 1228490075Sobrien if (ranges_table_in_use) 1228590075Sobrien { 1228690075Sobrien named_section_flags (DEBUG_RANGES_SECTION, SECTION_DEBUG); 1228790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label); 1228890075Sobrien output_ranges (); 1228990075Sobrien } 1229090075Sobrien 1229190075Sobrien /* Have to end the primary source file. */ 1229290075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1229390075Sobrien { 1229490075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1229590075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1229690075Sobrien } 1229790075Sobrien 1229890075Sobrien /* If we emitted any DW_FORM_strp form attribute, output the string 1229990075Sobrien table too. */ 1230090075Sobrien if (debug_str_hash) 1230190075Sobrien ht_forall (debug_str_hash, output_indirect_string, NULL); 1230250397Sobrien} 1230390075Sobrien#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */ 12304