dwarf2out.c revision 90075
150397Sobrien/* Output Dwarf2 format symbol table information from the GNU C compiler. 290075Sobrien Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 390075Sobrien Free Software Foundation, Inc. 450397Sobrien Contributed by Gary Funck (gary@intrepid.com). 550397Sobrien Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). 650397Sobrien Extensively modified by Jason Merrill (jason@cygnus.com). 750397Sobrien 890075SobrienThis file is part of GCC. 950397Sobrien 1090075SobrienGCC is free software; you can redistribute it and/or modify it under 1190075Sobrienthe terms of the GNU General Public License as published by the Free 1290075SobrienSoftware Foundation; either version 2, or (at your option) any later 1390075Sobrienversion. 1450397Sobrien 1590075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1690075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1790075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1890075Sobrienfor more details. 1950397Sobrien 2050397SobrienYou should have received a copy of the GNU General Public License 2190075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 2290075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2390075Sobrien02111-1307, USA. */ 2450397Sobrien 2590075Sobrien/* TODO: Emit .debug_line header even when there are no functions, since 2690075Sobrien the file numbers are used by .debug_info. Alternately, leave 2790075Sobrien out locations for types and decls. 2890075Sobrien Avoid talking about ctors and op= for PODs. 2990075Sobrien Factor out common prologue sequences into multiple CIEs. */ 3090075Sobrien 3150397Sobrien/* The first part of this file deals with the DWARF 2 frame unwind 3250397Sobrien information, which is also used by the GCC efficient exception handling 3350397Sobrien mechanism. The second part, controlled only by an #ifdef 3450397Sobrien DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging 3550397Sobrien information. */ 3650397Sobrien 3750397Sobrien#include "config.h" 3850397Sobrien#include "system.h" 3950397Sobrien#include "tree.h" 4050397Sobrien#include "flags.h" 4150397Sobrien#include "rtl.h" 4250397Sobrien#include "hard-reg-set.h" 4350397Sobrien#include "regs.h" 4450397Sobrien#include "insn-config.h" 4550397Sobrien#include "reload.h" 4690075Sobrien#include "function.h" 4750397Sobrien#include "output.h" 4850397Sobrien#include "expr.h" 4990075Sobrien#include "libfuncs.h" 5050397Sobrien#include "except.h" 5150397Sobrien#include "dwarf2.h" 5250397Sobrien#include "dwarf2out.h" 5390075Sobrien#include "dwarf2asm.h" 5450397Sobrien#include "toplev.h" 5590075Sobrien#include "varray.h" 5690075Sobrien#include "ggc.h" 5790075Sobrien#include "md5.h" 5890075Sobrien#include "tm_p.h" 5990075Sobrien#include "diagnostic.h" 6090075Sobrien#include "debug.h" 6190075Sobrien#include "target.h" 6290075Sobrien#include "langhooks.h" 6390075Sobrien#include "hashtable.h" 6450397Sobrien 6590075Sobrien#ifdef DWARF2_DEBUGGING_INFO 6690075Sobrienstatic void dwarf2out_source_line PARAMS ((unsigned int, const char *)); 6750397Sobrien#endif 6850397Sobrien 6990075Sobrien/* DWARF2 Abbreviation Glossary: 7090075Sobrien CFA = Canonical Frame Address 7190075Sobrien a fixed address on the stack which identifies a call frame. 7290075Sobrien We define it to be the value of SP just before the call insn. 7390075Sobrien The CFA register and offset, which may change during the course 7490075Sobrien of the function, are used to calculate its value at runtime. 7590075Sobrien CFI = Call Frame Instruction 7690075Sobrien an instruction for the DWARF2 abstract machine 7790075Sobrien CIE = Common Information Entry 7890075Sobrien information describing information common to one or more FDEs 7990075Sobrien DIE = Debugging Information Entry 8090075Sobrien FDE = Frame Description Entry 8190075Sobrien information describing the stack call frame, in particular, 8290075Sobrien how to restore registers 8390075Sobrien 8490075Sobrien DW_CFA_... = DWARF2 CFA call frame instruction 8590075Sobrien DW_TAG_... = DWARF2 DIE tag */ 8690075Sobrien 8750397Sobrien/* Decide whether we want to emit frame unwind information for the current 8850397Sobrien translation unit. */ 8950397Sobrien 9050397Sobrienint 9150397Sobriendwarf2out_do_frame () 9250397Sobrien{ 9350397Sobrien return (write_symbols == DWARF2_DEBUG 9490075Sobrien || write_symbols == VMS_AND_DWARF2_DEBUG 9550397Sobrien#ifdef DWARF2_FRAME_INFO 9690075Sobrien || DWARF2_FRAME_INFO 9750397Sobrien#endif 9850397Sobrien#ifdef DWARF2_UNWIND_INFO 9990075Sobrien || flag_unwind_tables 10090075Sobrien || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS) 10150397Sobrien#endif 10250397Sobrien ); 10350397Sobrien} 10450397Sobrien 10590075Sobrien/* The number of the current function definition for which debugging 10690075Sobrien information is being generated. These numbers range from 1 up to the 10790075Sobrien maximum number of function definitions contained within the current 10890075Sobrien compilation unit. These numbers are used to create unique label id's 10990075Sobrien unique to each function definition. */ 11090075Sobrienunsigned current_funcdef_number = 0; 11190075Sobrien 11290075Sobrien/* The size of the target's pointer type. */ 11390075Sobrien#ifndef PTR_SIZE 11490075Sobrien#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT) 11590075Sobrien#endif 11690075Sobrien 11790075Sobrien/* Default version of targetm.eh_frame_section. Note this must appear 11890075Sobrien outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro 11990075Sobrien guards. */ 12090075Sobrien 12190075Sobrienvoid 12290075Sobriendefault_eh_frame_section () 12390075Sobrien{ 12490075Sobrien#ifdef EH_FRAME_SECTION_NAME 12590075Sobrien named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE); 12690075Sobrien#else 12790075Sobrien tree label = get_file_function_name ('F'); 12890075Sobrien 12990075Sobrien data_section (); 13090075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 13190075Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 13290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 13390075Sobrien#endif 13490075Sobrien} 13590075Sobrien 13650397Sobrien#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) 13750397Sobrien 13850397Sobrien/* How to start an assembler comment. */ 13950397Sobrien#ifndef ASM_COMMENT_START 14050397Sobrien#define ASM_COMMENT_START ";#" 14150397Sobrien#endif 14250397Sobrien 14350397Sobrientypedef struct dw_cfi_struct *dw_cfi_ref; 14450397Sobrientypedef struct dw_fde_struct *dw_fde_ref; 14550397Sobrientypedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref; 14650397Sobrien 14750397Sobrien/* Call frames are described using a sequence of Call Frame 14850397Sobrien Information instructions. The register number, offset 14950397Sobrien and address fields are provided as possible operands; 15050397Sobrien their use is selected by the opcode field. */ 15150397Sobrien 15250397Sobrientypedef union dw_cfi_oprnd_struct 15350397Sobrien{ 15450397Sobrien unsigned long dw_cfi_reg_num; 15550397Sobrien long int dw_cfi_offset; 15690075Sobrien const char *dw_cfi_addr; 15790075Sobrien struct dw_loc_descr_struct *dw_cfi_loc; 15850397Sobrien} 15950397Sobriendw_cfi_oprnd; 16050397Sobrien 16150397Sobrientypedef struct dw_cfi_struct 16250397Sobrien{ 16350397Sobrien dw_cfi_ref dw_cfi_next; 16450397Sobrien enum dwarf_call_frame_info dw_cfi_opc; 16550397Sobrien dw_cfi_oprnd dw_cfi_oprnd1; 16650397Sobrien dw_cfi_oprnd dw_cfi_oprnd2; 16750397Sobrien} 16850397Sobriendw_cfi_node; 16950397Sobrien 17090075Sobrien/* This is how we define the location of the CFA. We use to handle it 17190075Sobrien as REG + OFFSET all the time, but now it can be more complex. 17290075Sobrien It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET. 17390075Sobrien Instead of passing around REG and OFFSET, we pass a copy 17490075Sobrien of this structure. */ 17590075Sobrientypedef struct cfa_loc 17690075Sobrien{ 17790075Sobrien unsigned long reg; 17890075Sobrien long offset; 17990075Sobrien long base_offset; 18090075Sobrien int indirect; /* 1 if CFA is accessed via a dereference. */ 18190075Sobrien} dw_cfa_location; 18290075Sobrien 18350397Sobrien/* All call frame descriptions (FDE's) in the GCC generated DWARF 18450397Sobrien refer to a single Common Information Entry (CIE), defined at 18590075Sobrien the beginning of the .debug_frame section. This use of a single 18650397Sobrien CIE obviates the need to keep track of multiple CIE's 18750397Sobrien in the DWARF generation routines below. */ 18850397Sobrien 18950397Sobrientypedef struct dw_fde_struct 19050397Sobrien{ 19190075Sobrien const char *dw_fde_begin; 19290075Sobrien const char *dw_fde_current_label; 19390075Sobrien const char *dw_fde_end; 19450397Sobrien dw_cfi_ref dw_fde_cfi; 19590075Sobrien unsigned funcdef_number; 19690075Sobrien unsigned nothrow : 1; 19790075Sobrien unsigned uses_eh_lsda : 1; 19850397Sobrien} 19950397Sobriendw_fde_node; 20050397Sobrien 20190075Sobrien/* Maximum size (in bytes) of an artificially generated label. */ 20250397Sobrien#define MAX_ARTIFICIAL_LABEL_BYTES 30 20350397Sobrien 20490075Sobrien/* The size of addresses as they appear in the Dwarf 2 data. 20590075Sobrien Some architectures use word addresses to refer to code locations, 20690075Sobrien but Dwarf 2 info always uses byte addresses. On such machines, 20790075Sobrien Dwarf 2 addresses need to be larger than the architecture's 20890075Sobrien pointers. */ 20990075Sobrien#ifndef DWARF2_ADDR_SIZE 21090075Sobrien#define DWARF2_ADDR_SIZE (POINTER_SIZE / BITS_PER_UNIT) 21150397Sobrien#endif 21250397Sobrien 21350397Sobrien/* The size in bytes of a DWARF field indicating an offset or length 21490075Sobrien relative to a debug info section, specified to be 4 bytes in the 21590075Sobrien DWARF-2 specification. The SGI/MIPS ABI defines it to be the same 21690075Sobrien as PTR_SIZE. */ 21750397Sobrien 21850397Sobrien#ifndef DWARF_OFFSET_SIZE 21950397Sobrien#define DWARF_OFFSET_SIZE 4 22050397Sobrien#endif 22150397Sobrien 22250397Sobrien#define DWARF_VERSION 2 22350397Sobrien 22450397Sobrien/* Round SIZE up to the nearest BOUNDARY. */ 22550397Sobrien#define DWARF_ROUND(SIZE,BOUNDARY) \ 22690075Sobrien ((((SIZE) + (BOUNDARY) - 1) / (BOUNDARY)) * (BOUNDARY)) 22750397Sobrien 22850397Sobrien/* Offsets recorded in opcodes are a multiple of this alignment factor. */ 22990075Sobrien#ifndef DWARF_CIE_DATA_ALIGNMENT 23050397Sobrien#ifdef STACK_GROWS_DOWNWARD 23190075Sobrien#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD)) 23250397Sobrien#else 23390075Sobrien#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD) 23450397Sobrien#endif 23590075Sobrien#endif 23650397Sobrien 23750397Sobrien/* A pointer to the base of a table that contains frame description 23850397Sobrien information for each routine. */ 23950397Sobrienstatic dw_fde_ref fde_table; 24050397Sobrien 24150397Sobrien/* Number of elements currently allocated for fde_table. */ 24250397Sobrienstatic unsigned fde_table_allocated; 24350397Sobrien 24450397Sobrien/* Number of elements in fde_table currently in use. */ 24550397Sobrienstatic unsigned fde_table_in_use; 24650397Sobrien 24750397Sobrien/* Size (in elements) of increments by which we may expand the 24850397Sobrien fde_table. */ 24950397Sobrien#define FDE_TABLE_INCREMENT 256 25050397Sobrien 25150397Sobrien/* A list of call frame insns for the CIE. */ 25250397Sobrienstatic dw_cfi_ref cie_cfi_head; 25350397Sobrien 25450397Sobrien/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram 25550397Sobrien attribute that accelerates the lookup of the FDE associated 25690075Sobrien with the subprogram. This variable holds the table index of the FDE 25750397Sobrien associated with the current function (body) definition. */ 25850397Sobrienstatic unsigned current_funcdef_fde; 25950397Sobrien 26090075Sobrienstruct ht *debug_str_hash; 26190075Sobrien 26290075Sobrienstruct indirect_string_node 26390075Sobrien{ 26490075Sobrien struct ht_identifier id; 26590075Sobrien unsigned int refcount; 26690075Sobrien unsigned int form; 26790075Sobrien char *label; 26890075Sobrien}; 26990075Sobrien 27050397Sobrien/* Forward declarations for functions defined in this file. */ 27150397Sobrien 27290075Sobrienstatic char *stripattributes PARAMS ((const char *)); 27390075Sobrienstatic const char *dwarf_cfi_name PARAMS ((unsigned)); 27490075Sobrienstatic dw_cfi_ref new_cfi PARAMS ((void)); 27590075Sobrienstatic void add_cfi PARAMS ((dw_cfi_ref *, dw_cfi_ref)); 27690075Sobrienstatic void add_fde_cfi PARAMS ((const char *, dw_cfi_ref)); 27790075Sobrienstatic void lookup_cfa_1 PARAMS ((dw_cfi_ref, 27890075Sobrien dw_cfa_location *)); 27990075Sobrienstatic void lookup_cfa PARAMS ((dw_cfa_location *)); 28090075Sobrienstatic void reg_save PARAMS ((const char *, unsigned, 28190075Sobrien unsigned, long)); 28290075Sobrienstatic void initial_return_save PARAMS ((rtx)); 28390075Sobrienstatic long stack_adjust_offset PARAMS ((rtx)); 28490075Sobrienstatic void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref, int)); 28590075Sobrienstatic void output_call_frame_info PARAMS ((int)); 28690075Sobrienstatic void dwarf2out_stack_adjust PARAMS ((rtx)); 28790075Sobrienstatic void queue_reg_save PARAMS ((const char *, rtx, long)); 28890075Sobrienstatic void flush_queued_reg_saves PARAMS ((void)); 28990075Sobrienstatic bool clobbers_queued_reg_save PARAMS ((rtx)); 29090075Sobrienstatic void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *)); 29150397Sobrien 29290075Sobrien/* Support for complex CFA locations. */ 29390075Sobrienstatic void output_cfa_loc PARAMS ((dw_cfi_ref)); 29490075Sobrienstatic void get_cfa_from_loc_descr PARAMS ((dw_cfa_location *, 29590075Sobrien struct dw_loc_descr_struct *)); 29690075Sobrienstatic struct dw_loc_descr_struct *build_cfa_loc 29790075Sobrien PARAMS ((dw_cfa_location *)); 29890075Sobrienstatic void def_cfa_1 PARAMS ((const char *, 29990075Sobrien dw_cfa_location *)); 30050397Sobrien 30190075Sobrien/* How to start an assembler comment. */ 30290075Sobrien#ifndef ASM_COMMENT_START 30390075Sobrien#define ASM_COMMENT_START ";#" 30450397Sobrien#endif 30550397Sobrien 30650397Sobrien/* Data and reference forms for relocatable data. */ 30750397Sobrien#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4) 30850397Sobrien#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4) 30950397Sobrien 31050397Sobrien/* Pseudo-op for defining a new section. */ 31150397Sobrien#ifndef SECTION_ASM_OP 31290075Sobrien#define SECTION_ASM_OP "\t.section\t" 31350397Sobrien#endif 31450397Sobrien 31590075Sobrien#ifndef DEBUG_FRAME_SECTION 31690075Sobrien#define DEBUG_FRAME_SECTION ".debug_frame" 31750397Sobrien#endif 31850397Sobrien 31950397Sobrien#ifndef FUNC_BEGIN_LABEL 32050397Sobrien#define FUNC_BEGIN_LABEL "LFB" 32150397Sobrien#endif 32290075Sobrien 32350397Sobrien#ifndef FUNC_END_LABEL 32450397Sobrien#define FUNC_END_LABEL "LFE" 32550397Sobrien#endif 32690075Sobrien 32790075Sobrien#define FRAME_BEGIN_LABEL "Lframe" 32850397Sobrien#define CIE_AFTER_SIZE_LABEL "LSCIE" 32950397Sobrien#define CIE_END_LABEL "LECIE" 33050397Sobrien#define CIE_LENGTH_LABEL "LLCIE" 33190075Sobrien#define FDE_LABEL "LSFDE" 33290075Sobrien#define FDE_AFTER_SIZE_LABEL "LASFDE" 33350397Sobrien#define FDE_END_LABEL "LEFDE" 33450397Sobrien#define FDE_LENGTH_LABEL "LLFDE" 33590075Sobrien#define LINE_NUMBER_BEGIN_LABEL "LSLT" 33690075Sobrien#define LINE_NUMBER_END_LABEL "LELT" 33790075Sobrien#define LN_PROLOG_AS_LABEL "LASLTP" 33890075Sobrien#define LN_PROLOG_END_LABEL "LELTP" 33990075Sobrien#define DIE_LABEL_PREFIX "DW" 34050397Sobrien 34150397Sobrien/* Definitions of defaults for various types of primitive assembly language 34250397Sobrien output operations. These may be overridden from within the tm.h file, 34350397Sobrien but typically, that is unnecessary. */ 34450397Sobrien 34550397Sobrien#ifdef SET_ASM_OP 34650397Sobrien#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 34750397Sobrien#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \ 34850397Sobrien do { \ 34990075Sobrien fprintf (FILE, "%s", SET_ASM_OP); \ 35050397Sobrien assemble_name (FILE, SY); \ 35150397Sobrien fputc (',', FILE); \ 35250397Sobrien assemble_name (FILE, HI); \ 35350397Sobrien fputc ('-', FILE); \ 35450397Sobrien assemble_name (FILE, LO); \ 35550397Sobrien } while (0) 35650397Sobrien#endif 35750397Sobrien#endif 35850397Sobrien 35950397Sobrien/* The DWARF 2 CFA column which tracks the return address. Normally this 36050397Sobrien is the column for PC, or the first column after all of the hard 36150397Sobrien registers. */ 36250397Sobrien#ifndef DWARF_FRAME_RETURN_COLUMN 36350397Sobrien#ifdef PC_REGNUM 36450397Sobrien#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM) 36550397Sobrien#else 36690075Sobrien#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS 36750397Sobrien#endif 36850397Sobrien#endif 36950397Sobrien 37050397Sobrien/* The mapping from gcc register number to DWARF 2 CFA column number. By 37150397Sobrien default, we just provide columns for all registers. */ 37250397Sobrien#ifndef DWARF_FRAME_REGNUM 37350397Sobrien#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) 37450397Sobrien#endif 37550397Sobrien 37690075Sobrien/* The offset from the incoming value of %sp to the top of the stack frame 37790075Sobrien for the current function. */ 37890075Sobrien#ifndef INCOMING_FRAME_SP_OFFSET 37990075Sobrien#define INCOMING_FRAME_SP_OFFSET 0 38090075Sobrien#endif 38190075Sobrien 38250397Sobrien/* Hook used by __throw. */ 38350397Sobrien 38450397Sobrienrtx 38550397Sobrienexpand_builtin_dwarf_fp_regnum () 38650397Sobrien{ 38750397Sobrien return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM)); 38850397Sobrien} 38950397Sobrien 39050397Sobrien/* Return a pointer to a copy of the section string name S with all 39150397Sobrien attributes stripped off, and an asterisk prepended (for assemble_name). */ 39250397Sobrien 39350397Sobrienstatic inline char * 39450397Sobrienstripattributes (s) 39590075Sobrien const char *s; 39650397Sobrien{ 39750397Sobrien char *stripped = xmalloc (strlen (s) + 2); 39850397Sobrien char *p = stripped; 39950397Sobrien 40050397Sobrien *p++ = '*'; 40150397Sobrien 40250397Sobrien while (*s && *s != ',') 40350397Sobrien *p++ = *s++; 40450397Sobrien 40550397Sobrien *p = '\0'; 40650397Sobrien return stripped; 40750397Sobrien} 40850397Sobrien 40990075Sobrien/* Generate code to initialize the register size table. */ 41050397Sobrien 41190075Sobrienvoid 41290075Sobrienexpand_builtin_init_dwarf_reg_sizes (address) 41390075Sobrien tree address; 41450397Sobrien{ 41590075Sobrien int i; 41690075Sobrien enum machine_mode mode = TYPE_MODE (char_type_node); 41790075Sobrien rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0); 41890075Sobrien rtx mem = gen_rtx_MEM (BLKmode, addr); 41950397Sobrien 42090075Sobrien for (i = 0; i < DWARF_FRAME_REGISTERS; i++) 42150397Sobrien { 42290075Sobrien HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode); 42390075Sobrien HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]); 42450397Sobrien 42590075Sobrien if (offset < 0) 42650397Sobrien continue; 42750397Sobrien 42890075Sobrien emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); 42950397Sobrien } 43050397Sobrien} 43150397Sobrien 43250397Sobrien/* Convert a DWARF call frame info. operation to its string name */ 43350397Sobrien 43490075Sobrienstatic const char * 43550397Sobriendwarf_cfi_name (cfi_opc) 43690075Sobrien unsigned cfi_opc; 43750397Sobrien{ 43850397Sobrien switch (cfi_opc) 43950397Sobrien { 44050397Sobrien case DW_CFA_advance_loc: 44150397Sobrien return "DW_CFA_advance_loc"; 44250397Sobrien case DW_CFA_offset: 44350397Sobrien return "DW_CFA_offset"; 44450397Sobrien case DW_CFA_restore: 44550397Sobrien return "DW_CFA_restore"; 44650397Sobrien case DW_CFA_nop: 44750397Sobrien return "DW_CFA_nop"; 44850397Sobrien case DW_CFA_set_loc: 44950397Sobrien return "DW_CFA_set_loc"; 45050397Sobrien case DW_CFA_advance_loc1: 45150397Sobrien return "DW_CFA_advance_loc1"; 45250397Sobrien case DW_CFA_advance_loc2: 45350397Sobrien return "DW_CFA_advance_loc2"; 45450397Sobrien case DW_CFA_advance_loc4: 45550397Sobrien return "DW_CFA_advance_loc4"; 45650397Sobrien case DW_CFA_offset_extended: 45750397Sobrien return "DW_CFA_offset_extended"; 45850397Sobrien case DW_CFA_restore_extended: 45950397Sobrien return "DW_CFA_restore_extended"; 46050397Sobrien case DW_CFA_undefined: 46150397Sobrien return "DW_CFA_undefined"; 46250397Sobrien case DW_CFA_same_value: 46350397Sobrien return "DW_CFA_same_value"; 46450397Sobrien case DW_CFA_register: 46550397Sobrien return "DW_CFA_register"; 46650397Sobrien case DW_CFA_remember_state: 46750397Sobrien return "DW_CFA_remember_state"; 46850397Sobrien case DW_CFA_restore_state: 46950397Sobrien return "DW_CFA_restore_state"; 47050397Sobrien case DW_CFA_def_cfa: 47150397Sobrien return "DW_CFA_def_cfa"; 47250397Sobrien case DW_CFA_def_cfa_register: 47350397Sobrien return "DW_CFA_def_cfa_register"; 47450397Sobrien case DW_CFA_def_cfa_offset: 47550397Sobrien return "DW_CFA_def_cfa_offset"; 47650397Sobrien 47790075Sobrien /* DWARF 3 */ 47890075Sobrien case DW_CFA_def_cfa_expression: 47990075Sobrien return "DW_CFA_def_cfa_expression"; 48090075Sobrien case DW_CFA_expression: 48190075Sobrien return "DW_CFA_expression"; 48290075Sobrien case DW_CFA_offset_extended_sf: 48390075Sobrien return "DW_CFA_offset_extended_sf"; 48490075Sobrien case DW_CFA_def_cfa_sf: 48590075Sobrien return "DW_CFA_def_cfa_sf"; 48690075Sobrien case DW_CFA_def_cfa_offset_sf: 48790075Sobrien return "DW_CFA_def_cfa_offset_sf"; 48890075Sobrien 48950397Sobrien /* SGI/MIPS specific */ 49050397Sobrien case DW_CFA_MIPS_advance_loc8: 49150397Sobrien return "DW_CFA_MIPS_advance_loc8"; 49250397Sobrien 49350397Sobrien /* GNU extensions */ 49450397Sobrien case DW_CFA_GNU_window_save: 49550397Sobrien return "DW_CFA_GNU_window_save"; 49650397Sobrien case DW_CFA_GNU_args_size: 49750397Sobrien return "DW_CFA_GNU_args_size"; 49870635Sobrien case DW_CFA_GNU_negative_offset_extended: 49970635Sobrien return "DW_CFA_GNU_negative_offset_extended"; 50050397Sobrien 50150397Sobrien default: 50250397Sobrien return "DW_CFA_<unknown>"; 50350397Sobrien } 50450397Sobrien} 50550397Sobrien 50650397Sobrien/* Return a pointer to a newly allocated Call Frame Instruction. */ 50750397Sobrien 50850397Sobrienstatic inline dw_cfi_ref 50950397Sobriennew_cfi () 51050397Sobrien{ 51190075Sobrien dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node)); 51250397Sobrien 51350397Sobrien cfi->dw_cfi_next = NULL; 51450397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0; 51550397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0; 51650397Sobrien 51750397Sobrien return cfi; 51850397Sobrien} 51950397Sobrien 52050397Sobrien/* Add a Call Frame Instruction to list of instructions. */ 52150397Sobrien 52250397Sobrienstatic inline void 52350397Sobrienadd_cfi (list_head, cfi) 52490075Sobrien dw_cfi_ref *list_head; 52590075Sobrien dw_cfi_ref cfi; 52650397Sobrien{ 52790075Sobrien dw_cfi_ref *p; 52850397Sobrien 52950397Sobrien /* Find the end of the chain. */ 53050397Sobrien for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next) 53150397Sobrien ; 53250397Sobrien 53350397Sobrien *p = cfi; 53450397Sobrien} 53550397Sobrien 53650397Sobrien/* Generate a new label for the CFI info to refer to. */ 53750397Sobrien 53850397Sobrienchar * 53950397Sobriendwarf2out_cfi_label () 54050397Sobrien{ 54150397Sobrien static char label[20]; 54250397Sobrien static unsigned long label_num = 0; 54390075Sobrien 54450397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++); 54550397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 54650397Sobrien return label; 54750397Sobrien} 54850397Sobrien 54950397Sobrien/* Add CFI to the current fde at the PC value indicated by LABEL if specified, 55050397Sobrien or to the CIE if LABEL is NULL. */ 55150397Sobrien 55250397Sobrienstatic void 55350397Sobrienadd_fde_cfi (label, cfi) 55490075Sobrien const char *label; 55590075Sobrien dw_cfi_ref cfi; 55650397Sobrien{ 55750397Sobrien if (label) 55850397Sobrien { 55990075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 56050397Sobrien 56150397Sobrien if (*label == 0) 56250397Sobrien label = dwarf2out_cfi_label (); 56350397Sobrien 56450397Sobrien if (fde->dw_fde_current_label == NULL 56550397Sobrien || strcmp (label, fde->dw_fde_current_label) != 0) 56650397Sobrien { 56790075Sobrien dw_cfi_ref xcfi; 56850397Sobrien 56950397Sobrien fde->dw_fde_current_label = label = xstrdup (label); 57050397Sobrien 57150397Sobrien /* Set the location counter to the new label. */ 57250397Sobrien xcfi = new_cfi (); 57350397Sobrien xcfi->dw_cfi_opc = DW_CFA_advance_loc4; 57450397Sobrien xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; 57550397Sobrien add_cfi (&fde->dw_fde_cfi, xcfi); 57650397Sobrien } 57750397Sobrien 57850397Sobrien add_cfi (&fde->dw_fde_cfi, cfi); 57950397Sobrien } 58050397Sobrien 58150397Sobrien else 58250397Sobrien add_cfi (&cie_cfi_head, cfi); 58350397Sobrien} 58450397Sobrien 58550397Sobrien/* Subroutine of lookup_cfa. */ 58650397Sobrien 58750397Sobrienstatic inline void 58890075Sobrienlookup_cfa_1 (cfi, loc) 58990075Sobrien dw_cfi_ref cfi; 59090075Sobrien dw_cfa_location *loc; 59150397Sobrien{ 59250397Sobrien switch (cfi->dw_cfi_opc) 59350397Sobrien { 59450397Sobrien case DW_CFA_def_cfa_offset: 59590075Sobrien loc->offset = cfi->dw_cfi_oprnd1.dw_cfi_offset; 59650397Sobrien break; 59750397Sobrien case DW_CFA_def_cfa_register: 59890075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 59950397Sobrien break; 60050397Sobrien case DW_CFA_def_cfa: 60190075Sobrien loc->reg = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 60290075Sobrien loc->offset = cfi->dw_cfi_oprnd2.dw_cfi_offset; 60350397Sobrien break; 60490075Sobrien case DW_CFA_def_cfa_expression: 60590075Sobrien get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc); 60690075Sobrien break; 60750397Sobrien default: 60850397Sobrien break; 60950397Sobrien } 61050397Sobrien} 61150397Sobrien 61250397Sobrien/* Find the previous value for the CFA. */ 61350397Sobrien 61450397Sobrienstatic void 61590075Sobrienlookup_cfa (loc) 61690075Sobrien dw_cfa_location *loc; 61750397Sobrien{ 61890075Sobrien dw_cfi_ref cfi; 61950397Sobrien 62090075Sobrien loc->reg = (unsigned long) -1; 62190075Sobrien loc->offset = 0; 62290075Sobrien loc->indirect = 0; 62390075Sobrien loc->base_offset = 0; 62450397Sobrien 62550397Sobrien for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next) 62690075Sobrien lookup_cfa_1 (cfi, loc); 62750397Sobrien 62850397Sobrien if (fde_table_in_use) 62950397Sobrien { 63090075Sobrien dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 63150397Sobrien for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) 63290075Sobrien lookup_cfa_1 (cfi, loc); 63350397Sobrien } 63450397Sobrien} 63550397Sobrien 63650397Sobrien/* The current rule for calculating the DWARF2 canonical frame address. */ 63790075Sobrienstatic dw_cfa_location cfa; 63850397Sobrien 63950397Sobrien/* The register used for saving registers to the stack, and its offset 64050397Sobrien from the CFA. */ 64190075Sobrienstatic dw_cfa_location cfa_store; 64250397Sobrien 64350397Sobrien/* The running total of the size of arguments pushed onto the stack. */ 64450397Sobrienstatic long args_size; 64550397Sobrien 64650397Sobrien/* The last args_size we actually output. */ 64750397Sobrienstatic long old_args_size; 64850397Sobrien 64950397Sobrien/* Entry point to update the canonical frame address (CFA). 65050397Sobrien LABEL is passed to add_fde_cfi. The value of CFA is now to be 65150397Sobrien calculated from REG+OFFSET. */ 65250397Sobrien 65350397Sobrienvoid 65450397Sobriendwarf2out_def_cfa (label, reg, offset) 65590075Sobrien const char *label; 65690075Sobrien unsigned reg; 65790075Sobrien long offset; 65850397Sobrien{ 65990075Sobrien dw_cfa_location loc; 66090075Sobrien loc.indirect = 0; 66190075Sobrien loc.base_offset = 0; 66290075Sobrien loc.reg = reg; 66390075Sobrien loc.offset = offset; 66490075Sobrien def_cfa_1 (label, &loc); 66590075Sobrien} 66650397Sobrien 66790075Sobrien/* This routine does the actual work. The CFA is now calculated from 66890075Sobrien the dw_cfa_location structure. */ 66950397Sobrien 67090075Sobrienstatic void 67190075Sobriendef_cfa_1 (label, loc_p) 67290075Sobrien const char *label; 67390075Sobrien dw_cfa_location *loc_p; 67490075Sobrien{ 67590075Sobrien dw_cfi_ref cfi; 67690075Sobrien dw_cfa_location old_cfa, loc; 67750397Sobrien 67890075Sobrien cfa = *loc_p; 67990075Sobrien loc = *loc_p; 68090075Sobrien 68190075Sobrien if (cfa_store.reg == loc.reg && loc.indirect == 0) 68290075Sobrien cfa_store.offset = loc.offset; 68390075Sobrien 68490075Sobrien loc.reg = DWARF_FRAME_REGNUM (loc.reg); 68590075Sobrien lookup_cfa (&old_cfa); 68690075Sobrien 68790075Sobrien /* If nothing changed, no need to issue any call frame instructions. */ 68890075Sobrien if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset 68990075Sobrien && loc.indirect == old_cfa.indirect 69090075Sobrien && (loc.indirect == 0 || loc.base_offset == old_cfa.base_offset)) 69150397Sobrien return; 69250397Sobrien 69350397Sobrien cfi = new_cfi (); 69450397Sobrien 69590075Sobrien if (loc.reg == old_cfa.reg && !loc.indirect) 69650397Sobrien { 69790075Sobrien /* Construct a "DW_CFA_def_cfa_offset <offset>" instruction, 69890075Sobrien indicating the CFA register did not change but the offset 69990075Sobrien did. */ 70050397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; 70190075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = loc.offset; 70250397Sobrien } 70350397Sobrien 70450397Sobrien#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ 70590075Sobrien else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1 70690075Sobrien && !loc.indirect) 70750397Sobrien { 70890075Sobrien /* Construct a "DW_CFA_def_cfa_register <register>" instruction, 70990075Sobrien indicating the CFA register has changed to <register> but the 71090075Sobrien offset has not changed. */ 71150397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_register; 71290075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 71350397Sobrien } 71450397Sobrien#endif 71550397Sobrien 71690075Sobrien else if (loc.indirect == 0) 71750397Sobrien { 71890075Sobrien /* Construct a "DW_CFA_def_cfa <register> <offset>" instruction, 71990075Sobrien indicating the CFA register has changed to <register> with 72090075Sobrien the specified offset. */ 72150397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa; 72290075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = loc.reg; 72390075Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = loc.offset; 72450397Sobrien } 72590075Sobrien else 72690075Sobrien { 72790075Sobrien /* Construct a DW_CFA_def_cfa_expression instruction to 72890075Sobrien calculate the CFA using a full location expression since no 72990075Sobrien register-offset pair is available. */ 73090075Sobrien struct dw_loc_descr_struct *loc_list; 73150397Sobrien 73290075Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_expression; 73390075Sobrien loc_list = build_cfa_loc (&loc); 73490075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_loc = loc_list; 73590075Sobrien } 73690075Sobrien 73750397Sobrien add_fde_cfi (label, cfi); 73850397Sobrien} 73950397Sobrien 74050397Sobrien/* Add the CFI for saving a register. REG is the CFA column number. 74150397Sobrien LABEL is passed to add_fde_cfi. 74250397Sobrien If SREG is -1, the register is saved at OFFSET from the CFA; 74350397Sobrien otherwise it is saved in SREG. */ 74450397Sobrien 74550397Sobrienstatic void 74650397Sobrienreg_save (label, reg, sreg, offset) 74790075Sobrien const char *label; 74890075Sobrien unsigned reg; 74990075Sobrien unsigned sreg; 75090075Sobrien long offset; 75150397Sobrien{ 75290075Sobrien dw_cfi_ref cfi = new_cfi (); 75350397Sobrien 75450397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 75550397Sobrien 75650397Sobrien /* The following comparison is correct. -1 is used to indicate that 75750397Sobrien the value isn't a register number. */ 75850397Sobrien if (sreg == (unsigned int) -1) 75950397Sobrien { 76050397Sobrien if (reg & ~0x3f) 76150397Sobrien /* The register number won't fit in 6 bits, so we have to use 76250397Sobrien the long form. */ 76350397Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended; 76450397Sobrien else 76550397Sobrien cfi->dw_cfi_opc = DW_CFA_offset; 76650397Sobrien 76790075Sobrien#ifdef ENABLE_CHECKING 76890075Sobrien { 76990075Sobrien /* If we get an offset that is not a multiple of 77090075Sobrien DWARF_CIE_DATA_ALIGNMENT, there is either a bug in the 77190075Sobrien definition of DWARF_CIE_DATA_ALIGNMENT, or a bug in the machine 77290075Sobrien description. */ 77390075Sobrien long check_offset = offset / DWARF_CIE_DATA_ALIGNMENT; 77490075Sobrien 77590075Sobrien if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset) 77690075Sobrien abort (); 77790075Sobrien } 77890075Sobrien#endif 77950397Sobrien offset /= DWARF_CIE_DATA_ALIGNMENT; 78050397Sobrien if (offset < 0) 78190075Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended_sf; 78290075Sobrien 78350397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; 78450397Sobrien } 78590075Sobrien else if (sreg == reg) 78690075Sobrien /* We could emit a DW_CFA_same_value in this case, but don't bother. */ 78790075Sobrien return; 78850397Sobrien else 78950397Sobrien { 79050397Sobrien cfi->dw_cfi_opc = DW_CFA_register; 79150397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg; 79250397Sobrien } 79350397Sobrien 79450397Sobrien add_fde_cfi (label, cfi); 79550397Sobrien} 79650397Sobrien 79750397Sobrien/* Add the CFI for saving a register window. LABEL is passed to reg_save. 79850397Sobrien This CFI tells the unwinder that it needs to restore the window registers 79950397Sobrien from the previous frame's window save area. 80090075Sobrien 80150397Sobrien ??? Perhaps we should note in the CIE where windows are saved (instead of 80250397Sobrien assuming 0(cfa)) and what registers are in the window. */ 80350397Sobrien 80450397Sobrienvoid 80550397Sobriendwarf2out_window_save (label) 80690075Sobrien const char *label; 80750397Sobrien{ 80890075Sobrien dw_cfi_ref cfi = new_cfi (); 80990075Sobrien 81050397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_window_save; 81150397Sobrien add_fde_cfi (label, cfi); 81250397Sobrien} 81350397Sobrien 81450397Sobrien/* Add a CFI to update the running total of the size of arguments 81550397Sobrien pushed onto the stack. */ 81650397Sobrien 81750397Sobrienvoid 81850397Sobriendwarf2out_args_size (label, size) 81990075Sobrien const char *label; 82050397Sobrien long size; 82150397Sobrien{ 82290075Sobrien dw_cfi_ref cfi; 82350397Sobrien 82450397Sobrien if (size == old_args_size) 82550397Sobrien return; 82690075Sobrien 82750397Sobrien old_args_size = size; 82850397Sobrien 82950397Sobrien cfi = new_cfi (); 83050397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_args_size; 83150397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = size; 83250397Sobrien add_fde_cfi (label, cfi); 83350397Sobrien} 83450397Sobrien 83550397Sobrien/* Entry point for saving a register to the stack. REG is the GCC register 83650397Sobrien number. LABEL and OFFSET are passed to reg_save. */ 83750397Sobrien 83850397Sobrienvoid 83950397Sobriendwarf2out_reg_save (label, reg, offset) 84090075Sobrien const char *label; 84190075Sobrien unsigned reg; 84290075Sobrien long offset; 84350397Sobrien{ 84450397Sobrien reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset); 84550397Sobrien} 84650397Sobrien 84750397Sobrien/* Entry point for saving the return address in the stack. 84850397Sobrien LABEL and OFFSET are passed to reg_save. */ 84950397Sobrien 85050397Sobrienvoid 85150397Sobriendwarf2out_return_save (label, offset) 85290075Sobrien const char *label; 85390075Sobrien long offset; 85450397Sobrien{ 85550397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset); 85650397Sobrien} 85750397Sobrien 85850397Sobrien/* Entry point for saving the return address in a register. 85950397Sobrien LABEL and SREG are passed to reg_save. */ 86050397Sobrien 86150397Sobrienvoid 86250397Sobriendwarf2out_return_reg (label, sreg) 86390075Sobrien const char *label; 86490075Sobrien unsigned sreg; 86550397Sobrien{ 86650397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0); 86750397Sobrien} 86850397Sobrien 86950397Sobrien/* Record the initial position of the return address. RTL is 87050397Sobrien INCOMING_RETURN_ADDR_RTX. */ 87150397Sobrien 87250397Sobrienstatic void 87350397Sobrieninitial_return_save (rtl) 87490075Sobrien rtx rtl; 87550397Sobrien{ 87652284Sobrien unsigned int reg = (unsigned int) -1; 87790075Sobrien HOST_WIDE_INT offset = 0; 87850397Sobrien 87950397Sobrien switch (GET_CODE (rtl)) 88050397Sobrien { 88150397Sobrien case REG: 88250397Sobrien /* RA is in a register. */ 88390075Sobrien reg = DWARF_FRAME_REGNUM (REGNO (rtl)); 88450397Sobrien break; 88590075Sobrien 88650397Sobrien case MEM: 88750397Sobrien /* RA is on the stack. */ 88850397Sobrien rtl = XEXP (rtl, 0); 88950397Sobrien switch (GET_CODE (rtl)) 89050397Sobrien { 89150397Sobrien case REG: 89250397Sobrien if (REGNO (rtl) != STACK_POINTER_REGNUM) 89350397Sobrien abort (); 89450397Sobrien offset = 0; 89550397Sobrien break; 89690075Sobrien 89750397Sobrien case PLUS: 89850397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 89950397Sobrien abort (); 90050397Sobrien offset = INTVAL (XEXP (rtl, 1)); 90150397Sobrien break; 90290075Sobrien 90350397Sobrien case MINUS: 90450397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 90550397Sobrien abort (); 90650397Sobrien offset = -INTVAL (XEXP (rtl, 1)); 90750397Sobrien break; 90890075Sobrien 90950397Sobrien default: 91050397Sobrien abort (); 91150397Sobrien } 91290075Sobrien 91350397Sobrien break; 91490075Sobrien 91550397Sobrien case PLUS: 91650397Sobrien /* The return address is at some offset from any value we can 91750397Sobrien actually load. For instance, on the SPARC it is in %i7+8. Just 91850397Sobrien ignore the offset for now; it doesn't matter for unwinding frames. */ 91950397Sobrien if (GET_CODE (XEXP (rtl, 1)) != CONST_INT) 92050397Sobrien abort (); 92150397Sobrien initial_return_save (XEXP (rtl, 0)); 92250397Sobrien return; 92390075Sobrien 92450397Sobrien default: 92550397Sobrien abort (); 92650397Sobrien } 92750397Sobrien 92890075Sobrien reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa.offset); 92950397Sobrien} 93050397Sobrien 93190075Sobrien/* Given a SET, calculate the amount of stack adjustment it 93290075Sobrien contains. */ 93390075Sobrien 93490075Sobrienstatic long 93590075Sobrienstack_adjust_offset (pattern) 93690075Sobrien rtx pattern; 93790075Sobrien{ 93890075Sobrien rtx src = SET_SRC (pattern); 93990075Sobrien rtx dest = SET_DEST (pattern); 94090075Sobrien HOST_WIDE_INT offset = 0; 94190075Sobrien enum rtx_code code; 94290075Sobrien 94390075Sobrien if (dest == stack_pointer_rtx) 94490075Sobrien { 94590075Sobrien /* (set (reg sp) (plus (reg sp) (const_int))) */ 94690075Sobrien code = GET_CODE (src); 94790075Sobrien if (! (code == PLUS || code == MINUS) 94890075Sobrien || XEXP (src, 0) != stack_pointer_rtx 94990075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 95090075Sobrien return 0; 95190075Sobrien 95290075Sobrien offset = INTVAL (XEXP (src, 1)); 95390075Sobrien } 95490075Sobrien else if (GET_CODE (dest) == MEM) 95590075Sobrien { 95690075Sobrien /* (set (mem (pre_dec (reg sp))) (foo)) */ 95790075Sobrien src = XEXP (dest, 0); 95890075Sobrien code = GET_CODE (src); 95990075Sobrien 96090075Sobrien if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY) 96190075Sobrien || XEXP (src, 0) != stack_pointer_rtx) 96290075Sobrien return 0; 96390075Sobrien 96490075Sobrien if (code == PRE_MODIFY) 96590075Sobrien { 96690075Sobrien rtx val = XEXP (XEXP (src, 1), 1); 96790075Sobrien 96890075Sobrien /* We handle only adjustments by constant amount. */ 96990075Sobrien if (GET_CODE (XEXP (src, 1)) != PLUS || 97090075Sobrien GET_CODE (val) != CONST_INT) 97190075Sobrien abort (); 97290075Sobrien 97390075Sobrien offset = -INTVAL (val); 97490075Sobrien } 97590075Sobrien else 97690075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 97790075Sobrien } 97890075Sobrien else 97990075Sobrien return 0; 98090075Sobrien 98190075Sobrien if (code == PLUS || code == PRE_INC) 98290075Sobrien offset = -offset; 98390075Sobrien 98490075Sobrien return offset; 98590075Sobrien} 98690075Sobrien 98750397Sobrien/* Check INSN to see if it looks like a push or a stack adjustment, and 98850397Sobrien make a note of it if it does. EH uses this information to find out how 98950397Sobrien much extra space it needs to pop off the stack. */ 99050397Sobrien 99150397Sobrienstatic void 99250397Sobriendwarf2out_stack_adjust (insn) 99350397Sobrien rtx insn; 99450397Sobrien{ 99590075Sobrien HOST_WIDE_INT offset; 99690075Sobrien const char *label; 99790075Sobrien int i; 99850397Sobrien 99990075Sobrien if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN) 100050397Sobrien { 100150397Sobrien /* Extract the size of the args from the CALL rtx itself. */ 100250397Sobrien insn = PATTERN (insn); 100350397Sobrien if (GET_CODE (insn) == PARALLEL) 100450397Sobrien insn = XVECEXP (insn, 0, 0); 100550397Sobrien if (GET_CODE (insn) == SET) 100650397Sobrien insn = SET_SRC (insn); 100790075Sobrien if (GET_CODE (insn) != CALL) 100890075Sobrien abort (); 100990075Sobrien 101050397Sobrien dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); 101150397Sobrien return; 101250397Sobrien } 101350397Sobrien 101450397Sobrien /* If only calls can throw, and we have a frame pointer, 101550397Sobrien save up adjustments until we see the CALL_INSN. */ 101690075Sobrien else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM) 101750397Sobrien return; 101850397Sobrien 101950397Sobrien if (GET_CODE (insn) == BARRIER) 102050397Sobrien { 102150397Sobrien /* When we see a BARRIER, we know to reset args_size to 0. Usually 102250397Sobrien the compiler will have already emitted a stack adjustment, but 102350397Sobrien doesn't bother for calls to noreturn functions. */ 102450397Sobrien#ifdef STACK_GROWS_DOWNWARD 102550397Sobrien offset = -args_size; 102650397Sobrien#else 102750397Sobrien offset = args_size; 102850397Sobrien#endif 102950397Sobrien } 103050397Sobrien else if (GET_CODE (PATTERN (insn)) == SET) 103190075Sobrien offset = stack_adjust_offset (PATTERN (insn)); 103290075Sobrien else if (GET_CODE (PATTERN (insn)) == PARALLEL 103390075Sobrien || GET_CODE (PATTERN (insn)) == SEQUENCE) 103450397Sobrien { 103590075Sobrien /* There may be stack adjustments inside compound insns. Search 103690075Sobrien for them. */ 103790075Sobrien for (offset = 0, i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) 103890075Sobrien if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) 103990075Sobrien offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i)); 104050397Sobrien } 104150397Sobrien else 104250397Sobrien return; 104350397Sobrien 104450397Sobrien if (offset == 0) 104550397Sobrien return; 104650397Sobrien 104790075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 104890075Sobrien cfa.offset += offset; 104950397Sobrien 105050397Sobrien#ifndef STACK_GROWS_DOWNWARD 105150397Sobrien offset = -offset; 105250397Sobrien#endif 105390075Sobrien 105450397Sobrien args_size += offset; 105550397Sobrien if (args_size < 0) 105650397Sobrien args_size = 0; 105750397Sobrien 105850397Sobrien label = dwarf2out_cfi_label (); 105990075Sobrien def_cfa_1 (label, &cfa); 106050397Sobrien dwarf2out_args_size (label, args_size); 106150397Sobrien} 106250397Sobrien 106390075Sobrien/* We delay emitting a register save until either (a) we reach the end 106490075Sobrien of the prologue or (b) the register is clobbered. This clusters 106590075Sobrien register saves so that there are fewer pc advances. */ 106652284Sobrien 106790075Sobrienstruct queued_reg_save 106890075Sobrien{ 106990075Sobrien struct queued_reg_save *next; 107090075Sobrien rtx reg; 107190075Sobrien long cfa_offset; 107290075Sobrien}; 107352284Sobrien 107490075Sobrienstatic struct queued_reg_save *queued_reg_saves; 107590075Sobrienstatic const char *last_reg_save_label; 107650397Sobrien 107752284Sobrienstatic void 107890075Sobrienqueue_reg_save (label, reg, offset) 107990075Sobrien const char *label; 108090075Sobrien rtx reg; 108190075Sobrien long offset; 108290075Sobrien{ 108390075Sobrien struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q)); 108490075Sobrien 108590075Sobrien q->next = queued_reg_saves; 108690075Sobrien q->reg = reg; 108790075Sobrien q->cfa_offset = offset; 108890075Sobrien queued_reg_saves = q; 108990075Sobrien 109090075Sobrien last_reg_save_label = label; 109190075Sobrien} 109290075Sobrien 109390075Sobrienstatic void 109490075Sobrienflush_queued_reg_saves () 109590075Sobrien{ 109690075Sobrien struct queued_reg_save *q, *next; 109790075Sobrien 109890075Sobrien for (q = queued_reg_saves; q ; q = next) 109990075Sobrien { 110090075Sobrien dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset); 110190075Sobrien next = q->next; 110290075Sobrien free (q); 110390075Sobrien } 110490075Sobrien 110590075Sobrien queued_reg_saves = NULL; 110690075Sobrien last_reg_save_label = NULL; 110790075Sobrien} 110890075Sobrien 110990075Sobrienstatic bool 111090075Sobrienclobbers_queued_reg_save (insn) 111190075Sobrien rtx insn; 111290075Sobrien{ 111390075Sobrien struct queued_reg_save *q; 111490075Sobrien 111590075Sobrien for (q = queued_reg_saves; q ; q = q->next) 111690075Sobrien if (modified_in_p (q->reg, insn)) 111790075Sobrien return true; 111890075Sobrien 111990075Sobrien return false; 112090075Sobrien} 112190075Sobrien 112290075Sobrien 112390075Sobrien/* A temporary register holding an integral value used in adjusting SP 112490075Sobrien or setting up the store_reg. The "offset" field holds the integer 112590075Sobrien value, not an offset. */ 112690075Sobrienstatic dw_cfa_location cfa_temp; 112790075Sobrien 112890075Sobrien/* Record call frame debugging information for an expression EXPR, 112990075Sobrien which either sets SP or FP (adjusting how we calculate the frame 113090075Sobrien address) or saves a register to the stack. LABEL indicates the 113190075Sobrien address of EXPR. 113290075Sobrien 113390075Sobrien This function encodes a state machine mapping rtxes to actions on 113490075Sobrien cfa, cfa_store, and cfa_temp.reg. We describe these rules so 113590075Sobrien users need not read the source code. 113690075Sobrien 113790075Sobrien The High-Level Picture 113890075Sobrien 113990075Sobrien Changes in the register we use to calculate the CFA: Currently we 114090075Sobrien assume that if you copy the CFA register into another register, we 114190075Sobrien should take the other one as the new CFA register; this seems to 114290075Sobrien work pretty well. If it's wrong for some target, it's simple 114390075Sobrien enough not to set RTX_FRAME_RELATED_P on the insn in question. 114490075Sobrien 114590075Sobrien Changes in the register we use for saving registers to the stack: 114690075Sobrien This is usually SP, but not always. Again, we deduce that if you 114790075Sobrien copy SP into another register (and SP is not the CFA register), 114890075Sobrien then the new register is the one we will be using for register 114990075Sobrien saves. This also seems to work. 115090075Sobrien 115190075Sobrien Register saves: There's not much guesswork about this one; if 115290075Sobrien RTX_FRAME_RELATED_P is set on an insn which modifies memory, it's a 115390075Sobrien register save, and the register used to calculate the destination 115490075Sobrien had better be the one we think we're using for this purpose. 115590075Sobrien 115690075Sobrien Except: If the register being saved is the CFA register, and the 115790075Sobrien offset is non-zero, we are saving the CFA, so we assume we have to 115890075Sobrien use DW_CFA_def_cfa_expression. If the offset is 0, we assume that 115990075Sobrien the intent is to save the value of SP from the previous frame. 116090075Sobrien 116190075Sobrien Invariants / Summaries of Rules 116290075Sobrien 116390075Sobrien cfa current rule for calculating the CFA. It usually 116490075Sobrien consists of a register and an offset. 116590075Sobrien cfa_store register used by prologue code to save things to the stack 116690075Sobrien cfa_store.offset is the offset from the value of 116790075Sobrien cfa_store.reg to the actual CFA 116890075Sobrien cfa_temp register holding an integral value. cfa_temp.offset 116990075Sobrien stores the value, which will be used to adjust the 117090075Sobrien stack pointer. cfa_temp is also used like cfa_store, 117190075Sobrien to track stores to the stack via fp or a temp reg. 117290075Sobrien 117390075Sobrien Rules 1- 4: Setting a register's value to cfa.reg or an expression 117490075Sobrien with cfa.reg as the first operand changes the cfa.reg and its 117590075Sobrien cfa.offset. Rule 1 and 4 also set cfa_temp.reg and 117690075Sobrien cfa_temp.offset. 117790075Sobrien 117890075Sobrien Rules 6- 9: Set a non-cfa.reg register value to a constant or an 117990075Sobrien expression yielding a constant. This sets cfa_temp.reg 118090075Sobrien and cfa_temp.offset. 118190075Sobrien 118290075Sobrien Rule 5: Create a new register cfa_store used to save items to the 118390075Sobrien stack. 118490075Sobrien 118590075Sobrien Rules 10-14: Save a register to the stack. Define offset as the 118690075Sobrien difference of the original location and cfa_store's 118790075Sobrien location (or cfa_temp's location if cfa_temp is used). 118890075Sobrien 118990075Sobrien The Rules 119090075Sobrien 119190075Sobrien "{a,b}" indicates a choice of a xor b. 119290075Sobrien "<reg>:cfa.reg" indicates that <reg> must equal cfa.reg. 119390075Sobrien 119490075Sobrien Rule 1: 119590075Sobrien (set <reg1> <reg2>:cfa.reg) 119690075Sobrien effects: cfa.reg = <reg1> 119790075Sobrien cfa.offset unchanged 119890075Sobrien cfa_temp.reg = <reg1> 119990075Sobrien cfa_temp.offset = cfa.offset 120090075Sobrien 120190075Sobrien Rule 2: 120290075Sobrien (set sp ({minus,plus,losum} {sp,fp}:cfa.reg 120390075Sobrien {<const_int>,<reg>:cfa_temp.reg})) 120490075Sobrien effects: cfa.reg = sp if fp used 120590075Sobrien cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp 120690075Sobrien cfa_store.offset += {+/- <const_int>, cfa_temp.offset} 120790075Sobrien if cfa_store.reg==sp 120890075Sobrien 120990075Sobrien Rule 3: 121090075Sobrien (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>)) 121190075Sobrien effects: cfa.reg = fp 121290075Sobrien cfa_offset += +/- <const_int> 121390075Sobrien 121490075Sobrien Rule 4: 121590075Sobrien (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>)) 121690075Sobrien constraints: <reg1> != fp 121790075Sobrien <reg1> != sp 121890075Sobrien effects: cfa.reg = <reg1> 121990075Sobrien cfa_temp.reg = <reg1> 122090075Sobrien cfa_temp.offset = cfa.offset 122190075Sobrien 122290075Sobrien Rule 5: 122390075Sobrien (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg)) 122490075Sobrien constraints: <reg1> != fp 122590075Sobrien <reg1> != sp 122690075Sobrien effects: cfa_store.reg = <reg1> 122790075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset 122890075Sobrien 122990075Sobrien Rule 6: 123090075Sobrien (set <reg> <const_int>) 123190075Sobrien effects: cfa_temp.reg = <reg> 123290075Sobrien cfa_temp.offset = <const_int> 123390075Sobrien 123490075Sobrien Rule 7: 123590075Sobrien (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>)) 123690075Sobrien effects: cfa_temp.reg = <reg1> 123790075Sobrien cfa_temp.offset |= <const_int> 123890075Sobrien 123990075Sobrien Rule 8: 124090075Sobrien (set <reg> (high <exp>)) 124190075Sobrien effects: none 124290075Sobrien 124390075Sobrien Rule 9: 124490075Sobrien (set <reg> (lo_sum <exp> <const_int>)) 124590075Sobrien effects: cfa_temp.reg = <reg> 124690075Sobrien cfa_temp.offset = <const_int> 124790075Sobrien 124890075Sobrien Rule 10: 124990075Sobrien (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>) 125090075Sobrien effects: cfa_store.offset -= <const_int> 125190075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 125290075Sobrien cfa.reg = sp 125390075Sobrien cfa.base_offset = -cfa_store.offset 125490075Sobrien 125590075Sobrien Rule 11: 125690075Sobrien (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) <reg>) 125790075Sobrien effects: cfa_store.offset += -/+ mode_size(mem) 125890075Sobrien cfa.offset = cfa_store.offset if cfa.reg == sp 125990075Sobrien cfa.reg = sp 126090075Sobrien cfa.base_offset = -cfa_store.offset 126190075Sobrien 126290075Sobrien Rule 12: 126390075Sobrien (set (mem ({minus,plus,losum} <reg1>:{cfa_store,cfa_temp} <const_int>)) 126490075Sobrien 126590075Sobrien <reg2>) 126690075Sobrien effects: cfa.reg = <reg1> 126790075Sobrien cfa.base_offset = -/+ <const_int> - {cfa_store,cfa_temp}.offset 126890075Sobrien 126990075Sobrien Rule 13: 127090075Sobrien (set (mem <reg1>:{cfa_store,cfa_temp}) <reg2>) 127190075Sobrien effects: cfa.reg = <reg1> 127290075Sobrien cfa.base_offset = -{cfa_store,cfa_temp}.offset 127390075Sobrien 127490075Sobrien Rule 14: 127590075Sobrien (set (mem (postinc <reg1>:cfa_temp <const_int>)) <reg2>) 127690075Sobrien effects: cfa.reg = <reg1> 127790075Sobrien cfa.base_offset = -cfa_temp.offset 127890075Sobrien cfa_temp.offset -= mode_size(mem) */ 127990075Sobrien 128090075Sobrienstatic void 128152284Sobriendwarf2out_frame_debug_expr (expr, label) 128252284Sobrien rtx expr; 128390075Sobrien const char *label; 128450397Sobrien{ 128550397Sobrien rtx src, dest; 128690075Sobrien HOST_WIDE_INT offset; 128750397Sobrien 128890075Sobrien /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of 128990075Sobrien the PARALLEL independently. The first element is always processed if 129090075Sobrien it is a SET. This is for backward compatibility. Other elements 129190075Sobrien are processed only if they are SETs and the RTX_FRAME_RELATED_P 129290075Sobrien flag is set in them. */ 129390075Sobrien if (GET_CODE (expr) == PARALLEL || GET_CODE (expr) == SEQUENCE) 129490075Sobrien { 129552284Sobrien int par_index; 129652284Sobrien int limit = XVECLEN (expr, 0); 129750397Sobrien 129852284Sobrien for (par_index = 0; par_index < limit; par_index++) 129990075Sobrien if (GET_CODE (XVECEXP (expr, 0, par_index)) == SET 130090075Sobrien && (RTX_FRAME_RELATED_P (XVECEXP (expr, 0, par_index)) 130190075Sobrien || par_index == 0)) 130290075Sobrien dwarf2out_frame_debug_expr (XVECEXP (expr, 0, par_index), label); 130390075Sobrien 130450397Sobrien return; 130550397Sobrien } 130690075Sobrien 130752284Sobrien if (GET_CODE (expr) != SET) 130850397Sobrien abort (); 130950397Sobrien 131052284Sobrien src = SET_SRC (expr); 131152284Sobrien dest = SET_DEST (expr); 131250397Sobrien 131350397Sobrien switch (GET_CODE (dest)) 131450397Sobrien { 131550397Sobrien case REG: 131690075Sobrien /* Rule 1 */ 131750397Sobrien /* Update the CFA rule wrt SP or FP. Make sure src is 131852284Sobrien relative to the current CFA register. */ 131950397Sobrien switch (GET_CODE (src)) 132090075Sobrien { 132190075Sobrien /* Setting FP from SP. */ 132290075Sobrien case REG: 132390075Sobrien if (cfa.reg == (unsigned) REGNO (src)) 132490075Sobrien /* OK. */ 132590075Sobrien ; 132690075Sobrien else 132790075Sobrien abort (); 132850397Sobrien 132990075Sobrien /* We used to require that dest be either SP or FP, but the 133090075Sobrien ARM copies SP to a temporary register, and from there to 133190075Sobrien FP. So we just rely on the backends to only set 133290075Sobrien RTX_FRAME_RELATED_P on appropriate insns. */ 133390075Sobrien cfa.reg = REGNO (dest); 133490075Sobrien cfa_temp.reg = cfa.reg; 133590075Sobrien cfa_temp.offset = cfa.offset; 133690075Sobrien break; 133750397Sobrien 133890075Sobrien case PLUS: 133990075Sobrien case MINUS: 134090075Sobrien case LO_SUM: 134190075Sobrien if (dest == stack_pointer_rtx) 134290075Sobrien { 134390075Sobrien /* Rule 2 */ 134490075Sobrien /* Adjusting SP. */ 134590075Sobrien switch (GET_CODE (XEXP (src, 1))) 134690075Sobrien { 134790075Sobrien case CONST_INT: 134890075Sobrien offset = INTVAL (XEXP (src, 1)); 134990075Sobrien break; 135090075Sobrien case REG: 135190075Sobrien if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp.reg) 135290075Sobrien abort (); 135390075Sobrien offset = cfa_temp.offset; 135490075Sobrien break; 135590075Sobrien default: 135690075Sobrien abort (); 135790075Sobrien } 135850397Sobrien 135990075Sobrien if (XEXP (src, 0) == hard_frame_pointer_rtx) 136090075Sobrien { 136190075Sobrien /* Restoring SP from FP in the epilogue. */ 136290075Sobrien if (cfa.reg != (unsigned) HARD_FRAME_POINTER_REGNUM) 136390075Sobrien abort (); 136490075Sobrien cfa.reg = STACK_POINTER_REGNUM; 136590075Sobrien } 136690075Sobrien else if (GET_CODE (src) == LO_SUM) 136790075Sobrien /* Assume we've set the source reg of the LO_SUM from sp. */ 136890075Sobrien ; 136990075Sobrien else if (XEXP (src, 0) != stack_pointer_rtx) 137090075Sobrien abort (); 137150397Sobrien 137290075Sobrien if (GET_CODE (src) != MINUS) 137390075Sobrien offset = -offset; 137490075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 137590075Sobrien cfa.offset += offset; 137690075Sobrien if (cfa_store.reg == STACK_POINTER_REGNUM) 137790075Sobrien cfa_store.offset += offset; 137890075Sobrien } 137990075Sobrien else if (dest == hard_frame_pointer_rtx) 138090075Sobrien { 138190075Sobrien /* Rule 3 */ 138290075Sobrien /* Either setting the FP from an offset of the SP, 138390075Sobrien or adjusting the FP */ 138490075Sobrien if (! frame_pointer_needed) 138590075Sobrien abort (); 138650397Sobrien 138790075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 138890075Sobrien && (unsigned) REGNO (XEXP (src, 0)) == cfa.reg 138990075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 139090075Sobrien { 139190075Sobrien offset = INTVAL (XEXP (src, 1)); 139290075Sobrien if (GET_CODE (src) != MINUS) 139390075Sobrien offset = -offset; 139490075Sobrien cfa.offset += offset; 139590075Sobrien cfa.reg = HARD_FRAME_POINTER_REGNUM; 139690075Sobrien } 139790075Sobrien else 139890075Sobrien abort (); 139990075Sobrien } 140090075Sobrien else 140190075Sobrien { 140290075Sobrien if (GET_CODE (src) == MINUS) 140390075Sobrien abort (); 140450397Sobrien 140590075Sobrien /* Rule 4 */ 140690075Sobrien if (GET_CODE (XEXP (src, 0)) == REG 140790075Sobrien && REGNO (XEXP (src, 0)) == cfa.reg 140890075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 140990075Sobrien { 141090075Sobrien /* Setting a temporary CFA register that will be copied 141190075Sobrien into the FP later on. */ 141290075Sobrien offset = - INTVAL (XEXP (src, 1)); 141390075Sobrien cfa.offset += offset; 141490075Sobrien cfa.reg = REGNO (dest); 141590075Sobrien /* Or used to save regs to the stack. */ 141690075Sobrien cfa_temp.reg = cfa.reg; 141790075Sobrien cfa_temp.offset = cfa.offset; 141890075Sobrien } 141950397Sobrien 142090075Sobrien /* Rule 5 */ 142190075Sobrien else if (GET_CODE (XEXP (src, 0)) == REG 142290075Sobrien && REGNO (XEXP (src, 0)) == cfa_temp.reg 142390075Sobrien && XEXP (src, 1) == stack_pointer_rtx) 142490075Sobrien { 142590075Sobrien /* Setting a scratch register that we will use instead 142690075Sobrien of SP for saving registers to the stack. */ 142790075Sobrien if (cfa.reg != STACK_POINTER_REGNUM) 142890075Sobrien abort (); 142990075Sobrien cfa_store.reg = REGNO (dest); 143090075Sobrien cfa_store.offset = cfa.offset - cfa_temp.offset; 143190075Sobrien } 143250397Sobrien 143390075Sobrien /* Rule 9 */ 143490075Sobrien else if (GET_CODE (src) == LO_SUM 143590075Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 143690075Sobrien { 143790075Sobrien cfa_temp.reg = REGNO (dest); 143890075Sobrien cfa_temp.offset = INTVAL (XEXP (src, 1)); 143990075Sobrien } 144090075Sobrien else 144190075Sobrien abort (); 144290075Sobrien } 144390075Sobrien break; 144450397Sobrien 144590075Sobrien /* Rule 6 */ 144690075Sobrien case CONST_INT: 144790075Sobrien cfa_temp.reg = REGNO (dest); 144890075Sobrien cfa_temp.offset = INTVAL (src); 144990075Sobrien break; 145050397Sobrien 145190075Sobrien /* Rule 7 */ 145290075Sobrien case IOR: 145390075Sobrien if (GET_CODE (XEXP (src, 0)) != REG 145490075Sobrien || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg 145590075Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 145690075Sobrien abort (); 145750397Sobrien 145890075Sobrien if ((unsigned) REGNO (dest) != cfa_temp.reg) 145990075Sobrien cfa_temp.reg = REGNO (dest); 146090075Sobrien cfa_temp.offset |= INTVAL (XEXP (src, 1)); 146190075Sobrien break; 146250397Sobrien 146390075Sobrien /* Skip over HIGH, assuming it will be followed by a LO_SUM, 146490075Sobrien which will fill in all of the bits. */ 146590075Sobrien /* Rule 8 */ 146690075Sobrien case HIGH: 146790075Sobrien break; 146850397Sobrien 146990075Sobrien default: 147090075Sobrien abort (); 147190075Sobrien } 147250397Sobrien 147390075Sobrien def_cfa_1 (label, &cfa); 147490075Sobrien break; 147550397Sobrien 147690075Sobrien case MEM: 147790075Sobrien if (GET_CODE (src) != REG) 147890075Sobrien abort (); 147952284Sobrien 148090075Sobrien /* Saving a register to the stack. Make sure dest is relative to the 148190075Sobrien CFA register. */ 148290075Sobrien switch (GET_CODE (XEXP (dest, 0))) 148390075Sobrien { 148490075Sobrien /* Rule 10 */ 148590075Sobrien /* With a push. */ 148690075Sobrien case PRE_MODIFY: 148790075Sobrien /* We can't handle variable size modifications. */ 148890075Sobrien if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT) 148990075Sobrien abort (); 149090075Sobrien offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)); 149190075Sobrien 149290075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 149390075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 149490075Sobrien abort (); 149590075Sobrien 149690075Sobrien cfa_store.offset += offset; 149790075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 149890075Sobrien cfa.offset = cfa_store.offset; 149990075Sobrien 150090075Sobrien offset = -cfa_store.offset; 150190075Sobrien break; 150290075Sobrien 150390075Sobrien /* Rule 11 */ 150490075Sobrien case PRE_INC: 150590075Sobrien case PRE_DEC: 150690075Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 150790075Sobrien if (GET_CODE (XEXP (dest, 0)) == PRE_INC) 150890075Sobrien offset = -offset; 150990075Sobrien 151090075Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 151190075Sobrien || cfa_store.reg != STACK_POINTER_REGNUM) 151290075Sobrien abort (); 151390075Sobrien 151490075Sobrien cfa_store.offset += offset; 151590075Sobrien if (cfa.reg == STACK_POINTER_REGNUM) 151690075Sobrien cfa.offset = cfa_store.offset; 151790075Sobrien 151890075Sobrien offset = -cfa_store.offset; 151990075Sobrien break; 152090075Sobrien 152190075Sobrien /* Rule 12 */ 152290075Sobrien /* With an offset. */ 152390075Sobrien case PLUS: 152490075Sobrien case MINUS: 152590075Sobrien case LO_SUM: 152690075Sobrien if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT) 152790075Sobrien abort (); 152890075Sobrien offset = INTVAL (XEXP (XEXP (dest, 0), 1)); 152990075Sobrien if (GET_CODE (XEXP (dest, 0)) == MINUS) 153090075Sobrien offset = -offset; 153190075Sobrien 153290075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153390075Sobrien offset -= cfa_store.offset; 153490075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 153590075Sobrien offset -= cfa_temp.offset; 153690075Sobrien else 153790075Sobrien abort (); 153890075Sobrien break; 153990075Sobrien 154090075Sobrien /* Rule 13 */ 154190075Sobrien /* Without an offset. */ 154290075Sobrien case REG: 154390075Sobrien if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0))) 154490075Sobrien offset = -cfa_store.offset; 154590075Sobrien else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0))) 154690075Sobrien offset = -cfa_temp.offset; 154790075Sobrien else 154890075Sobrien abort (); 154990075Sobrien break; 155090075Sobrien 155190075Sobrien /* Rule 14 */ 155290075Sobrien case POST_INC: 155390075Sobrien if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 155490075Sobrien abort (); 155590075Sobrien offset = -cfa_temp.offset; 155690075Sobrien cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest)); 155790075Sobrien break; 155890075Sobrien 155990075Sobrien default: 156090075Sobrien abort (); 156190075Sobrien } 156290075Sobrien 156390075Sobrien if (REGNO (src) != STACK_POINTER_REGNUM 156490075Sobrien && REGNO (src) != HARD_FRAME_POINTER_REGNUM 156590075Sobrien && (unsigned) REGNO (src) == cfa.reg) 156690075Sobrien { 156790075Sobrien /* We're storing the current CFA reg into the stack. */ 156890075Sobrien 156990075Sobrien if (cfa.offset == 0) 157090075Sobrien { 157190075Sobrien /* If the source register is exactly the CFA, assume 157290075Sobrien we're saving SP like any other register; this happens 157390075Sobrien on the ARM. */ 157490075Sobrien def_cfa_1 (label, &cfa); 157590075Sobrien queue_reg_save (label, stack_pointer_rtx, offset); 157690075Sobrien break; 157790075Sobrien } 157890075Sobrien else 157990075Sobrien { 158090075Sobrien /* Otherwise, we'll need to look in the stack to 158190075Sobrien calculate the CFA. */ 158290075Sobrien rtx x = XEXP (dest, 0); 158390075Sobrien 158490075Sobrien if (GET_CODE (x) != REG) 158590075Sobrien x = XEXP (x, 0); 158690075Sobrien if (GET_CODE (x) != REG) 158790075Sobrien abort (); 158890075Sobrien 158990075Sobrien cfa.reg = REGNO (x); 159090075Sobrien cfa.base_offset = offset; 159190075Sobrien cfa.indirect = 1; 159290075Sobrien def_cfa_1 (label, &cfa); 159390075Sobrien break; 159490075Sobrien } 159590075Sobrien } 159690075Sobrien 159790075Sobrien def_cfa_1 (label, &cfa); 159890075Sobrien queue_reg_save (label, src, offset); 159990075Sobrien break; 160090075Sobrien 160190075Sobrien default: 160290075Sobrien abort (); 160390075Sobrien } 160452284Sobrien} 160552284Sobrien 160652284Sobrien/* Record call frame debugging information for INSN, which either 160752284Sobrien sets SP or FP (adjusting how we calculate the frame address) or saves a 160852284Sobrien register to the stack. If INSN is NULL_RTX, initialize our state. */ 160952284Sobrien 161052284Sobrienvoid 161152284Sobriendwarf2out_frame_debug (insn) 161252284Sobrien rtx insn; 161352284Sobrien{ 161490075Sobrien const char *label; 161552284Sobrien rtx src; 161652284Sobrien 161752284Sobrien if (insn == NULL_RTX) 161852284Sobrien { 161990075Sobrien /* Flush any queued register saves. */ 162090075Sobrien flush_queued_reg_saves (); 162190075Sobrien 162252284Sobrien /* Set up state for generating call frame debug info. */ 162390075Sobrien lookup_cfa (&cfa); 162490075Sobrien if (cfa.reg != (unsigned long) DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)) 162552284Sobrien abort (); 162690075Sobrien 162790075Sobrien cfa.reg = STACK_POINTER_REGNUM; 162890075Sobrien cfa_store = cfa; 162990075Sobrien cfa_temp.reg = -1; 163090075Sobrien cfa_temp.offset = 0; 163152284Sobrien return; 163250397Sobrien } 163352284Sobrien 163490075Sobrien if (GET_CODE (insn) != INSN || clobbers_queued_reg_save (insn)) 163590075Sobrien flush_queued_reg_saves (); 163690075Sobrien 163752284Sobrien if (! RTX_FRAME_RELATED_P (insn)) 163852284Sobrien { 163990075Sobrien if (!ACCUMULATE_OUTGOING_ARGS) 164090075Sobrien dwarf2out_stack_adjust (insn); 164190075Sobrien 164252284Sobrien return; 164352284Sobrien } 164452284Sobrien 164552284Sobrien label = dwarf2out_cfi_label (); 164652284Sobrien src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 164752284Sobrien if (src) 164852284Sobrien insn = XEXP (src, 0); 164990075Sobrien else 165052284Sobrien insn = PATTERN (insn); 165152284Sobrien 165252284Sobrien dwarf2out_frame_debug_expr (insn, label); 165350397Sobrien} 165450397Sobrien 165550397Sobrien/* Output a Call Frame Information opcode and its operand(s). */ 165650397Sobrien 165750397Sobrienstatic void 165890075Sobrienoutput_cfi (cfi, fde, for_eh) 165990075Sobrien dw_cfi_ref cfi; 166090075Sobrien dw_fde_ref fde; 166190075Sobrien int for_eh; 166250397Sobrien{ 166350397Sobrien if (cfi->dw_cfi_opc == DW_CFA_advance_loc) 166490075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 166590075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)), 166690075Sobrien "DW_CFA_advance_loc 0x%lx", 166790075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset); 166850397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_offset) 166950397Sobrien { 167090075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167190075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 167290075Sobrien "DW_CFA_offset, column 0x%lx", 167390075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 167490075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 167550397Sobrien } 167650397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_restore) 167790075Sobrien dw2_asm_output_data (1, (cfi->dw_cfi_opc 167890075Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), 167990075Sobrien "DW_CFA_restore, column 0x%lx", 168090075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 168150397Sobrien else 168250397Sobrien { 168390075Sobrien dw2_asm_output_data (1, cfi->dw_cfi_opc, 168490075Sobrien "%s", dwarf_cfi_name (cfi->dw_cfi_opc)); 168550397Sobrien 168650397Sobrien switch (cfi->dw_cfi_opc) 168750397Sobrien { 168850397Sobrien case DW_CFA_set_loc: 168990075Sobrien if (for_eh) 169090075Sobrien dw2_asm_output_encoded_addr_rtx ( 169190075Sobrien ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0), 169290075Sobrien gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr), 169390075Sobrien NULL); 169490075Sobrien else 169590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, 169690075Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL); 169750397Sobrien break; 169890075Sobrien 169950397Sobrien case DW_CFA_advance_loc1: 170090075Sobrien dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170190075Sobrien fde->dw_fde_current_label, NULL); 170250397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 170350397Sobrien break; 170490075Sobrien 170550397Sobrien case DW_CFA_advance_loc2: 170690075Sobrien dw2_asm_output_delta (2, cfi->dw_cfi_oprnd1.dw_cfi_addr, 170790075Sobrien fde->dw_fde_current_label, NULL); 170850397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 170950397Sobrien break; 171090075Sobrien 171150397Sobrien case DW_CFA_advance_loc4: 171290075Sobrien dw2_asm_output_delta (4, cfi->dw_cfi_oprnd1.dw_cfi_addr, 171390075Sobrien fde->dw_fde_current_label, NULL); 171450397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 171550397Sobrien break; 171690075Sobrien 171750397Sobrien case DW_CFA_MIPS_advance_loc8: 171890075Sobrien dw2_asm_output_delta (8, cfi->dw_cfi_oprnd1.dw_cfi_addr, 171990075Sobrien fde->dw_fde_current_label, NULL); 172090075Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 172150397Sobrien break; 172290075Sobrien 172350397Sobrien case DW_CFA_offset_extended: 172450397Sobrien case DW_CFA_def_cfa: 172590075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 172690075Sobrien NULL); 172790075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 172850397Sobrien break; 172990075Sobrien 173090075Sobrien case DW_CFA_offset_extended_sf: 173190075Sobrien case DW_CFA_def_cfa_sf: 173290075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 173390075Sobrien NULL); 173490075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); 173590075Sobrien break; 173690075Sobrien 173750397Sobrien case DW_CFA_restore_extended: 173850397Sobrien case DW_CFA_undefined: 173950397Sobrien case DW_CFA_same_value: 174050397Sobrien case DW_CFA_def_cfa_register: 174190075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174290075Sobrien NULL); 174350397Sobrien break; 174490075Sobrien 174550397Sobrien case DW_CFA_register: 174690075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 174790075Sobrien NULL); 174890075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, 174990075Sobrien NULL); 175050397Sobrien break; 175190075Sobrien 175250397Sobrien case DW_CFA_def_cfa_offset: 175390075Sobrien case DW_CFA_GNU_args_size: 175490075Sobrien dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 175550397Sobrien break; 175690075Sobrien 175790075Sobrien case DW_CFA_def_cfa_offset_sf: 175890075Sobrien dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL); 175990075Sobrien break; 176090075Sobrien 176150397Sobrien case DW_CFA_GNU_window_save: 176250397Sobrien break; 176390075Sobrien 176490075Sobrien case DW_CFA_def_cfa_expression: 176590075Sobrien case DW_CFA_expression: 176690075Sobrien output_cfa_loc (cfi); 176750397Sobrien break; 176890075Sobrien 176990075Sobrien case DW_CFA_GNU_negative_offset_extended: 177090075Sobrien /* Obsoleted by DW_CFA_offset_extended_sf. */ 177190075Sobrien abort (); 177290075Sobrien 177350397Sobrien default: 177450397Sobrien break; 177550397Sobrien } 177690075Sobrien } 177750397Sobrien} 177850397Sobrien 177950397Sobrien/* Output the call frame information used to used to record information 178050397Sobrien that relates to calculating the frame pointer, and records the 178150397Sobrien location of saved registers. */ 178250397Sobrien 178350397Sobrienstatic void 178450397Sobrienoutput_call_frame_info (for_eh) 178550397Sobrien int for_eh; 178650397Sobrien{ 178790075Sobrien unsigned int i; 178890075Sobrien dw_fde_ref fde; 178990075Sobrien dw_cfi_ref cfi; 179090075Sobrien char l1[20], l2[20], section_start_label[20]; 179190075Sobrien int any_lsda_needed = 0; 179290075Sobrien char augmentation[6]; 179390075Sobrien int augmentation_size; 179490075Sobrien int fde_encoding = DW_EH_PE_absptr; 179590075Sobrien int per_encoding = DW_EH_PE_absptr; 179690075Sobrien int lsda_encoding = DW_EH_PE_absptr; 179750397Sobrien 179890075Sobrien /* If we don't have any functions we'll want to unwind out of, don't emit any 179990075Sobrien EH unwind information. */ 180090075Sobrien if (for_eh) 180190075Sobrien { 180290075Sobrien int any_eh_needed = flag_asynchronous_unwind_tables; 180350397Sobrien 180490075Sobrien for (i = 0; i < fde_table_in_use; i++) 180590075Sobrien if (fde_table[i].uses_eh_lsda) 180690075Sobrien any_eh_needed = any_lsda_needed = 1; 180790075Sobrien else if (! fde_table[i].nothrow) 180890075Sobrien any_eh_needed = 1; 180950397Sobrien 181090075Sobrien if (! any_eh_needed) 181190075Sobrien return; 181290075Sobrien } 181390075Sobrien 181450397Sobrien /* We're going to be generating comments, so turn on app. */ 181550397Sobrien if (flag_debug_asm) 181650397Sobrien app_enable (); 181750397Sobrien 181850397Sobrien if (for_eh) 181990075Sobrien (*targetm.asm_out.eh_frame_section) (); 182050397Sobrien else 182190075Sobrien named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG); 182250397Sobrien 182390075Sobrien ASM_GENERATE_INTERNAL_LABEL (section_start_label, FRAME_BEGIN_LABEL, for_eh); 182490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, section_start_label); 182590075Sobrien 182690075Sobrien /* Output the CIE. */ 182750397Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); 182850397Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); 182990075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 183090075Sobrien "Length of Common Information Entry"); 183150397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 183250397Sobrien 183390075Sobrien /* Now that the CIE pointer is PC-relative for EH, 183490075Sobrien use 0 to identify the CIE. */ 183590075Sobrien dw2_asm_output_data ((for_eh ? 4 : DWARF_OFFSET_SIZE), 183690075Sobrien (for_eh ? 0 : DW_CIE_ID), 183790075Sobrien "CIE Identifier Tag"); 183850397Sobrien 183990075Sobrien dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version"); 184050397Sobrien 184190075Sobrien augmentation[0] = 0; 184290075Sobrien augmentation_size = 0; 184390075Sobrien if (for_eh) 184450397Sobrien { 184590075Sobrien char *p; 184650397Sobrien 184790075Sobrien /* Augmentation: 184890075Sobrien z Indicates that a uleb128 is present to size the 184990075Sobrien augmentation section. 185090075Sobrien L Indicates the encoding (and thus presence) of 185190075Sobrien an LSDA pointer in the FDE augmentation. 185290075Sobrien R Indicates a non-default pointer encoding for 185390075Sobrien FDE code pointers. 185490075Sobrien P Indicates the presence of an encoding + language 185590075Sobrien personality routine in the CIE augmentation. */ 185650397Sobrien 185790075Sobrien fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0); 185890075Sobrien per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); 185990075Sobrien lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); 186090075Sobrien 186190075Sobrien p = augmentation + 1; 186290075Sobrien if (eh_personality_libfunc) 186350397Sobrien { 186490075Sobrien *p++ = 'P'; 186590075Sobrien augmentation_size += 1 + size_of_encoded_value (per_encoding); 186650397Sobrien } 186790075Sobrien if (any_lsda_needed) 186850397Sobrien { 186990075Sobrien *p++ = 'L'; 187090075Sobrien augmentation_size += 1; 187150397Sobrien } 187290075Sobrien if (fde_encoding != DW_EH_PE_absptr) 187390075Sobrien { 187490075Sobrien *p++ = 'R'; 187590075Sobrien augmentation_size += 1; 187690075Sobrien } 187790075Sobrien if (p > augmentation + 1) 187890075Sobrien { 187990075Sobrien augmentation[0] = 'z'; 188090075Sobrien *p = '\0'; 188190075Sobrien } 188250397Sobrien 188390075Sobrien /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ 188490075Sobrien if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) 188590075Sobrien { 188690075Sobrien int offset = ( 4 /* Length */ 188790075Sobrien + 4 /* CIE Id */ 188890075Sobrien + 1 /* CIE version */ 188990075Sobrien + strlen (augmentation) + 1 /* Augmentation */ 189090075Sobrien + size_of_uleb128 (1) /* Code alignment */ 189190075Sobrien + size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT) 189290075Sobrien + 1 /* RA column */ 189390075Sobrien + 1 /* Augmentation size */ 189490075Sobrien + 1 /* Personality encoding */ ); 189590075Sobrien int pad = -offset & (PTR_SIZE - 1); 189690075Sobrien 189790075Sobrien augmentation_size += pad; 189890075Sobrien 189990075Sobrien /* Augmentations should be small, so there's scarce need to 190090075Sobrien iterate for a solution. Die if we exceed one uleb128 byte. */ 190190075Sobrien if (size_of_uleb128 (augmentation_size) != 1) 190290075Sobrien abort (); 190390075Sobrien } 190450397Sobrien } 190550397Sobrien 190690075Sobrien dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); 190790075Sobrien dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); 190890075Sobrien dw2_asm_output_data_sleb128 (DWARF_CIE_DATA_ALIGNMENT, 190990075Sobrien "CIE Data Alignment Factor"); 191090075Sobrien dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column"); 191150397Sobrien 191290075Sobrien if (augmentation[0]) 191390075Sobrien { 191490075Sobrien dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); 191590075Sobrien if (eh_personality_libfunc) 191690075Sobrien { 191790075Sobrien dw2_asm_output_data (1, per_encoding, "Personality (%s)", 191890075Sobrien eh_data_format_name (per_encoding)); 191990075Sobrien dw2_asm_output_encoded_addr_rtx (per_encoding, 192090075Sobrien eh_personality_libfunc, NULL); 192190075Sobrien } 192250397Sobrien 192390075Sobrien if (any_lsda_needed) 192490075Sobrien dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)", 192590075Sobrien eh_data_format_name (lsda_encoding)); 192650397Sobrien 192790075Sobrien if (fde_encoding != DW_EH_PE_absptr) 192890075Sobrien dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)", 192990075Sobrien eh_data_format_name (fde_encoding)); 193090075Sobrien } 193150397Sobrien 193250397Sobrien for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next) 193390075Sobrien output_cfi (cfi, NULL, for_eh); 193450397Sobrien 193550397Sobrien /* Pad the CIE out to an address sized boundary. */ 193690075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 193790075Sobrien floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)); 193850397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 193950397Sobrien 194050397Sobrien /* Loop through all of the FDE's. */ 194190075Sobrien for (i = 0; i < fde_table_in_use; i++) 194250397Sobrien { 194350397Sobrien fde = &fde_table[i]; 194450397Sobrien 194590075Sobrien /* Don't emit EH unwind info for leaf functions that don't need it. */ 194690075Sobrien if (for_eh && fde->nothrow && ! fde->uses_eh_lsda) 194790075Sobrien continue; 194890075Sobrien 194990075Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2); 195090075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2); 195190075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2); 195290075Sobrien dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, 195390075Sobrien "FDE Length"); 195490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 195590075Sobrien 195650397Sobrien if (for_eh) 195790075Sobrien dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset"); 195850397Sobrien else 195990075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label, 196090075Sobrien "FDE CIE offset"); 196150397Sobrien 196250397Sobrien if (for_eh) 196390075Sobrien { 196490075Sobrien dw2_asm_output_encoded_addr_rtx (fde_encoding, 196590075Sobrien gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin), 196690075Sobrien "FDE initial location"); 196790075Sobrien dw2_asm_output_delta (size_of_encoded_value (fde_encoding), 196890075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 196990075Sobrien "FDE address range"); 197090075Sobrien } 197150397Sobrien else 197290075Sobrien { 197390075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, 197490075Sobrien "FDE initial location"); 197590075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, 197690075Sobrien fde->dw_fde_end, fde->dw_fde_begin, 197790075Sobrien "FDE address range"); 197890075Sobrien } 197950397Sobrien 198090075Sobrien if (augmentation[0]) 198190075Sobrien { 198290075Sobrien if (any_lsda_needed) 198390075Sobrien { 198490075Sobrien int size = size_of_encoded_value (lsda_encoding); 198550397Sobrien 198690075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 198790075Sobrien { 198890075Sobrien int offset = ( 4 /* Length */ 198990075Sobrien + 4 /* CIE offset */ 199090075Sobrien + 2 * size_of_encoded_value (fde_encoding) 199190075Sobrien + 1 /* Augmentation size */ ); 199290075Sobrien int pad = -offset & (PTR_SIZE - 1); 199350397Sobrien 199490075Sobrien size += pad; 199590075Sobrien if (size_of_uleb128 (size) != 1) 199690075Sobrien abort (); 199790075Sobrien } 199850397Sobrien 199990075Sobrien dw2_asm_output_data_uleb128 (size, "Augmentation size"); 200090075Sobrien 200190075Sobrien if (fde->uses_eh_lsda) 200290075Sobrien { 200390075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", 200490075Sobrien fde->funcdef_number); 200590075Sobrien dw2_asm_output_encoded_addr_rtx ( 200690075Sobrien lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1), 200790075Sobrien "Language Specific Data Area"); 200890075Sobrien } 200990075Sobrien else 201090075Sobrien { 201190075Sobrien if (lsda_encoding == DW_EH_PE_aligned) 201290075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 201390075Sobrien dw2_asm_output_data 201490075Sobrien (size_of_encoded_value (lsda_encoding), 0, 201590075Sobrien "Language Specific Data Area (none)"); 201690075Sobrien } 201790075Sobrien } 201890075Sobrien else 201990075Sobrien dw2_asm_output_data_uleb128 (0, "Augmentation size"); 202090075Sobrien } 202190075Sobrien 202250397Sobrien /* Loop through the Call Frame Instructions associated with 202350397Sobrien this FDE. */ 202450397Sobrien fde->dw_fde_current_label = fde->dw_fde_begin; 202550397Sobrien for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) 202690075Sobrien output_cfi (cfi, fde, for_eh); 202750397Sobrien 202850397Sobrien /* Pad the FDE out to an address sized boundary. */ 202990075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 203090075Sobrien floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); 203150397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 203250397Sobrien } 203390075Sobrien 203490075Sobrien#ifndef EH_FRAME_SECTION_NAME 203550397Sobrien if (for_eh) 203690075Sobrien dw2_asm_output_data (4, 0, "End of Table"); 203750397Sobrien#endif 203850397Sobrien#ifdef MIPS_DEBUGGING_INFO 203950397Sobrien /* Work around Irix 6 assembler bug whereby labels at the end of a section 204050397Sobrien get a value of 0. Putting .align 0 after the label fixes it. */ 204150397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 0); 204250397Sobrien#endif 204350397Sobrien 204450397Sobrien /* Turn off app to make assembly quicker. */ 204550397Sobrien if (flag_debug_asm) 204650397Sobrien app_disable (); 204750397Sobrien} 204850397Sobrien 204950397Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before 205050397Sobrien the prologue. */ 205150397Sobrien 205250397Sobrienvoid 205390075Sobriendwarf2out_begin_prologue (line, file) 205490075Sobrien unsigned int line ATTRIBUTE_UNUSED; 205590075Sobrien const char *file ATTRIBUTE_UNUSED; 205650397Sobrien{ 205750397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 205890075Sobrien dw_fde_ref fde; 205950397Sobrien 206090075Sobrien current_function_func_begin_label = 0; 206150397Sobrien 206290075Sobrien#ifdef IA64_UNWIND_INFO 206390075Sobrien /* ??? current_function_func_begin_label is also used by except.c 206490075Sobrien for call-site information. We must emit this label if it might 206590075Sobrien be used. */ 206690075Sobrien if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS) 206790075Sobrien && ! dwarf2out_do_frame ()) 206890075Sobrien return; 206990075Sobrien#else 207090075Sobrien if (! dwarf2out_do_frame ()) 207190075Sobrien return; 207290075Sobrien#endif 207390075Sobrien 207490075Sobrien current_funcdef_number++; 207550397Sobrien function_section (current_function_decl); 207650397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 207750397Sobrien current_funcdef_number); 207890075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL, 207990075Sobrien current_funcdef_number); 208090075Sobrien current_function_func_begin_label = get_identifier (label); 208150397Sobrien 208290075Sobrien#ifdef IA64_UNWIND_INFO 208390075Sobrien /* We can elide the fde allocation if we're not emitting debug info. */ 208490075Sobrien if (! dwarf2out_do_frame ()) 208590075Sobrien return; 208690075Sobrien#endif 208790075Sobrien 208850397Sobrien /* Expand the fde table if necessary. */ 208950397Sobrien if (fde_table_in_use == fde_table_allocated) 209050397Sobrien { 209150397Sobrien fde_table_allocated += FDE_TABLE_INCREMENT; 209250397Sobrien fde_table 209350397Sobrien = (dw_fde_ref) xrealloc (fde_table, 209450397Sobrien fde_table_allocated * sizeof (dw_fde_node)); 209550397Sobrien } 209650397Sobrien 209750397Sobrien /* Record the FDE associated with this function. */ 209850397Sobrien current_funcdef_fde = fde_table_in_use; 209950397Sobrien 210050397Sobrien /* Add the new FDE at the end of the fde_table. */ 210150397Sobrien fde = &fde_table[fde_table_in_use++]; 210250397Sobrien fde->dw_fde_begin = xstrdup (label); 210350397Sobrien fde->dw_fde_current_label = NULL; 210450397Sobrien fde->dw_fde_end = NULL; 210550397Sobrien fde->dw_fde_cfi = NULL; 210690075Sobrien fde->funcdef_number = current_funcdef_number; 210790075Sobrien fde->nothrow = current_function_nothrow; 210890075Sobrien fde->uses_eh_lsda = cfun->uses_eh_lsda; 210950397Sobrien 211050397Sobrien args_size = old_args_size = 0; 211190075Sobrien 211290075Sobrien /* We only want to output line number information for the genuine dwarf2 211390075Sobrien prologue case, not the eh frame case. */ 211490075Sobrien#ifdef DWARF2_DEBUGGING_INFO 211590075Sobrien if (file) 211690075Sobrien dwarf2out_source_line (line, file); 211790075Sobrien#endif 211850397Sobrien} 211950397Sobrien 212050397Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code 212150397Sobrien for a function definition. This gets called *after* the epilogue code has 212250397Sobrien been generated. */ 212350397Sobrien 212450397Sobrienvoid 212550397Sobriendwarf2out_end_epilogue () 212650397Sobrien{ 212750397Sobrien dw_fde_ref fde; 212850397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 212950397Sobrien 213050397Sobrien /* Output a label to mark the endpoint of the code generated for this 213190075Sobrien function. */ 213250397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number); 213350397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 213450397Sobrien fde = &fde_table[fde_table_in_use - 1]; 213550397Sobrien fde->dw_fde_end = xstrdup (label); 213650397Sobrien} 213750397Sobrien 213850397Sobrienvoid 213950397Sobriendwarf2out_frame_init () 214050397Sobrien{ 214150397Sobrien /* Allocate the initial hunk of the fde_table. */ 214290075Sobrien fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node)); 214350397Sobrien fde_table_allocated = FDE_TABLE_INCREMENT; 214450397Sobrien fde_table_in_use = 0; 214550397Sobrien 214650397Sobrien /* Generate the CFA instructions common to all FDE's. Do it now for the 214750397Sobrien sake of lookup_cfa. */ 214850397Sobrien 214950397Sobrien#ifdef DWARF2_UNWIND_INFO 215050397Sobrien /* On entry, the Canonical Frame Address is at SP. */ 215150397Sobrien dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); 215250397Sobrien initial_return_save (INCOMING_RETURN_ADDR_RTX); 215350397Sobrien#endif 215450397Sobrien} 215550397Sobrien 215650397Sobrienvoid 215750397Sobriendwarf2out_frame_finish () 215850397Sobrien{ 215950397Sobrien /* Output call frame information. */ 216090075Sobrien if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) 216150397Sobrien output_call_frame_info (0); 216290075Sobrien 216390075Sobrien if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions)) 216450397Sobrien output_call_frame_info (1); 216590075Sobrien} 216690075Sobrien 216790075Sobrien/* And now, the subset of the debugging information support code necessary 216890075Sobrien for emitting location expressions. */ 216950397Sobrien 217090075Sobrientypedef struct dw_val_struct *dw_val_ref; 217190075Sobrientypedef struct die_struct *dw_die_ref; 217290075Sobrientypedef struct dw_loc_descr_struct *dw_loc_descr_ref; 217390075Sobrientypedef struct dw_loc_list_struct *dw_loc_list_ref; 217450397Sobrien 217550397Sobrien/* Each DIE may have a series of attribute/value pairs. Values 217650397Sobrien can take on several forms. The forms that are used in this 217750397Sobrien implementation are listed below. */ 217850397Sobrien 217950397Sobrientypedef enum 218050397Sobrien{ 218150397Sobrien dw_val_class_addr, 218290075Sobrien dw_val_class_offset, 218350397Sobrien dw_val_class_loc, 218490075Sobrien dw_val_class_loc_list, 218590075Sobrien dw_val_class_range_list, 218650397Sobrien dw_val_class_const, 218750397Sobrien dw_val_class_unsigned_const, 218850397Sobrien dw_val_class_long_long, 218950397Sobrien dw_val_class_float, 219050397Sobrien dw_val_class_flag, 219150397Sobrien dw_val_class_die_ref, 219250397Sobrien dw_val_class_fde_ref, 219350397Sobrien dw_val_class_lbl_id, 219452284Sobrien dw_val_class_lbl_offset, 219550397Sobrien dw_val_class_str 219650397Sobrien} 219750397Sobriendw_val_class; 219850397Sobrien 219950397Sobrien/* Describe a double word constant value. */ 220090075Sobrien/* ??? Every instance of long_long in the code really means CONST_DOUBLE. */ 220150397Sobrien 220250397Sobrientypedef struct dw_long_long_struct 220350397Sobrien{ 220450397Sobrien unsigned long hi; 220550397Sobrien unsigned long low; 220650397Sobrien} 220750397Sobriendw_long_long_const; 220850397Sobrien 220950397Sobrien/* Describe a floating point constant value. */ 221050397Sobrien 221150397Sobrientypedef struct dw_fp_struct 221250397Sobrien{ 221350397Sobrien long *array; 221450397Sobrien unsigned length; 221550397Sobrien} 221650397Sobriendw_float_const; 221750397Sobrien 221850397Sobrien/* The dw_val_node describes an attribute's value, as it is 221950397Sobrien represented internally. */ 222050397Sobrien 222150397Sobrientypedef struct dw_val_struct 222250397Sobrien{ 222350397Sobrien dw_val_class val_class; 222450397Sobrien union 222550397Sobrien { 222690075Sobrien rtx val_addr; 222790075Sobrien long unsigned val_offset; 222890075Sobrien dw_loc_list_ref val_loc_list; 222950397Sobrien dw_loc_descr_ref val_loc; 223050397Sobrien long int val_int; 223150397Sobrien long unsigned val_unsigned; 223250397Sobrien dw_long_long_const val_long_long; 223350397Sobrien dw_float_const val_float; 223490075Sobrien struct 223590075Sobrien { 223690075Sobrien dw_die_ref die; 223790075Sobrien int external; 223890075Sobrien } val_die_ref; 223950397Sobrien unsigned val_fde_index; 224090075Sobrien struct indirect_string_node *val_str; 224150397Sobrien char *val_lbl_id; 224250397Sobrien unsigned char val_flag; 224350397Sobrien } 224450397Sobrien v; 224550397Sobrien} 224650397Sobriendw_val_node; 224750397Sobrien 224850397Sobrien/* Locations in memory are described using a sequence of stack machine 224950397Sobrien operations. */ 225050397Sobrien 225150397Sobrientypedef struct dw_loc_descr_struct 225250397Sobrien{ 225350397Sobrien dw_loc_descr_ref dw_loc_next; 225450397Sobrien enum dwarf_location_atom dw_loc_opc; 225550397Sobrien dw_val_node dw_loc_oprnd1; 225650397Sobrien dw_val_node dw_loc_oprnd2; 225790075Sobrien int dw_loc_addr; 225850397Sobrien} 225950397Sobriendw_loc_descr_node; 226050397Sobrien 226190075Sobrien/* Location lists are ranges + location descriptions for that range, 226290075Sobrien so you can track variables that are in different places over 226390075Sobrien their entire life. */ 226490075Sobrientypedef struct dw_loc_list_struct 226590075Sobrien{ 226690075Sobrien dw_loc_list_ref dw_loc_next; 226790075Sobrien const char *begin; /* Label for begin address of range */ 226890075Sobrien const char *end; /* Label for end address of range */ 226990075Sobrien char *ll_symbol; /* Label for beginning of location list. 227090075Sobrien Only on head of list */ 227190075Sobrien const char *section; /* Section this loclist is relative to */ 227290075Sobrien dw_loc_descr_ref expr; 227390075Sobrien} dw_loc_list_node; 227490075Sobrien 227590075Sobrienstatic const char *dwarf_stack_op_name PARAMS ((unsigned)); 227690075Sobrienstatic dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom, 227790075Sobrien unsigned long, 227890075Sobrien unsigned long)); 227990075Sobrienstatic void add_loc_descr PARAMS ((dw_loc_descr_ref *, 228090075Sobrien dw_loc_descr_ref)); 228190075Sobrienstatic unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref)); 228290075Sobrienstatic unsigned long size_of_locs PARAMS ((dw_loc_descr_ref)); 228390075Sobrienstatic void output_loc_operands PARAMS ((dw_loc_descr_ref)); 228490075Sobrienstatic void output_loc_sequence PARAMS ((dw_loc_descr_ref)); 228590075Sobrien 228690075Sobrien/* Convert a DWARF stack opcode into its string name. */ 228790075Sobrien 228890075Sobrienstatic const char * 228990075Sobriendwarf_stack_op_name (op) 229090075Sobrien unsigned op; 229190075Sobrien{ 229290075Sobrien switch (op) 229390075Sobrien { 229490075Sobrien case DW_OP_addr: 229590075Sobrien return "DW_OP_addr"; 229690075Sobrien case DW_OP_deref: 229790075Sobrien return "DW_OP_deref"; 229890075Sobrien case DW_OP_const1u: 229990075Sobrien return "DW_OP_const1u"; 230090075Sobrien case DW_OP_const1s: 230190075Sobrien return "DW_OP_const1s"; 230290075Sobrien case DW_OP_const2u: 230390075Sobrien return "DW_OP_const2u"; 230490075Sobrien case DW_OP_const2s: 230590075Sobrien return "DW_OP_const2s"; 230690075Sobrien case DW_OP_const4u: 230790075Sobrien return "DW_OP_const4u"; 230890075Sobrien case DW_OP_const4s: 230990075Sobrien return "DW_OP_const4s"; 231090075Sobrien case DW_OP_const8u: 231190075Sobrien return "DW_OP_const8u"; 231290075Sobrien case DW_OP_const8s: 231390075Sobrien return "DW_OP_const8s"; 231490075Sobrien case DW_OP_constu: 231590075Sobrien return "DW_OP_constu"; 231690075Sobrien case DW_OP_consts: 231790075Sobrien return "DW_OP_consts"; 231890075Sobrien case DW_OP_dup: 231990075Sobrien return "DW_OP_dup"; 232090075Sobrien case DW_OP_drop: 232190075Sobrien return "DW_OP_drop"; 232290075Sobrien case DW_OP_over: 232390075Sobrien return "DW_OP_over"; 232490075Sobrien case DW_OP_pick: 232590075Sobrien return "DW_OP_pick"; 232690075Sobrien case DW_OP_swap: 232790075Sobrien return "DW_OP_swap"; 232890075Sobrien case DW_OP_rot: 232990075Sobrien return "DW_OP_rot"; 233090075Sobrien case DW_OP_xderef: 233190075Sobrien return "DW_OP_xderef"; 233290075Sobrien case DW_OP_abs: 233390075Sobrien return "DW_OP_abs"; 233490075Sobrien case DW_OP_and: 233590075Sobrien return "DW_OP_and"; 233690075Sobrien case DW_OP_div: 233790075Sobrien return "DW_OP_div"; 233890075Sobrien case DW_OP_minus: 233990075Sobrien return "DW_OP_minus"; 234090075Sobrien case DW_OP_mod: 234190075Sobrien return "DW_OP_mod"; 234290075Sobrien case DW_OP_mul: 234390075Sobrien return "DW_OP_mul"; 234490075Sobrien case DW_OP_neg: 234590075Sobrien return "DW_OP_neg"; 234690075Sobrien case DW_OP_not: 234790075Sobrien return "DW_OP_not"; 234890075Sobrien case DW_OP_or: 234990075Sobrien return "DW_OP_or"; 235090075Sobrien case DW_OP_plus: 235190075Sobrien return "DW_OP_plus"; 235290075Sobrien case DW_OP_plus_uconst: 235390075Sobrien return "DW_OP_plus_uconst"; 235490075Sobrien case DW_OP_shl: 235590075Sobrien return "DW_OP_shl"; 235690075Sobrien case DW_OP_shr: 235790075Sobrien return "DW_OP_shr"; 235890075Sobrien case DW_OP_shra: 235990075Sobrien return "DW_OP_shra"; 236090075Sobrien case DW_OP_xor: 236190075Sobrien return "DW_OP_xor"; 236290075Sobrien case DW_OP_bra: 236390075Sobrien return "DW_OP_bra"; 236490075Sobrien case DW_OP_eq: 236590075Sobrien return "DW_OP_eq"; 236690075Sobrien case DW_OP_ge: 236790075Sobrien return "DW_OP_ge"; 236890075Sobrien case DW_OP_gt: 236990075Sobrien return "DW_OP_gt"; 237090075Sobrien case DW_OP_le: 237190075Sobrien return "DW_OP_le"; 237290075Sobrien case DW_OP_lt: 237390075Sobrien return "DW_OP_lt"; 237490075Sobrien case DW_OP_ne: 237590075Sobrien return "DW_OP_ne"; 237690075Sobrien case DW_OP_skip: 237790075Sobrien return "DW_OP_skip"; 237890075Sobrien case DW_OP_lit0: 237990075Sobrien return "DW_OP_lit0"; 238090075Sobrien case DW_OP_lit1: 238190075Sobrien return "DW_OP_lit1"; 238290075Sobrien case DW_OP_lit2: 238390075Sobrien return "DW_OP_lit2"; 238490075Sobrien case DW_OP_lit3: 238590075Sobrien return "DW_OP_lit3"; 238690075Sobrien case DW_OP_lit4: 238790075Sobrien return "DW_OP_lit4"; 238890075Sobrien case DW_OP_lit5: 238990075Sobrien return "DW_OP_lit5"; 239090075Sobrien case DW_OP_lit6: 239190075Sobrien return "DW_OP_lit6"; 239290075Sobrien case DW_OP_lit7: 239390075Sobrien return "DW_OP_lit7"; 239490075Sobrien case DW_OP_lit8: 239590075Sobrien return "DW_OP_lit8"; 239690075Sobrien case DW_OP_lit9: 239790075Sobrien return "DW_OP_lit9"; 239890075Sobrien case DW_OP_lit10: 239990075Sobrien return "DW_OP_lit10"; 240090075Sobrien case DW_OP_lit11: 240190075Sobrien return "DW_OP_lit11"; 240290075Sobrien case DW_OP_lit12: 240390075Sobrien return "DW_OP_lit12"; 240490075Sobrien case DW_OP_lit13: 240590075Sobrien return "DW_OP_lit13"; 240690075Sobrien case DW_OP_lit14: 240790075Sobrien return "DW_OP_lit14"; 240890075Sobrien case DW_OP_lit15: 240990075Sobrien return "DW_OP_lit15"; 241090075Sobrien case DW_OP_lit16: 241190075Sobrien return "DW_OP_lit16"; 241290075Sobrien case DW_OP_lit17: 241390075Sobrien return "DW_OP_lit17"; 241490075Sobrien case DW_OP_lit18: 241590075Sobrien return "DW_OP_lit18"; 241690075Sobrien case DW_OP_lit19: 241790075Sobrien return "DW_OP_lit19"; 241890075Sobrien case DW_OP_lit20: 241990075Sobrien return "DW_OP_lit20"; 242090075Sobrien case DW_OP_lit21: 242190075Sobrien return "DW_OP_lit21"; 242290075Sobrien case DW_OP_lit22: 242390075Sobrien return "DW_OP_lit22"; 242490075Sobrien case DW_OP_lit23: 242590075Sobrien return "DW_OP_lit23"; 242690075Sobrien case DW_OP_lit24: 242790075Sobrien return "DW_OP_lit24"; 242890075Sobrien case DW_OP_lit25: 242990075Sobrien return "DW_OP_lit25"; 243090075Sobrien case DW_OP_lit26: 243190075Sobrien return "DW_OP_lit26"; 243290075Sobrien case DW_OP_lit27: 243390075Sobrien return "DW_OP_lit27"; 243490075Sobrien case DW_OP_lit28: 243590075Sobrien return "DW_OP_lit28"; 243690075Sobrien case DW_OP_lit29: 243790075Sobrien return "DW_OP_lit29"; 243890075Sobrien case DW_OP_lit30: 243990075Sobrien return "DW_OP_lit30"; 244090075Sobrien case DW_OP_lit31: 244190075Sobrien return "DW_OP_lit31"; 244290075Sobrien case DW_OP_reg0: 244390075Sobrien return "DW_OP_reg0"; 244490075Sobrien case DW_OP_reg1: 244590075Sobrien return "DW_OP_reg1"; 244690075Sobrien case DW_OP_reg2: 244790075Sobrien return "DW_OP_reg2"; 244890075Sobrien case DW_OP_reg3: 244990075Sobrien return "DW_OP_reg3"; 245090075Sobrien case DW_OP_reg4: 245190075Sobrien return "DW_OP_reg4"; 245290075Sobrien case DW_OP_reg5: 245390075Sobrien return "DW_OP_reg5"; 245490075Sobrien case DW_OP_reg6: 245590075Sobrien return "DW_OP_reg6"; 245690075Sobrien case DW_OP_reg7: 245790075Sobrien return "DW_OP_reg7"; 245890075Sobrien case DW_OP_reg8: 245990075Sobrien return "DW_OP_reg8"; 246090075Sobrien case DW_OP_reg9: 246190075Sobrien return "DW_OP_reg9"; 246290075Sobrien case DW_OP_reg10: 246390075Sobrien return "DW_OP_reg10"; 246490075Sobrien case DW_OP_reg11: 246590075Sobrien return "DW_OP_reg11"; 246690075Sobrien case DW_OP_reg12: 246790075Sobrien return "DW_OP_reg12"; 246890075Sobrien case DW_OP_reg13: 246990075Sobrien return "DW_OP_reg13"; 247090075Sobrien case DW_OP_reg14: 247190075Sobrien return "DW_OP_reg14"; 247290075Sobrien case DW_OP_reg15: 247390075Sobrien return "DW_OP_reg15"; 247490075Sobrien case DW_OP_reg16: 247590075Sobrien return "DW_OP_reg16"; 247690075Sobrien case DW_OP_reg17: 247790075Sobrien return "DW_OP_reg17"; 247890075Sobrien case DW_OP_reg18: 247990075Sobrien return "DW_OP_reg18"; 248090075Sobrien case DW_OP_reg19: 248190075Sobrien return "DW_OP_reg19"; 248290075Sobrien case DW_OP_reg20: 248390075Sobrien return "DW_OP_reg20"; 248490075Sobrien case DW_OP_reg21: 248590075Sobrien return "DW_OP_reg21"; 248690075Sobrien case DW_OP_reg22: 248790075Sobrien return "DW_OP_reg22"; 248890075Sobrien case DW_OP_reg23: 248990075Sobrien return "DW_OP_reg23"; 249090075Sobrien case DW_OP_reg24: 249190075Sobrien return "DW_OP_reg24"; 249290075Sobrien case DW_OP_reg25: 249390075Sobrien return "DW_OP_reg25"; 249490075Sobrien case DW_OP_reg26: 249590075Sobrien return "DW_OP_reg26"; 249690075Sobrien case DW_OP_reg27: 249790075Sobrien return "DW_OP_reg27"; 249890075Sobrien case DW_OP_reg28: 249990075Sobrien return "DW_OP_reg28"; 250090075Sobrien case DW_OP_reg29: 250190075Sobrien return "DW_OP_reg29"; 250290075Sobrien case DW_OP_reg30: 250390075Sobrien return "DW_OP_reg30"; 250490075Sobrien case DW_OP_reg31: 250590075Sobrien return "DW_OP_reg31"; 250690075Sobrien case DW_OP_breg0: 250790075Sobrien return "DW_OP_breg0"; 250890075Sobrien case DW_OP_breg1: 250990075Sobrien return "DW_OP_breg1"; 251090075Sobrien case DW_OP_breg2: 251190075Sobrien return "DW_OP_breg2"; 251290075Sobrien case DW_OP_breg3: 251390075Sobrien return "DW_OP_breg3"; 251490075Sobrien case DW_OP_breg4: 251590075Sobrien return "DW_OP_breg4"; 251690075Sobrien case DW_OP_breg5: 251790075Sobrien return "DW_OP_breg5"; 251890075Sobrien case DW_OP_breg6: 251990075Sobrien return "DW_OP_breg6"; 252090075Sobrien case DW_OP_breg7: 252190075Sobrien return "DW_OP_breg7"; 252290075Sobrien case DW_OP_breg8: 252390075Sobrien return "DW_OP_breg8"; 252490075Sobrien case DW_OP_breg9: 252590075Sobrien return "DW_OP_breg9"; 252690075Sobrien case DW_OP_breg10: 252790075Sobrien return "DW_OP_breg10"; 252890075Sobrien case DW_OP_breg11: 252990075Sobrien return "DW_OP_breg11"; 253090075Sobrien case DW_OP_breg12: 253190075Sobrien return "DW_OP_breg12"; 253290075Sobrien case DW_OP_breg13: 253390075Sobrien return "DW_OP_breg13"; 253490075Sobrien case DW_OP_breg14: 253590075Sobrien return "DW_OP_breg14"; 253690075Sobrien case DW_OP_breg15: 253790075Sobrien return "DW_OP_breg15"; 253890075Sobrien case DW_OP_breg16: 253990075Sobrien return "DW_OP_breg16"; 254090075Sobrien case DW_OP_breg17: 254190075Sobrien return "DW_OP_breg17"; 254290075Sobrien case DW_OP_breg18: 254390075Sobrien return "DW_OP_breg18"; 254490075Sobrien case DW_OP_breg19: 254590075Sobrien return "DW_OP_breg19"; 254690075Sobrien case DW_OP_breg20: 254790075Sobrien return "DW_OP_breg20"; 254890075Sobrien case DW_OP_breg21: 254990075Sobrien return "DW_OP_breg21"; 255090075Sobrien case DW_OP_breg22: 255190075Sobrien return "DW_OP_breg22"; 255290075Sobrien case DW_OP_breg23: 255390075Sobrien return "DW_OP_breg23"; 255490075Sobrien case DW_OP_breg24: 255590075Sobrien return "DW_OP_breg24"; 255690075Sobrien case DW_OP_breg25: 255790075Sobrien return "DW_OP_breg25"; 255890075Sobrien case DW_OP_breg26: 255990075Sobrien return "DW_OP_breg26"; 256090075Sobrien case DW_OP_breg27: 256190075Sobrien return "DW_OP_breg27"; 256290075Sobrien case DW_OP_breg28: 256390075Sobrien return "DW_OP_breg28"; 256490075Sobrien case DW_OP_breg29: 256590075Sobrien return "DW_OP_breg29"; 256690075Sobrien case DW_OP_breg30: 256790075Sobrien return "DW_OP_breg30"; 256890075Sobrien case DW_OP_breg31: 256990075Sobrien return "DW_OP_breg31"; 257090075Sobrien case DW_OP_regx: 257190075Sobrien return "DW_OP_regx"; 257290075Sobrien case DW_OP_fbreg: 257390075Sobrien return "DW_OP_fbreg"; 257490075Sobrien case DW_OP_bregx: 257590075Sobrien return "DW_OP_bregx"; 257690075Sobrien case DW_OP_piece: 257790075Sobrien return "DW_OP_piece"; 257890075Sobrien case DW_OP_deref_size: 257990075Sobrien return "DW_OP_deref_size"; 258090075Sobrien case DW_OP_xderef_size: 258190075Sobrien return "DW_OP_xderef_size"; 258290075Sobrien case DW_OP_nop: 258390075Sobrien return "DW_OP_nop"; 258490075Sobrien default: 258590075Sobrien return "OP_<unknown>"; 258690075Sobrien } 258790075Sobrien} 258890075Sobrien 258990075Sobrien/* Return a pointer to a newly allocated location description. Location 259090075Sobrien descriptions are simple expression terms that can be strung 259190075Sobrien together to form more complicated location (address) descriptions. */ 259290075Sobrien 259390075Sobrienstatic inline dw_loc_descr_ref 259490075Sobriennew_loc_descr (op, oprnd1, oprnd2) 259590075Sobrien enum dwarf_location_atom op; 259690075Sobrien unsigned long oprnd1; 259790075Sobrien unsigned long oprnd2; 259890075Sobrien{ 259990075Sobrien /* Use xcalloc here so we clear out all of the long_long constant in 260090075Sobrien the union. */ 260190075Sobrien dw_loc_descr_ref descr 260290075Sobrien = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node)); 260390075Sobrien 260490075Sobrien descr->dw_loc_opc = op; 260590075Sobrien descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const; 260690075Sobrien descr->dw_loc_oprnd1.v.val_unsigned = oprnd1; 260790075Sobrien descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const; 260890075Sobrien descr->dw_loc_oprnd2.v.val_unsigned = oprnd2; 260990075Sobrien 261090075Sobrien return descr; 261190075Sobrien} 261290075Sobrien 261390075Sobrien 261490075Sobrien/* Add a location description term to a location description expression. */ 261590075Sobrien 261690075Sobrienstatic inline void 261790075Sobrienadd_loc_descr (list_head, descr) 261890075Sobrien dw_loc_descr_ref *list_head; 261990075Sobrien dw_loc_descr_ref descr; 262090075Sobrien{ 262190075Sobrien dw_loc_descr_ref *d; 262290075Sobrien 262390075Sobrien /* Find the end of the chain. */ 262490075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 262590075Sobrien ; 262690075Sobrien 262790075Sobrien *d = descr; 262890075Sobrien} 262990075Sobrien 263090075Sobrien/* Return the size of a location descriptor. */ 263190075Sobrien 263290075Sobrienstatic unsigned long 263390075Sobriensize_of_loc_descr (loc) 263490075Sobrien dw_loc_descr_ref loc; 263590075Sobrien{ 263690075Sobrien unsigned long size = 1; 263790075Sobrien 263890075Sobrien switch (loc->dw_loc_opc) 263990075Sobrien { 264090075Sobrien case DW_OP_addr: 264190075Sobrien size += DWARF2_ADDR_SIZE; 264290075Sobrien break; 264390075Sobrien case DW_OP_const1u: 264490075Sobrien case DW_OP_const1s: 264590075Sobrien size += 1; 264690075Sobrien break; 264790075Sobrien case DW_OP_const2u: 264890075Sobrien case DW_OP_const2s: 264990075Sobrien size += 2; 265090075Sobrien break; 265190075Sobrien case DW_OP_const4u: 265290075Sobrien case DW_OP_const4s: 265390075Sobrien size += 4; 265490075Sobrien break; 265590075Sobrien case DW_OP_const8u: 265690075Sobrien case DW_OP_const8s: 265790075Sobrien size += 8; 265890075Sobrien break; 265990075Sobrien case DW_OP_constu: 266090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 266190075Sobrien break; 266290075Sobrien case DW_OP_consts: 266390075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 266490075Sobrien break; 266590075Sobrien case DW_OP_pick: 266690075Sobrien size += 1; 266790075Sobrien break; 266890075Sobrien case DW_OP_plus_uconst: 266990075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 267090075Sobrien break; 267190075Sobrien case DW_OP_skip: 267290075Sobrien case DW_OP_bra: 267390075Sobrien size += 2; 267490075Sobrien break; 267590075Sobrien case DW_OP_breg0: 267690075Sobrien case DW_OP_breg1: 267790075Sobrien case DW_OP_breg2: 267890075Sobrien case DW_OP_breg3: 267990075Sobrien case DW_OP_breg4: 268090075Sobrien case DW_OP_breg5: 268190075Sobrien case DW_OP_breg6: 268290075Sobrien case DW_OP_breg7: 268390075Sobrien case DW_OP_breg8: 268490075Sobrien case DW_OP_breg9: 268590075Sobrien case DW_OP_breg10: 268690075Sobrien case DW_OP_breg11: 268790075Sobrien case DW_OP_breg12: 268890075Sobrien case DW_OP_breg13: 268990075Sobrien case DW_OP_breg14: 269090075Sobrien case DW_OP_breg15: 269190075Sobrien case DW_OP_breg16: 269290075Sobrien case DW_OP_breg17: 269390075Sobrien case DW_OP_breg18: 269490075Sobrien case DW_OP_breg19: 269590075Sobrien case DW_OP_breg20: 269690075Sobrien case DW_OP_breg21: 269790075Sobrien case DW_OP_breg22: 269890075Sobrien case DW_OP_breg23: 269990075Sobrien case DW_OP_breg24: 270090075Sobrien case DW_OP_breg25: 270190075Sobrien case DW_OP_breg26: 270290075Sobrien case DW_OP_breg27: 270390075Sobrien case DW_OP_breg28: 270490075Sobrien case DW_OP_breg29: 270590075Sobrien case DW_OP_breg30: 270690075Sobrien case DW_OP_breg31: 270790075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 270890075Sobrien break; 270990075Sobrien case DW_OP_regx: 271090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271190075Sobrien break; 271290075Sobrien case DW_OP_fbreg: 271390075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 271490075Sobrien break; 271590075Sobrien case DW_OP_bregx: 271690075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 271790075Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); 271890075Sobrien break; 271990075Sobrien case DW_OP_piece: 272090075Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 272190075Sobrien break; 272290075Sobrien case DW_OP_deref_size: 272390075Sobrien case DW_OP_xderef_size: 272490075Sobrien size += 1; 272590075Sobrien break; 272690075Sobrien default: 272790075Sobrien break; 272890075Sobrien } 272990075Sobrien 273090075Sobrien return size; 273190075Sobrien} 273290075Sobrien 273390075Sobrien/* Return the size of a series of location descriptors. */ 273490075Sobrien 273590075Sobrienstatic unsigned long 273690075Sobriensize_of_locs (loc) 273790075Sobrien dw_loc_descr_ref loc; 273890075Sobrien{ 273990075Sobrien unsigned long size; 274090075Sobrien 274190075Sobrien for (size = 0; loc != NULL; loc = loc->dw_loc_next) 274290075Sobrien { 274390075Sobrien loc->dw_loc_addr = size; 274490075Sobrien size += size_of_loc_descr (loc); 274590075Sobrien } 274690075Sobrien 274790075Sobrien return size; 274890075Sobrien} 274990075Sobrien 275090075Sobrien/* Output location description stack opcode's operands (if any). */ 275190075Sobrien 275290075Sobrienstatic void 275390075Sobrienoutput_loc_operands (loc) 275490075Sobrien dw_loc_descr_ref loc; 275590075Sobrien{ 275690075Sobrien dw_val_ref val1 = &loc->dw_loc_oprnd1; 275790075Sobrien dw_val_ref val2 = &loc->dw_loc_oprnd2; 275890075Sobrien 275990075Sobrien switch (loc->dw_loc_opc) 276090075Sobrien { 276190075Sobrien#ifdef DWARF2_DEBUGGING_INFO 276290075Sobrien case DW_OP_addr: 276390075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val1->v.val_addr, NULL); 276490075Sobrien break; 276590075Sobrien case DW_OP_const2u: 276690075Sobrien case DW_OP_const2s: 276790075Sobrien dw2_asm_output_data (2, val1->v.val_int, NULL); 276890075Sobrien break; 276990075Sobrien case DW_OP_const4u: 277090075Sobrien case DW_OP_const4s: 277190075Sobrien dw2_asm_output_data (4, val1->v.val_int, NULL); 277290075Sobrien break; 277390075Sobrien case DW_OP_const8u: 277490075Sobrien case DW_OP_const8s: 277590075Sobrien if (HOST_BITS_PER_LONG < 64) 277690075Sobrien abort (); 277790075Sobrien dw2_asm_output_data (8, val1->v.val_int, NULL); 277890075Sobrien break; 277990075Sobrien case DW_OP_skip: 278090075Sobrien case DW_OP_bra: 278190075Sobrien { 278290075Sobrien int offset; 278390075Sobrien 278490075Sobrien if (val1->val_class == dw_val_class_loc) 278590075Sobrien offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3); 278690075Sobrien else 278790075Sobrien abort (); 278890075Sobrien 278990075Sobrien dw2_asm_output_data (2, offset, NULL); 279090075Sobrien } 279190075Sobrien break; 279290075Sobrien#else 279390075Sobrien case DW_OP_addr: 279490075Sobrien case DW_OP_const2u: 279590075Sobrien case DW_OP_const2s: 279690075Sobrien case DW_OP_const4u: 279790075Sobrien case DW_OP_const4s: 279890075Sobrien case DW_OP_const8u: 279990075Sobrien case DW_OP_const8s: 280090075Sobrien case DW_OP_skip: 280190075Sobrien case DW_OP_bra: 280290075Sobrien /* We currently don't make any attempt to make sure these are 280390075Sobrien aligned properly like we do for the main unwind info, so 280490075Sobrien don't support emitting things larger than a byte if we're 280590075Sobrien only doing unwinding. */ 280690075Sobrien abort (); 280790075Sobrien#endif 280890075Sobrien case DW_OP_const1u: 280990075Sobrien case DW_OP_const1s: 281090075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 281190075Sobrien break; 281290075Sobrien case DW_OP_constu: 281390075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 281490075Sobrien break; 281590075Sobrien case DW_OP_consts: 281690075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 281790075Sobrien break; 281890075Sobrien case DW_OP_pick: 281990075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 282090075Sobrien break; 282190075Sobrien case DW_OP_plus_uconst: 282290075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 282390075Sobrien break; 282490075Sobrien case DW_OP_breg0: 282590075Sobrien case DW_OP_breg1: 282690075Sobrien case DW_OP_breg2: 282790075Sobrien case DW_OP_breg3: 282890075Sobrien case DW_OP_breg4: 282990075Sobrien case DW_OP_breg5: 283090075Sobrien case DW_OP_breg6: 283190075Sobrien case DW_OP_breg7: 283290075Sobrien case DW_OP_breg8: 283390075Sobrien case DW_OP_breg9: 283490075Sobrien case DW_OP_breg10: 283590075Sobrien case DW_OP_breg11: 283690075Sobrien case DW_OP_breg12: 283790075Sobrien case DW_OP_breg13: 283890075Sobrien case DW_OP_breg14: 283990075Sobrien case DW_OP_breg15: 284090075Sobrien case DW_OP_breg16: 284190075Sobrien case DW_OP_breg17: 284290075Sobrien case DW_OP_breg18: 284390075Sobrien case DW_OP_breg19: 284490075Sobrien case DW_OP_breg20: 284590075Sobrien case DW_OP_breg21: 284690075Sobrien case DW_OP_breg22: 284790075Sobrien case DW_OP_breg23: 284890075Sobrien case DW_OP_breg24: 284990075Sobrien case DW_OP_breg25: 285090075Sobrien case DW_OP_breg26: 285190075Sobrien case DW_OP_breg27: 285290075Sobrien case DW_OP_breg28: 285390075Sobrien case DW_OP_breg29: 285490075Sobrien case DW_OP_breg30: 285590075Sobrien case DW_OP_breg31: 285690075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 285790075Sobrien break; 285890075Sobrien case DW_OP_regx: 285990075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286090075Sobrien break; 286190075Sobrien case DW_OP_fbreg: 286290075Sobrien dw2_asm_output_data_sleb128 (val1->v.val_int, NULL); 286390075Sobrien break; 286490075Sobrien case DW_OP_bregx: 286590075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 286690075Sobrien dw2_asm_output_data_sleb128 (val2->v.val_int, NULL); 286790075Sobrien break; 286890075Sobrien case DW_OP_piece: 286990075Sobrien dw2_asm_output_data_uleb128 (val1->v.val_unsigned, NULL); 287090075Sobrien break; 287190075Sobrien case DW_OP_deref_size: 287290075Sobrien case DW_OP_xderef_size: 287390075Sobrien dw2_asm_output_data (1, val1->v.val_int, NULL); 287490075Sobrien break; 287590075Sobrien default: 287690075Sobrien /* Other codes have no operands. */ 287790075Sobrien break; 287890075Sobrien } 287990075Sobrien} 288090075Sobrien 288190075Sobrien/* Output a sequence of location operations. */ 288290075Sobrien 288390075Sobrienstatic void 288490075Sobrienoutput_loc_sequence (loc) 288590075Sobrien dw_loc_descr_ref loc; 288690075Sobrien{ 288790075Sobrien for (; loc != NULL; loc = loc->dw_loc_next) 288890075Sobrien { 288990075Sobrien /* Output the opcode. */ 289090075Sobrien dw2_asm_output_data (1, loc->dw_loc_opc, 289190075Sobrien "%s", dwarf_stack_op_name (loc->dw_loc_opc)); 289290075Sobrien 289390075Sobrien /* Output the operand(s) (if any). */ 289490075Sobrien output_loc_operands (loc); 289590075Sobrien } 289690075Sobrien} 289790075Sobrien 289890075Sobrien/* This routine will generate the correct assembly data for a location 289990075Sobrien description based on a cfi entry with a complex address. */ 290090075Sobrien 290190075Sobrienstatic void 290290075Sobrienoutput_cfa_loc (cfi) 290390075Sobrien dw_cfi_ref cfi; 290490075Sobrien{ 290590075Sobrien dw_loc_descr_ref loc; 290690075Sobrien unsigned long size; 290790075Sobrien 290890075Sobrien /* Output the size of the block. */ 290990075Sobrien loc = cfi->dw_cfi_oprnd1.dw_cfi_loc; 291090075Sobrien size = size_of_locs (loc); 291190075Sobrien dw2_asm_output_data_uleb128 (size, NULL); 291290075Sobrien 291390075Sobrien /* Now output the operations themselves. */ 291490075Sobrien output_loc_sequence (loc); 291590075Sobrien} 291690075Sobrien 291790075Sobrien/* This function builds a dwarf location descriptor sequence from 291890075Sobrien a dw_cfa_location. */ 291990075Sobrien 292090075Sobrienstatic struct dw_loc_descr_struct * 292190075Sobrienbuild_cfa_loc (cfa) 292290075Sobrien dw_cfa_location *cfa; 292390075Sobrien{ 292490075Sobrien struct dw_loc_descr_struct *head, *tmp; 292590075Sobrien 292690075Sobrien if (cfa->indirect == 0) 292790075Sobrien abort (); 292890075Sobrien 292990075Sobrien if (cfa->base_offset) 293090075Sobrien { 293190075Sobrien if (cfa->reg <= 31) 293290075Sobrien head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0); 293390075Sobrien else 293490075Sobrien head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset); 293590075Sobrien } 293690075Sobrien else if (cfa->reg <= 31) 293790075Sobrien head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); 293890075Sobrien else 293990075Sobrien head = new_loc_descr (DW_OP_regx, cfa->reg, 0); 294090075Sobrien 294190075Sobrien head->dw_loc_oprnd1.val_class = dw_val_class_const; 294290075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 294390075Sobrien add_loc_descr (&head, tmp); 294490075Sobrien if (cfa->offset != 0) 294590075Sobrien { 294690075Sobrien tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0); 294790075Sobrien add_loc_descr (&head, tmp); 294890075Sobrien } 294990075Sobrien 295090075Sobrien return head; 295190075Sobrien} 295290075Sobrien 295390075Sobrien/* This function fills in aa dw_cfa_location structure from a dwarf location 295490075Sobrien descriptor sequence. */ 295590075Sobrien 295690075Sobrienstatic void 295790075Sobrienget_cfa_from_loc_descr (cfa, loc) 295890075Sobrien dw_cfa_location *cfa; 295990075Sobrien struct dw_loc_descr_struct *loc; 296090075Sobrien{ 296190075Sobrien struct dw_loc_descr_struct *ptr; 296290075Sobrien cfa->offset = 0; 296390075Sobrien cfa->base_offset = 0; 296490075Sobrien cfa->indirect = 0; 296590075Sobrien cfa->reg = -1; 296690075Sobrien 296790075Sobrien for (ptr = loc; ptr != NULL; ptr = ptr->dw_loc_next) 296890075Sobrien { 296990075Sobrien enum dwarf_location_atom op = ptr->dw_loc_opc; 297090075Sobrien 297190075Sobrien switch (op) 297290075Sobrien { 297390075Sobrien case DW_OP_reg0: 297490075Sobrien case DW_OP_reg1: 297590075Sobrien case DW_OP_reg2: 297690075Sobrien case DW_OP_reg3: 297790075Sobrien case DW_OP_reg4: 297890075Sobrien case DW_OP_reg5: 297990075Sobrien case DW_OP_reg6: 298090075Sobrien case DW_OP_reg7: 298190075Sobrien case DW_OP_reg8: 298290075Sobrien case DW_OP_reg9: 298390075Sobrien case DW_OP_reg10: 298490075Sobrien case DW_OP_reg11: 298590075Sobrien case DW_OP_reg12: 298690075Sobrien case DW_OP_reg13: 298790075Sobrien case DW_OP_reg14: 298890075Sobrien case DW_OP_reg15: 298990075Sobrien case DW_OP_reg16: 299090075Sobrien case DW_OP_reg17: 299190075Sobrien case DW_OP_reg18: 299290075Sobrien case DW_OP_reg19: 299390075Sobrien case DW_OP_reg20: 299490075Sobrien case DW_OP_reg21: 299590075Sobrien case DW_OP_reg22: 299690075Sobrien case DW_OP_reg23: 299790075Sobrien case DW_OP_reg24: 299890075Sobrien case DW_OP_reg25: 299990075Sobrien case DW_OP_reg26: 300090075Sobrien case DW_OP_reg27: 300190075Sobrien case DW_OP_reg28: 300290075Sobrien case DW_OP_reg29: 300390075Sobrien case DW_OP_reg30: 300490075Sobrien case DW_OP_reg31: 300590075Sobrien cfa->reg = op - DW_OP_reg0; 300690075Sobrien break; 300790075Sobrien case DW_OP_regx: 300890075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 300990075Sobrien break; 301090075Sobrien case DW_OP_breg0: 301190075Sobrien case DW_OP_breg1: 301290075Sobrien case DW_OP_breg2: 301390075Sobrien case DW_OP_breg3: 301490075Sobrien case DW_OP_breg4: 301590075Sobrien case DW_OP_breg5: 301690075Sobrien case DW_OP_breg6: 301790075Sobrien case DW_OP_breg7: 301890075Sobrien case DW_OP_breg8: 301990075Sobrien case DW_OP_breg9: 302090075Sobrien case DW_OP_breg10: 302190075Sobrien case DW_OP_breg11: 302290075Sobrien case DW_OP_breg12: 302390075Sobrien case DW_OP_breg13: 302490075Sobrien case DW_OP_breg14: 302590075Sobrien case DW_OP_breg15: 302690075Sobrien case DW_OP_breg16: 302790075Sobrien case DW_OP_breg17: 302890075Sobrien case DW_OP_breg18: 302990075Sobrien case DW_OP_breg19: 303090075Sobrien case DW_OP_breg20: 303190075Sobrien case DW_OP_breg21: 303290075Sobrien case DW_OP_breg22: 303390075Sobrien case DW_OP_breg23: 303490075Sobrien case DW_OP_breg24: 303590075Sobrien case DW_OP_breg25: 303690075Sobrien case DW_OP_breg26: 303790075Sobrien case DW_OP_breg27: 303890075Sobrien case DW_OP_breg28: 303990075Sobrien case DW_OP_breg29: 304090075Sobrien case DW_OP_breg30: 304190075Sobrien case DW_OP_breg31: 304290075Sobrien cfa->reg = op - DW_OP_breg0; 304390075Sobrien cfa->base_offset = ptr->dw_loc_oprnd1.v.val_int; 304490075Sobrien break; 304590075Sobrien case DW_OP_bregx: 304690075Sobrien cfa->reg = ptr->dw_loc_oprnd1.v.val_int; 304790075Sobrien cfa->base_offset = ptr->dw_loc_oprnd2.v.val_int; 304890075Sobrien break; 304990075Sobrien case DW_OP_deref: 305090075Sobrien cfa->indirect = 1; 305190075Sobrien break; 305290075Sobrien case DW_OP_plus_uconst: 305390075Sobrien cfa->offset = ptr->dw_loc_oprnd1.v.val_unsigned; 305490075Sobrien break; 305590075Sobrien default: 305690075Sobrien internal_error ("DW_LOC_OP %s not implemented\n", 305790075Sobrien dwarf_stack_op_name (ptr->dw_loc_opc)); 305890075Sobrien } 305990075Sobrien } 306090075Sobrien} 306190075Sobrien#endif /* .debug_frame support */ 306290075Sobrien 306390075Sobrien/* And now, the support for symbolic debugging information. */ 306490075Sobrien#ifdef DWARF2_DEBUGGING_INFO 306590075Sobrien 306690075Sobrien/* .debug_str support. */ 306790075Sobrienstatic hashnode indirect_string_alloc PARAMS ((hash_table *)); 306890075Sobrienstatic int output_indirect_string PARAMS ((struct cpp_reader *, 306990075Sobrien hashnode, const PTR)); 307090075Sobrien 307190075Sobrien 307290075Sobrienstatic void dwarf2out_init PARAMS ((const char *)); 307390075Sobrienstatic void dwarf2out_finish PARAMS ((const char *)); 307490075Sobrienstatic void dwarf2out_define PARAMS ((unsigned int, const char *)); 307590075Sobrienstatic void dwarf2out_undef PARAMS ((unsigned int, const char *)); 307690075Sobrienstatic void dwarf2out_start_source_file PARAMS ((unsigned, const char *)); 307790075Sobrienstatic void dwarf2out_end_source_file PARAMS ((unsigned)); 307890075Sobrienstatic void dwarf2out_begin_block PARAMS ((unsigned, unsigned)); 307990075Sobrienstatic void dwarf2out_end_block PARAMS ((unsigned, unsigned)); 308090075Sobrienstatic bool dwarf2out_ignore_block PARAMS ((tree)); 308190075Sobrienstatic void dwarf2out_global_decl PARAMS ((tree)); 308290075Sobrienstatic void dwarf2out_abstract_function PARAMS ((tree)); 308390075Sobrien 308490075Sobrien/* The debug hooks structure. */ 308590075Sobrien 308690075Sobrienstruct gcc_debug_hooks dwarf2_debug_hooks = 308790075Sobrien{ 308890075Sobrien dwarf2out_init, 308990075Sobrien dwarf2out_finish, 309090075Sobrien dwarf2out_define, 309190075Sobrien dwarf2out_undef, 309290075Sobrien dwarf2out_start_source_file, 309390075Sobrien dwarf2out_end_source_file, 309490075Sobrien dwarf2out_begin_block, 309590075Sobrien dwarf2out_end_block, 309690075Sobrien dwarf2out_ignore_block, 309790075Sobrien dwarf2out_source_line, 309890075Sobrien dwarf2out_begin_prologue, 309990075Sobrien debug_nothing_int, /* end_prologue */ 310090075Sobrien dwarf2out_end_epilogue, 310190075Sobrien debug_nothing_tree, /* begin_function */ 310290075Sobrien debug_nothing_int, /* end_function */ 310390075Sobrien dwarf2out_decl, /* function_decl */ 310490075Sobrien dwarf2out_global_decl, 310590075Sobrien debug_nothing_tree, /* deferred_inline_function */ 310690075Sobrien /* The DWARF 2 backend tries to reduce debugging bloat by not 310790075Sobrien emitting the abstract description of inline functions until 310890075Sobrien something tries to reference them. */ 310990075Sobrien dwarf2out_abstract_function, /* outlining_inline_function */ 311090075Sobrien debug_nothing_rtx /* label */ 311190075Sobrien}; 311290075Sobrien 311390075Sobrien/* NOTE: In the comments in this file, many references are made to 311490075Sobrien "Debugging Information Entries". This term is abbreviated as `DIE' 311590075Sobrien throughout the remainder of this file. */ 311690075Sobrien 311790075Sobrien/* An internal representation of the DWARF output is built, and then 311890075Sobrien walked to generate the DWARF debugging info. The walk of the internal 311990075Sobrien representation is done after the entire program has been compiled. 312090075Sobrien The types below are used to describe the internal representation. */ 312190075Sobrien 312290075Sobrien/* Various DIE's use offsets relative to the beginning of the 312390075Sobrien .debug_info section to refer to each other. */ 312490075Sobrien 312590075Sobrientypedef long int dw_offset; 312690075Sobrien 312790075Sobrien/* Define typedefs here to avoid circular dependencies. */ 312890075Sobrien 312990075Sobrientypedef struct dw_attr_struct *dw_attr_ref; 313090075Sobrientypedef struct dw_line_info_struct *dw_line_info_ref; 313190075Sobrientypedef struct dw_separate_line_info_struct *dw_separate_line_info_ref; 313290075Sobrientypedef struct pubname_struct *pubname_ref; 313390075Sobrientypedef struct dw_ranges_struct *dw_ranges_ref; 313490075Sobrien 313590075Sobrien/* Each entry in the line_info_table maintains the file and 313690075Sobrien line number associated with the label generated for that 313790075Sobrien entry. The label gives the PC value associated with 313890075Sobrien the line number entry. */ 313990075Sobrien 314090075Sobrientypedef struct dw_line_info_struct 314190075Sobrien{ 314290075Sobrien unsigned long dw_file_num; 314390075Sobrien unsigned long dw_line_num; 314490075Sobrien} 314590075Sobriendw_line_info_entry; 314690075Sobrien 314790075Sobrien/* Line information for functions in separate sections; each one gets its 314890075Sobrien own sequence. */ 314990075Sobrientypedef struct dw_separate_line_info_struct 315090075Sobrien{ 315190075Sobrien unsigned long dw_file_num; 315290075Sobrien unsigned long dw_line_num; 315390075Sobrien unsigned long function; 315490075Sobrien} 315590075Sobriendw_separate_line_info_entry; 315690075Sobrien 315750397Sobrien/* Each DIE attribute has a field specifying the attribute kind, 315850397Sobrien a link to the next attribute in the chain, and an attribute value. 315950397Sobrien Attributes are typically linked below the DIE they modify. */ 316050397Sobrien 316150397Sobrientypedef struct dw_attr_struct 316250397Sobrien{ 316350397Sobrien enum dwarf_attribute dw_attr; 316450397Sobrien dw_attr_ref dw_attr_next; 316550397Sobrien dw_val_node dw_attr_val; 316650397Sobrien} 316750397Sobriendw_attr_node; 316850397Sobrien 316950397Sobrien/* The Debugging Information Entry (DIE) structure */ 317050397Sobrien 317150397Sobrientypedef struct die_struct 317250397Sobrien{ 317350397Sobrien enum dwarf_tag die_tag; 317490075Sobrien char *die_symbol; 317550397Sobrien dw_attr_ref die_attr; 317650397Sobrien dw_die_ref die_parent; 317750397Sobrien dw_die_ref die_child; 317850397Sobrien dw_die_ref die_sib; 317950397Sobrien dw_offset die_offset; 318050397Sobrien unsigned long die_abbrev; 318190075Sobrien int die_mark; 318250397Sobrien} 318350397Sobriendie_node; 318450397Sobrien 318550397Sobrien/* The pubname structure */ 318650397Sobrien 318750397Sobrientypedef struct pubname_struct 318850397Sobrien{ 318950397Sobrien dw_die_ref die; 319090075Sobrien char *name; 319150397Sobrien} 319250397Sobrienpubname_entry; 319350397Sobrien 319490075Sobrienstruct dw_ranges_struct 319590075Sobrien{ 319690075Sobrien int block_num; 319790075Sobrien}; 319890075Sobrien 319950397Sobrien/* The limbo die list structure. */ 320050397Sobrientypedef struct limbo_die_struct 320150397Sobrien{ 320250397Sobrien dw_die_ref die; 320390075Sobrien tree created_for; 320450397Sobrien struct limbo_die_struct *next; 320550397Sobrien} 320650397Sobrienlimbo_die_node; 320750397Sobrien 320850397Sobrien/* How to start an assembler comment. */ 320950397Sobrien#ifndef ASM_COMMENT_START 321050397Sobrien#define ASM_COMMENT_START ";#" 321150397Sobrien#endif 321250397Sobrien 321350397Sobrien/* Define a macro which returns non-zero for a TYPE_DECL which was 321450397Sobrien implicitly generated for a tagged type. 321550397Sobrien 321650397Sobrien Note that unlike the gcc front end (which generates a NULL named 321750397Sobrien TYPE_DECL node for each complete tagged type, each array type, and 321850397Sobrien each function type node created) the g++ front end generates a 321950397Sobrien _named_ TYPE_DECL node for each tagged type node created. 322050397Sobrien These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to 322150397Sobrien generate a DW_TAG_typedef DIE for them. */ 322250397Sobrien 322350397Sobrien#define TYPE_DECL_IS_STUB(decl) \ 322450397Sobrien (DECL_NAME (decl) == NULL_TREE \ 322550397Sobrien || (DECL_ARTIFICIAL (decl) \ 322650397Sobrien && is_tagged_type (TREE_TYPE (decl)) \ 322750397Sobrien && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \ 322850397Sobrien /* This is necessary for stub decls that \ 322950397Sobrien appear in nested inline functions. */ \ 323050397Sobrien || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \ 323150397Sobrien && (decl_ultimate_origin (decl) \ 323250397Sobrien == TYPE_STUB_DECL (TREE_TYPE (decl))))))) 323350397Sobrien 323450397Sobrien/* Information concerning the compilation unit's programming 323550397Sobrien language, and compiler version. */ 323650397Sobrien 323750397Sobrienextern int flag_traditional; 323850397Sobrien 323950397Sobrien/* Fixed size portion of the DWARF compilation unit header. */ 324050397Sobrien#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3) 324150397Sobrien 324250397Sobrien/* Fixed size portion of debugging line information prolog. */ 324350397Sobrien#define DWARF_LINE_PROLOG_HEADER_SIZE 5 324450397Sobrien 324550397Sobrien/* Fixed size portion of public names info. */ 324650397Sobrien#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2) 324750397Sobrien 324850397Sobrien/* Fixed size portion of the address range info. */ 324990075Sobrien#define DWARF_ARANGES_HEADER_SIZE \ 325090075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325190075Sobrien - DWARF_OFFSET_SIZE) 325250397Sobrien 325390075Sobrien/* Size of padding portion in the address range info. It must be 325490075Sobrien aligned to twice the pointer size. */ 325590075Sobrien#define DWARF_ARANGES_PAD_SIZE \ 325690075Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ 325790075Sobrien - (2 * DWARF_OFFSET_SIZE + 4)) 325890075Sobrien 325990075Sobrien/* Use assembler line directives if available. */ 326090075Sobrien#ifndef DWARF2_ASM_LINE_DEBUG_INFO 326190075Sobrien#ifdef HAVE_AS_DWARF2_DEBUG_LINE 326290075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 1 326390075Sobrien#else 326490075Sobrien#define DWARF2_ASM_LINE_DEBUG_INFO 0 326590075Sobrien#endif 326690075Sobrien#endif 326790075Sobrien 326850397Sobrien/* Define the architecture-dependent minimum instruction length (in bytes). 326950397Sobrien In this implementation of DWARF, this field is used for information 327050397Sobrien purposes only. Since GCC generates assembly language, we have 327150397Sobrien no a priori knowledge of how many instruction bytes are generated 327250397Sobrien for each source line, and therefore can use only the DW_LNE_set_address 327350397Sobrien and DW_LNS_fixed_advance_pc line information commands. */ 327450397Sobrien#ifndef DWARF_LINE_MIN_INSTR_LENGTH 327550397Sobrien#define DWARF_LINE_MIN_INSTR_LENGTH 4 327650397Sobrien#endif 327750397Sobrien 327850397Sobrien/* Minimum line offset in a special line info. opcode. 327950397Sobrien This value was chosen to give a reasonable range of values. */ 328050397Sobrien#define DWARF_LINE_BASE -10 328150397Sobrien 328290075Sobrien/* First special line opcode - leave room for the standard opcodes. */ 328350397Sobrien#define DWARF_LINE_OPCODE_BASE 10 328450397Sobrien 328550397Sobrien/* Range of line offsets in a special line info. opcode. */ 328650397Sobrien#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1) 328750397Sobrien 328850397Sobrien/* Flag that indicates the initial value of the is_stmt_start flag. 328950397Sobrien In the present implementation, we do not mark any lines as 329050397Sobrien the beginning of a source statement, because that information 329150397Sobrien is not made available by the GCC front-end. */ 329250397Sobrien#define DWARF_LINE_DEFAULT_IS_STMT_START 1 329350397Sobrien 329450397Sobrien/* This location is used by calc_die_sizes() to keep track 329550397Sobrien the offset of each DIE within the .debug_info section. */ 329650397Sobrienstatic unsigned long next_die_offset; 329750397Sobrien 329850397Sobrien/* Record the root of the DIE's built for the current compilation unit. */ 329950397Sobrienstatic dw_die_ref comp_unit_die; 330050397Sobrien 330150397Sobrien/* A list of DIEs with a NULL parent waiting to be relocated. */ 330250397Sobrienstatic limbo_die_node *limbo_die_list = 0; 330350397Sobrien 330490075Sobrien/* Structure used by lookup_filename to manage sets of filenames. */ 330590075Sobrienstruct file_table 330690075Sobrien{ 330790075Sobrien char **table; 330890075Sobrien unsigned allocated; 330990075Sobrien unsigned in_use; 331090075Sobrien unsigned last_lookup_index; 331190075Sobrien}; 331250397Sobrien 331350397Sobrien/* Size (in elements) of increments by which we may expand the filename 331450397Sobrien table. */ 331550397Sobrien#define FILE_TABLE_INCREMENT 64 331650397Sobrien 331790075Sobrien/* Filenames referenced by this compilation unit. */ 331890075Sobrienstatic struct file_table file_table; 331990075Sobrien 332050397Sobrien/* Local pointer to the name of the main input file. Initialized in 332150397Sobrien dwarf2out_init. */ 332290075Sobrienstatic const char *primary_filename; 332350397Sobrien 332450397Sobrien/* A pointer to the base of a table of references to DIE's that describe 332550397Sobrien declarations. The table is indexed by DECL_UID() which is a unique 332650397Sobrien number identifying each decl. */ 332750397Sobrienstatic dw_die_ref *decl_die_table; 332850397Sobrien 332950397Sobrien/* Number of elements currently allocated for the decl_die_table. */ 333050397Sobrienstatic unsigned decl_die_table_allocated; 333150397Sobrien 333250397Sobrien/* Number of elements in decl_die_table currently in use. */ 333350397Sobrienstatic unsigned decl_die_table_in_use; 333450397Sobrien 333550397Sobrien/* Size (in elements) of increments by which we may expand the 333650397Sobrien decl_die_table. */ 333750397Sobrien#define DECL_DIE_TABLE_INCREMENT 256 333850397Sobrien 333950397Sobrien/* A pointer to the base of a table of references to declaration 334050397Sobrien scopes. This table is a display which tracks the nesting 334150397Sobrien of declaration scopes at the current scope and containing 334250397Sobrien scopes. This table is used to find the proper place to 334350397Sobrien define type declaration DIE's. */ 334490075Sobrienvarray_type decl_scope_table; 334550397Sobrien 334650397Sobrien/* A pointer to the base of a list of references to DIE's that 334750397Sobrien are uniquely identified by their tag, presence/absence of 334850397Sobrien children DIE's, and list of attribute/value pairs. */ 334950397Sobrienstatic dw_die_ref *abbrev_die_table; 335050397Sobrien 335150397Sobrien/* Number of elements currently allocated for abbrev_die_table. */ 335250397Sobrienstatic unsigned abbrev_die_table_allocated; 335350397Sobrien 335450397Sobrien/* Number of elements in type_die_table currently in use. */ 335550397Sobrienstatic unsigned abbrev_die_table_in_use; 335650397Sobrien 335750397Sobrien/* Size (in elements) of increments by which we may expand the 335850397Sobrien abbrev_die_table. */ 335950397Sobrien#define ABBREV_DIE_TABLE_INCREMENT 256 336050397Sobrien 336150397Sobrien/* A pointer to the base of a table that contains line information 336250397Sobrien for each source code line in .text in the compilation unit. */ 336350397Sobrienstatic dw_line_info_ref line_info_table; 336450397Sobrien 336550397Sobrien/* Number of elements currently allocated for line_info_table. */ 336650397Sobrienstatic unsigned line_info_table_allocated; 336750397Sobrien 336850397Sobrien/* Number of elements in separate_line_info_table currently in use. */ 336950397Sobrienstatic unsigned separate_line_info_table_in_use; 337050397Sobrien 337150397Sobrien/* A pointer to the base of a table that contains line information 337250397Sobrien for each source code line outside of .text in the compilation unit. */ 337350397Sobrienstatic dw_separate_line_info_ref separate_line_info_table; 337450397Sobrien 337550397Sobrien/* Number of elements currently allocated for separate_line_info_table. */ 337650397Sobrienstatic unsigned separate_line_info_table_allocated; 337750397Sobrien 337850397Sobrien/* Number of elements in line_info_table currently in use. */ 337950397Sobrienstatic unsigned line_info_table_in_use; 338050397Sobrien 338150397Sobrien/* Size (in elements) of increments by which we may expand the 338250397Sobrien line_info_table. */ 338350397Sobrien#define LINE_INFO_TABLE_INCREMENT 1024 338450397Sobrien 338550397Sobrien/* A pointer to the base of a table that contains a list of publicly 338650397Sobrien accessible names. */ 338750397Sobrienstatic pubname_ref pubname_table; 338850397Sobrien 338950397Sobrien/* Number of elements currently allocated for pubname_table. */ 339050397Sobrienstatic unsigned pubname_table_allocated; 339150397Sobrien 339250397Sobrien/* Number of elements in pubname_table currently in use. */ 339350397Sobrienstatic unsigned pubname_table_in_use; 339450397Sobrien 339550397Sobrien/* Size (in elements) of increments by which we may expand the 339650397Sobrien pubname_table. */ 339750397Sobrien#define PUBNAME_TABLE_INCREMENT 64 339850397Sobrien 339990075Sobrien/* Array of dies for which we should generate .debug_arange info. */ 340090075Sobrienstatic dw_die_ref *arange_table; 340150397Sobrien 340250397Sobrien/* Number of elements currently allocated for arange_table. */ 340350397Sobrienstatic unsigned arange_table_allocated; 340450397Sobrien 340550397Sobrien/* Number of elements in arange_table currently in use. */ 340650397Sobrienstatic unsigned arange_table_in_use; 340750397Sobrien 340850397Sobrien/* Size (in elements) of increments by which we may expand the 340950397Sobrien arange_table. */ 341050397Sobrien#define ARANGE_TABLE_INCREMENT 64 341150397Sobrien 341290075Sobrien/* Array of dies for which we should generate .debug_ranges info. */ 341390075Sobrienstatic dw_ranges_ref ranges_table; 341450397Sobrien 341590075Sobrien/* Number of elements currently allocated for ranges_table. */ 341690075Sobrienstatic unsigned ranges_table_allocated; 341750397Sobrien 341890075Sobrien/* Number of elements in ranges_table currently in use. */ 341990075Sobrienstatic unsigned ranges_table_in_use; 342050397Sobrien 342190075Sobrien/* Size (in elements) of increments by which we may expand the 342290075Sobrien ranges_table. */ 342390075Sobrien#define RANGES_TABLE_INCREMENT 64 342450397Sobrien 342590075Sobrien/* Whether we have location lists that need outputting */ 342690075Sobrienstatic unsigned have_location_lists; 342750397Sobrien 342852284Sobrien/* A pointer to the base of a list of incomplete types which might be 342990075Sobrien completed at some later time. incomplete_types_list needs to be a VARRAY 343090075Sobrien because we want to tell the garbage collector about it. */ 343190075Sobrienvarray_type incomplete_types; 343252284Sobrien 343350397Sobrien/* Record whether the function being analyzed contains inlined functions. */ 343450397Sobrienstatic int current_function_has_inlines; 343550397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 343650397Sobrienstatic int comp_unit_has_inlines; 343750397Sobrien#endif 343850397Sobrien 343990075Sobrien/* Array of RTXes referenced by the debugging information, which therefore 344090075Sobrien must be kept around forever. This is a GC root. */ 344190075Sobrienstatic varray_type used_rtx_varray; 344250397Sobrien 344350397Sobrien/* Forward declarations for functions defined in this file. */ 344450397Sobrien 344590075Sobrienstatic int is_pseudo_reg PARAMS ((rtx)); 344690075Sobrienstatic tree type_main_variant PARAMS ((tree)); 344790075Sobrienstatic int is_tagged_type PARAMS ((tree)); 344890075Sobrienstatic const char *dwarf_tag_name PARAMS ((unsigned)); 344990075Sobrienstatic const char *dwarf_attr_name PARAMS ((unsigned)); 345090075Sobrienstatic const char *dwarf_form_name PARAMS ((unsigned)); 345150397Sobrien#if 0 345290075Sobrienstatic const char *dwarf_type_encoding_name PARAMS ((unsigned)); 345350397Sobrien#endif 345490075Sobrienstatic tree decl_ultimate_origin PARAMS ((tree)); 345590075Sobrienstatic tree block_ultimate_origin PARAMS ((tree)); 345690075Sobrienstatic tree decl_class_context PARAMS ((tree)); 345790075Sobrienstatic void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref)); 345890075Sobrienstatic inline dw_val_class AT_class PARAMS ((dw_attr_ref)); 345990075Sobrienstatic void add_AT_flag PARAMS ((dw_die_ref, 346090075Sobrien enum dwarf_attribute, 346190075Sobrien unsigned)); 346290075Sobrienstatic inline unsigned AT_flag PARAMS ((dw_attr_ref)); 346390075Sobrienstatic void add_AT_int PARAMS ((dw_die_ref, 346490075Sobrien enum dwarf_attribute, long)); 346590075Sobrienstatic inline long int AT_int PARAMS ((dw_attr_ref)); 346690075Sobrienstatic void add_AT_unsigned PARAMS ((dw_die_ref, 346790075Sobrien enum dwarf_attribute, 346890075Sobrien unsigned long)); 346990075Sobrienstatic inline unsigned long AT_unsigned PARAMS ((dw_attr_ref)); 347090075Sobrienstatic void add_AT_long_long PARAMS ((dw_die_ref, 347190075Sobrien enum dwarf_attribute, 347290075Sobrien unsigned long, 347390075Sobrien unsigned long)); 347490075Sobrienstatic void add_AT_float PARAMS ((dw_die_ref, 347590075Sobrien enum dwarf_attribute, 347690075Sobrien unsigned, long *)); 347790075Sobrienstatic void add_AT_string PARAMS ((dw_die_ref, 347890075Sobrien enum dwarf_attribute, 347990075Sobrien const char *)); 348090075Sobrienstatic inline const char *AT_string PARAMS ((dw_attr_ref)); 348190075Sobrienstatic int AT_string_form PARAMS ((dw_attr_ref)); 348290075Sobrienstatic void add_AT_die_ref PARAMS ((dw_die_ref, 348390075Sobrien enum dwarf_attribute, 348490075Sobrien dw_die_ref)); 348590075Sobrienstatic inline dw_die_ref AT_ref PARAMS ((dw_attr_ref)); 348690075Sobrienstatic inline int AT_ref_external PARAMS ((dw_attr_ref)); 348790075Sobrienstatic inline void set_AT_ref_external PARAMS ((dw_attr_ref, int)); 348890075Sobrienstatic void add_AT_fde_ref PARAMS ((dw_die_ref, 348990075Sobrien enum dwarf_attribute, 349090075Sobrien unsigned)); 349190075Sobrienstatic void add_AT_loc PARAMS ((dw_die_ref, 349290075Sobrien enum dwarf_attribute, 349390075Sobrien dw_loc_descr_ref)); 349490075Sobrienstatic inline dw_loc_descr_ref AT_loc PARAMS ((dw_attr_ref)); 349590075Sobrienstatic void add_AT_loc_list PARAMS ((dw_die_ref, 349690075Sobrien enum dwarf_attribute, 349790075Sobrien dw_loc_list_ref)); 349890075Sobrienstatic inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref)); 349990075Sobrienstatic void add_AT_addr PARAMS ((dw_die_ref, 350090075Sobrien enum dwarf_attribute, 350190075Sobrien rtx)); 350290075Sobrienstatic inline rtx AT_addr PARAMS ((dw_attr_ref)); 350390075Sobrienstatic void add_AT_lbl_id PARAMS ((dw_die_ref, 350490075Sobrien enum dwarf_attribute, 350590075Sobrien const char *)); 350690075Sobrienstatic void add_AT_lbl_offset PARAMS ((dw_die_ref, 350790075Sobrien enum dwarf_attribute, 350890075Sobrien const char *)); 350990075Sobrienstatic void add_AT_offset PARAMS ((dw_die_ref, 351090075Sobrien enum dwarf_attribute, 351190075Sobrien unsigned long)); 351290075Sobrienstatic void add_AT_range_list PARAMS ((dw_die_ref, 351390075Sobrien enum dwarf_attribute, 351490075Sobrien unsigned long)); 351590075Sobrienstatic inline const char *AT_lbl PARAMS ((dw_attr_ref)); 351690075Sobrienstatic dw_attr_ref get_AT PARAMS ((dw_die_ref, 351790075Sobrien enum dwarf_attribute)); 351890075Sobrienstatic const char *get_AT_low_pc PARAMS ((dw_die_ref)); 351990075Sobrienstatic const char *get_AT_hi_pc PARAMS ((dw_die_ref)); 352090075Sobrienstatic const char *get_AT_string PARAMS ((dw_die_ref, 352190075Sobrien enum dwarf_attribute)); 352290075Sobrienstatic int get_AT_flag PARAMS ((dw_die_ref, 352390075Sobrien enum dwarf_attribute)); 352490075Sobrienstatic unsigned get_AT_unsigned PARAMS ((dw_die_ref, 352590075Sobrien enum dwarf_attribute)); 352690075Sobrienstatic inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref, 352790075Sobrien enum dwarf_attribute)); 352890075Sobrienstatic int is_c_family PARAMS ((void)); 352990075Sobrienstatic int is_cxx PARAMS ((void)); 353090075Sobrienstatic int is_java PARAMS ((void)); 353190075Sobrienstatic int is_fortran PARAMS ((void)); 353290075Sobrienstatic void remove_AT PARAMS ((dw_die_ref, 353390075Sobrien enum dwarf_attribute)); 353490075Sobrienstatic inline void free_die PARAMS ((dw_die_ref)); 353590075Sobrienstatic void remove_children PARAMS ((dw_die_ref)); 353690075Sobrienstatic void add_child_die PARAMS ((dw_die_ref, dw_die_ref)); 353790075Sobrienstatic dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref, 353890075Sobrien tree)); 353990075Sobrienstatic dw_die_ref lookup_type_die PARAMS ((tree)); 354090075Sobrienstatic void equate_type_number_to_die PARAMS ((tree, dw_die_ref)); 354190075Sobrienstatic dw_die_ref lookup_decl_die PARAMS ((tree)); 354290075Sobrienstatic void equate_decl_number_to_die PARAMS ((tree, dw_die_ref)); 354390075Sobrienstatic void print_spaces PARAMS ((FILE *)); 354490075Sobrienstatic void print_die PARAMS ((dw_die_ref, FILE *)); 354590075Sobrienstatic void print_dwarf_line_table PARAMS ((FILE *)); 354690075Sobrienstatic void reverse_die_lists PARAMS ((dw_die_ref)); 354790075Sobrienstatic void reverse_all_dies PARAMS ((dw_die_ref)); 354890075Sobrienstatic dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref)); 354990075Sobrienstatic dw_die_ref pop_compile_unit PARAMS ((dw_die_ref)); 355090075Sobrienstatic void loc_checksum PARAMS ((dw_loc_descr_ref, 355190075Sobrien struct md5_ctx *)); 355290075Sobrienstatic void attr_checksum PARAMS ((dw_attr_ref, 355390075Sobrien struct md5_ctx *)); 355490075Sobrienstatic void die_checksum PARAMS ((dw_die_ref, 355590075Sobrien struct md5_ctx *)); 355690075Sobrienstatic void compute_section_prefix PARAMS ((dw_die_ref)); 355790075Sobrienstatic int is_type_die PARAMS ((dw_die_ref)); 355890075Sobrienstatic int is_comdat_die PARAMS ((dw_die_ref)); 355990075Sobrienstatic int is_symbol_die PARAMS ((dw_die_ref)); 356090075Sobrienstatic void assign_symbol_names PARAMS ((dw_die_ref)); 356190075Sobrienstatic void break_out_includes PARAMS ((dw_die_ref)); 356290075Sobrienstatic void add_sibling_attributes PARAMS ((dw_die_ref)); 356390075Sobrienstatic void build_abbrev_table PARAMS ((dw_die_ref)); 356490075Sobrienstatic void output_location_lists PARAMS ((dw_die_ref)); 356590075Sobrienstatic int constant_size PARAMS ((long unsigned)); 356690075Sobrienstatic unsigned long size_of_die PARAMS ((dw_die_ref)); 356790075Sobrienstatic void calc_die_sizes PARAMS ((dw_die_ref)); 356890075Sobrienstatic void mark_dies PARAMS ((dw_die_ref)); 356990075Sobrienstatic void unmark_dies PARAMS ((dw_die_ref)); 357090075Sobrienstatic unsigned long size_of_pubnames PARAMS ((void)); 357190075Sobrienstatic unsigned long size_of_aranges PARAMS ((void)); 357290075Sobrienstatic enum dwarf_form value_format PARAMS ((dw_attr_ref)); 357390075Sobrienstatic void output_value_format PARAMS ((dw_attr_ref)); 357490075Sobrienstatic void output_abbrev_section PARAMS ((void)); 357590075Sobrienstatic void output_die_symbol PARAMS ((dw_die_ref)); 357690075Sobrienstatic void output_die PARAMS ((dw_die_ref)); 357790075Sobrienstatic void output_compilation_unit_header PARAMS ((void)); 357890075Sobrienstatic void output_comp_unit PARAMS ((dw_die_ref)); 357990075Sobrienstatic const char *dwarf2_name PARAMS ((tree, int)); 358090075Sobrienstatic void add_pubname PARAMS ((tree, dw_die_ref)); 358190075Sobrienstatic void output_pubnames PARAMS ((void)); 358290075Sobrienstatic void add_arange PARAMS ((tree, dw_die_ref)); 358390075Sobrienstatic void output_aranges PARAMS ((void)); 358490075Sobrienstatic unsigned int add_ranges PARAMS ((tree)); 358590075Sobrienstatic void output_ranges PARAMS ((void)); 358690075Sobrienstatic void output_line_info PARAMS ((void)); 358790075Sobrienstatic void output_file_names PARAMS ((void)); 358890075Sobrienstatic dw_die_ref base_type_die PARAMS ((tree)); 358990075Sobrienstatic tree root_type PARAMS ((tree)); 359090075Sobrienstatic int is_base_type PARAMS ((tree)); 359190075Sobrienstatic dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref)); 359290075Sobrienstatic int type_is_enum PARAMS ((tree)); 359390075Sobrienstatic unsigned int reg_number PARAMS ((rtx)); 359490075Sobrienstatic dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx)); 359590075Sobrienstatic dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT)); 359690075Sobrienstatic dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long)); 359790075Sobrienstatic int is_based_loc PARAMS ((rtx)); 359890075Sobrienstatic dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode)); 359990075Sobrienstatic dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx)); 360090075Sobrienstatic dw_loc_descr_ref loc_descriptor PARAMS ((rtx)); 360190075Sobrienstatic dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int)); 360290075Sobrienstatic HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int)); 360390075Sobrienstatic tree field_type PARAMS ((tree)); 360490075Sobrienstatic unsigned int simple_type_align_in_bits PARAMS ((tree)); 360590075Sobrienstatic unsigned int simple_decl_align_in_bits PARAMS ((tree)); 360690075Sobrienstatic unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree)); 360790075Sobrienstatic HOST_WIDE_INT field_byte_offset PARAMS ((tree)); 360890075Sobrienstatic void add_AT_location_description PARAMS ((dw_die_ref, 360990075Sobrien enum dwarf_attribute, rtx)); 361090075Sobrienstatic void add_data_member_location_attribute PARAMS ((dw_die_ref, tree)); 361190075Sobrienstatic void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); 361290075Sobrienstatic rtx rtl_for_decl_location PARAMS ((tree)); 361390075Sobrienstatic void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree)); 361490075Sobrienstatic void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree)); 361590075Sobrienstatic void add_name_attribute PARAMS ((dw_die_ref, const char *)); 361690075Sobrienstatic void add_bound_info PARAMS ((dw_die_ref, 361790075Sobrien enum dwarf_attribute, tree)); 361890075Sobrienstatic void add_subscript_info PARAMS ((dw_die_ref, tree)); 361990075Sobrienstatic void add_byte_size_attribute PARAMS ((dw_die_ref, tree)); 362090075Sobrienstatic void add_bit_offset_attribute PARAMS ((dw_die_ref, tree)); 362190075Sobrienstatic void add_bit_size_attribute PARAMS ((dw_die_ref, tree)); 362290075Sobrienstatic void add_prototyped_attribute PARAMS ((dw_die_ref, tree)); 362390075Sobrienstatic void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree)); 362490075Sobrienstatic void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree)); 362590075Sobrienstatic void add_src_coords_attributes PARAMS ((dw_die_ref, tree)); 362690075Sobrienstatic void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree)); 362790075Sobrienstatic void push_decl_scope PARAMS ((tree)); 362890075Sobrienstatic void pop_decl_scope PARAMS ((void)); 362990075Sobrienstatic dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref)); 363090075Sobrienstatic inline int local_scope_p PARAMS ((dw_die_ref)); 363190075Sobrienstatic inline int class_scope_p PARAMS ((dw_die_ref)); 363290075Sobrienstatic void add_type_attribute PARAMS ((dw_die_ref, tree, int, int, 363390075Sobrien dw_die_ref)); 363490075Sobrienstatic const char *type_tag PARAMS ((tree)); 363590075Sobrienstatic tree member_declared_type PARAMS ((tree)); 363650397Sobrien#if 0 363790075Sobrienstatic const char *decl_start_label PARAMS ((tree)); 363850397Sobrien#endif 363990075Sobrienstatic void gen_array_type_die PARAMS ((tree, dw_die_ref)); 364090075Sobrienstatic void gen_set_type_die PARAMS ((tree, dw_die_ref)); 364150397Sobrien#if 0 364290075Sobrienstatic void gen_entry_point_die PARAMS ((tree, dw_die_ref)); 364350397Sobrien#endif 364490075Sobrienstatic void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref)); 364590075Sobrienstatic void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref)); 364690075Sobrienstatic void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref)); 364790075Sobrienstatic void gen_enumeration_type_die PARAMS ((tree, dw_die_ref)); 364890075Sobrienstatic dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref)); 364990075Sobrienstatic void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref)); 365090075Sobrienstatic void gen_formal_types_die PARAMS ((tree, dw_die_ref)); 365190075Sobrienstatic void gen_subprogram_die PARAMS ((tree, dw_die_ref)); 365290075Sobrienstatic void gen_variable_die PARAMS ((tree, dw_die_ref)); 365390075Sobrienstatic void gen_label_die PARAMS ((tree, dw_die_ref)); 365490075Sobrienstatic void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int)); 365590075Sobrienstatic void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int)); 365690075Sobrienstatic void gen_field_die PARAMS ((tree, dw_die_ref)); 365790075Sobrienstatic void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref)); 365890075Sobrienstatic dw_die_ref gen_compile_unit_die PARAMS ((const char *)); 365990075Sobrienstatic void gen_string_type_die PARAMS ((tree, dw_die_ref)); 366090075Sobrienstatic void gen_inheritance_die PARAMS ((tree, dw_die_ref)); 366190075Sobrienstatic void gen_member_die PARAMS ((tree, dw_die_ref)); 366290075Sobrienstatic void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref)); 366390075Sobrienstatic void gen_subroutine_type_die PARAMS ((tree, dw_die_ref)); 366490075Sobrienstatic void gen_typedef_die PARAMS ((tree, dw_die_ref)); 366590075Sobrienstatic void gen_type_die PARAMS ((tree, dw_die_ref)); 366690075Sobrienstatic void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref)); 366790075Sobrienstatic void gen_block_die PARAMS ((tree, dw_die_ref, int)); 366890075Sobrienstatic void decls_for_scope PARAMS ((tree, dw_die_ref, int)); 366990075Sobrienstatic int is_redundant_typedef PARAMS ((tree)); 367090075Sobrienstatic void gen_decl_die PARAMS ((tree, dw_die_ref)); 367190075Sobrienstatic unsigned lookup_filename PARAMS ((const char *)); 367290075Sobrienstatic void init_file_table PARAMS ((void)); 367390075Sobrienstatic void retry_incomplete_types PARAMS ((void)); 367490075Sobrienstatic void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); 367590075Sobrienstatic void splice_child_die PARAMS ((dw_die_ref, dw_die_ref)); 367690075Sobrienstatic int file_info_cmp PARAMS ((const void *, const void *)); 367790075Sobrienstatic dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref, 367890075Sobrien const char *, const char *, 367990075Sobrien const char *, unsigned)); 368090075Sobrienstatic void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *, 368190075Sobrien dw_loc_descr_ref, 368290075Sobrien const char *, const char *, const char *)); 368390075Sobrienstatic void output_loc_list PARAMS ((dw_loc_list_ref)); 368490075Sobrienstatic char *gen_internal_sym PARAMS ((const char *)); 368590075Sobrienstatic void mark_limbo_die_list PARAMS ((void *)); 368650397Sobrien 368750397Sobrien/* Section names used to hold DWARF debugging information. */ 368850397Sobrien#ifndef DEBUG_INFO_SECTION 368950397Sobrien#define DEBUG_INFO_SECTION ".debug_info" 369050397Sobrien#endif 369190075Sobrien#ifndef DEBUG_ABBREV_SECTION 369290075Sobrien#define DEBUG_ABBREV_SECTION ".debug_abbrev" 369350397Sobrien#endif 369490075Sobrien#ifndef DEBUG_ARANGES_SECTION 369590075Sobrien#define DEBUG_ARANGES_SECTION ".debug_aranges" 369650397Sobrien#endif 369790075Sobrien#ifndef DEBUG_MACINFO_SECTION 369890075Sobrien#define DEBUG_MACINFO_SECTION ".debug_macinfo" 369950397Sobrien#endif 370050397Sobrien#ifndef DEBUG_LINE_SECTION 370150397Sobrien#define DEBUG_LINE_SECTION ".debug_line" 370250397Sobrien#endif 370390075Sobrien#ifndef DEBUG_LOC_SECTION 370490075Sobrien#define DEBUG_LOC_SECTION ".debug_loc" 370550397Sobrien#endif 370690075Sobrien#ifndef DEBUG_PUBNAMES_SECTION 370790075Sobrien#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" 370850397Sobrien#endif 370990075Sobrien#ifndef DEBUG_STR_SECTION 371090075Sobrien#define DEBUG_STR_SECTION ".debug_str" 371150397Sobrien#endif 371290075Sobrien#ifndef DEBUG_RANGES_SECTION 371390075Sobrien#define DEBUG_RANGES_SECTION ".debug_ranges" 371490075Sobrien#endif 371550397Sobrien 371650397Sobrien/* Standard ELF section names for compiled code and data. */ 371790075Sobrien#ifndef TEXT_SECTION_NAME 371890075Sobrien#define TEXT_SECTION_NAME ".text" 371950397Sobrien#endif 372090075Sobrien 372190075Sobrien/* Section flags for .debug_str section. */ 372290075Sobrien#ifdef HAVE_GAS_SHF_MERGE 372390075Sobrien#define DEBUG_STR_SECTION_FLAGS \ 372490075Sobrien (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1) 372590075Sobrien#else 372690075Sobrien#define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG 372750397Sobrien#endif 372850397Sobrien 372952284Sobrien/* Labels we insert at beginning sections we can reference instead of 373090075Sobrien the section names themselves. */ 373150397Sobrien 373252284Sobrien#ifndef TEXT_SECTION_LABEL 373390075Sobrien#define TEXT_SECTION_LABEL "Ltext" 373452284Sobrien#endif 373552284Sobrien#ifndef DEBUG_LINE_SECTION_LABEL 373690075Sobrien#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" 373752284Sobrien#endif 373852284Sobrien#ifndef DEBUG_INFO_SECTION_LABEL 373990075Sobrien#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" 374052284Sobrien#endif 374190075Sobrien#ifndef DEBUG_ABBREV_SECTION_LABEL 374290075Sobrien#define DEBUG_ABBREV_SECTION_LABEL "Ldebug_abbrev" 374352284Sobrien#endif 374490075Sobrien#ifndef DEBUG_LOC_SECTION_LABEL 374590075Sobrien#define DEBUG_LOC_SECTION_LABEL "Ldebug_loc" 374690075Sobrien#endif 374790075Sobrien#ifndef DEBUG_RANGES_SECTION_LABEL 374890075Sobrien#define DEBUG_RANGES_SECTION_LABEL "Ldebug_ranges" 374990075Sobrien#endif 375090075Sobrien#ifndef DEBUG_MACINFO_SECTION_LABEL 375190075Sobrien#define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo" 375290075Sobrien#endif 375352284Sobrien 375450397Sobrien/* Definitions of defaults for formats and names of various special 375550397Sobrien (artificial) labels which may be generated within this file (when the -g 375650397Sobrien options is used and DWARF_DEBUGGING_INFO is in effect. 375750397Sobrien If necessary, these may be overridden from within the tm.h file, but 375850397Sobrien typically, overriding these defaults is unnecessary. */ 375950397Sobrien 376050397Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376152284Sobrienstatic char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376252284Sobrienstatic char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376352284Sobrienstatic char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376452284Sobrienstatic char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376590075Sobrienstatic char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376690075Sobrienstatic char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 376790075Sobrienstatic char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; 376850397Sobrien 376950397Sobrien#ifndef TEXT_END_LABEL 377050397Sobrien#define TEXT_END_LABEL "Letext" 377150397Sobrien#endif 377250397Sobrien#ifndef DATA_END_LABEL 377350397Sobrien#define DATA_END_LABEL "Ledata" 377450397Sobrien#endif 377550397Sobrien#ifndef BSS_END_LABEL 377650397Sobrien#define BSS_END_LABEL "Lebss" 377750397Sobrien#endif 377850397Sobrien#ifndef BLOCK_BEGIN_LABEL 377950397Sobrien#define BLOCK_BEGIN_LABEL "LBB" 378050397Sobrien#endif 378150397Sobrien#ifndef BLOCK_END_LABEL 378250397Sobrien#define BLOCK_END_LABEL "LBE" 378350397Sobrien#endif 378450397Sobrien#ifndef BODY_BEGIN_LABEL 378550397Sobrien#define BODY_BEGIN_LABEL "Lbb" 378650397Sobrien#endif 378750397Sobrien#ifndef BODY_END_LABEL 378850397Sobrien#define BODY_END_LABEL "Lbe" 378950397Sobrien#endif 379050397Sobrien#ifndef LINE_CODE_LABEL 379150397Sobrien#define LINE_CODE_LABEL "LM" 379250397Sobrien#endif 379350397Sobrien#ifndef SEPARATE_LINE_CODE_LABEL 379450397Sobrien#define SEPARATE_LINE_CODE_LABEL "LSM" 379550397Sobrien#endif 379650397Sobrien 379790075Sobrien/* We allow a language front-end to designate a function that is to be 379890075Sobrien called to "demangle" any name before it it put into a DIE. */ 379950397Sobrien 380090075Sobrienstatic const char *(*demangle_name_func) PARAMS ((const char *)); 380150397Sobrien 380290075Sobrienvoid 380390075Sobriendwarf2out_set_demangle_name_func (func) 380490075Sobrien const char *(*func) PARAMS ((const char *)); 380550397Sobrien{ 380690075Sobrien demangle_name_func = func; 380750397Sobrien} 380850397Sobrien 380950397Sobrien/* Test if rtl node points to a pseudo register. */ 381050397Sobrien 381150397Sobrienstatic inline int 381250397Sobrienis_pseudo_reg (rtl) 381390075Sobrien rtx rtl; 381450397Sobrien{ 381590075Sobrien return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 381690075Sobrien || (GET_CODE (rtl) == SUBREG 381790075Sobrien && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)); 381850397Sobrien} 381950397Sobrien 382050397Sobrien/* Return a reference to a type, with its const and volatile qualifiers 382150397Sobrien removed. */ 382250397Sobrien 382350397Sobrienstatic inline tree 382450397Sobrientype_main_variant (type) 382590075Sobrien tree type; 382650397Sobrien{ 382750397Sobrien type = TYPE_MAIN_VARIANT (type); 382850397Sobrien 382990075Sobrien /* ??? There really should be only one main variant among any group of 383090075Sobrien variants of a given type (and all of the MAIN_VARIANT values for all 383190075Sobrien members of the group should point to that one type) but sometimes the C 383290075Sobrien front-end messes this up for array types, so we work around that bug 383390075Sobrien here. */ 383450397Sobrien if (TREE_CODE (type) == ARRAY_TYPE) 383550397Sobrien while (type != TYPE_MAIN_VARIANT (type)) 383650397Sobrien type = TYPE_MAIN_VARIANT (type); 383750397Sobrien 383850397Sobrien return type; 383950397Sobrien} 384050397Sobrien 384150397Sobrien/* Return non-zero if the given type node represents a tagged type. */ 384250397Sobrien 384350397Sobrienstatic inline int 384450397Sobrienis_tagged_type (type) 384590075Sobrien tree type; 384650397Sobrien{ 384790075Sobrien enum tree_code code = TREE_CODE (type); 384850397Sobrien 384950397Sobrien return (code == RECORD_TYPE || code == UNION_TYPE 385050397Sobrien || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE); 385150397Sobrien} 385250397Sobrien 385350397Sobrien/* Convert a DIE tag into its string name. */ 385450397Sobrien 385590075Sobrienstatic const char * 385650397Sobriendwarf_tag_name (tag) 385790075Sobrien unsigned tag; 385850397Sobrien{ 385950397Sobrien switch (tag) 386050397Sobrien { 386150397Sobrien case DW_TAG_padding: 386250397Sobrien return "DW_TAG_padding"; 386350397Sobrien case DW_TAG_array_type: 386450397Sobrien return "DW_TAG_array_type"; 386550397Sobrien case DW_TAG_class_type: 386650397Sobrien return "DW_TAG_class_type"; 386750397Sobrien case DW_TAG_entry_point: 386850397Sobrien return "DW_TAG_entry_point"; 386950397Sobrien case DW_TAG_enumeration_type: 387050397Sobrien return "DW_TAG_enumeration_type"; 387150397Sobrien case DW_TAG_formal_parameter: 387250397Sobrien return "DW_TAG_formal_parameter"; 387350397Sobrien case DW_TAG_imported_declaration: 387450397Sobrien return "DW_TAG_imported_declaration"; 387550397Sobrien case DW_TAG_label: 387650397Sobrien return "DW_TAG_label"; 387750397Sobrien case DW_TAG_lexical_block: 387850397Sobrien return "DW_TAG_lexical_block"; 387950397Sobrien case DW_TAG_member: 388050397Sobrien return "DW_TAG_member"; 388150397Sobrien case DW_TAG_pointer_type: 388250397Sobrien return "DW_TAG_pointer_type"; 388350397Sobrien case DW_TAG_reference_type: 388450397Sobrien return "DW_TAG_reference_type"; 388550397Sobrien case DW_TAG_compile_unit: 388650397Sobrien return "DW_TAG_compile_unit"; 388750397Sobrien case DW_TAG_string_type: 388850397Sobrien return "DW_TAG_string_type"; 388950397Sobrien case DW_TAG_structure_type: 389050397Sobrien return "DW_TAG_structure_type"; 389150397Sobrien case DW_TAG_subroutine_type: 389250397Sobrien return "DW_TAG_subroutine_type"; 389350397Sobrien case DW_TAG_typedef: 389450397Sobrien return "DW_TAG_typedef"; 389550397Sobrien case DW_TAG_union_type: 389650397Sobrien return "DW_TAG_union_type"; 389750397Sobrien case DW_TAG_unspecified_parameters: 389850397Sobrien return "DW_TAG_unspecified_parameters"; 389950397Sobrien case DW_TAG_variant: 390050397Sobrien return "DW_TAG_variant"; 390150397Sobrien case DW_TAG_common_block: 390250397Sobrien return "DW_TAG_common_block"; 390350397Sobrien case DW_TAG_common_inclusion: 390450397Sobrien return "DW_TAG_common_inclusion"; 390550397Sobrien case DW_TAG_inheritance: 390650397Sobrien return "DW_TAG_inheritance"; 390750397Sobrien case DW_TAG_inlined_subroutine: 390850397Sobrien return "DW_TAG_inlined_subroutine"; 390950397Sobrien case DW_TAG_module: 391050397Sobrien return "DW_TAG_module"; 391150397Sobrien case DW_TAG_ptr_to_member_type: 391250397Sobrien return "DW_TAG_ptr_to_member_type"; 391350397Sobrien case DW_TAG_set_type: 391450397Sobrien return "DW_TAG_set_type"; 391550397Sobrien case DW_TAG_subrange_type: 391650397Sobrien return "DW_TAG_subrange_type"; 391750397Sobrien case DW_TAG_with_stmt: 391850397Sobrien return "DW_TAG_with_stmt"; 391950397Sobrien case DW_TAG_access_declaration: 392050397Sobrien return "DW_TAG_access_declaration"; 392150397Sobrien case DW_TAG_base_type: 392250397Sobrien return "DW_TAG_base_type"; 392350397Sobrien case DW_TAG_catch_block: 392450397Sobrien return "DW_TAG_catch_block"; 392550397Sobrien case DW_TAG_const_type: 392650397Sobrien return "DW_TAG_const_type"; 392750397Sobrien case DW_TAG_constant: 392850397Sobrien return "DW_TAG_constant"; 392950397Sobrien case DW_TAG_enumerator: 393050397Sobrien return "DW_TAG_enumerator"; 393150397Sobrien case DW_TAG_file_type: 393250397Sobrien return "DW_TAG_file_type"; 393350397Sobrien case DW_TAG_friend: 393450397Sobrien return "DW_TAG_friend"; 393550397Sobrien case DW_TAG_namelist: 393650397Sobrien return "DW_TAG_namelist"; 393750397Sobrien case DW_TAG_namelist_item: 393850397Sobrien return "DW_TAG_namelist_item"; 393950397Sobrien case DW_TAG_packed_type: 394050397Sobrien return "DW_TAG_packed_type"; 394150397Sobrien case DW_TAG_subprogram: 394250397Sobrien return "DW_TAG_subprogram"; 394350397Sobrien case DW_TAG_template_type_param: 394450397Sobrien return "DW_TAG_template_type_param"; 394550397Sobrien case DW_TAG_template_value_param: 394650397Sobrien return "DW_TAG_template_value_param"; 394750397Sobrien case DW_TAG_thrown_type: 394850397Sobrien return "DW_TAG_thrown_type"; 394950397Sobrien case DW_TAG_try_block: 395050397Sobrien return "DW_TAG_try_block"; 395150397Sobrien case DW_TAG_variant_part: 395250397Sobrien return "DW_TAG_variant_part"; 395350397Sobrien case DW_TAG_variable: 395450397Sobrien return "DW_TAG_variable"; 395550397Sobrien case DW_TAG_volatile_type: 395650397Sobrien return "DW_TAG_volatile_type"; 395750397Sobrien case DW_TAG_MIPS_loop: 395850397Sobrien return "DW_TAG_MIPS_loop"; 395950397Sobrien case DW_TAG_format_label: 396050397Sobrien return "DW_TAG_format_label"; 396150397Sobrien case DW_TAG_function_template: 396250397Sobrien return "DW_TAG_function_template"; 396350397Sobrien case DW_TAG_class_template: 396450397Sobrien return "DW_TAG_class_template"; 396590075Sobrien case DW_TAG_GNU_BINCL: 396690075Sobrien return "DW_TAG_GNU_BINCL"; 396790075Sobrien case DW_TAG_GNU_EINCL: 396890075Sobrien return "DW_TAG_GNU_EINCL"; 396950397Sobrien default: 397050397Sobrien return "DW_TAG_<unknown>"; 397150397Sobrien } 397250397Sobrien} 397350397Sobrien 397450397Sobrien/* Convert a DWARF attribute code into its string name. */ 397550397Sobrien 397690075Sobrienstatic const char * 397750397Sobriendwarf_attr_name (attr) 397890075Sobrien unsigned attr; 397950397Sobrien{ 398050397Sobrien switch (attr) 398150397Sobrien { 398250397Sobrien case DW_AT_sibling: 398350397Sobrien return "DW_AT_sibling"; 398450397Sobrien case DW_AT_location: 398550397Sobrien return "DW_AT_location"; 398650397Sobrien case DW_AT_name: 398750397Sobrien return "DW_AT_name"; 398850397Sobrien case DW_AT_ordering: 398950397Sobrien return "DW_AT_ordering"; 399050397Sobrien case DW_AT_subscr_data: 399150397Sobrien return "DW_AT_subscr_data"; 399250397Sobrien case DW_AT_byte_size: 399350397Sobrien return "DW_AT_byte_size"; 399450397Sobrien case DW_AT_bit_offset: 399550397Sobrien return "DW_AT_bit_offset"; 399650397Sobrien case DW_AT_bit_size: 399750397Sobrien return "DW_AT_bit_size"; 399850397Sobrien case DW_AT_element_list: 399950397Sobrien return "DW_AT_element_list"; 400050397Sobrien case DW_AT_stmt_list: 400150397Sobrien return "DW_AT_stmt_list"; 400250397Sobrien case DW_AT_low_pc: 400350397Sobrien return "DW_AT_low_pc"; 400450397Sobrien case DW_AT_high_pc: 400550397Sobrien return "DW_AT_high_pc"; 400650397Sobrien case DW_AT_language: 400750397Sobrien return "DW_AT_language"; 400850397Sobrien case DW_AT_member: 400950397Sobrien return "DW_AT_member"; 401050397Sobrien case DW_AT_discr: 401150397Sobrien return "DW_AT_discr"; 401250397Sobrien case DW_AT_discr_value: 401350397Sobrien return "DW_AT_discr_value"; 401450397Sobrien case DW_AT_visibility: 401550397Sobrien return "DW_AT_visibility"; 401650397Sobrien case DW_AT_import: 401750397Sobrien return "DW_AT_import"; 401850397Sobrien case DW_AT_string_length: 401950397Sobrien return "DW_AT_string_length"; 402050397Sobrien case DW_AT_common_reference: 402150397Sobrien return "DW_AT_common_reference"; 402250397Sobrien case DW_AT_comp_dir: 402350397Sobrien return "DW_AT_comp_dir"; 402450397Sobrien case DW_AT_const_value: 402550397Sobrien return "DW_AT_const_value"; 402650397Sobrien case DW_AT_containing_type: 402750397Sobrien return "DW_AT_containing_type"; 402850397Sobrien case DW_AT_default_value: 402950397Sobrien return "DW_AT_default_value"; 403050397Sobrien case DW_AT_inline: 403150397Sobrien return "DW_AT_inline"; 403250397Sobrien case DW_AT_is_optional: 403350397Sobrien return "DW_AT_is_optional"; 403450397Sobrien case DW_AT_lower_bound: 403550397Sobrien return "DW_AT_lower_bound"; 403650397Sobrien case DW_AT_producer: 403750397Sobrien return "DW_AT_producer"; 403850397Sobrien case DW_AT_prototyped: 403950397Sobrien return "DW_AT_prototyped"; 404050397Sobrien case DW_AT_return_addr: 404150397Sobrien return "DW_AT_return_addr"; 404250397Sobrien case DW_AT_start_scope: 404350397Sobrien return "DW_AT_start_scope"; 404450397Sobrien case DW_AT_stride_size: 404550397Sobrien return "DW_AT_stride_size"; 404650397Sobrien case DW_AT_upper_bound: 404750397Sobrien return "DW_AT_upper_bound"; 404850397Sobrien case DW_AT_abstract_origin: 404950397Sobrien return "DW_AT_abstract_origin"; 405050397Sobrien case DW_AT_accessibility: 405150397Sobrien return "DW_AT_accessibility"; 405250397Sobrien case DW_AT_address_class: 405350397Sobrien return "DW_AT_address_class"; 405450397Sobrien case DW_AT_artificial: 405550397Sobrien return "DW_AT_artificial"; 405650397Sobrien case DW_AT_base_types: 405750397Sobrien return "DW_AT_base_types"; 405850397Sobrien case DW_AT_calling_convention: 405950397Sobrien return "DW_AT_calling_convention"; 406050397Sobrien case DW_AT_count: 406150397Sobrien return "DW_AT_count"; 406250397Sobrien case DW_AT_data_member_location: 406350397Sobrien return "DW_AT_data_member_location"; 406450397Sobrien case DW_AT_decl_column: 406550397Sobrien return "DW_AT_decl_column"; 406650397Sobrien case DW_AT_decl_file: 406750397Sobrien return "DW_AT_decl_file"; 406850397Sobrien case DW_AT_decl_line: 406950397Sobrien return "DW_AT_decl_line"; 407050397Sobrien case DW_AT_declaration: 407150397Sobrien return "DW_AT_declaration"; 407250397Sobrien case DW_AT_discr_list: 407350397Sobrien return "DW_AT_discr_list"; 407450397Sobrien case DW_AT_encoding: 407550397Sobrien return "DW_AT_encoding"; 407650397Sobrien case DW_AT_external: 407750397Sobrien return "DW_AT_external"; 407850397Sobrien case DW_AT_frame_base: 407950397Sobrien return "DW_AT_frame_base"; 408050397Sobrien case DW_AT_friend: 408150397Sobrien return "DW_AT_friend"; 408250397Sobrien case DW_AT_identifier_case: 408350397Sobrien return "DW_AT_identifier_case"; 408450397Sobrien case DW_AT_macro_info: 408550397Sobrien return "DW_AT_macro_info"; 408650397Sobrien case DW_AT_namelist_items: 408750397Sobrien return "DW_AT_namelist_items"; 408850397Sobrien case DW_AT_priority: 408950397Sobrien return "DW_AT_priority"; 409050397Sobrien case DW_AT_segment: 409150397Sobrien return "DW_AT_segment"; 409250397Sobrien case DW_AT_specification: 409350397Sobrien return "DW_AT_specification"; 409450397Sobrien case DW_AT_static_link: 409550397Sobrien return "DW_AT_static_link"; 409650397Sobrien case DW_AT_type: 409750397Sobrien return "DW_AT_type"; 409850397Sobrien case DW_AT_use_location: 409950397Sobrien return "DW_AT_use_location"; 410050397Sobrien case DW_AT_variable_parameter: 410150397Sobrien return "DW_AT_variable_parameter"; 410250397Sobrien case DW_AT_virtuality: 410350397Sobrien return "DW_AT_virtuality"; 410450397Sobrien case DW_AT_vtable_elem_location: 410550397Sobrien return "DW_AT_vtable_elem_location"; 410650397Sobrien 410790075Sobrien case DW_AT_allocated: 410890075Sobrien return "DW_AT_allocated"; 410990075Sobrien case DW_AT_associated: 411090075Sobrien return "DW_AT_associated"; 411190075Sobrien case DW_AT_data_location: 411290075Sobrien return "DW_AT_data_location"; 411390075Sobrien case DW_AT_stride: 411490075Sobrien return "DW_AT_stride"; 411590075Sobrien case DW_AT_entry_pc: 411690075Sobrien return "DW_AT_entry_pc"; 411790075Sobrien case DW_AT_use_UTF8: 411890075Sobrien return "DW_AT_use_UTF8"; 411990075Sobrien case DW_AT_extension: 412090075Sobrien return "DW_AT_extension"; 412190075Sobrien case DW_AT_ranges: 412290075Sobrien return "DW_AT_ranges"; 412390075Sobrien case DW_AT_trampoline: 412490075Sobrien return "DW_AT_trampoline"; 412590075Sobrien case DW_AT_call_column: 412690075Sobrien return "DW_AT_call_column"; 412790075Sobrien case DW_AT_call_file: 412890075Sobrien return "DW_AT_call_file"; 412990075Sobrien case DW_AT_call_line: 413090075Sobrien return "DW_AT_call_line"; 413190075Sobrien 413250397Sobrien case DW_AT_MIPS_fde: 413350397Sobrien return "DW_AT_MIPS_fde"; 413450397Sobrien case DW_AT_MIPS_loop_begin: 413550397Sobrien return "DW_AT_MIPS_loop_begin"; 413650397Sobrien case DW_AT_MIPS_tail_loop_begin: 413750397Sobrien return "DW_AT_MIPS_tail_loop_begin"; 413850397Sobrien case DW_AT_MIPS_epilog_begin: 413950397Sobrien return "DW_AT_MIPS_epilog_begin"; 414050397Sobrien case DW_AT_MIPS_loop_unroll_factor: 414150397Sobrien return "DW_AT_MIPS_loop_unroll_factor"; 414250397Sobrien case DW_AT_MIPS_software_pipeline_depth: 414350397Sobrien return "DW_AT_MIPS_software_pipeline_depth"; 414450397Sobrien case DW_AT_MIPS_linkage_name: 414550397Sobrien return "DW_AT_MIPS_linkage_name"; 414650397Sobrien case DW_AT_MIPS_stride: 414750397Sobrien return "DW_AT_MIPS_stride"; 414850397Sobrien case DW_AT_MIPS_abstract_name: 414950397Sobrien return "DW_AT_MIPS_abstract_name"; 415050397Sobrien case DW_AT_MIPS_clone_origin: 415150397Sobrien return "DW_AT_MIPS_clone_origin"; 415250397Sobrien case DW_AT_MIPS_has_inlines: 415350397Sobrien return "DW_AT_MIPS_has_inlines"; 415450397Sobrien 415550397Sobrien case DW_AT_sf_names: 415650397Sobrien return "DW_AT_sf_names"; 415750397Sobrien case DW_AT_src_info: 415850397Sobrien return "DW_AT_src_info"; 415950397Sobrien case DW_AT_mac_info: 416050397Sobrien return "DW_AT_mac_info"; 416150397Sobrien case DW_AT_src_coords: 416250397Sobrien return "DW_AT_src_coords"; 416350397Sobrien case DW_AT_body_begin: 416450397Sobrien return "DW_AT_body_begin"; 416550397Sobrien case DW_AT_body_end: 416650397Sobrien return "DW_AT_body_end"; 416790075Sobrien case DW_AT_VMS_rtnbeg_pd_address: 416890075Sobrien return "DW_AT_VMS_rtnbeg_pd_address"; 416990075Sobrien 417050397Sobrien default: 417150397Sobrien return "DW_AT_<unknown>"; 417250397Sobrien } 417350397Sobrien} 417450397Sobrien 417550397Sobrien/* Convert a DWARF value form code into its string name. */ 417650397Sobrien 417790075Sobrienstatic const char * 417850397Sobriendwarf_form_name (form) 417990075Sobrien unsigned form; 418050397Sobrien{ 418150397Sobrien switch (form) 418250397Sobrien { 418350397Sobrien case DW_FORM_addr: 418450397Sobrien return "DW_FORM_addr"; 418550397Sobrien case DW_FORM_block2: 418650397Sobrien return "DW_FORM_block2"; 418750397Sobrien case DW_FORM_block4: 418850397Sobrien return "DW_FORM_block4"; 418950397Sobrien case DW_FORM_data2: 419050397Sobrien return "DW_FORM_data2"; 419150397Sobrien case DW_FORM_data4: 419250397Sobrien return "DW_FORM_data4"; 419350397Sobrien case DW_FORM_data8: 419450397Sobrien return "DW_FORM_data8"; 419550397Sobrien case DW_FORM_string: 419650397Sobrien return "DW_FORM_string"; 419750397Sobrien case DW_FORM_block: 419850397Sobrien return "DW_FORM_block"; 419950397Sobrien case DW_FORM_block1: 420050397Sobrien return "DW_FORM_block1"; 420150397Sobrien case DW_FORM_data1: 420250397Sobrien return "DW_FORM_data1"; 420350397Sobrien case DW_FORM_flag: 420450397Sobrien return "DW_FORM_flag"; 420550397Sobrien case DW_FORM_sdata: 420650397Sobrien return "DW_FORM_sdata"; 420750397Sobrien case DW_FORM_strp: 420850397Sobrien return "DW_FORM_strp"; 420950397Sobrien case DW_FORM_udata: 421050397Sobrien return "DW_FORM_udata"; 421150397Sobrien case DW_FORM_ref_addr: 421250397Sobrien return "DW_FORM_ref_addr"; 421350397Sobrien case DW_FORM_ref1: 421450397Sobrien return "DW_FORM_ref1"; 421550397Sobrien case DW_FORM_ref2: 421650397Sobrien return "DW_FORM_ref2"; 421750397Sobrien case DW_FORM_ref4: 421850397Sobrien return "DW_FORM_ref4"; 421950397Sobrien case DW_FORM_ref8: 422050397Sobrien return "DW_FORM_ref8"; 422150397Sobrien case DW_FORM_ref_udata: 422250397Sobrien return "DW_FORM_ref_udata"; 422350397Sobrien case DW_FORM_indirect: 422450397Sobrien return "DW_FORM_indirect"; 422550397Sobrien default: 422650397Sobrien return "DW_FORM_<unknown>"; 422750397Sobrien } 422850397Sobrien} 422950397Sobrien 423050397Sobrien/* Convert a DWARF type code into its string name. */ 423150397Sobrien 423250397Sobrien#if 0 423390075Sobrienstatic const char * 423450397Sobriendwarf_type_encoding_name (enc) 423590075Sobrien unsigned enc; 423650397Sobrien{ 423750397Sobrien switch (enc) 423850397Sobrien { 423950397Sobrien case DW_ATE_address: 424050397Sobrien return "DW_ATE_address"; 424150397Sobrien case DW_ATE_boolean: 424250397Sobrien return "DW_ATE_boolean"; 424350397Sobrien case DW_ATE_complex_float: 424450397Sobrien return "DW_ATE_complex_float"; 424550397Sobrien case DW_ATE_float: 424650397Sobrien return "DW_ATE_float"; 424750397Sobrien case DW_ATE_signed: 424850397Sobrien return "DW_ATE_signed"; 424950397Sobrien case DW_ATE_signed_char: 425050397Sobrien return "DW_ATE_signed_char"; 425150397Sobrien case DW_ATE_unsigned: 425250397Sobrien return "DW_ATE_unsigned"; 425350397Sobrien case DW_ATE_unsigned_char: 425450397Sobrien return "DW_ATE_unsigned_char"; 425550397Sobrien default: 425650397Sobrien return "DW_ATE_<unknown>"; 425750397Sobrien } 425850397Sobrien} 425950397Sobrien#endif 426050397Sobrien 426150397Sobrien/* Determine the "ultimate origin" of a decl. The decl may be an inlined 426250397Sobrien instance of an inlined instance of a decl which is local to an inline 426350397Sobrien function, so we have to trace all of the way back through the origin chain 426450397Sobrien to find out what sort of node actually served as the original seed for the 426550397Sobrien given block. */ 426650397Sobrien 426750397Sobrienstatic tree 426850397Sobriendecl_ultimate_origin (decl) 426990075Sobrien tree decl; 427050397Sobrien{ 427190075Sobrien /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the 427290075Sobrien nodes in the function to point to themselves; ignore that if 427390075Sobrien we're trying to output the abstract instance of this function. */ 427490075Sobrien if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl) 427590075Sobrien return NULL_TREE; 427690075Sobrien 427790075Sobrien#ifdef ENABLE_CHECKING 427852284Sobrien if (DECL_FROM_INLINE (DECL_ORIGIN (decl))) 427952284Sobrien /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the 428052284Sobrien most distant ancestor, this should never happen. */ 428152284Sobrien abort (); 428252284Sobrien#endif 428350397Sobrien 428452284Sobrien return DECL_ABSTRACT_ORIGIN (decl); 428550397Sobrien} 428650397Sobrien 428750397Sobrien/* Determine the "ultimate origin" of a block. The block may be an inlined 428850397Sobrien instance of an inlined instance of a block which is local to an inline 428950397Sobrien function, so we have to trace all of the way back through the origin chain 429050397Sobrien to find out what sort of node actually served as the original seed for the 429150397Sobrien given block. */ 429250397Sobrien 429350397Sobrienstatic tree 429450397Sobrienblock_ultimate_origin (block) 429590075Sobrien tree block; 429650397Sobrien{ 429790075Sobrien tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); 429850397Sobrien 429990075Sobrien /* output_inline_function sets BLOCK_ABSTRACT_ORIGIN for all the 430090075Sobrien nodes in the function to point to themselves; ignore that if 430190075Sobrien we're trying to output the abstract instance of this function. */ 430290075Sobrien if (BLOCK_ABSTRACT (block) && immediate_origin == block) 430390075Sobrien return NULL_TREE; 430490075Sobrien 430550397Sobrien if (immediate_origin == NULL_TREE) 430650397Sobrien return NULL_TREE; 430750397Sobrien else 430850397Sobrien { 430990075Sobrien tree ret_val; 431090075Sobrien tree lookahead = immediate_origin; 431150397Sobrien 431250397Sobrien do 431350397Sobrien { 431450397Sobrien ret_val = lookahead; 431590075Sobrien lookahead = (TREE_CODE (ret_val) == BLOCK 431690075Sobrien ? BLOCK_ABSTRACT_ORIGIN (ret_val) : NULL); 431750397Sobrien } 431850397Sobrien while (lookahead != NULL && lookahead != ret_val); 431950397Sobrien 432050397Sobrien return ret_val; 432150397Sobrien } 432250397Sobrien} 432350397Sobrien 432450397Sobrien/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT 432550397Sobrien of a virtual function may refer to a base class, so we check the 'this' 432650397Sobrien parameter. */ 432750397Sobrien 432850397Sobrienstatic tree 432950397Sobriendecl_class_context (decl) 433050397Sobrien tree decl; 433150397Sobrien{ 433250397Sobrien tree context = NULL_TREE; 433350397Sobrien 433450397Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl)) 433550397Sobrien context = DECL_CONTEXT (decl); 433650397Sobrien else 433750397Sobrien context = TYPE_MAIN_VARIANT 433850397Sobrien (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); 433950397Sobrien 434090075Sobrien if (context && !TYPE_P (context)) 434150397Sobrien context = NULL_TREE; 434250397Sobrien 434350397Sobrien return context; 434450397Sobrien} 434550397Sobrien 434690075Sobrien/* Add an attribute/value pair to a DIE. We build the lists up in reverse 434790075Sobrien addition order, and correct that in reverse_all_dies. */ 434850397Sobrien 434950397Sobrienstatic inline void 435050397Sobrienadd_dwarf_attr (die, attr) 435190075Sobrien dw_die_ref die; 435290075Sobrien dw_attr_ref attr; 435350397Sobrien{ 435450397Sobrien if (die != NULL && attr != NULL) 435550397Sobrien { 435690075Sobrien attr->dw_attr_next = die->die_attr; 435790075Sobrien die->die_attr = attr; 435850397Sobrien } 435950397Sobrien} 436050397Sobrien 436190075Sobrienstatic inline dw_val_class 436290075SobrienAT_class (a) 436390075Sobrien dw_attr_ref a; 436490075Sobrien{ 436590075Sobrien return a->dw_attr_val.val_class; 436690075Sobrien} 436790075Sobrien 436850397Sobrien/* Add a flag value attribute to a DIE. */ 436950397Sobrien 437050397Sobrienstatic inline void 437150397Sobrienadd_AT_flag (die, attr_kind, flag) 437290075Sobrien dw_die_ref die; 437390075Sobrien enum dwarf_attribute attr_kind; 437490075Sobrien unsigned flag; 437550397Sobrien{ 437690075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 437750397Sobrien 437850397Sobrien attr->dw_attr_next = NULL; 437950397Sobrien attr->dw_attr = attr_kind; 438050397Sobrien attr->dw_attr_val.val_class = dw_val_class_flag; 438150397Sobrien attr->dw_attr_val.v.val_flag = flag; 438250397Sobrien add_dwarf_attr (die, attr); 438350397Sobrien} 438450397Sobrien 438590075Sobrienstatic inline unsigned 438690075SobrienAT_flag (a) 438790075Sobrien dw_attr_ref a; 438890075Sobrien{ 438990075Sobrien if (a && AT_class (a) == dw_val_class_flag) 439090075Sobrien return a->dw_attr_val.v.val_flag; 439190075Sobrien 439290075Sobrien abort (); 439390075Sobrien} 439490075Sobrien 439550397Sobrien/* Add a signed integer attribute value to a DIE. */ 439650397Sobrien 439750397Sobrienstatic inline void 439850397Sobrienadd_AT_int (die, attr_kind, int_val) 439990075Sobrien dw_die_ref die; 440090075Sobrien enum dwarf_attribute attr_kind; 440190075Sobrien long int int_val; 440250397Sobrien{ 440390075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 440450397Sobrien 440550397Sobrien attr->dw_attr_next = NULL; 440650397Sobrien attr->dw_attr = attr_kind; 440750397Sobrien attr->dw_attr_val.val_class = dw_val_class_const; 440850397Sobrien attr->dw_attr_val.v.val_int = int_val; 440950397Sobrien add_dwarf_attr (die, attr); 441050397Sobrien} 441150397Sobrien 441290075Sobrienstatic inline long int 441390075SobrienAT_int (a) 441490075Sobrien dw_attr_ref a; 441590075Sobrien{ 441690075Sobrien if (a && AT_class (a) == dw_val_class_const) 441790075Sobrien return a->dw_attr_val.v.val_int; 441890075Sobrien 441990075Sobrien abort (); 442090075Sobrien} 442190075Sobrien 442250397Sobrien/* Add an unsigned integer attribute value to a DIE. */ 442350397Sobrien 442450397Sobrienstatic inline void 442550397Sobrienadd_AT_unsigned (die, attr_kind, unsigned_val) 442690075Sobrien dw_die_ref die; 442790075Sobrien enum dwarf_attribute attr_kind; 442890075Sobrien unsigned long unsigned_val; 442950397Sobrien{ 443090075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 443150397Sobrien 443250397Sobrien attr->dw_attr_next = NULL; 443350397Sobrien attr->dw_attr = attr_kind; 443450397Sobrien attr->dw_attr_val.val_class = dw_val_class_unsigned_const; 443550397Sobrien attr->dw_attr_val.v.val_unsigned = unsigned_val; 443650397Sobrien add_dwarf_attr (die, attr); 443750397Sobrien} 443850397Sobrien 443990075Sobrienstatic inline unsigned long 444090075SobrienAT_unsigned (a) 444190075Sobrien dw_attr_ref a; 444290075Sobrien{ 444390075Sobrien if (a && AT_class (a) == dw_val_class_unsigned_const) 444490075Sobrien return a->dw_attr_val.v.val_unsigned; 444590075Sobrien 444690075Sobrien abort (); 444790075Sobrien} 444890075Sobrien 444950397Sobrien/* Add an unsigned double integer attribute value to a DIE. */ 445050397Sobrien 445150397Sobrienstatic inline void 445250397Sobrienadd_AT_long_long (die, attr_kind, val_hi, val_low) 445390075Sobrien dw_die_ref die; 445490075Sobrien enum dwarf_attribute attr_kind; 445590075Sobrien unsigned long val_hi; 445690075Sobrien unsigned long val_low; 445750397Sobrien{ 445890075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 445950397Sobrien 446050397Sobrien attr->dw_attr_next = NULL; 446150397Sobrien attr->dw_attr = attr_kind; 446250397Sobrien attr->dw_attr_val.val_class = dw_val_class_long_long; 446350397Sobrien attr->dw_attr_val.v.val_long_long.hi = val_hi; 446450397Sobrien attr->dw_attr_val.v.val_long_long.low = val_low; 446550397Sobrien add_dwarf_attr (die, attr); 446650397Sobrien} 446750397Sobrien 446850397Sobrien/* Add a floating point attribute value to a DIE and return it. */ 446950397Sobrien 447050397Sobrienstatic inline void 447150397Sobrienadd_AT_float (die, attr_kind, length, array) 447290075Sobrien dw_die_ref die; 447390075Sobrien enum dwarf_attribute attr_kind; 447490075Sobrien unsigned length; 447590075Sobrien long *array; 447650397Sobrien{ 447790075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 447850397Sobrien 447950397Sobrien attr->dw_attr_next = NULL; 448050397Sobrien attr->dw_attr = attr_kind; 448150397Sobrien attr->dw_attr_val.val_class = dw_val_class_float; 448250397Sobrien attr->dw_attr_val.v.val_float.length = length; 448350397Sobrien attr->dw_attr_val.v.val_float.array = array; 448450397Sobrien add_dwarf_attr (die, attr); 448550397Sobrien} 448650397Sobrien 448750397Sobrien/* Add a string attribute value to a DIE. */ 448850397Sobrien 448950397Sobrienstatic inline void 449050397Sobrienadd_AT_string (die, attr_kind, str) 449190075Sobrien dw_die_ref die; 449290075Sobrien enum dwarf_attribute attr_kind; 449390075Sobrien const char *str; 449450397Sobrien{ 449590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 449690075Sobrien struct indirect_string_node *node; 449790075Sobrien 449890075Sobrien if (! debug_str_hash) 449990075Sobrien { 450090075Sobrien debug_str_hash = ht_create (10); 450190075Sobrien debug_str_hash->alloc_node = indirect_string_alloc; 450290075Sobrien } 450350397Sobrien 450490075Sobrien node = (struct indirect_string_node *) 450590075Sobrien ht_lookup (debug_str_hash, (const unsigned char *) str, 450690075Sobrien strlen (str), HT_ALLOC); 450790075Sobrien node->refcount++; 450890075Sobrien 450950397Sobrien attr->dw_attr_next = NULL; 451050397Sobrien attr->dw_attr = attr_kind; 451150397Sobrien attr->dw_attr_val.val_class = dw_val_class_str; 451290075Sobrien attr->dw_attr_val.v.val_str = node; 451350397Sobrien add_dwarf_attr (die, attr); 451450397Sobrien} 451550397Sobrien 451690075Sobrienstatic inline const char * 451790075SobrienAT_string (a) 451890075Sobrien dw_attr_ref a; 451990075Sobrien{ 452090075Sobrien if (a && AT_class (a) == dw_val_class_str) 452190075Sobrien return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id); 452290075Sobrien 452390075Sobrien abort (); 452490075Sobrien} 452590075Sobrien 452690075Sobrien/* Find out whether a string should be output inline in DIE 452790075Sobrien or out-of-line in .debug_str section. */ 452890075Sobrien 452990075Sobrienstatic int 453090075SobrienAT_string_form (a) 453190075Sobrien dw_attr_ref a; 453290075Sobrien{ 453390075Sobrien if (a && AT_class (a) == dw_val_class_str) 453490075Sobrien { 453590075Sobrien struct indirect_string_node *node; 453690075Sobrien unsigned int len; 453790075Sobrien extern int const_labelno; 453890075Sobrien char label[32]; 453990075Sobrien 454090075Sobrien node = a->dw_attr_val.v.val_str; 454190075Sobrien if (node->form) 454290075Sobrien return node->form; 454390075Sobrien 454490075Sobrien len = HT_LEN (&node->id) + 1; 454590075Sobrien 454690075Sobrien /* If the string is shorter or equal to the size of the reference, it is 454790075Sobrien always better to put it inline. */ 454890075Sobrien if (len <= DWARF_OFFSET_SIZE || node->refcount == 0) 454990075Sobrien return node->form = DW_FORM_string; 455090075Sobrien 455190075Sobrien /* If we cannot expect the linker to merge strings in .debug_str 455290075Sobrien section, only put it into .debug_str if it is worth even in this 455390075Sobrien single module. */ 455490075Sobrien if ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) == 0 455590075Sobrien && (len - DWARF_OFFSET_SIZE) * node->refcount <= len) 455690075Sobrien return node->form = DW_FORM_string; 455790075Sobrien 455890075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); 455990075Sobrien ++const_labelno; 456090075Sobrien node->label = xstrdup (label); 456190075Sobrien 456290075Sobrien return node->form = DW_FORM_strp; 456390075Sobrien } 456490075Sobrien 456590075Sobrien abort (); 456690075Sobrien} 456790075Sobrien 456850397Sobrien/* Add a DIE reference attribute value to a DIE. */ 456950397Sobrien 457050397Sobrienstatic inline void 457150397Sobrienadd_AT_die_ref (die, attr_kind, targ_die) 457290075Sobrien dw_die_ref die; 457390075Sobrien enum dwarf_attribute attr_kind; 457490075Sobrien dw_die_ref targ_die; 457550397Sobrien{ 457690075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 457750397Sobrien 457850397Sobrien attr->dw_attr_next = NULL; 457950397Sobrien attr->dw_attr = attr_kind; 458050397Sobrien attr->dw_attr_val.val_class = dw_val_class_die_ref; 458190075Sobrien attr->dw_attr_val.v.val_die_ref.die = targ_die; 458290075Sobrien attr->dw_attr_val.v.val_die_ref.external = 0; 458350397Sobrien add_dwarf_attr (die, attr); 458450397Sobrien} 458550397Sobrien 458690075Sobrienstatic inline dw_die_ref 458790075SobrienAT_ref (a) 458890075Sobrien dw_attr_ref a; 458990075Sobrien{ 459090075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 459190075Sobrien return a->dw_attr_val.v.val_die_ref.die; 459290075Sobrien 459390075Sobrien abort (); 459490075Sobrien} 459590075Sobrien 459690075Sobrienstatic inline int 459790075SobrienAT_ref_external (a) 459890075Sobrien dw_attr_ref a; 459990075Sobrien{ 460090075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 460190075Sobrien return a->dw_attr_val.v.val_die_ref.external; 460290075Sobrien 460390075Sobrien return 0; 460490075Sobrien} 460590075Sobrien 460690075Sobrienstatic inline void 460790075Sobrienset_AT_ref_external (a, i) 460890075Sobrien dw_attr_ref a; 460990075Sobrien int i; 461090075Sobrien{ 461190075Sobrien if (a && AT_class (a) == dw_val_class_die_ref) 461290075Sobrien a->dw_attr_val.v.val_die_ref.external = i; 461390075Sobrien else 461490075Sobrien abort (); 461590075Sobrien} 461690075Sobrien 461750397Sobrien/* Add an FDE reference attribute value to a DIE. */ 461850397Sobrien 461950397Sobrienstatic inline void 462050397Sobrienadd_AT_fde_ref (die, attr_kind, targ_fde) 462190075Sobrien dw_die_ref die; 462290075Sobrien enum dwarf_attribute attr_kind; 462390075Sobrien unsigned targ_fde; 462450397Sobrien{ 462590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 462650397Sobrien 462750397Sobrien attr->dw_attr_next = NULL; 462850397Sobrien attr->dw_attr = attr_kind; 462950397Sobrien attr->dw_attr_val.val_class = dw_val_class_fde_ref; 463050397Sobrien attr->dw_attr_val.v.val_fde_index = targ_fde; 463150397Sobrien add_dwarf_attr (die, attr); 463250397Sobrien} 463350397Sobrien 463450397Sobrien/* Add a location description attribute value to a DIE. */ 463550397Sobrien 463650397Sobrienstatic inline void 463750397Sobrienadd_AT_loc (die, attr_kind, loc) 463890075Sobrien dw_die_ref die; 463990075Sobrien enum dwarf_attribute attr_kind; 464090075Sobrien dw_loc_descr_ref loc; 464150397Sobrien{ 464290075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 464350397Sobrien 464450397Sobrien attr->dw_attr_next = NULL; 464550397Sobrien attr->dw_attr = attr_kind; 464650397Sobrien attr->dw_attr_val.val_class = dw_val_class_loc; 464750397Sobrien attr->dw_attr_val.v.val_loc = loc; 464850397Sobrien add_dwarf_attr (die, attr); 464950397Sobrien} 465050397Sobrien 465190075Sobrienstatic inline dw_loc_descr_ref 465290075SobrienAT_loc (a) 465390075Sobrien dw_attr_ref a; 465490075Sobrien{ 465590075Sobrien if (a && AT_class (a) == dw_val_class_loc) 465690075Sobrien return a->dw_attr_val.v.val_loc; 465790075Sobrien 465890075Sobrien abort (); 465990075Sobrien} 466090075Sobrien 466190075Sobrienstatic inline void 466290075Sobrienadd_AT_loc_list (die, attr_kind, loc_list) 466390075Sobrien dw_die_ref die; 466490075Sobrien enum dwarf_attribute attr_kind; 466590075Sobrien dw_loc_list_ref loc_list; 466690075Sobrien{ 466790075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 466890075Sobrien 466990075Sobrien attr->dw_attr_next = NULL; 467090075Sobrien attr->dw_attr = attr_kind; 467190075Sobrien attr->dw_attr_val.val_class = dw_val_class_loc_list; 467290075Sobrien attr->dw_attr_val.v.val_loc_list = loc_list; 467390075Sobrien add_dwarf_attr (die, attr); 467490075Sobrien have_location_lists = 1; 467590075Sobrien} 467690075Sobrien 467790075Sobrienstatic inline dw_loc_list_ref 467890075SobrienAT_loc_list (a) 467990075Sobrien dw_attr_ref a; 468090075Sobrien{ 468190075Sobrien if (a && AT_class (a) == dw_val_class_loc_list) 468290075Sobrien return a->dw_attr_val.v.val_loc_list; 468390075Sobrien 468490075Sobrien abort (); 468590075Sobrien} 468690075Sobrien 468750397Sobrien/* Add an address constant attribute value to a DIE. */ 468850397Sobrien 468950397Sobrienstatic inline void 469050397Sobrienadd_AT_addr (die, attr_kind, addr) 469190075Sobrien dw_die_ref die; 469290075Sobrien enum dwarf_attribute attr_kind; 469390075Sobrien rtx addr; 469450397Sobrien{ 469590075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 469650397Sobrien 469750397Sobrien attr->dw_attr_next = NULL; 469850397Sobrien attr->dw_attr = attr_kind; 469950397Sobrien attr->dw_attr_val.val_class = dw_val_class_addr; 470050397Sobrien attr->dw_attr_val.v.val_addr = addr; 470150397Sobrien add_dwarf_attr (die, attr); 470250397Sobrien} 470350397Sobrien 470490075Sobrienstatic inline rtx 470590075SobrienAT_addr (a) 470690075Sobrien dw_attr_ref a; 470790075Sobrien{ 470890075Sobrien if (a && AT_class (a) == dw_val_class_addr) 470990075Sobrien return a->dw_attr_val.v.val_addr; 471090075Sobrien 471190075Sobrien abort (); 471290075Sobrien} 471390075Sobrien 471450397Sobrien/* Add a label identifier attribute value to a DIE. */ 471550397Sobrien 471650397Sobrienstatic inline void 471750397Sobrienadd_AT_lbl_id (die, attr_kind, lbl_id) 471890075Sobrien dw_die_ref die; 471990075Sobrien enum dwarf_attribute attr_kind; 472090075Sobrien const char *lbl_id; 472150397Sobrien{ 472290075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 472350397Sobrien 472450397Sobrien attr->dw_attr_next = NULL; 472550397Sobrien attr->dw_attr = attr_kind; 472650397Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_id; 472750397Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); 472850397Sobrien add_dwarf_attr (die, attr); 472950397Sobrien} 473050397Sobrien 473150397Sobrien/* Add a section offset attribute value to a DIE. */ 473250397Sobrien 473350397Sobrienstatic inline void 473452284Sobrienadd_AT_lbl_offset (die, attr_kind, label) 473590075Sobrien dw_die_ref die; 473690075Sobrien enum dwarf_attribute attr_kind; 473790075Sobrien const char *label; 473850397Sobrien{ 473990075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 474050397Sobrien 474150397Sobrien attr->dw_attr_next = NULL; 474250397Sobrien attr->dw_attr = attr_kind; 474352284Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_offset; 474490075Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (label); 474550397Sobrien add_dwarf_attr (die, attr); 474650397Sobrien} 474750397Sobrien 474890075Sobrien/* Add an offset attribute value to a DIE. */ 474950397Sobrien 475090075Sobrienstatic inline void 475190075Sobrienadd_AT_offset (die, attr_kind, offset) 475290075Sobrien dw_die_ref die; 475390075Sobrien enum dwarf_attribute attr_kind; 475490075Sobrien unsigned long offset; 475550397Sobrien{ 475690075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 475750397Sobrien 475890075Sobrien attr->dw_attr_next = NULL; 475990075Sobrien attr->dw_attr = attr_kind; 476090075Sobrien attr->dw_attr_val.val_class = dw_val_class_offset; 476190075Sobrien attr->dw_attr_val.v.val_offset = offset; 476290075Sobrien add_dwarf_attr (die, attr); 476390075Sobrien} 476450397Sobrien 476590075Sobrien/* Add an range_list attribute value to a DIE. */ 476690075Sobrien 476790075Sobrienstatic void 476890075Sobrienadd_AT_range_list (die, attr_kind, offset) 476990075Sobrien dw_die_ref die; 477090075Sobrien enum dwarf_attribute attr_kind; 477190075Sobrien unsigned long offset; 477290075Sobrien{ 477390075Sobrien dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 477490075Sobrien 477590075Sobrien attr->dw_attr_next = NULL; 477690075Sobrien attr->dw_attr = attr_kind; 477790075Sobrien attr->dw_attr_val.val_class = dw_val_class_range_list; 477890075Sobrien attr->dw_attr_val.v.val_offset = offset; 477990075Sobrien add_dwarf_attr (die, attr); 478050397Sobrien} 478150397Sobrien 478290075Sobrienstatic inline const char * 478390075SobrienAT_lbl (a) 478490075Sobrien dw_attr_ref a; 478590075Sobrien{ 478690075Sobrien if (a && (AT_class (a) == dw_val_class_lbl_id 478790075Sobrien || AT_class (a) == dw_val_class_lbl_offset)) 478890075Sobrien return a->dw_attr_val.v.val_lbl_id; 478990075Sobrien 479090075Sobrien abort (); 479190075Sobrien} 479290075Sobrien 479350397Sobrien/* Get the attribute of type attr_kind. */ 479450397Sobrien 479550397Sobrienstatic inline dw_attr_ref 479650397Sobrienget_AT (die, attr_kind) 479790075Sobrien dw_die_ref die; 479890075Sobrien enum dwarf_attribute attr_kind; 479950397Sobrien{ 480090075Sobrien dw_attr_ref a; 480190075Sobrien dw_die_ref spec = NULL; 480290075Sobrien 480350397Sobrien if (die != NULL) 480450397Sobrien { 480550397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 480690075Sobrien if (a->dw_attr == attr_kind) 480790075Sobrien return a; 480890075Sobrien else if (a->dw_attr == DW_AT_specification 480990075Sobrien || a->dw_attr == DW_AT_abstract_origin) 481090075Sobrien spec = AT_ref (a); 481150397Sobrien 481250397Sobrien if (spec) 481350397Sobrien return get_AT (spec, attr_kind); 481450397Sobrien } 481550397Sobrien 481650397Sobrien return NULL; 481750397Sobrien} 481850397Sobrien 481990075Sobrien/* Return the "low pc" attribute value, typically associated with a subprogram 482090075Sobrien DIE. Return null if the "low pc" attribute is either not present, or if it 482190075Sobrien cannot be represented as an assembler label identifier. */ 482250397Sobrien 482390075Sobrienstatic inline const char * 482450397Sobrienget_AT_low_pc (die) 482590075Sobrien dw_die_ref die; 482650397Sobrien{ 482790075Sobrien dw_attr_ref a = get_AT (die, DW_AT_low_pc); 482850397Sobrien 482990075Sobrien return a ? AT_lbl (a) : NULL; 483050397Sobrien} 483150397Sobrien 483290075Sobrien/* Return the "high pc" attribute value, typically associated with a subprogram 483390075Sobrien DIE. Return null if the "high pc" attribute is either not present, or if it 483490075Sobrien cannot be represented as an assembler label identifier. */ 483550397Sobrien 483690075Sobrienstatic inline const char * 483750397Sobrienget_AT_hi_pc (die) 483890075Sobrien dw_die_ref die; 483950397Sobrien{ 484090075Sobrien dw_attr_ref a = get_AT (die, DW_AT_high_pc); 484150397Sobrien 484290075Sobrien return a ? AT_lbl (a) : NULL; 484350397Sobrien} 484450397Sobrien 484550397Sobrien/* Return the value of the string attribute designated by ATTR_KIND, or 484650397Sobrien NULL if it is not present. */ 484750397Sobrien 484890075Sobrienstatic inline const char * 484950397Sobrienget_AT_string (die, attr_kind) 485090075Sobrien dw_die_ref die; 485190075Sobrien enum dwarf_attribute attr_kind; 485250397Sobrien{ 485390075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 485450397Sobrien 485590075Sobrien return a ? AT_string (a) : NULL; 485650397Sobrien} 485750397Sobrien 485850397Sobrien/* Return the value of the flag attribute designated by ATTR_KIND, or -1 485950397Sobrien if it is not present. */ 486050397Sobrien 486150397Sobrienstatic inline int 486250397Sobrienget_AT_flag (die, attr_kind) 486390075Sobrien dw_die_ref die; 486490075Sobrien enum dwarf_attribute attr_kind; 486550397Sobrien{ 486690075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 486750397Sobrien 486890075Sobrien return a ? AT_flag (a) : 0; 486950397Sobrien} 487050397Sobrien 487150397Sobrien/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0 487250397Sobrien if it is not present. */ 487350397Sobrien 487450397Sobrienstatic inline unsigned 487550397Sobrienget_AT_unsigned (die, attr_kind) 487690075Sobrien dw_die_ref die; 487790075Sobrien enum dwarf_attribute attr_kind; 487850397Sobrien{ 487990075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 488050397Sobrien 488190075Sobrien return a ? AT_unsigned (a) : 0; 488290075Sobrien} 488350397Sobrien 488490075Sobrienstatic inline dw_die_ref 488590075Sobrienget_AT_ref (die, attr_kind) 488690075Sobrien dw_die_ref die; 488790075Sobrien enum dwarf_attribute attr_kind; 488890075Sobrien{ 488990075Sobrien dw_attr_ref a = get_AT (die, attr_kind); 489090075Sobrien 489190075Sobrien return a ? AT_ref (a) : NULL; 489250397Sobrien} 489350397Sobrien 489450397Sobrienstatic inline int 489550397Sobrienis_c_family () 489650397Sobrien{ 489790075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 489850397Sobrien 489950397Sobrien return (lang == DW_LANG_C || lang == DW_LANG_C89 490050397Sobrien || lang == DW_LANG_C_plus_plus); 490190075Sobrien} 490250397Sobrien 490350397Sobrienstatic inline int 490490075Sobrienis_cxx () 490590075Sobrien{ 490690075Sobrien return (get_AT_unsigned (comp_unit_die, DW_AT_language) 490790075Sobrien == DW_LANG_C_plus_plus); 490890075Sobrien} 490990075Sobrien 491090075Sobrienstatic inline int 491150397Sobrienis_fortran () 491250397Sobrien{ 491390075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 491450397Sobrien 491550397Sobrien return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90); 491690075Sobrien} 491750397Sobrien 491890075Sobrienstatic inline int 491990075Sobrienis_java () 492090075Sobrien{ 492190075Sobrien unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 492290075Sobrien 492390075Sobrien return (lang == DW_LANG_Java); 492490075Sobrien} 492590075Sobrien 492690075Sobrien/* Free up the memory used by A. */ 492790075Sobrien 492890075Sobrienstatic inline void free_AT PARAMS ((dw_attr_ref)); 492990075Sobrienstatic inline void 493090075Sobrienfree_AT (a) 493190075Sobrien dw_attr_ref a; 493290075Sobrien{ 493390075Sobrien switch (AT_class (a)) 493490075Sobrien { 493590075Sobrien case dw_val_class_str: 493690075Sobrien if (a->dw_attr_val.v.val_str->refcount) 493790075Sobrien a->dw_attr_val.v.val_str->refcount--; 493890075Sobrien break; 493990075Sobrien 494090075Sobrien case dw_val_class_lbl_id: 494190075Sobrien case dw_val_class_lbl_offset: 494290075Sobrien free (a->dw_attr_val.v.val_lbl_id); 494390075Sobrien break; 494490075Sobrien 494590075Sobrien case dw_val_class_float: 494690075Sobrien free (a->dw_attr_val.v.val_float.array); 494790075Sobrien break; 494890075Sobrien 494990075Sobrien default: 495090075Sobrien break; 495190075Sobrien } 495290075Sobrien 495390075Sobrien free (a); 495490075Sobrien} 495590075Sobrien 495650397Sobrien/* Remove the specified attribute if present. */ 495750397Sobrien 495890075Sobrienstatic void 495950397Sobrienremove_AT (die, attr_kind) 496090075Sobrien dw_die_ref die; 496190075Sobrien enum dwarf_attribute attr_kind; 496250397Sobrien{ 496390075Sobrien dw_attr_ref *p; 496490075Sobrien dw_attr_ref removed = NULL; 496550397Sobrien 496650397Sobrien if (die != NULL) 496750397Sobrien { 496890075Sobrien for (p = &(die->die_attr); *p; p = &((*p)->dw_attr_next)) 496990075Sobrien if ((*p)->dw_attr == attr_kind) 497090075Sobrien { 497190075Sobrien removed = *p; 497290075Sobrien *p = (*p)->dw_attr_next; 497390075Sobrien break; 497490075Sobrien } 497550397Sobrien 497650397Sobrien if (removed != 0) 497790075Sobrien free_AT (removed); 497850397Sobrien } 497950397Sobrien} 498050397Sobrien 498190075Sobrien/* Free up the memory used by DIE. */ 498290075Sobrien 498390075Sobrienstatic inline void 498490075Sobrienfree_die (die) 498590075Sobrien dw_die_ref die; 498690075Sobrien{ 498790075Sobrien remove_children (die); 498890075Sobrien free (die); 498990075Sobrien} 499090075Sobrien 499150397Sobrien/* Discard the children of this DIE. */ 499250397Sobrien 499390075Sobrienstatic void 499450397Sobrienremove_children (die) 499590075Sobrien dw_die_ref die; 499650397Sobrien{ 499790075Sobrien dw_die_ref child_die = die->die_child; 499850397Sobrien 499950397Sobrien die->die_child = NULL; 500050397Sobrien 500150397Sobrien while (child_die != NULL) 500250397Sobrien { 500390075Sobrien dw_die_ref tmp_die = child_die; 500490075Sobrien dw_attr_ref a; 500550397Sobrien 500650397Sobrien child_die = child_die->die_sib; 500790075Sobrien 500890075Sobrien for (a = tmp_die->die_attr; a != NULL;) 500950397Sobrien { 501090075Sobrien dw_attr_ref tmp_a = a; 501150397Sobrien 501250397Sobrien a = a->dw_attr_next; 501390075Sobrien free_AT (tmp_a); 501450397Sobrien } 501550397Sobrien 501690075Sobrien free_die (tmp_die); 501750397Sobrien } 501850397Sobrien} 501950397Sobrien 502090075Sobrien/* Add a child DIE below its parent. We build the lists up in reverse 502190075Sobrien addition order, and correct that in reverse_all_dies. */ 502250397Sobrien 502350397Sobrienstatic inline void 502450397Sobrienadd_child_die (die, child_die) 502590075Sobrien dw_die_ref die; 502690075Sobrien dw_die_ref child_die; 502750397Sobrien{ 502850397Sobrien if (die != NULL && child_die != NULL) 502950397Sobrien { 503050397Sobrien if (die == child_die) 503150397Sobrien abort (); 503290075Sobrien 503350397Sobrien child_die->die_parent = die; 503490075Sobrien child_die->die_sib = die->die_child; 503590075Sobrien die->die_child = child_die; 503690075Sobrien } 503790075Sobrien} 503850397Sobrien 503990075Sobrien/* Move CHILD, which must be a child of PARENT or the DIE for which PARENT 504090075Sobrien is the specification, to the front of PARENT's list of children. */ 504190075Sobrien 504290075Sobrienstatic void 504390075Sobriensplice_child_die (parent, child) 504490075Sobrien dw_die_ref parent, child; 504590075Sobrien{ 504690075Sobrien dw_die_ref *p; 504790075Sobrien 504890075Sobrien /* We want the declaration DIE from inside the class, not the 504990075Sobrien specification DIE at toplevel. */ 505090075Sobrien if (child->die_parent != parent) 505190075Sobrien { 505290075Sobrien dw_die_ref tmp = get_AT_ref (child, DW_AT_specification); 505390075Sobrien 505490075Sobrien if (tmp) 505590075Sobrien child = tmp; 505650397Sobrien } 505790075Sobrien 505890075Sobrien if (child->die_parent != parent 505990075Sobrien && child->die_parent != get_AT_ref (parent, DW_AT_specification)) 506090075Sobrien abort (); 506190075Sobrien 506290075Sobrien for (p = &(child->die_parent->die_child); *p; p = &((*p)->die_sib)) 506390075Sobrien if (*p == child) 506490075Sobrien { 506590075Sobrien *p = child->die_sib; 506690075Sobrien break; 506790075Sobrien } 506890075Sobrien 506990075Sobrien child->die_sib = parent->die_child; 507090075Sobrien parent->die_child = child; 507150397Sobrien} 507250397Sobrien 507350397Sobrien/* Return a pointer to a newly created DIE node. */ 507450397Sobrien 507550397Sobrienstatic inline dw_die_ref 507690075Sobriennew_die (tag_value, parent_die, t) 507790075Sobrien enum dwarf_tag tag_value; 507890075Sobrien dw_die_ref parent_die; 507990075Sobrien tree t; 508050397Sobrien{ 508190075Sobrien dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node)); 508250397Sobrien 508350397Sobrien die->die_tag = tag_value; 508450397Sobrien 508550397Sobrien if (parent_die != NULL) 508650397Sobrien add_child_die (parent_die, die); 508750397Sobrien else 508850397Sobrien { 508950397Sobrien limbo_die_node *limbo_node; 509050397Sobrien 509150397Sobrien limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node)); 509250397Sobrien limbo_node->die = die; 509390075Sobrien limbo_node->created_for = t; 509450397Sobrien limbo_node->next = limbo_die_list; 509550397Sobrien limbo_die_list = limbo_node; 509650397Sobrien } 509750397Sobrien 509850397Sobrien return die; 509950397Sobrien} 510050397Sobrien 510150397Sobrien/* Return the DIE associated with the given type specifier. */ 510250397Sobrien 510350397Sobrienstatic inline dw_die_ref 510450397Sobrienlookup_type_die (type) 510590075Sobrien tree type; 510650397Sobrien{ 510790075Sobrien if (TREE_CODE (type) == VECTOR_TYPE) 510890075Sobrien type = TYPE_DEBUG_REPRESENTATION_TYPE (type); 510990075Sobrien 511050397Sobrien return (dw_die_ref) TYPE_SYMTAB_POINTER (type); 511150397Sobrien} 511250397Sobrien 511350397Sobrien/* Equate a DIE to a given type specifier. */ 511450397Sobrien 511590075Sobrienstatic inline void 511650397Sobrienequate_type_number_to_die (type, type_die) 511790075Sobrien tree type; 511890075Sobrien dw_die_ref type_die; 511950397Sobrien{ 512050397Sobrien TYPE_SYMTAB_POINTER (type) = (char *) type_die; 512150397Sobrien} 512250397Sobrien 512350397Sobrien/* Return the DIE associated with a given declaration. */ 512450397Sobrien 512550397Sobrienstatic inline dw_die_ref 512650397Sobrienlookup_decl_die (decl) 512790075Sobrien tree decl; 512850397Sobrien{ 512990075Sobrien unsigned decl_id = DECL_UID (decl); 513050397Sobrien 513190075Sobrien return (decl_id < decl_die_table_in_use ? decl_die_table[decl_id] : NULL); 513250397Sobrien} 513350397Sobrien 513450397Sobrien/* Equate a DIE to a particular declaration. */ 513550397Sobrien 513650397Sobrienstatic void 513750397Sobrienequate_decl_number_to_die (decl, decl_die) 513890075Sobrien tree decl; 513990075Sobrien dw_die_ref decl_die; 514050397Sobrien{ 514190075Sobrien unsigned int decl_id = DECL_UID (decl); 514290075Sobrien unsigned int num_allocated; 514350397Sobrien 514450397Sobrien if (decl_id >= decl_die_table_allocated) 514550397Sobrien { 514650397Sobrien num_allocated 514750397Sobrien = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1) 514850397Sobrien / DECL_DIE_TABLE_INCREMENT) 514950397Sobrien * DECL_DIE_TABLE_INCREMENT; 515050397Sobrien 515150397Sobrien decl_die_table 515250397Sobrien = (dw_die_ref *) xrealloc (decl_die_table, 515350397Sobrien sizeof (dw_die_ref) * num_allocated); 515450397Sobrien 515590075Sobrien memset ((char *) &decl_die_table[decl_die_table_allocated], 0, 515650397Sobrien (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref)); 515750397Sobrien decl_die_table_allocated = num_allocated; 515850397Sobrien } 515950397Sobrien 516050397Sobrien if (decl_id >= decl_die_table_in_use) 516150397Sobrien decl_die_table_in_use = (decl_id + 1); 516250397Sobrien 516350397Sobrien decl_die_table[decl_id] = decl_die; 516450397Sobrien} 516550397Sobrien 516650397Sobrien/* Keep track of the number of spaces used to indent the 516750397Sobrien output of the debugging routines that print the structure of 516850397Sobrien the DIE internal representation. */ 516950397Sobrienstatic int print_indent; 517050397Sobrien 517150397Sobrien/* Indent the line the number of spaces given by print_indent. */ 517250397Sobrien 517350397Sobrienstatic inline void 517450397Sobrienprint_spaces (outfile) 517550397Sobrien FILE *outfile; 517650397Sobrien{ 517750397Sobrien fprintf (outfile, "%*s", print_indent, ""); 517850397Sobrien} 517950397Sobrien 518050397Sobrien/* Print the information associated with a given DIE, and its children. 518150397Sobrien This routine is a debugging aid only. */ 518250397Sobrien 518350397Sobrienstatic void 518450397Sobrienprint_die (die, outfile) 518550397Sobrien dw_die_ref die; 518650397Sobrien FILE *outfile; 518750397Sobrien{ 518890075Sobrien dw_attr_ref a; 518990075Sobrien dw_die_ref c; 519050397Sobrien 519150397Sobrien print_spaces (outfile); 519250397Sobrien fprintf (outfile, "DIE %4lu: %s\n", 519350397Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 519450397Sobrien print_spaces (outfile); 519550397Sobrien fprintf (outfile, " abbrev id: %lu", die->die_abbrev); 519650397Sobrien fprintf (outfile, " offset: %lu\n", die->die_offset); 519750397Sobrien 519850397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 519950397Sobrien { 520050397Sobrien print_spaces (outfile); 520150397Sobrien fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr)); 520250397Sobrien 520390075Sobrien switch (AT_class (a)) 520450397Sobrien { 520550397Sobrien case dw_val_class_addr: 520650397Sobrien fprintf (outfile, "address"); 520750397Sobrien break; 520890075Sobrien case dw_val_class_offset: 520990075Sobrien fprintf (outfile, "offset"); 521090075Sobrien break; 521150397Sobrien case dw_val_class_loc: 521250397Sobrien fprintf (outfile, "location descriptor"); 521350397Sobrien break; 521490075Sobrien case dw_val_class_loc_list: 521590075Sobrien fprintf (outfile, "location list -> label:%s", 521690075Sobrien AT_loc_list (a)->ll_symbol); 521790075Sobrien break; 521890075Sobrien case dw_val_class_range_list: 521990075Sobrien fprintf (outfile, "range list"); 522090075Sobrien break; 522150397Sobrien case dw_val_class_const: 522290075Sobrien fprintf (outfile, "%ld", AT_int (a)); 522350397Sobrien break; 522450397Sobrien case dw_val_class_unsigned_const: 522590075Sobrien fprintf (outfile, "%lu", AT_unsigned (a)); 522650397Sobrien break; 522750397Sobrien case dw_val_class_long_long: 522850397Sobrien fprintf (outfile, "constant (%lu,%lu)", 522990075Sobrien a->dw_attr_val.v.val_long_long.hi, 523090075Sobrien a->dw_attr_val.v.val_long_long.low); 523150397Sobrien break; 523250397Sobrien case dw_val_class_float: 523350397Sobrien fprintf (outfile, "floating-point constant"); 523450397Sobrien break; 523550397Sobrien case dw_val_class_flag: 523690075Sobrien fprintf (outfile, "%u", AT_flag (a)); 523750397Sobrien break; 523850397Sobrien case dw_val_class_die_ref: 523990075Sobrien if (AT_ref (a) != NULL) 524090075Sobrien { 524190075Sobrien if (AT_ref (a)->die_symbol) 524290075Sobrien fprintf (outfile, "die -> label: %s", AT_ref (a)->die_symbol); 524390075Sobrien else 524490075Sobrien fprintf (outfile, "die -> %lu", AT_ref (a)->die_offset); 524590075Sobrien } 524650397Sobrien else 524750397Sobrien fprintf (outfile, "die -> <null>"); 524850397Sobrien break; 524950397Sobrien case dw_val_class_lbl_id: 525052284Sobrien case dw_val_class_lbl_offset: 525190075Sobrien fprintf (outfile, "label: %s", AT_lbl (a)); 525250397Sobrien break; 525350397Sobrien case dw_val_class_str: 525490075Sobrien if (AT_string (a) != NULL) 525590075Sobrien fprintf (outfile, "\"%s\"", AT_string (a)); 525650397Sobrien else 525750397Sobrien fprintf (outfile, "<null>"); 525850397Sobrien break; 525950397Sobrien default: 526050397Sobrien break; 526150397Sobrien } 526250397Sobrien 526350397Sobrien fprintf (outfile, "\n"); 526450397Sobrien } 526550397Sobrien 526650397Sobrien if (die->die_child != NULL) 526750397Sobrien { 526850397Sobrien print_indent += 4; 526950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 527050397Sobrien print_die (c, outfile); 527150397Sobrien 527250397Sobrien print_indent -= 4; 527350397Sobrien } 527490075Sobrien if (print_indent == 0) 527590075Sobrien fprintf (outfile, "\n"); 527650397Sobrien} 527750397Sobrien 527850397Sobrien/* Print the contents of the source code line number correspondence table. 527950397Sobrien This routine is a debugging aid only. */ 528050397Sobrien 528150397Sobrienstatic void 528250397Sobrienprint_dwarf_line_table (outfile) 528350397Sobrien FILE *outfile; 528450397Sobrien{ 528590075Sobrien unsigned i; 528690075Sobrien dw_line_info_ref line_info; 528750397Sobrien 528850397Sobrien fprintf (outfile, "\n\nDWARF source line information\n"); 528990075Sobrien for (i = 1; i < line_info_table_in_use; i++) 529050397Sobrien { 529150397Sobrien line_info = &line_info_table[i]; 529250397Sobrien fprintf (outfile, "%5d: ", i); 529390075Sobrien fprintf (outfile, "%-20s", file_table.table[line_info->dw_file_num]); 529450397Sobrien fprintf (outfile, "%6ld", line_info->dw_line_num); 529550397Sobrien fprintf (outfile, "\n"); 529650397Sobrien } 529750397Sobrien 529850397Sobrien fprintf (outfile, "\n\n"); 529950397Sobrien} 530050397Sobrien 530150397Sobrien/* Print the information collected for a given DIE. */ 530250397Sobrien 530350397Sobrienvoid 530450397Sobriendebug_dwarf_die (die) 530550397Sobrien dw_die_ref die; 530650397Sobrien{ 530750397Sobrien print_die (die, stderr); 530850397Sobrien} 530950397Sobrien 531050397Sobrien/* Print all DWARF information collected for the compilation unit. 531150397Sobrien This routine is a debugging aid only. */ 531250397Sobrien 531350397Sobrienvoid 531450397Sobriendebug_dwarf () 531550397Sobrien{ 531650397Sobrien print_indent = 0; 531750397Sobrien print_die (comp_unit_die, stderr); 531890075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 531990075Sobrien print_dwarf_line_table (stderr); 532050397Sobrien} 532150397Sobrien 532290075Sobrien/* We build up the lists of children and attributes by pushing new ones 532390075Sobrien onto the beginning of the list. Reverse the lists for DIE so that 532490075Sobrien they are in order of addition. */ 532550397Sobrien 532650397Sobrienstatic void 532790075Sobrienreverse_die_lists (die) 532890075Sobrien dw_die_ref die; 532950397Sobrien{ 533090075Sobrien dw_die_ref c, cp, cn; 533190075Sobrien dw_attr_ref a, ap, an; 533290075Sobrien 533390075Sobrien for (a = die->die_attr, ap = 0; a; a = an) 533450397Sobrien { 533590075Sobrien an = a->dw_attr_next; 533690075Sobrien a->dw_attr_next = ap; 533790075Sobrien ap = a; 533890075Sobrien } 533950397Sobrien 534090075Sobrien die->die_attr = ap; 534150397Sobrien 534290075Sobrien for (c = die->die_child, cp = 0; c; c = cn) 534390075Sobrien { 534490075Sobrien cn = c->die_sib; 534590075Sobrien c->die_sib = cp; 534690075Sobrien cp = c; 534750397Sobrien } 534850397Sobrien 534990075Sobrien die->die_child = cp; 535090075Sobrien} 535190075Sobrien 535290075Sobrien/* reverse_die_lists only reverses the single die you pass it. Since we used to 535390075Sobrien reverse all dies in add_sibling_attributes, which runs through all the dies, 535490075Sobrien it would reverse all the dies. Now, however, since we don't call 535590075Sobrien reverse_die_lists in add_sibling_attributes, we need a routine to 535690075Sobrien recursively reverse all the dies. This is that routine. */ 535790075Sobrien 535890075Sobrienstatic void 535990075Sobrienreverse_all_dies (die) 536090075Sobrien dw_die_ref die; 536190075Sobrien{ 536290075Sobrien dw_die_ref c; 536390075Sobrien 536490075Sobrien reverse_die_lists (die); 536590075Sobrien 536690075Sobrien for (c = die->die_child; c; c = c->die_sib) 536790075Sobrien reverse_all_dies (c); 536890075Sobrien} 536990075Sobrien 537090075Sobrien/* Start a new compilation unit DIE for an include file. OLD_UNIT is the CU 537190075Sobrien for the enclosing include file, if any. BINCL_DIE is the DW_TAG_GNU_BINCL 537290075Sobrien DIE that marks the start of the DIEs for this include file. */ 537390075Sobrien 537490075Sobrienstatic dw_die_ref 537590075Sobrienpush_new_compile_unit (old_unit, bincl_die) 537690075Sobrien dw_die_ref old_unit, bincl_die; 537790075Sobrien{ 537890075Sobrien const char *filename = get_AT_string (bincl_die, DW_AT_name); 537990075Sobrien dw_die_ref new_unit = gen_compile_unit_die (filename); 538090075Sobrien 538190075Sobrien new_unit->die_sib = old_unit; 538290075Sobrien return new_unit; 538390075Sobrien} 538490075Sobrien 538590075Sobrien/* Close an include-file CU and reopen the enclosing one. */ 538690075Sobrien 538790075Sobrienstatic dw_die_ref 538890075Sobrienpop_compile_unit (old_unit) 538990075Sobrien dw_die_ref old_unit; 539090075Sobrien{ 539190075Sobrien dw_die_ref new_unit = old_unit->die_sib; 539290075Sobrien 539390075Sobrien old_unit->die_sib = NULL; 539490075Sobrien return new_unit; 539590075Sobrien} 539690075Sobrien 539790075Sobrien#define CHECKSUM(FOO) md5_process_bytes (&(FOO), sizeof (FOO), ctx) 539890075Sobrien#define CHECKSUM_STRING(FOO) md5_process_bytes ((FOO), strlen (FOO), ctx) 539990075Sobrien 540090075Sobrien/* Calculate the checksum of a location expression. */ 540190075Sobrien 540290075Sobrienstatic inline void 540390075Sobrienloc_checksum (loc, ctx) 540490075Sobrien dw_loc_descr_ref loc; 540590075Sobrien struct md5_ctx *ctx; 540690075Sobrien{ 540790075Sobrien CHECKSUM (loc->dw_loc_opc); 540890075Sobrien CHECKSUM (loc->dw_loc_oprnd1); 540990075Sobrien CHECKSUM (loc->dw_loc_oprnd2); 541090075Sobrien} 541190075Sobrien 541290075Sobrien/* Calculate the checksum of an attribute. */ 541390075Sobrien 541490075Sobrienstatic void 541590075Sobrienattr_checksum (at, ctx) 541690075Sobrien dw_attr_ref at; 541790075Sobrien struct md5_ctx *ctx; 541890075Sobrien{ 541990075Sobrien dw_loc_descr_ref loc; 542090075Sobrien rtx r; 542190075Sobrien 542290075Sobrien CHECKSUM (at->dw_attr); 542390075Sobrien 542490075Sobrien /* We don't care about differences in file numbering. */ 542590075Sobrien if (at->dw_attr == DW_AT_decl_file 542690075Sobrien /* Or that this was compiled with a different compiler snapshot; if 542790075Sobrien the output is the same, that's what matters. */ 542890075Sobrien || at->dw_attr == DW_AT_producer) 542990075Sobrien return; 543090075Sobrien 543190075Sobrien switch (AT_class (at)) 543290075Sobrien { 543390075Sobrien case dw_val_class_const: 543490075Sobrien CHECKSUM (at->dw_attr_val.v.val_int); 543590075Sobrien break; 543690075Sobrien case dw_val_class_unsigned_const: 543790075Sobrien CHECKSUM (at->dw_attr_val.v.val_unsigned); 543890075Sobrien break; 543990075Sobrien case dw_val_class_long_long: 544090075Sobrien CHECKSUM (at->dw_attr_val.v.val_long_long); 544190075Sobrien break; 544290075Sobrien case dw_val_class_float: 544390075Sobrien CHECKSUM (at->dw_attr_val.v.val_float); 544490075Sobrien break; 544590075Sobrien case dw_val_class_flag: 544690075Sobrien CHECKSUM (at->dw_attr_val.v.val_flag); 544790075Sobrien break; 544890075Sobrien case dw_val_class_str: 544990075Sobrien CHECKSUM_STRING (AT_string (at)); 545090075Sobrien break; 545190075Sobrien 545290075Sobrien case dw_val_class_addr: 545390075Sobrien r = AT_addr (at); 545490075Sobrien switch (GET_CODE (r)) 545590075Sobrien { 545690075Sobrien case SYMBOL_REF: 545790075Sobrien CHECKSUM_STRING (XSTR (r, 0)); 545890075Sobrien break; 545990075Sobrien 546090075Sobrien default: 546190075Sobrien abort (); 546290075Sobrien } 546390075Sobrien break; 546490075Sobrien 546590075Sobrien case dw_val_class_offset: 546690075Sobrien CHECKSUM (at->dw_attr_val.v.val_offset); 546790075Sobrien break; 546890075Sobrien 546990075Sobrien case dw_val_class_loc: 547090075Sobrien for (loc = AT_loc (at); loc; loc = loc->dw_loc_next) 547190075Sobrien loc_checksum (loc, ctx); 547290075Sobrien break; 547390075Sobrien 547490075Sobrien case dw_val_class_die_ref: 547590075Sobrien if (AT_ref (at)->die_offset) 547690075Sobrien CHECKSUM (AT_ref (at)->die_offset); 547790075Sobrien /* FIXME else use target die name or something. */ 547890075Sobrien 547990075Sobrien case dw_val_class_fde_ref: 548090075Sobrien case dw_val_class_lbl_id: 548190075Sobrien case dw_val_class_lbl_offset: 548290075Sobrien break; 548390075Sobrien 548490075Sobrien default: 548590075Sobrien break; 548690075Sobrien } 548790075Sobrien} 548890075Sobrien 548990075Sobrien/* Calculate the checksum of a DIE. */ 549090075Sobrien 549190075Sobrienstatic void 549290075Sobriendie_checksum (die, ctx) 549390075Sobrien dw_die_ref die; 549490075Sobrien struct md5_ctx *ctx; 549590075Sobrien{ 549690075Sobrien dw_die_ref c; 549790075Sobrien dw_attr_ref a; 549890075Sobrien 549990075Sobrien CHECKSUM (die->die_tag); 550090075Sobrien 550190075Sobrien for (a = die->die_attr; a; a = a->dw_attr_next) 550290075Sobrien attr_checksum (a, ctx); 550390075Sobrien 550490075Sobrien for (c = die->die_child; c; c = c->die_sib) 550590075Sobrien die_checksum (c, ctx); 550690075Sobrien} 550790075Sobrien 550890075Sobrien#undef CHECKSUM 550990075Sobrien#undef CHECKSUM_STRING 551090075Sobrien 551190075Sobrien/* The prefix to attach to symbols on DIEs in the current comdat debug 551290075Sobrien info section. */ 551390075Sobrienstatic char *comdat_symbol_id; 551490075Sobrien 551590075Sobrien/* The index of the current symbol within the current comdat CU. */ 551690075Sobrienstatic unsigned int comdat_symbol_number; 551790075Sobrien 551890075Sobrien/* Calculate the MD5 checksum of the compilation unit DIE UNIT_DIE and its 551990075Sobrien children, and set comdat_symbol_id accordingly. */ 552090075Sobrien 552190075Sobrienstatic void 552290075Sobriencompute_section_prefix (unit_die) 552390075Sobrien dw_die_ref unit_die; 552490075Sobrien{ 552590075Sobrien const char *base = lbasename (get_AT_string (unit_die, DW_AT_name)); 552690075Sobrien char *name = (char *) alloca (strlen (base) + 64); 552790075Sobrien char *p; 552890075Sobrien int i; 552990075Sobrien unsigned char checksum[16]; 553090075Sobrien struct md5_ctx ctx; 553190075Sobrien 553290075Sobrien /* Compute the checksum of the DIE, then append part of it as hex digits to 553390075Sobrien the name filename of the unit. */ 553490075Sobrien 553590075Sobrien md5_init_ctx (&ctx); 553690075Sobrien die_checksum (unit_die, &ctx); 553790075Sobrien md5_finish_ctx (&ctx, checksum); 553890075Sobrien 553990075Sobrien sprintf (name, "%s.", base); 554090075Sobrien clean_symbol_name (name); 554190075Sobrien 554290075Sobrien p = name + strlen (name); 554390075Sobrien for (i = 0; i < 4; i++) 554490075Sobrien { 554590075Sobrien sprintf (p, "%.2x", checksum[i]); 554690075Sobrien p += 2; 554790075Sobrien } 554890075Sobrien 554990075Sobrien comdat_symbol_id = unit_die->die_symbol = xstrdup (name); 555090075Sobrien comdat_symbol_number = 0; 555190075Sobrien} 555290075Sobrien 555390075Sobrien/* Returns nonzero if DIE represents a type, in the sense of TYPE_P. */ 555490075Sobrien 555590075Sobrienstatic int 555690075Sobrienis_type_die (die) 555790075Sobrien dw_die_ref die; 555890075Sobrien{ 555990075Sobrien switch (die->die_tag) 556090075Sobrien { 556190075Sobrien case DW_TAG_array_type: 556290075Sobrien case DW_TAG_class_type: 556390075Sobrien case DW_TAG_enumeration_type: 556490075Sobrien case DW_TAG_pointer_type: 556590075Sobrien case DW_TAG_reference_type: 556690075Sobrien case DW_TAG_string_type: 556790075Sobrien case DW_TAG_structure_type: 556890075Sobrien case DW_TAG_subroutine_type: 556990075Sobrien case DW_TAG_union_type: 557090075Sobrien case DW_TAG_ptr_to_member_type: 557190075Sobrien case DW_TAG_set_type: 557290075Sobrien case DW_TAG_subrange_type: 557390075Sobrien case DW_TAG_base_type: 557490075Sobrien case DW_TAG_const_type: 557590075Sobrien case DW_TAG_file_type: 557690075Sobrien case DW_TAG_packed_type: 557790075Sobrien case DW_TAG_volatile_type: 557890075Sobrien return 1; 557990075Sobrien default: 558090075Sobrien return 0; 558190075Sobrien } 558290075Sobrien} 558390075Sobrien 558490075Sobrien/* Returns 1 iff C is the sort of DIE that should go into a COMDAT CU. 558590075Sobrien Basically, we want to choose the bits that are likely to be shared between 558690075Sobrien compilations (types) and leave out the bits that are specific to individual 558790075Sobrien compilations (functions). */ 558890075Sobrien 558990075Sobrienstatic int 559090075Sobrienis_comdat_die (c) 559190075Sobrien dw_die_ref c; 559290075Sobrien{ 559390075Sobrien /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as 559490075Sobrien we do for stabs. The advantage is a greater likelihood of sharing between 559590075Sobrien objects that don't include headers in the same order (and therefore would 559690075Sobrien put the base types in a different comdat). jason 8/28/00 */ 559790075Sobrien 559890075Sobrien if (c->die_tag == DW_TAG_base_type) 559990075Sobrien return 0; 560090075Sobrien 560190075Sobrien if (c->die_tag == DW_TAG_pointer_type 560290075Sobrien || c->die_tag == DW_TAG_reference_type 560390075Sobrien || c->die_tag == DW_TAG_const_type 560490075Sobrien || c->die_tag == DW_TAG_volatile_type) 560590075Sobrien { 560690075Sobrien dw_die_ref t = get_AT_ref (c, DW_AT_type); 560790075Sobrien 560890075Sobrien return t ? is_comdat_die (t) : 0; 560990075Sobrien } 561090075Sobrien 561190075Sobrien return is_type_die (c); 561290075Sobrien} 561390075Sobrien 561490075Sobrien/* Returns 1 iff C is the sort of DIE that might be referred to from another 561590075Sobrien compilation unit. */ 561690075Sobrien 561790075Sobrienstatic int 561890075Sobrienis_symbol_die (c) 561990075Sobrien dw_die_ref c; 562090075Sobrien{ 562190075Sobrien return (is_type_die (c) 562290075Sobrien || (get_AT (c, DW_AT_declaration) 562390075Sobrien && !get_AT (c, DW_AT_specification))); 562490075Sobrien} 562590075Sobrien 562690075Sobrienstatic char * 562790075Sobriengen_internal_sym (prefix) 562890075Sobrien const char *prefix; 562990075Sobrien{ 563090075Sobrien char buf[256]; 563190075Sobrien static int label_num; 563290075Sobrien 563390075Sobrien ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++); 563490075Sobrien return xstrdup (buf); 563590075Sobrien} 563690075Sobrien 563790075Sobrien/* Assign symbols to all worthy DIEs under DIE. */ 563890075Sobrien 563990075Sobrienstatic void 564090075Sobrienassign_symbol_names (die) 564190075Sobrien dw_die_ref die; 564290075Sobrien{ 564390075Sobrien dw_die_ref c; 564490075Sobrien 564590075Sobrien if (is_symbol_die (die)) 564690075Sobrien { 564790075Sobrien if (comdat_symbol_id) 564890075Sobrien { 564990075Sobrien char *p = alloca (strlen (comdat_symbol_id) + 64); 565090075Sobrien 565190075Sobrien sprintf (p, "%s.%s.%x", DIE_LABEL_PREFIX, 565290075Sobrien comdat_symbol_id, comdat_symbol_number++); 565390075Sobrien die->die_symbol = xstrdup (p); 565490075Sobrien } 565590075Sobrien else 565690075Sobrien die->die_symbol = gen_internal_sym ("LDIE"); 565790075Sobrien } 565890075Sobrien 565950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 566090075Sobrien assign_symbol_names (c); 566190075Sobrien} 566290075Sobrien 566390075Sobrien/* Traverse the DIE (which is always comp_unit_die), and set up 566490075Sobrien additional compilation units for each of the include files we see 566590075Sobrien bracketed by BINCL/EINCL. */ 566690075Sobrien 566790075Sobrienstatic void 566890075Sobrienbreak_out_includes (die) 566990075Sobrien dw_die_ref die; 567090075Sobrien{ 567190075Sobrien dw_die_ref *ptr; 567290075Sobrien dw_die_ref unit = NULL; 567390075Sobrien limbo_die_node *node; 567490075Sobrien 567590075Sobrien for (ptr = &(die->die_child); *ptr; ) 567690075Sobrien { 567790075Sobrien dw_die_ref c = *ptr; 567890075Sobrien 567990075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL || c->die_tag == DW_TAG_GNU_EINCL 568090075Sobrien || (unit && is_comdat_die (c))) 568190075Sobrien { 568290075Sobrien /* This DIE is for a secondary CU; remove it from the main one. */ 568390075Sobrien *ptr = c->die_sib; 568490075Sobrien 568590075Sobrien if (c->die_tag == DW_TAG_GNU_BINCL) 568690075Sobrien { 568790075Sobrien unit = push_new_compile_unit (unit, c); 568890075Sobrien free_die (c); 568990075Sobrien } 569090075Sobrien else if (c->die_tag == DW_TAG_GNU_EINCL) 569190075Sobrien { 569290075Sobrien unit = pop_compile_unit (unit); 569390075Sobrien free_die (c); 569490075Sobrien } 569590075Sobrien else 569690075Sobrien add_child_die (unit, c); 569790075Sobrien } 569890075Sobrien else 569990075Sobrien { 570090075Sobrien /* Leave this DIE in the main CU. */ 570190075Sobrien ptr = &(c->die_sib); 570290075Sobrien continue; 570390075Sobrien } 570490075Sobrien } 570590075Sobrien 570690075Sobrien#if 0 570790075Sobrien /* We can only use this in debugging, since the frontend doesn't check 570890075Sobrien to make sure that we leave every include file we enter. */ 570990075Sobrien if (unit != NULL) 571090075Sobrien abort (); 571190075Sobrien#endif 571290075Sobrien 571390075Sobrien assign_symbol_names (die); 571490075Sobrien for (node = limbo_die_list; node; node = node->next) 571590075Sobrien { 571690075Sobrien compute_section_prefix (node->die); 571790075Sobrien assign_symbol_names (node->die); 571890075Sobrien } 571990075Sobrien} 572090075Sobrien 572190075Sobrien/* Traverse the DIE and add a sibling attribute if it may have the 572290075Sobrien effect of speeding up access to siblings. To save some space, 572390075Sobrien avoid generating sibling attributes for DIE's without children. */ 572490075Sobrien 572590075Sobrienstatic void 572690075Sobrienadd_sibling_attributes (die) 572790075Sobrien dw_die_ref die; 572890075Sobrien{ 572990075Sobrien dw_die_ref c; 573090075Sobrien 573190075Sobrien if (die->die_tag != DW_TAG_compile_unit 573290075Sobrien && die->die_sib && die->die_child != NULL) 573390075Sobrien /* Add the sibling link to the front of the attribute list. */ 573490075Sobrien add_AT_die_ref (die, DW_AT_sibling, die->die_sib); 573590075Sobrien 573690075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 573750397Sobrien add_sibling_attributes (c); 573850397Sobrien} 573950397Sobrien 574090075Sobrien/* Output all location lists for the DIE and its children. */ 574150397Sobrien 574250397Sobrienstatic void 574390075Sobrienoutput_location_lists (die) 574490075Sobrien dw_die_ref die; 574590075Sobrien{ 574690075Sobrien dw_die_ref c; 574790075Sobrien dw_attr_ref d_attr; 574890075Sobrien 574990075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 575090075Sobrien if (AT_class (d_attr) == dw_val_class_loc_list) 575190075Sobrien output_loc_list (AT_loc_list (d_attr)); 575290075Sobrien 575390075Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 575490075Sobrien output_location_lists (c); 575590075Sobrien 575690075Sobrien} 575790075Sobrien/* The format of each DIE (and its attribute value pairs) is encoded in an 575890075Sobrien abbreviation table. This routine builds the abbreviation table and assigns 575990075Sobrien a unique abbreviation id for each abbreviation entry. The children of each 576090075Sobrien die are visited recursively. */ 576190075Sobrien 576290075Sobrienstatic void 576350397Sobrienbuild_abbrev_table (die) 576490075Sobrien dw_die_ref die; 576550397Sobrien{ 576690075Sobrien unsigned long abbrev_id; 576790075Sobrien unsigned int n_alloc; 576890075Sobrien dw_die_ref c; 576990075Sobrien dw_attr_ref d_attr, a_attr; 577090075Sobrien 577190075Sobrien /* Scan the DIE references, and mark as external any that refer to 577290075Sobrien DIEs from other CUs (i.e. those which are not marked). */ 577390075Sobrien for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) 577490075Sobrien if (AT_class (d_attr) == dw_val_class_die_ref 577590075Sobrien && AT_ref (d_attr)->die_mark == 0) 577690075Sobrien { 577790075Sobrien if (AT_ref (d_attr)->die_symbol == 0) 577890075Sobrien abort (); 577990075Sobrien 578090075Sobrien set_AT_ref_external (d_attr, 1); 578190075Sobrien } 578290075Sobrien 578350397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 578450397Sobrien { 578590075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 578650397Sobrien 578750397Sobrien if (abbrev->die_tag == die->die_tag) 578850397Sobrien { 578950397Sobrien if ((abbrev->die_child != NULL) == (die->die_child != NULL)) 579050397Sobrien { 579150397Sobrien a_attr = abbrev->die_attr; 579250397Sobrien d_attr = die->die_attr; 579350397Sobrien 579450397Sobrien while (a_attr != NULL && d_attr != NULL) 579550397Sobrien { 579650397Sobrien if ((a_attr->dw_attr != d_attr->dw_attr) 579790075Sobrien || (value_format (a_attr) != value_format (d_attr))) 579850397Sobrien break; 579950397Sobrien 580050397Sobrien a_attr = a_attr->dw_attr_next; 580150397Sobrien d_attr = d_attr->dw_attr_next; 580250397Sobrien } 580350397Sobrien 580450397Sobrien if (a_attr == NULL && d_attr == NULL) 580550397Sobrien break; 580650397Sobrien } 580750397Sobrien } 580850397Sobrien } 580950397Sobrien 581050397Sobrien if (abbrev_id >= abbrev_die_table_in_use) 581150397Sobrien { 581250397Sobrien if (abbrev_die_table_in_use >= abbrev_die_table_allocated) 581350397Sobrien { 581450397Sobrien n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; 581590075Sobrien abbrev_die_table 581650397Sobrien = (dw_die_ref *) xrealloc (abbrev_die_table, 581750397Sobrien sizeof (dw_die_ref) * n_alloc); 581850397Sobrien 581990075Sobrien memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0, 582050397Sobrien (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); 582150397Sobrien abbrev_die_table_allocated = n_alloc; 582250397Sobrien } 582350397Sobrien 582450397Sobrien ++abbrev_die_table_in_use; 582550397Sobrien abbrev_die_table[abbrev_id] = die; 582650397Sobrien } 582750397Sobrien 582850397Sobrien die->die_abbrev = abbrev_id; 582950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 583050397Sobrien build_abbrev_table (c); 583150397Sobrien} 583250397Sobrien 583350397Sobrien/* Return the power-of-two number of bytes necessary to represent VALUE. */ 583450397Sobrien 583550397Sobrienstatic int 583650397Sobrienconstant_size (value) 583750397Sobrien long unsigned value; 583850397Sobrien{ 583950397Sobrien int log; 584050397Sobrien 584150397Sobrien if (value == 0) 584250397Sobrien log = 0; 584350397Sobrien else 584450397Sobrien log = floor_log2 (value); 584550397Sobrien 584650397Sobrien log = log / 8; 584750397Sobrien log = 1 << (floor_log2 (log) + 1); 584850397Sobrien 584950397Sobrien return log; 585050397Sobrien} 585150397Sobrien 585290075Sobrien/* Return the size of a DIE as it is represented in the 585350397Sobrien .debug_info section. */ 585450397Sobrien 585550397Sobrienstatic unsigned long 585650397Sobriensize_of_die (die) 585790075Sobrien dw_die_ref die; 585850397Sobrien{ 585990075Sobrien unsigned long size = 0; 586090075Sobrien dw_attr_ref a; 586150397Sobrien 586250397Sobrien size += size_of_uleb128 (die->die_abbrev); 586350397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 586450397Sobrien { 586590075Sobrien switch (AT_class (a)) 586650397Sobrien { 586750397Sobrien case dw_val_class_addr: 586890075Sobrien size += DWARF2_ADDR_SIZE; 586950397Sobrien break; 587090075Sobrien case dw_val_class_offset: 587190075Sobrien size += DWARF_OFFSET_SIZE; 587290075Sobrien break; 587350397Sobrien case dw_val_class_loc: 587450397Sobrien { 587590075Sobrien unsigned long lsize = size_of_locs (AT_loc (a)); 587650397Sobrien 587750397Sobrien /* Block length. */ 587850397Sobrien size += constant_size (lsize); 587950397Sobrien size += lsize; 588050397Sobrien } 588150397Sobrien break; 588290075Sobrien case dw_val_class_loc_list: 588390075Sobrien size += DWARF_OFFSET_SIZE; 588490075Sobrien break; 588590075Sobrien case dw_val_class_range_list: 588690075Sobrien size += DWARF_OFFSET_SIZE; 588790075Sobrien break; 588850397Sobrien case dw_val_class_const: 588990075Sobrien size += size_of_sleb128 (AT_int (a)); 589050397Sobrien break; 589150397Sobrien case dw_val_class_unsigned_const: 589290075Sobrien size += constant_size (AT_unsigned (a)); 589350397Sobrien break; 589450397Sobrien case dw_val_class_long_long: 589590075Sobrien size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */ 589650397Sobrien break; 589750397Sobrien case dw_val_class_float: 589850397Sobrien size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ 589950397Sobrien break; 590050397Sobrien case dw_val_class_flag: 590150397Sobrien size += 1; 590250397Sobrien break; 590350397Sobrien case dw_val_class_die_ref: 590450397Sobrien size += DWARF_OFFSET_SIZE; 590550397Sobrien break; 590650397Sobrien case dw_val_class_fde_ref: 590750397Sobrien size += DWARF_OFFSET_SIZE; 590850397Sobrien break; 590950397Sobrien case dw_val_class_lbl_id: 591090075Sobrien size += DWARF2_ADDR_SIZE; 591150397Sobrien break; 591252284Sobrien case dw_val_class_lbl_offset: 591350397Sobrien size += DWARF_OFFSET_SIZE; 591450397Sobrien break; 591550397Sobrien case dw_val_class_str: 591690075Sobrien if (AT_string_form (a) == DW_FORM_strp) 591790075Sobrien size += DWARF_OFFSET_SIZE; 591890075Sobrien else 591990075Sobrien size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1; 592050397Sobrien break; 592150397Sobrien default: 592250397Sobrien abort (); 592350397Sobrien } 592450397Sobrien } 592550397Sobrien 592650397Sobrien return size; 592750397Sobrien} 592850397Sobrien 592990075Sobrien/* Size the debugging information associated with a given DIE. Visits the 593090075Sobrien DIE's children recursively. Updates the global variable next_die_offset, on 593190075Sobrien each time through. Uses the current value of next_die_offset to update the 593290075Sobrien die_offset field in each DIE. */ 593350397Sobrien 593450397Sobrienstatic void 593550397Sobriencalc_die_sizes (die) 593650397Sobrien dw_die_ref die; 593750397Sobrien{ 593890075Sobrien dw_die_ref c; 593990075Sobrien 594050397Sobrien die->die_offset = next_die_offset; 594150397Sobrien next_die_offset += size_of_die (die); 594250397Sobrien 594350397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 594450397Sobrien calc_die_sizes (c); 594550397Sobrien 594650397Sobrien if (die->die_child != NULL) 594750397Sobrien /* Count the null byte used to terminate sibling lists. */ 594850397Sobrien next_die_offset += 1; 594950397Sobrien} 595050397Sobrien 595190075Sobrien/* Set the marks for a die and its children. We do this so 595290075Sobrien that we know whether or not a reference needs to use FORM_ref_addr; only 595390075Sobrien DIEs in the same CU will be marked. We used to clear out the offset 595490075Sobrien and use that as the flag, but ran into ordering problems. */ 595550397Sobrien 595690075Sobrienstatic void 595790075Sobrienmark_dies (die) 595890075Sobrien dw_die_ref die; 595950397Sobrien{ 596090075Sobrien dw_die_ref c; 596150397Sobrien 596290075Sobrien die->die_mark = 1; 596390075Sobrien for (c = die->die_child; c; c = c->die_sib) 596490075Sobrien mark_dies (c); 596550397Sobrien} 596650397Sobrien 596790075Sobrien/* Clear the marks for a die and its children. */ 596850397Sobrien 596990075Sobrienstatic void 597090075Sobrienunmark_dies (die) 597190075Sobrien dw_die_ref die; 597250397Sobrien{ 597390075Sobrien dw_die_ref c; 597450397Sobrien 597590075Sobrien die->die_mark = 0; 597690075Sobrien for (c = die->die_child; c; c = c->die_sib) 597790075Sobrien unmark_dies (c); 597850397Sobrien} 597950397Sobrien 598050397Sobrien/* Return the size of the .debug_pubnames table generated for the 598150397Sobrien compilation unit. */ 598250397Sobrien 598350397Sobrienstatic unsigned long 598450397Sobriensize_of_pubnames () 598550397Sobrien{ 598690075Sobrien unsigned long size; 598790075Sobrien unsigned i; 598850397Sobrien 598950397Sobrien size = DWARF_PUBNAMES_HEADER_SIZE; 599090075Sobrien for (i = 0; i < pubname_table_in_use; i++) 599150397Sobrien { 599290075Sobrien pubname_ref p = &pubname_table[i]; 599390075Sobrien size += DWARF_OFFSET_SIZE + strlen (p->name) + 1; 599450397Sobrien } 599550397Sobrien 599650397Sobrien size += DWARF_OFFSET_SIZE; 599750397Sobrien return size; 599850397Sobrien} 599950397Sobrien 600050397Sobrien/* Return the size of the information in the .debug_aranges section. */ 600150397Sobrien 600250397Sobrienstatic unsigned long 600350397Sobriensize_of_aranges () 600450397Sobrien{ 600590075Sobrien unsigned long size; 600650397Sobrien 600750397Sobrien size = DWARF_ARANGES_HEADER_SIZE; 600850397Sobrien 600950397Sobrien /* Count the address/length pair for this compilation unit. */ 601090075Sobrien size += 2 * DWARF2_ADDR_SIZE; 601190075Sobrien size += 2 * DWARF2_ADDR_SIZE * arange_table_in_use; 601250397Sobrien 601350397Sobrien /* Count the two zero words used to terminated the address range table. */ 601490075Sobrien size += 2 * DWARF2_ADDR_SIZE; 601550397Sobrien return size; 601650397Sobrien} 601750397Sobrien 601850397Sobrien/* Select the encoding of an attribute value. */ 601950397Sobrien 602050397Sobrienstatic enum dwarf_form 602190075Sobrienvalue_format (a) 602290075Sobrien dw_attr_ref a; 602350397Sobrien{ 602490075Sobrien switch (a->dw_attr_val.val_class) 602550397Sobrien { 602650397Sobrien case dw_val_class_addr: 602750397Sobrien return DW_FORM_addr; 602890075Sobrien case dw_val_class_range_list: 602990075Sobrien case dw_val_class_offset: 603090075Sobrien if (DWARF_OFFSET_SIZE == 4) 603190075Sobrien return DW_FORM_data4; 603290075Sobrien if (DWARF_OFFSET_SIZE == 8) 603390075Sobrien return DW_FORM_data8; 603490075Sobrien abort (); 603590075Sobrien case dw_val_class_loc_list: 603690075Sobrien /* FIXME: Could be DW_FORM_data8, with a > 32 bit size 603790075Sobrien .debug_loc section */ 603890075Sobrien return DW_FORM_data4; 603950397Sobrien case dw_val_class_loc: 604090075Sobrien switch (constant_size (size_of_locs (AT_loc (a)))) 604150397Sobrien { 604250397Sobrien case 1: 604350397Sobrien return DW_FORM_block1; 604450397Sobrien case 2: 604550397Sobrien return DW_FORM_block2; 604650397Sobrien default: 604750397Sobrien abort (); 604850397Sobrien } 604950397Sobrien case dw_val_class_const: 605090075Sobrien return DW_FORM_sdata; 605150397Sobrien case dw_val_class_unsigned_const: 605290075Sobrien switch (constant_size (AT_unsigned (a))) 605350397Sobrien { 605450397Sobrien case 1: 605550397Sobrien return DW_FORM_data1; 605650397Sobrien case 2: 605750397Sobrien return DW_FORM_data2; 605850397Sobrien case 4: 605950397Sobrien return DW_FORM_data4; 606050397Sobrien case 8: 606150397Sobrien return DW_FORM_data8; 606250397Sobrien default: 606350397Sobrien abort (); 606450397Sobrien } 606550397Sobrien case dw_val_class_long_long: 606650397Sobrien return DW_FORM_block1; 606750397Sobrien case dw_val_class_float: 606850397Sobrien return DW_FORM_block1; 606950397Sobrien case dw_val_class_flag: 607050397Sobrien return DW_FORM_flag; 607150397Sobrien case dw_val_class_die_ref: 607290075Sobrien if (AT_ref_external (a)) 607390075Sobrien return DW_FORM_ref_addr; 607490075Sobrien else 607590075Sobrien return DW_FORM_ref; 607650397Sobrien case dw_val_class_fde_ref: 607750397Sobrien return DW_FORM_data; 607850397Sobrien case dw_val_class_lbl_id: 607950397Sobrien return DW_FORM_addr; 608052284Sobrien case dw_val_class_lbl_offset: 608150397Sobrien return DW_FORM_data; 608250397Sobrien case dw_val_class_str: 608390075Sobrien return AT_string_form (a); 608490075Sobrien 608550397Sobrien default: 608650397Sobrien abort (); 608750397Sobrien } 608850397Sobrien} 608950397Sobrien 609050397Sobrien/* Output the encoding of an attribute value. */ 609150397Sobrien 609250397Sobrienstatic void 609390075Sobrienoutput_value_format (a) 609490075Sobrien dw_attr_ref a; 609550397Sobrien{ 609690075Sobrien enum dwarf_form form = value_format (a); 609750397Sobrien 609890075Sobrien dw2_asm_output_data_uleb128 (form, "(%s)", dwarf_form_name (form)); 609950397Sobrien} 610050397Sobrien 610150397Sobrien/* Output the .debug_abbrev section which defines the DIE abbreviation 610250397Sobrien table. */ 610350397Sobrien 610450397Sobrienstatic void 610550397Sobrienoutput_abbrev_section () 610650397Sobrien{ 610750397Sobrien unsigned long abbrev_id; 610850397Sobrien 610950397Sobrien dw_attr_ref a_attr; 611090075Sobrien 611150397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 611250397Sobrien { 611390075Sobrien dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 611450397Sobrien 611590075Sobrien dw2_asm_output_data_uleb128 (abbrev_id, "(abbrev code)"); 611690075Sobrien dw2_asm_output_data_uleb128 (abbrev->die_tag, "(TAG: %s)", 611790075Sobrien dwarf_tag_name (abbrev->die_tag)); 611850397Sobrien 611990075Sobrien if (abbrev->die_child != NULL) 612090075Sobrien dw2_asm_output_data (1, DW_children_yes, "DW_children_yes"); 612190075Sobrien else 612290075Sobrien dw2_asm_output_data (1, DW_children_no, "DW_children_no"); 612350397Sobrien 612450397Sobrien for (a_attr = abbrev->die_attr; a_attr != NULL; 612550397Sobrien a_attr = a_attr->dw_attr_next) 612650397Sobrien { 612790075Sobrien dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)", 612890075Sobrien dwarf_attr_name (a_attr->dw_attr)); 612990075Sobrien output_value_format (a_attr); 613050397Sobrien } 613150397Sobrien 613290075Sobrien dw2_asm_output_data (1, 0, NULL); 613390075Sobrien dw2_asm_output_data (1, 0, NULL); 613450397Sobrien } 613552284Sobrien 613690075Sobrien /* Terminate the table. */ 613790075Sobrien dw2_asm_output_data (1, 0, NULL); 613850397Sobrien} 613950397Sobrien 614090075Sobrien/* Output a symbol we can use to refer to this DIE from another CU. */ 614150397Sobrien 614290075Sobrienstatic inline void 614390075Sobrienoutput_die_symbol (die) 614490075Sobrien dw_die_ref die; 614590075Sobrien{ 614690075Sobrien char *sym = die->die_symbol; 614790075Sobrien 614890075Sobrien if (sym == 0) 614990075Sobrien return; 615090075Sobrien 615190075Sobrien if (strncmp (sym, DIE_LABEL_PREFIX, sizeof (DIE_LABEL_PREFIX) - 1) == 0) 615290075Sobrien /* We make these global, not weak; if the target doesn't support 615390075Sobrien .linkonce, it doesn't support combining the sections, so debugging 615490075Sobrien will break. */ 615590075Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, sym); 615690075Sobrien 615790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, sym); 615890075Sobrien} 615990075Sobrien 616090075Sobrien/* Return a new location list, given the begin and end range, and the 616190075Sobrien expression. gensym tells us whether to generate a new internal symbol for 616290075Sobrien this location list node, which is done for the head of the list only. */ 616390075Sobrien 616490075Sobrienstatic inline dw_loc_list_ref 616590075Sobriennew_loc_list (expr, begin, end, section, gensym) 616690075Sobrien dw_loc_descr_ref expr; 616790075Sobrien const char *begin; 616890075Sobrien const char *end; 616990075Sobrien const char *section; 617090075Sobrien unsigned gensym; 617190075Sobrien{ 617290075Sobrien dw_loc_list_ref retlist 617390075Sobrien = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node)); 617490075Sobrien 617590075Sobrien retlist->begin = begin; 617690075Sobrien retlist->end = end; 617790075Sobrien retlist->expr = expr; 617890075Sobrien retlist->section = section; 617990075Sobrien if (gensym) 618090075Sobrien retlist->ll_symbol = gen_internal_sym ("LLST"); 618190075Sobrien 618290075Sobrien return retlist; 618390075Sobrien} 618490075Sobrien 618590075Sobrien/* Add a location description expression to a location list */ 618690075Sobrien 618790075Sobrienstatic inline void 618890075Sobrienadd_loc_descr_to_loc_list (list_head, descr, begin, end, section) 618990075Sobrien dw_loc_list_ref *list_head; 619090075Sobrien dw_loc_descr_ref descr; 619190075Sobrien const char *begin; 619290075Sobrien const char *end; 619390075Sobrien const char *section; 619490075Sobrien{ 619590075Sobrien dw_loc_list_ref *d; 619690075Sobrien 619790075Sobrien /* Find the end of the chain. */ 619890075Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 619990075Sobrien ; 620090075Sobrien 620190075Sobrien /* Add a new location list node to the list */ 620290075Sobrien *d = new_loc_list (descr, begin, end, section, 0); 620390075Sobrien} 620490075Sobrien 620590075Sobrien/* Output the location list given to us */ 620690075Sobrien 620750397Sobrienstatic void 620890075Sobrienoutput_loc_list (list_head) 620990075Sobrien dw_loc_list_ref list_head; 621050397Sobrien{ 621190075Sobrien dw_loc_list_ref curr = list_head; 621250397Sobrien 621390075Sobrien ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); 621490075Sobrien 621590075Sobrien /* ??? This shouldn't be needed now that we've forced the 621690075Sobrien compilation unit base address to zero when there is code 621790075Sobrien in more than one section. */ 621890075Sobrien if (strcmp (curr->section, ".text") == 0) 621950397Sobrien { 622090075Sobrien /* dw2_asm_output_data will mask off any extra bits in the ~0. */ 622190075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0, 622290075Sobrien "Location list base address specifier fake entry"); 622390075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section, 622490075Sobrien "Location list base address specifier base"); 622550397Sobrien } 622650397Sobrien 622790075Sobrien for (curr = list_head; curr != NULL; curr=curr->dw_loc_next) 622890075Sobrien { 622990075Sobrien unsigned long size; 623050397Sobrien 623190075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, 623290075Sobrien "Location list begin address (%s)", 623390075Sobrien list_head->ll_symbol); 623490075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section, 623590075Sobrien "Location list end address (%s)", 623690075Sobrien list_head->ll_symbol); 623790075Sobrien size = size_of_locs (curr->expr); 623890075Sobrien 623990075Sobrien /* Output the block length for this list of location operations. */ 624090075Sobrien if (size > 0xffff) 624190075Sobrien abort (); 624290075Sobrien dw2_asm_output_data (2, size, "%s", "Location expression size"); 624350397Sobrien 624490075Sobrien output_loc_sequence (curr->expr); 624590075Sobrien } 624650397Sobrien 624790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 624890075Sobrien "Location list terminator begin (%s)", 624990075Sobrien list_head->ll_symbol); 625090075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, 625190075Sobrien "Location list terminator end (%s)", 625290075Sobrien list_head->ll_symbol); 625350397Sobrien} 625450397Sobrien 625550397Sobrien/* Output the DIE and its attributes. Called recursively to generate 625650397Sobrien the definitions of each child DIE. */ 625750397Sobrien 625850397Sobrienstatic void 625950397Sobrienoutput_die (die) 626090075Sobrien dw_die_ref die; 626150397Sobrien{ 626290075Sobrien dw_attr_ref a; 626390075Sobrien dw_die_ref c; 626490075Sobrien unsigned long size; 626550397Sobrien 626690075Sobrien /* If someone in another CU might refer to us, set up a symbol for 626790075Sobrien them to point to. */ 626890075Sobrien if (die->die_symbol) 626990075Sobrien output_die_symbol (die); 627050397Sobrien 627190075Sobrien dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (0x%lx) %s)", 627290075Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 627350397Sobrien 627450397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 627550397Sobrien { 627690075Sobrien const char *name = dwarf_attr_name (a->dw_attr); 627790075Sobrien 627890075Sobrien switch (AT_class (a)) 627950397Sobrien { 628050397Sobrien case dw_val_class_addr: 628190075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name); 628250397Sobrien break; 628350397Sobrien 628490075Sobrien case dw_val_class_offset: 628590075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset, 628690075Sobrien "%s", name); 628790075Sobrien break; 628850397Sobrien 628990075Sobrien case dw_val_class_range_list: 629090075Sobrien { 629190075Sobrien char *p = strchr (ranges_section_label, '\0'); 629250397Sobrien 629390075Sobrien sprintf (p, "+0x%lx", a->dw_attr_val.v.val_offset); 629490075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label, 629590075Sobrien "%s", name); 629690075Sobrien *p = '\0'; 629790075Sobrien } 629890075Sobrien break; 629950397Sobrien 630090075Sobrien case dw_val_class_loc: 630190075Sobrien size = size_of_locs (AT_loc (a)); 630250397Sobrien 630390075Sobrien /* Output the block length for this list of location operations. */ 630490075Sobrien dw2_asm_output_data (constant_size (size), size, "%s", name); 630550397Sobrien 630690075Sobrien output_loc_sequence (AT_loc (a)); 630750397Sobrien break; 630850397Sobrien 630950397Sobrien case dw_val_class_const: 631090075Sobrien /* ??? It would be slightly more efficient to use a scheme like is 631190075Sobrien used for unsigned constants below, but gdb 4.x does not sign 631290075Sobrien extend. Gdb 5.x does sign extend. */ 631390075Sobrien dw2_asm_output_data_sleb128 (AT_int (a), "%s", name); 631450397Sobrien break; 631550397Sobrien 631650397Sobrien case dw_val_class_unsigned_const: 631790075Sobrien dw2_asm_output_data (constant_size (AT_unsigned (a)), 631890075Sobrien AT_unsigned (a), "%s", name); 631950397Sobrien break; 632050397Sobrien 632150397Sobrien case dw_val_class_long_long: 632290075Sobrien { 632390075Sobrien unsigned HOST_WIDE_INT first, second; 632450397Sobrien 632590075Sobrien dw2_asm_output_data (1, 632690075Sobrien 2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 632790075Sobrien "%s", name); 632850397Sobrien 632990075Sobrien if (WORDS_BIG_ENDIAN) 633090075Sobrien { 633190075Sobrien first = a->dw_attr_val.v.val_long_long.hi; 633290075Sobrien second = a->dw_attr_val.v.val_long_long.low; 633390075Sobrien } 633490075Sobrien else 633590075Sobrien { 633690075Sobrien first = a->dw_attr_val.v.val_long_long.low; 633790075Sobrien second = a->dw_attr_val.v.val_long_long.hi; 633890075Sobrien } 633990075Sobrien 634090075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 634190075Sobrien first, "long long constant"); 634290075Sobrien dw2_asm_output_data (HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR, 634390075Sobrien second, NULL); 634490075Sobrien } 634550397Sobrien break; 634650397Sobrien 634750397Sobrien case dw_val_class_float: 634852284Sobrien { 634990075Sobrien unsigned int i; 635050397Sobrien 635190075Sobrien dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4, 635290075Sobrien "%s", name); 635350397Sobrien 635490075Sobrien for (i = 0; i < a->dw_attr_val.v.val_float.length; i++) 635590075Sobrien dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i], 635690075Sobrien "fp constant word %u", i); 635790075Sobrien break; 635852284Sobrien } 635950397Sobrien 636050397Sobrien case dw_val_class_flag: 636190075Sobrien dw2_asm_output_data (1, AT_flag (a), "%s", name); 636250397Sobrien break; 636350397Sobrien 636490075Sobrien case dw_val_class_loc_list: 636590075Sobrien { 636690075Sobrien char *sym = AT_loc_list (a)->ll_symbol; 636790075Sobrien 636890075Sobrien if (sym == 0) 636990075Sobrien abort (); 637090075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, 637190075Sobrien loc_section_label, "%s", name); 637290075Sobrien } 637390075Sobrien break; 637490075Sobrien 637550397Sobrien case dw_val_class_die_ref: 637690075Sobrien if (AT_ref_external (a)) 637790075Sobrien { 637890075Sobrien char *sym = AT_ref (a)->die_symbol; 637990075Sobrien 638090075Sobrien if (sym == 0) 638190075Sobrien abort (); 638290075Sobrien dw2_asm_output_offset (DWARF2_ADDR_SIZE, sym, "%s", name); 638390075Sobrien } 638490075Sobrien else if (AT_ref (a)->die_offset == 0) 638590075Sobrien abort (); 638650397Sobrien else 638790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, AT_ref (a)->die_offset, 638890075Sobrien "%s", name); 638950397Sobrien break; 639050397Sobrien 639150397Sobrien case dw_val_class_fde_ref: 639250397Sobrien { 639350397Sobrien char l1[20]; 639490075Sobrien 639590075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_LABEL, 639690075Sobrien a->dw_attr_val.v.val_fde_index * 2); 639790075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, l1, "%s", name); 639850397Sobrien } 639950397Sobrien break; 640050397Sobrien 640150397Sobrien case dw_val_class_lbl_id: 640290075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name); 640350397Sobrien break; 640450397Sobrien 640552284Sobrien case dw_val_class_lbl_offset: 640690075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a), "%s", name); 640750397Sobrien break; 640850397Sobrien 640950397Sobrien case dw_val_class_str: 641090075Sobrien if (AT_string_form (a) == DW_FORM_strp) 641190075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, 641290075Sobrien a->dw_attr_val.v.val_str->label, 641390075Sobrien "%s: \"%s\"", name, AT_string (a)); 641450397Sobrien else 641590075Sobrien dw2_asm_output_nstring (AT_string (a), -1, "%s", name); 641650397Sobrien break; 641750397Sobrien 641850397Sobrien default: 641950397Sobrien abort (); 642050397Sobrien } 642150397Sobrien } 642250397Sobrien 642350397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 642450397Sobrien output_die (c); 642550397Sobrien 642690075Sobrien /* Add null byte to terminate sibling list. */ 642750397Sobrien if (die->die_child != NULL) 642890075Sobrien dw2_asm_output_data (1, 0, "end of children of DIE 0x%lx", 642990075Sobrien die->die_offset); 643050397Sobrien} 643150397Sobrien 643250397Sobrien/* Output the compilation unit that appears at the beginning of the 643350397Sobrien .debug_info section, and precedes the DIE descriptions. */ 643450397Sobrien 643550397Sobrienstatic void 643650397Sobrienoutput_compilation_unit_header () 643750397Sobrien{ 643890075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset - DWARF_OFFSET_SIZE, 643990075Sobrien "Length of Compilation Unit Info"); 644090075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number"); 644190075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label, 644290075Sobrien "Offset Into Abbrev. Section"); 644390075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)"); 644490075Sobrien} 644550397Sobrien 644690075Sobrien/* Output the compilation unit DIE and its children. */ 644750397Sobrien 644890075Sobrienstatic void 644990075Sobrienoutput_comp_unit (die) 645090075Sobrien dw_die_ref die; 645190075Sobrien{ 645290075Sobrien const char *secname; 645350397Sobrien 645490075Sobrien /* Even if there are no children of this DIE, we must output the information 645590075Sobrien about the compilation unit. Otherwise, on an empty translation unit, we 645690075Sobrien will generate a present, but empty, .debug_info section. IRIX 6.5 `nm' 645790075Sobrien will then complain when examining the file. First mark all the DIEs in 645890075Sobrien this CU so we know which get local refs. */ 645990075Sobrien mark_dies (die); 646050397Sobrien 646190075Sobrien build_abbrev_table (die); 646290075Sobrien 646390075Sobrien /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ 646490075Sobrien next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; 646590075Sobrien calc_die_sizes (die); 646690075Sobrien 646790075Sobrien if (die->die_symbol) 646890075Sobrien { 646990075Sobrien char *tmp = (char *) alloca (strlen (die->die_symbol) + 24); 647090075Sobrien 647190075Sobrien sprintf (tmp, ".gnu.linkonce.wi.%s", die->die_symbol); 647290075Sobrien secname = tmp; 647390075Sobrien die->die_symbol = NULL; 647490075Sobrien } 647590075Sobrien else 647690075Sobrien secname = (const char *) DEBUG_INFO_SECTION; 647790075Sobrien 647890075Sobrien /* Output debugging information. */ 647990075Sobrien named_section_flags (secname, SECTION_DEBUG); 648090075Sobrien output_compilation_unit_header (); 648190075Sobrien output_die (die); 648290075Sobrien 648390075Sobrien /* Leave the marks on the main CU, so we can check them in 648490075Sobrien output_pubnames. */ 648590075Sobrien if (die->die_symbol) 648690075Sobrien unmark_dies (die); 648750397Sobrien} 648850397Sobrien 648950397Sobrien/* The DWARF2 pubname for a nested thingy looks like "A::f". The output 649050397Sobrien of decl_printable_name for C++ looks like "A::f(int)". Let's drop the 649150397Sobrien argument list, and maybe the scope. */ 649250397Sobrien 649390075Sobrienstatic const char * 649450397Sobriendwarf2_name (decl, scope) 649550397Sobrien tree decl; 649650397Sobrien int scope; 649750397Sobrien{ 649850397Sobrien return (*decl_printable_name) (decl, scope ? 1 : 0); 649950397Sobrien} 650050397Sobrien 650150397Sobrien/* Add a new entry to .debug_pubnames if appropriate. */ 650250397Sobrien 650350397Sobrienstatic void 650450397Sobrienadd_pubname (decl, die) 650550397Sobrien tree decl; 650650397Sobrien dw_die_ref die; 650750397Sobrien{ 650850397Sobrien pubname_ref p; 650950397Sobrien 651050397Sobrien if (! TREE_PUBLIC (decl)) 651150397Sobrien return; 651250397Sobrien 651350397Sobrien if (pubname_table_in_use == pubname_table_allocated) 651450397Sobrien { 651550397Sobrien pubname_table_allocated += PUBNAME_TABLE_INCREMENT; 651690075Sobrien pubname_table 651790075Sobrien = (pubname_ref) xrealloc (pubname_table, 651890075Sobrien (pubname_table_allocated 651990075Sobrien * sizeof (pubname_entry))); 652050397Sobrien } 652150397Sobrien 652250397Sobrien p = &pubname_table[pubname_table_in_use++]; 652350397Sobrien p->die = die; 652450397Sobrien p->name = xstrdup (dwarf2_name (decl, 1)); 652550397Sobrien} 652650397Sobrien 652750397Sobrien/* Output the public names table used to speed up access to externally 652850397Sobrien visible names. For now, only generate entries for externally 652950397Sobrien visible procedures. */ 653050397Sobrien 653150397Sobrienstatic void 653250397Sobrienoutput_pubnames () 653350397Sobrien{ 653490075Sobrien unsigned i; 653590075Sobrien unsigned long pubnames_length = size_of_pubnames (); 653650397Sobrien 653790075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, 653890075Sobrien "Length of Public Names Info"); 653990075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 654090075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 654190075Sobrien "Offset of Compilation Unit Info"); 654290075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset, 654390075Sobrien "Compilation Unit Length"); 654450397Sobrien 654590075Sobrien for (i = 0; i < pubname_table_in_use; i++) 654650397Sobrien { 654790075Sobrien pubname_ref pub = &pubname_table[i]; 654850397Sobrien 654990075Sobrien /* We shouldn't see pubnames for DIEs outside of the main CU. */ 655090075Sobrien if (pub->die->die_mark == 0) 655190075Sobrien abort (); 655250397Sobrien 655390075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, pub->die->die_offset, 655490075Sobrien "DIE offset"); 655550397Sobrien 655690075Sobrien dw2_asm_output_nstring (pub->name, -1, "external name"); 655750397Sobrien } 655850397Sobrien 655990075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); 656050397Sobrien} 656150397Sobrien 656250397Sobrien/* Add a new entry to .debug_aranges if appropriate. */ 656350397Sobrien 656450397Sobrienstatic void 656550397Sobrienadd_arange (decl, die) 656650397Sobrien tree decl; 656750397Sobrien dw_die_ref die; 656850397Sobrien{ 656950397Sobrien if (! DECL_SECTION_NAME (decl)) 657050397Sobrien return; 657150397Sobrien 657250397Sobrien if (arange_table_in_use == arange_table_allocated) 657350397Sobrien { 657450397Sobrien arange_table_allocated += ARANGE_TABLE_INCREMENT; 657590075Sobrien arange_table = (dw_die_ref *) 657690075Sobrien xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref)); 657750397Sobrien } 657850397Sobrien 657950397Sobrien arange_table[arange_table_in_use++] = die; 658050397Sobrien} 658150397Sobrien 658250397Sobrien/* Output the information that goes into the .debug_aranges table. 658350397Sobrien Namely, define the beginning and ending address range of the 658450397Sobrien text section generated for this compilation unit. */ 658550397Sobrien 658650397Sobrienstatic void 658750397Sobrienoutput_aranges () 658850397Sobrien{ 658990075Sobrien unsigned i; 659090075Sobrien unsigned long aranges_length = size_of_aranges (); 659150397Sobrien 659290075Sobrien dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length, 659390075Sobrien "Length of Address Ranges Info"); 659490075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 659590075Sobrien dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_info_section_label, 659690075Sobrien "Offset of Compilation Unit Info"); 659790075Sobrien dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address"); 659890075Sobrien dw2_asm_output_data (1, 0, "Size of Segment Descriptor"); 659950397Sobrien 660090075Sobrien /* We need to align to twice the pointer size here. */ 660190075Sobrien if (DWARF_ARANGES_PAD_SIZE) 660290075Sobrien { 660390075Sobrien /* Pad using a 2 byte words so that padding is correct for any 660490075Sobrien pointer size. */ 660590075Sobrien dw2_asm_output_data (2, 0, "Pad to %d byte boundary", 660690075Sobrien 2 * DWARF2_ADDR_SIZE); 660790075Sobrien for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2) 660890075Sobrien dw2_asm_output_data (2, 0, NULL); 660990075Sobrien } 661050397Sobrien 661190075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); 661290075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, 661390075Sobrien text_section_label, "Length"); 661450397Sobrien 661590075Sobrien for (i = 0; i < arange_table_in_use; i++) 661690075Sobrien { 661790075Sobrien dw_die_ref die = arange_table[i]; 661850397Sobrien 661990075Sobrien /* We shouldn't see aranges for DIEs outside of the main CU. */ 662090075Sobrien if (die->die_mark == 0) 662190075Sobrien abort (); 662250397Sobrien 662390075Sobrien if (die->die_tag == DW_TAG_subprogram) 662490075Sobrien { 662590075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die), 662690075Sobrien "Address"); 662790075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die), 662890075Sobrien get_AT_low_pc (die), "Length"); 662990075Sobrien } 663090075Sobrien else 663190075Sobrien { 663290075Sobrien /* A static variable; extract the symbol from DW_AT_location. 663390075Sobrien Note that this code isn't currently hit, as we only emit 663490075Sobrien aranges for functions (jason 9/23/99). */ 663590075Sobrien dw_attr_ref a = get_AT (die, DW_AT_location); 663690075Sobrien dw_loc_descr_ref loc; 663750397Sobrien 663890075Sobrien if (! a || AT_class (a) != dw_val_class_loc) 663990075Sobrien abort (); 664050397Sobrien 664190075Sobrien loc = AT_loc (a); 664290075Sobrien if (loc->dw_loc_opc != DW_OP_addr) 664390075Sobrien abort (); 664450397Sobrien 664590075Sobrien dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, 664690075Sobrien loc->dw_loc_oprnd1.v.val_addr, "Address"); 664790075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 664890075Sobrien get_AT_unsigned (die, DW_AT_byte_size), 664990075Sobrien "Length"); 665090075Sobrien } 665190075Sobrien } 665250397Sobrien 665390075Sobrien /* Output the terminator words. */ 665490075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 665590075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 665690075Sobrien} 665790075Sobrien 665890075Sobrien/* Add a new entry to .debug_ranges. Return the offset at which it 665990075Sobrien was placed. */ 666090075Sobrien 666190075Sobrienstatic unsigned int 666290075Sobrienadd_ranges (block) 666390075Sobrien tree block; 666490075Sobrien{ 666590075Sobrien unsigned int in_use = ranges_table_in_use; 666690075Sobrien 666790075Sobrien if (in_use == ranges_table_allocated) 666850397Sobrien { 666990075Sobrien ranges_table_allocated += RANGES_TABLE_INCREMENT; 667090075Sobrien ranges_table = (dw_ranges_ref) 667190075Sobrien xrealloc (ranges_table, (ranges_table_allocated 667290075Sobrien * sizeof (struct dw_ranges_struct))); 667390075Sobrien } 667450397Sobrien 667590075Sobrien ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0); 667690075Sobrien ranges_table_in_use = in_use + 1; 667790075Sobrien 667890075Sobrien return in_use * 2 * DWARF2_ADDR_SIZE; 667990075Sobrien} 668090075Sobrien 668190075Sobrienstatic void 668290075Sobrienoutput_ranges () 668390075Sobrien{ 668490075Sobrien unsigned i; 668590075Sobrien static const char *const start_fmt = "Offset 0x%x"; 668690075Sobrien const char *fmt = start_fmt; 668790075Sobrien 668890075Sobrien for (i = 0; i < ranges_table_in_use; i++) 668990075Sobrien { 669090075Sobrien int block_num = ranges_table[i].block_num; 669190075Sobrien 669290075Sobrien if (block_num) 669390075Sobrien { 669490075Sobrien char blabel[MAX_ARTIFICIAL_LABEL_BYTES]; 669590075Sobrien char elabel[MAX_ARTIFICIAL_LABEL_BYTES]; 669690075Sobrien 669790075Sobrien ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num); 669890075Sobrien ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num); 669990075Sobrien 670090075Sobrien /* If all code is in the text section, then the compilation 670190075Sobrien unit base address defaults to DW_AT_low_pc, which is the 670290075Sobrien base of the text section. */ 670390075Sobrien if (separate_line_info_table_in_use == 0) 670490075Sobrien { 670590075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, blabel, 670690075Sobrien text_section_label, 670790075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 670890075Sobrien dw2_asm_output_delta (DWARF2_ADDR_SIZE, elabel, 670990075Sobrien text_section_label, NULL); 671090075Sobrien } 671190075Sobrien 671290075Sobrien /* Otherwise, we add a DW_AT_entry_pc attribute to force the 671390075Sobrien compilation unit base address to zero, which allows us to 671490075Sobrien use absolute addresses, and not worry about whether the 671590075Sobrien target supports cross-section arithmetic. */ 671690075Sobrien else 671790075Sobrien { 671890075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel, 671990075Sobrien fmt, i * 2 * DWARF2_ADDR_SIZE); 672090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel, NULL); 672190075Sobrien } 672290075Sobrien 672390075Sobrien fmt = NULL; 672490075Sobrien } 672550397Sobrien else 672650397Sobrien { 672790075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 672890075Sobrien dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL); 672990075Sobrien fmt = start_fmt; 673090075Sobrien } 673190075Sobrien } 673290075Sobrien} 673350397Sobrien 673490075Sobrien/* Data structure containing information about input files. */ 673590075Sobrienstruct file_info 673690075Sobrien{ 673790075Sobrien char *path; /* Complete file name. */ 673890075Sobrien char *fname; /* File name part. */ 673990075Sobrien int length; /* Length of entire string. */ 674090075Sobrien int file_idx; /* Index in input file table. */ 674190075Sobrien int dir_idx; /* Index in directory table. */ 674290075Sobrien}; 674390075Sobrien 674490075Sobrien/* Data structure containing information about directories with source 674590075Sobrien files. */ 674690075Sobrienstruct dir_info 674790075Sobrien{ 674890075Sobrien char *path; /* Path including directory name. */ 674990075Sobrien int length; /* Path length. */ 675090075Sobrien int prefix; /* Index of directory entry which is a prefix. */ 675190075Sobrien int count; /* Number of files in this directory. */ 675290075Sobrien int dir_idx; /* Index of directory used as base. */ 675390075Sobrien int used; /* Used in the end? */ 675490075Sobrien}; 675590075Sobrien 675690075Sobrien/* Callback function for file_info comparison. We sort by looking at 675790075Sobrien the directories in the path. */ 675890075Sobrien 675990075Sobrienstatic int 676090075Sobrienfile_info_cmp (p1, p2) 676190075Sobrien const void *p1; 676290075Sobrien const void *p2; 676390075Sobrien{ 676490075Sobrien const struct file_info *s1 = p1; 676590075Sobrien const struct file_info *s2 = p2; 676690075Sobrien unsigned char *cp1; 676790075Sobrien unsigned char *cp2; 676890075Sobrien 676990075Sobrien /* Take care of file names without directories. We need to make sure that 677090075Sobrien we return consistent values to qsort since some will get confused if 677190075Sobrien we return the same value when identical operands are passed in opposite 677290075Sobrien orders. So if neither has a directory, return 0 and otherwise return 677390075Sobrien 1 or -1 depending on which one has the directory. */ 677490075Sobrien if ((s1->path == s1->fname || s2->path == s2->fname)) 677590075Sobrien return (s2->path == s2->fname) - (s1->path == s1->fname); 677690075Sobrien 677790075Sobrien cp1 = (unsigned char *) s1->path; 677890075Sobrien cp2 = (unsigned char *) s2->path; 677990075Sobrien 678090075Sobrien while (1) 678190075Sobrien { 678290075Sobrien ++cp1; 678390075Sobrien ++cp2; 678490075Sobrien /* Reached the end of the first path? If so, handle like above. */ 678590075Sobrien if ((cp1 == (unsigned char *) s1->fname) 678690075Sobrien || (cp2 == (unsigned char *) s2->fname)) 678790075Sobrien return ((cp2 == (unsigned char *) s2->fname) 678890075Sobrien - (cp1 == (unsigned char *) s1->fname)); 678990075Sobrien 679090075Sobrien /* Character of current path component the same? */ 679190075Sobrien else if (*cp1 != *cp2) 679290075Sobrien return *cp1 - *cp2; 679390075Sobrien } 679490075Sobrien} 679590075Sobrien 679690075Sobrien/* Output the directory table and the file name table. We try to minimize 679790075Sobrien the total amount of memory needed. A heuristic is used to avoid large 679890075Sobrien slowdowns with many input files. */ 679990075Sobrien 680090075Sobrienstatic void 680190075Sobrienoutput_file_names () 680290075Sobrien{ 680390075Sobrien struct file_info *files; 680490075Sobrien struct dir_info *dirs; 680590075Sobrien int *saved; 680690075Sobrien int *savehere; 680790075Sobrien int *backmap; 680890075Sobrien int ndirs; 680990075Sobrien int idx_offset; 681090075Sobrien int i; 681190075Sobrien int idx; 681290075Sobrien 681390075Sobrien /* Allocate the various arrays we need. */ 681490075Sobrien files = (struct file_info *) alloca (file_table.in_use 681590075Sobrien * sizeof (struct file_info)); 681690075Sobrien dirs = (struct dir_info *) alloca (file_table.in_use 681790075Sobrien * sizeof (struct dir_info)); 681890075Sobrien 681990075Sobrien /* Sort the file names. */ 682090075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 682190075Sobrien { 682290075Sobrien char *f; 682390075Sobrien 682490075Sobrien /* Skip all leading "./". */ 682590075Sobrien f = file_table.table[i]; 682690075Sobrien while (f[0] == '.' && f[1] == '/') 682790075Sobrien f += 2; 682890075Sobrien 682990075Sobrien /* Create a new array entry. */ 683090075Sobrien files[i].path = f; 683190075Sobrien files[i].length = strlen (f); 683290075Sobrien files[i].file_idx = i; 683390075Sobrien 683490075Sobrien /* Search for the file name part. */ 683590075Sobrien f = strrchr (f, '/'); 683690075Sobrien files[i].fname = f == NULL ? files[i].path : f + 1; 683790075Sobrien } 683890075Sobrien 683990075Sobrien qsort (files + 1, file_table.in_use - 1, sizeof (files[0]), file_info_cmp); 684090075Sobrien 684190075Sobrien /* Find all the different directories used. */ 684290075Sobrien dirs[0].path = files[1].path; 684390075Sobrien dirs[0].length = files[1].fname - files[1].path; 684490075Sobrien dirs[0].prefix = -1; 684590075Sobrien dirs[0].count = 1; 684690075Sobrien dirs[0].dir_idx = 0; 684790075Sobrien dirs[0].used = 0; 684890075Sobrien files[1].dir_idx = 0; 684990075Sobrien ndirs = 1; 685090075Sobrien 685190075Sobrien for (i = 2; i < (int) file_table.in_use; i++) 685290075Sobrien if (files[i].fname - files[i].path == dirs[ndirs - 1].length 685390075Sobrien && memcmp (dirs[ndirs - 1].path, files[i].path, 685490075Sobrien dirs[ndirs - 1].length) == 0) 685590075Sobrien { 685690075Sobrien /* Same directory as last entry. */ 685790075Sobrien files[i].dir_idx = ndirs - 1; 685890075Sobrien ++dirs[ndirs - 1].count; 685990075Sobrien } 686090075Sobrien else 686190075Sobrien { 686290075Sobrien int j; 686390075Sobrien 686490075Sobrien /* This is a new directory. */ 686590075Sobrien dirs[ndirs].path = files[i].path; 686690075Sobrien dirs[ndirs].length = files[i].fname - files[i].path; 686790075Sobrien dirs[ndirs].count = 1; 686890075Sobrien dirs[ndirs].dir_idx = ndirs; 686990075Sobrien dirs[ndirs].used = 0; 687090075Sobrien files[i].dir_idx = ndirs; 687190075Sobrien 687290075Sobrien /* Search for a prefix. */ 687390075Sobrien dirs[ndirs].prefix = -1; 687490075Sobrien for (j = 0; j < ndirs; j++) 687590075Sobrien if (dirs[j].length < dirs[ndirs].length 687690075Sobrien && dirs[j].length > 1 687790075Sobrien && (dirs[ndirs].prefix == -1 687890075Sobrien || dirs[j].length > dirs[dirs[ndirs].prefix].length) 687990075Sobrien && memcmp (dirs[j].path, dirs[ndirs].path, dirs[j].length) == 0) 688090075Sobrien dirs[ndirs].prefix = j; 688190075Sobrien 688290075Sobrien ++ndirs; 688390075Sobrien } 688490075Sobrien 688590075Sobrien /* Now to the actual work. We have to find a subset of the directories which 688690075Sobrien allow expressing the file name using references to the directory table 688790075Sobrien with the least amount of characters. We do not do an exhaustive search 688890075Sobrien where we would have to check out every combination of every single 688990075Sobrien possible prefix. Instead we use a heuristic which provides nearly optimal 689090075Sobrien results in most cases and never is much off. */ 689190075Sobrien saved = (int *) alloca (ndirs * sizeof (int)); 689290075Sobrien savehere = (int *) alloca (ndirs * sizeof (int)); 689390075Sobrien 689490075Sobrien memset (saved, '\0', ndirs * sizeof (saved[0])); 689590075Sobrien for (i = 0; i < ndirs; i++) 689690075Sobrien { 689790075Sobrien int j; 689890075Sobrien int total; 689990075Sobrien 690090075Sobrien /* We can always save some space for the current directory. But this 690190075Sobrien does not mean it will be enough to justify adding the directory. */ 690290075Sobrien savehere[i] = dirs[i].length; 690390075Sobrien total = (savehere[i] - saved[i]) * dirs[i].count; 690490075Sobrien 690590075Sobrien for (j = i + 1; j < ndirs; j++) 690690075Sobrien { 690790075Sobrien savehere[j] = 0; 690890075Sobrien if (saved[j] < dirs[i].length) 690990075Sobrien { 691090075Sobrien /* Determine whether the dirs[i] path is a prefix of the 691190075Sobrien dirs[j] path. */ 691290075Sobrien int k; 691390075Sobrien 691490075Sobrien k = dirs[j].prefix; 691590075Sobrien while (k != -1 && k != i) 691690075Sobrien k = dirs[k].prefix; 691790075Sobrien 691890075Sobrien if (k == i) 691990075Sobrien { 692090075Sobrien /* Yes it is. We can possibly safe some memory but 692190075Sobrien writing the filenames in dirs[j] relative to 692290075Sobrien dirs[i]. */ 692390075Sobrien savehere[j] = dirs[i].length; 692490075Sobrien total += (savehere[j] - saved[j]) * dirs[j].count; 692590075Sobrien } 692690075Sobrien } 692750397Sobrien } 692850397Sobrien 692990075Sobrien /* Check whether we can safe enough to justify adding the dirs[i] 693090075Sobrien directory. */ 693190075Sobrien if (total > dirs[i].length + 1) 693290075Sobrien { 693390075Sobrien /* It's worthwhile adding. */ 693490075Sobrien for (j = i; j < ndirs; j++) 693590075Sobrien if (savehere[j] > 0) 693690075Sobrien { 693790075Sobrien /* Remember how much we saved for this directory so far. */ 693890075Sobrien saved[j] = savehere[j]; 693950397Sobrien 694090075Sobrien /* Remember the prefix directory. */ 694190075Sobrien dirs[j].dir_idx = i; 694290075Sobrien } 694390075Sobrien } 694490075Sobrien } 694550397Sobrien 694690075Sobrien /* We have to emit them in the order they appear in the file_table array 694790075Sobrien since the index is used in the debug info generation. To do this 694890075Sobrien efficiently we generate a back-mapping of the indices first. */ 694990075Sobrien backmap = (int *) alloca (file_table.in_use * sizeof (int)); 695090075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 695190075Sobrien { 695290075Sobrien backmap[files[i].file_idx] = i; 695350397Sobrien 695490075Sobrien /* Mark this directory as used. */ 695590075Sobrien dirs[dirs[files[i].dir_idx].dir_idx].used = 1; 695650397Sobrien } 695750397Sobrien 695890075Sobrien /* That was it. We are ready to emit the information. First emit the 695990075Sobrien directory name table. We have to make sure the first actually emitted 696090075Sobrien directory name has index one; zero is reserved for the current working 696190075Sobrien directory. Make sure we do not confuse these indices with the one for the 696290075Sobrien constructed table (even though most of the time they are identical). */ 696390075Sobrien idx = 1; 696490075Sobrien idx_offset = dirs[0].length > 0 ? 1 : 0; 696590075Sobrien for (i = 1 - idx_offset; i < ndirs; i++) 696690075Sobrien if (dirs[i].used != 0) 696790075Sobrien { 696890075Sobrien dirs[i].used = idx++; 696990075Sobrien dw2_asm_output_nstring (dirs[i].path, dirs[i].length - 1, 697090075Sobrien "Directory Entry: 0x%x", dirs[i].used); 697190075Sobrien } 697290075Sobrien 697390075Sobrien dw2_asm_output_data (1, 0, "End directory table"); 697490075Sobrien 697590075Sobrien /* Correct the index for the current working directory entry if it 697690075Sobrien exists. */ 697790075Sobrien if (idx_offset == 0) 697890075Sobrien dirs[0].used = 0; 697990075Sobrien 698090075Sobrien /* Now write all the file names. */ 698190075Sobrien for (i = 1; i < (int) file_table.in_use; i++) 698290075Sobrien { 698390075Sobrien int file_idx = backmap[i]; 698490075Sobrien int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; 698590075Sobrien 698690075Sobrien dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, 698790075Sobrien "File Entry: 0x%x", i); 698890075Sobrien 698990075Sobrien /* Include directory index. */ 699090075Sobrien dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL); 699190075Sobrien 699290075Sobrien /* Modification time. */ 699390075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 699490075Sobrien 699590075Sobrien /* File length in bytes. */ 699690075Sobrien dw2_asm_output_data_uleb128 (0, NULL); 699790075Sobrien } 699890075Sobrien 699990075Sobrien dw2_asm_output_data (1, 0, "End file name table"); 700050397Sobrien} 700150397Sobrien 700290075Sobrien 700350397Sobrien/* Output the source line number correspondence information. This 700490075Sobrien information goes into the .debug_line section. */ 700550397Sobrien 700650397Sobrienstatic void 700750397Sobrienoutput_line_info () 700850397Sobrien{ 700990075Sobrien char l1[20], l2[20], p1[20], p2[20]; 701050397Sobrien char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 701150397Sobrien char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 701290075Sobrien unsigned opc; 701390075Sobrien unsigned n_op_args; 701490075Sobrien unsigned long lt_index; 701590075Sobrien unsigned long current_line; 701690075Sobrien long line_offset; 701790075Sobrien long line_delta; 701890075Sobrien unsigned long current_file; 701990075Sobrien unsigned long function; 702050397Sobrien 702190075Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, LINE_NUMBER_BEGIN_LABEL, 0); 702290075Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, LINE_NUMBER_END_LABEL, 0); 702390075Sobrien ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0); 702490075Sobrien ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0); 702550397Sobrien 702690075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, 702790075Sobrien "Length of Source Line Info"); 702890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 702950397Sobrien 703090075Sobrien dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); 703190075Sobrien dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length"); 703290075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p1); 703350397Sobrien 703490075Sobrien dw2_asm_output_data (1, DWARF_LINE_MIN_INSTR_LENGTH, 703590075Sobrien "Minimum Instruction Length"); 703690075Sobrien dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START, 703790075Sobrien "Default is_stmt_start flag"); 703890075Sobrien dw2_asm_output_data (1, DWARF_LINE_BASE, 703990075Sobrien "Line Base Value (Special Opcodes)"); 704090075Sobrien dw2_asm_output_data (1, DWARF_LINE_RANGE, 704190075Sobrien "Line Range Value (Special Opcodes)"); 704290075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE, 704390075Sobrien "Special Opcode Base"); 704450397Sobrien 704590075Sobrien for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; opc++) 704650397Sobrien { 704750397Sobrien switch (opc) 704850397Sobrien { 704950397Sobrien case DW_LNS_advance_pc: 705050397Sobrien case DW_LNS_advance_line: 705150397Sobrien case DW_LNS_set_file: 705250397Sobrien case DW_LNS_set_column: 705350397Sobrien case DW_LNS_fixed_advance_pc: 705450397Sobrien n_op_args = 1; 705550397Sobrien break; 705650397Sobrien default: 705750397Sobrien n_op_args = 0; 705850397Sobrien break; 705950397Sobrien } 706050397Sobrien 706190075Sobrien dw2_asm_output_data (1, n_op_args, "opcode: 0x%x has %d args", 706290075Sobrien opc, n_op_args); 706350397Sobrien } 706450397Sobrien 706590075Sobrien /* Write out the information about the files we use. */ 706690075Sobrien output_file_names (); 706790075Sobrien ASM_OUTPUT_LABEL (asm_out_file, p2); 706850397Sobrien 706952284Sobrien /* We used to set the address register to the first location in the text 707052284Sobrien section here, but that didn't accomplish anything since we already 707152284Sobrien have a line note for the opening brace of the first function. */ 707250397Sobrien 707350397Sobrien /* Generate the line number to PC correspondence table, encoded as 707450397Sobrien a series of state machine operations. */ 707550397Sobrien current_file = 1; 707650397Sobrien current_line = 1; 707752284Sobrien strcpy (prev_line_label, text_section_label); 707850397Sobrien for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) 707950397Sobrien { 708090075Sobrien dw_line_info_ref line_info = &line_info_table[lt_index]; 708150397Sobrien 708290075Sobrien#if 0 708390075Sobrien /* Disable this optimization for now; GDB wants to see two line notes 708490075Sobrien at the beginning of a function so it can find the end of the 708590075Sobrien prologue. */ 708690075Sobrien 708752284Sobrien /* Don't emit anything for redundant notes. Just updating the 708852284Sobrien address doesn't accomplish anything, because we already assume 708952284Sobrien that anything after the last address is this line. */ 709052284Sobrien if (line_info->dw_line_num == current_line 709152284Sobrien && line_info->dw_file_num == current_file) 709252284Sobrien continue; 709390075Sobrien#endif 709452284Sobrien 709590075Sobrien /* Emit debug info for the address of the current line. 709690075Sobrien 709790075Sobrien Unfortunately, we have little choice here currently, and must always 709890075Sobrien use the most general form. GCC does not know the address delta 709990075Sobrien itself, so we can't use DW_LNS_advance_pc. Many ports do have length 710090075Sobrien attributes which will give an upper bound on the address range. We 710190075Sobrien could perhaps use length attributes to determine when it is safe to 710290075Sobrien use DW_LNS_fixed_advance_pc. */ 710390075Sobrien 710450397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index); 710550397Sobrien if (0) 710650397Sobrien { 710750397Sobrien /* This can handle deltas up to 0xffff. This takes 3 bytes. */ 710890075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 710990075Sobrien "DW_LNS_fixed_advance_pc"); 711090075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 711150397Sobrien } 711250397Sobrien else 711350397Sobrien { 711490075Sobrien /* This can handle any delta. This takes 711590075Sobrien 4+DWARF2_ADDR_SIZE bytes. */ 711690075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 711790075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 711890075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 711990075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 712050397Sobrien } 712190075Sobrien 712250397Sobrien strcpy (prev_line_label, line_label); 712350397Sobrien 712450397Sobrien /* Emit debug info for the source file of the current line, if 712550397Sobrien different from the previous line. */ 712650397Sobrien if (line_info->dw_file_num != current_file) 712750397Sobrien { 712850397Sobrien current_file = line_info->dw_file_num; 712990075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 713090075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 713190075Sobrien file_table.table[current_file]); 713250397Sobrien } 713350397Sobrien 713450397Sobrien /* Emit debug info for the current line number, choosing the encoding 713550397Sobrien that uses the least amount of space. */ 713652284Sobrien if (line_info->dw_line_num != current_line) 713750397Sobrien { 713852284Sobrien line_offset = line_info->dw_line_num - current_line; 713952284Sobrien line_delta = line_offset - DWARF_LINE_BASE; 714052284Sobrien current_line = line_info->dw_line_num; 714152284Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 714290075Sobrien /* This can handle deltas from -10 to 234, using the current 714390075Sobrien definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This 714490075Sobrien takes 1 byte. */ 714590075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 714690075Sobrien "line %lu", current_line); 714752284Sobrien else 714852284Sobrien { 714952284Sobrien /* This can handle any delta. This takes at least 4 bytes, 715052284Sobrien depending on the value being encoded. */ 715190075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 715290075Sobrien "advance to line %lu", current_line); 715390075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 715490075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 715552284Sobrien } 715650397Sobrien } 715750397Sobrien else 715890075Sobrien /* We still need to start a new row, so output a copy insn. */ 715990075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 716050397Sobrien } 716150397Sobrien 716250397Sobrien /* Emit debug info for the address of the end of the function. */ 716350397Sobrien if (0) 716450397Sobrien { 716590075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 716690075Sobrien "DW_LNS_fixed_advance_pc"); 716790075Sobrien dw2_asm_output_delta (2, text_end_label, prev_line_label, NULL); 716850397Sobrien } 716950397Sobrien else 717050397Sobrien { 717190075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 717290075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 717390075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 717490075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_end_label, NULL); 717550397Sobrien } 717650397Sobrien 717790075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 717890075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 717990075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 718050397Sobrien 718150397Sobrien function = 0; 718250397Sobrien current_file = 1; 718350397Sobrien current_line = 1; 718490075Sobrien for (lt_index = 0; lt_index < separate_line_info_table_in_use;) 718550397Sobrien { 718690075Sobrien dw_separate_line_info_ref line_info 718750397Sobrien = &separate_line_info_table[lt_index]; 718850397Sobrien 718990075Sobrien#if 0 719052284Sobrien /* Don't emit anything for redundant notes. */ 719152284Sobrien if (line_info->dw_line_num == current_line 719252284Sobrien && line_info->dw_file_num == current_file 719352284Sobrien && line_info->function == function) 719452284Sobrien goto cont; 719590075Sobrien#endif 719652284Sobrien 719750397Sobrien /* Emit debug info for the address of the current line. If this is 719850397Sobrien a new function, or the first line of a function, then we need 719950397Sobrien to handle it differently. */ 720050397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL, 720150397Sobrien lt_index); 720250397Sobrien if (function != line_info->function) 720350397Sobrien { 720450397Sobrien function = line_info->function; 720550397Sobrien 720650397Sobrien /* Set the address register to the first line in the function */ 720790075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 720890075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 720990075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 721090075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 721150397Sobrien } 721250397Sobrien else 721350397Sobrien { 721450397Sobrien /* ??? See the DW_LNS_advance_pc comment above. */ 721550397Sobrien if (0) 721650397Sobrien { 721790075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 721890075Sobrien "DW_LNS_fixed_advance_pc"); 721990075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 722050397Sobrien } 722150397Sobrien else 722250397Sobrien { 722390075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 722490075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 722590075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 722690075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 722750397Sobrien } 722850397Sobrien } 722990075Sobrien 723050397Sobrien strcpy (prev_line_label, line_label); 723150397Sobrien 723250397Sobrien /* Emit debug info for the source file of the current line, if 723350397Sobrien different from the previous line. */ 723450397Sobrien if (line_info->dw_file_num != current_file) 723550397Sobrien { 723650397Sobrien current_file = line_info->dw_file_num; 723790075Sobrien dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); 723890075Sobrien dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", 723990075Sobrien file_table.table[current_file]); 724050397Sobrien } 724150397Sobrien 724250397Sobrien /* Emit debug info for the current line number, choosing the encoding 724350397Sobrien that uses the least amount of space. */ 724450397Sobrien if (line_info->dw_line_num != current_line) 724550397Sobrien { 724650397Sobrien line_offset = line_info->dw_line_num - current_line; 724750397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 724850397Sobrien current_line = line_info->dw_line_num; 724950397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 725090075Sobrien dw2_asm_output_data (1, DWARF_LINE_OPCODE_BASE + line_delta, 725190075Sobrien "line %lu", current_line); 725250397Sobrien else 725350397Sobrien { 725490075Sobrien dw2_asm_output_data (1, DW_LNS_advance_line, 725590075Sobrien "advance to line %lu", current_line); 725690075Sobrien dw2_asm_output_data_sleb128 (line_offset, NULL); 725790075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 725850397Sobrien } 725950397Sobrien } 726052284Sobrien else 726190075Sobrien dw2_asm_output_data (1, DW_LNS_copy, "DW_LNS_copy"); 726250397Sobrien 726390075Sobrien#if 0 726452284Sobrien cont: 726590075Sobrien#endif 726650397Sobrien 726790075Sobrien lt_index++; 726890075Sobrien 726950397Sobrien /* If we're done with a function, end its sequence. */ 727050397Sobrien if (lt_index == separate_line_info_table_in_use 727150397Sobrien || separate_line_info_table[lt_index].function != function) 727250397Sobrien { 727350397Sobrien current_file = 1; 727450397Sobrien current_line = 1; 727550397Sobrien 727650397Sobrien /* Emit debug info for the address of the end of the function. */ 727750397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function); 727850397Sobrien if (0) 727950397Sobrien { 728090075Sobrien dw2_asm_output_data (1, DW_LNS_fixed_advance_pc, 728190075Sobrien "DW_LNS_fixed_advance_pc"); 728290075Sobrien dw2_asm_output_delta (2, line_label, prev_line_label, NULL); 728350397Sobrien } 728450397Sobrien else 728550397Sobrien { 728690075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_set_address"); 728790075Sobrien dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); 728890075Sobrien dw2_asm_output_data (1, DW_LNE_set_address, NULL); 728990075Sobrien dw2_asm_output_addr (DWARF2_ADDR_SIZE, line_label, NULL); 729050397Sobrien } 729150397Sobrien 729250397Sobrien /* Output the marker for the end of this sequence. */ 729390075Sobrien dw2_asm_output_data (1, 0, "DW_LNE_end_sequence"); 729490075Sobrien dw2_asm_output_data_uleb128 (1, NULL); 729590075Sobrien dw2_asm_output_data (1, DW_LNE_end_sequence, NULL); 729650397Sobrien } 729750397Sobrien } 729890075Sobrien 729990075Sobrien /* Output the marker for the end of the line number info. */ 730090075Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 730150397Sobrien} 730250397Sobrien 730350397Sobrien/* Given a pointer to a tree node for some base type, return a pointer to 730450397Sobrien a DIE that describes the given type. 730550397Sobrien 730650397Sobrien This routine must only be called for GCC type nodes that correspond to 730750397Sobrien Dwarf base (fundamental) types. */ 730850397Sobrien 730950397Sobrienstatic dw_die_ref 731050397Sobrienbase_type_die (type) 731190075Sobrien tree type; 731250397Sobrien{ 731390075Sobrien dw_die_ref base_type_result; 731490075Sobrien const char *type_name; 731590075Sobrien enum dwarf_type encoding; 731690075Sobrien tree name = TYPE_NAME (type); 731750397Sobrien 731890075Sobrien if (TREE_CODE (type) == ERROR_MARK || TREE_CODE (type) == VOID_TYPE) 731950397Sobrien return 0; 732050397Sobrien 732190075Sobrien if (name) 732290075Sobrien { 732390075Sobrien if (TREE_CODE (name) == TYPE_DECL) 732490075Sobrien name = DECL_NAME (name); 732550397Sobrien 732690075Sobrien type_name = IDENTIFIER_POINTER (name); 732790075Sobrien } 732890075Sobrien else 732990075Sobrien type_name = "__unknown__"; 733090075Sobrien 733150397Sobrien switch (TREE_CODE (type)) 733250397Sobrien { 733350397Sobrien case INTEGER_TYPE: 733450397Sobrien /* Carefully distinguish the C character types, without messing 733550397Sobrien up if the language is not C. Note that we check only for the names 733690075Sobrien that contain spaces; other names might occur by coincidence in other 733750397Sobrien languages. */ 733850397Sobrien if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE 733950397Sobrien && (type == char_type_node 734050397Sobrien || ! strcmp (type_name, "signed char") 734150397Sobrien || ! strcmp (type_name, "unsigned char")))) 734250397Sobrien { 734350397Sobrien if (TREE_UNSIGNED (type)) 734450397Sobrien encoding = DW_ATE_unsigned; 734550397Sobrien else 734650397Sobrien encoding = DW_ATE_signed; 734750397Sobrien break; 734850397Sobrien } 734990075Sobrien /* else fall through. */ 735050397Sobrien 735150397Sobrien case CHAR_TYPE: 735250397Sobrien /* GNU Pascal/Ada CHAR type. Not used in C. */ 735350397Sobrien if (TREE_UNSIGNED (type)) 735450397Sobrien encoding = DW_ATE_unsigned_char; 735550397Sobrien else 735650397Sobrien encoding = DW_ATE_signed_char; 735750397Sobrien break; 735850397Sobrien 735950397Sobrien case REAL_TYPE: 736050397Sobrien encoding = DW_ATE_float; 736150397Sobrien break; 736250397Sobrien 736390075Sobrien /* Dwarf2 doesn't know anything about complex ints, so use 736490075Sobrien a user defined type for it. */ 736550397Sobrien case COMPLEX_TYPE: 736690075Sobrien if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE) 736790075Sobrien encoding = DW_ATE_complex_float; 736890075Sobrien else 736990075Sobrien encoding = DW_ATE_lo_user; 737050397Sobrien break; 737150397Sobrien 737250397Sobrien case BOOLEAN_TYPE: 737350397Sobrien /* GNU FORTRAN/Ada/C++ BOOLEAN type. */ 737450397Sobrien encoding = DW_ATE_boolean; 737550397Sobrien break; 737650397Sobrien 737750397Sobrien default: 737890075Sobrien /* No other TREE_CODEs are Dwarf fundamental types. */ 737990075Sobrien abort (); 738050397Sobrien } 738150397Sobrien 738290075Sobrien base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type); 738390075Sobrien if (demangle_name_func) 738490075Sobrien type_name = (*demangle_name_func) (type_name); 738590075Sobrien 738650397Sobrien add_AT_string (base_type_result, DW_AT_name, type_name); 738750397Sobrien add_AT_unsigned (base_type_result, DW_AT_byte_size, 738850397Sobrien int_size_in_bytes (type)); 738950397Sobrien add_AT_unsigned (base_type_result, DW_AT_encoding, encoding); 739050397Sobrien 739150397Sobrien return base_type_result; 739250397Sobrien} 739350397Sobrien 739450397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to 739550397Sobrien the Dwarf "root" type for the given input type. The Dwarf "root" type of 739650397Sobrien a given type is generally the same as the given type, except that if the 739750397Sobrien given type is a pointer or reference type, then the root type of the given 739850397Sobrien type is the root type of the "basis" type for the pointer or reference 739950397Sobrien type. (This definition of the "root" type is recursive.) Also, the root 740050397Sobrien type of a `const' qualified type or a `volatile' qualified type is the 740150397Sobrien root type of the given type without the qualifiers. */ 740250397Sobrien 740350397Sobrienstatic tree 740450397Sobrienroot_type (type) 740590075Sobrien tree type; 740650397Sobrien{ 740750397Sobrien if (TREE_CODE (type) == ERROR_MARK) 740850397Sobrien return error_mark_node; 740950397Sobrien 741050397Sobrien switch (TREE_CODE (type)) 741150397Sobrien { 741250397Sobrien case ERROR_MARK: 741350397Sobrien return error_mark_node; 741450397Sobrien 741550397Sobrien case POINTER_TYPE: 741650397Sobrien case REFERENCE_TYPE: 741750397Sobrien return type_main_variant (root_type (TREE_TYPE (type))); 741850397Sobrien 741950397Sobrien default: 742050397Sobrien return type_main_variant (type); 742150397Sobrien } 742250397Sobrien} 742350397Sobrien 742450397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the 742550397Sobrien given input type is a Dwarf "fundamental" type. Otherwise return null. */ 742650397Sobrien 742750397Sobrienstatic inline int 742850397Sobrienis_base_type (type) 742990075Sobrien tree type; 743050397Sobrien{ 743150397Sobrien switch (TREE_CODE (type)) 743250397Sobrien { 743350397Sobrien case ERROR_MARK: 743450397Sobrien case VOID_TYPE: 743550397Sobrien case INTEGER_TYPE: 743650397Sobrien case REAL_TYPE: 743750397Sobrien case COMPLEX_TYPE: 743850397Sobrien case BOOLEAN_TYPE: 743950397Sobrien case CHAR_TYPE: 744050397Sobrien return 1; 744150397Sobrien 744250397Sobrien case SET_TYPE: 744350397Sobrien case ARRAY_TYPE: 744450397Sobrien case RECORD_TYPE: 744550397Sobrien case UNION_TYPE: 744650397Sobrien case QUAL_UNION_TYPE: 744750397Sobrien case ENUMERAL_TYPE: 744850397Sobrien case FUNCTION_TYPE: 744950397Sobrien case METHOD_TYPE: 745050397Sobrien case POINTER_TYPE: 745150397Sobrien case REFERENCE_TYPE: 745250397Sobrien case FILE_TYPE: 745350397Sobrien case OFFSET_TYPE: 745450397Sobrien case LANG_TYPE: 745590075Sobrien case VECTOR_TYPE: 745650397Sobrien return 0; 745750397Sobrien 745850397Sobrien default: 745950397Sobrien abort (); 746050397Sobrien } 746150397Sobrien 746250397Sobrien return 0; 746350397Sobrien} 746450397Sobrien 746550397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging 746650397Sobrien entry that chains various modifiers in front of the given type. */ 746750397Sobrien 746850397Sobrienstatic dw_die_ref 746950397Sobrienmodified_type_die (type, is_const_type, is_volatile_type, context_die) 747090075Sobrien tree type; 747190075Sobrien int is_const_type; 747290075Sobrien int is_volatile_type; 747390075Sobrien dw_die_ref context_die; 747450397Sobrien{ 747590075Sobrien enum tree_code code = TREE_CODE (type); 747690075Sobrien dw_die_ref mod_type_die = NULL; 747790075Sobrien dw_die_ref sub_die = NULL; 747890075Sobrien tree item_type = NULL; 747950397Sobrien 748050397Sobrien if (code != ERROR_MARK) 748150397Sobrien { 748290075Sobrien tree qualified_type; 748350397Sobrien 748490075Sobrien /* See if we already have the appropriately qualified variant of 748590075Sobrien this type. */ 748690075Sobrien qualified_type 748790075Sobrien = get_qualified_type (type, 748890075Sobrien ((is_const_type ? TYPE_QUAL_CONST : 0) 748990075Sobrien | (is_volatile_type 749090075Sobrien ? TYPE_QUAL_VOLATILE : 0))); 749150397Sobrien 749290075Sobrien /* If we do, then we can just use its DIE, if it exists. */ 749390075Sobrien if (qualified_type) 749450397Sobrien { 749590075Sobrien mod_type_die = lookup_type_die (qualified_type); 749690075Sobrien if (mod_type_die) 749790075Sobrien return mod_type_die; 749890075Sobrien } 749990075Sobrien 750090075Sobrien /* Handle C typedef types. */ 750190075Sobrien if (qualified_type && TYPE_NAME (qualified_type) 750290075Sobrien && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL 750390075Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type))) 750490075Sobrien { 750590075Sobrien tree type_name = TYPE_NAME (qualified_type); 750690075Sobrien tree dtype = TREE_TYPE (type_name); 750790075Sobrien 750890075Sobrien if (qualified_type == dtype) 750950397Sobrien { 751050397Sobrien /* For a named type, use the typedef. */ 751190075Sobrien gen_type_die (qualified_type, context_die); 751290075Sobrien mod_type_die = lookup_type_die (qualified_type); 751350397Sobrien } 751450397Sobrien else if (is_const_type < TYPE_READONLY (dtype) 751550397Sobrien || is_volatile_type < TYPE_VOLATILE (dtype)) 751650397Sobrien /* cv-unqualified version of named type. Just use the unnamed 751750397Sobrien type to which it refers. */ 751850397Sobrien mod_type_die 751990075Sobrien = modified_type_die (DECL_ORIGINAL_TYPE (type_name), 752050397Sobrien is_const_type, is_volatile_type, 752150397Sobrien context_die); 752290075Sobrien 752350397Sobrien /* Else cv-qualified version of named type; fall through. */ 752450397Sobrien } 752550397Sobrien 752650397Sobrien if (mod_type_die) 752790075Sobrien /* OK. */ 752890075Sobrien ; 752950397Sobrien else if (is_const_type) 753050397Sobrien { 753190075Sobrien mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type); 753250397Sobrien sub_die = modified_type_die (type, 0, is_volatile_type, context_die); 753350397Sobrien } 753450397Sobrien else if (is_volatile_type) 753550397Sobrien { 753690075Sobrien mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type); 753750397Sobrien sub_die = modified_type_die (type, 0, 0, context_die); 753850397Sobrien } 753950397Sobrien else if (code == POINTER_TYPE) 754050397Sobrien { 754190075Sobrien mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); 754250397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 754350397Sobrien#if 0 754450397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 754550397Sobrien#endif 754650397Sobrien item_type = TREE_TYPE (type); 754750397Sobrien } 754850397Sobrien else if (code == REFERENCE_TYPE) 754950397Sobrien { 755090075Sobrien mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); 755150397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 755250397Sobrien#if 0 755350397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 755490075Sobrien#endif 755550397Sobrien item_type = TREE_TYPE (type); 755650397Sobrien } 755750397Sobrien else if (is_base_type (type)) 755850397Sobrien mod_type_die = base_type_die (type); 755950397Sobrien else 756050397Sobrien { 756150397Sobrien gen_type_die (type, context_die); 756250397Sobrien 756350397Sobrien /* We have to get the type_main_variant here (and pass that to the 756450397Sobrien `lookup_type_die' routine) because the ..._TYPE node we have 756550397Sobrien might simply be a *copy* of some original type node (where the 756650397Sobrien copy was created to help us keep track of typedef names) and 756750397Sobrien that copy might have a different TYPE_UID from the original 756850397Sobrien ..._TYPE node. */ 756950397Sobrien mod_type_die = lookup_type_die (type_main_variant (type)); 757050397Sobrien if (mod_type_die == NULL) 757150397Sobrien abort (); 757250397Sobrien } 757390075Sobrien 757490075Sobrien /* We want to equate the qualified type to the die below. */ 757590075Sobrien if (qualified_type) 757690075Sobrien type = qualified_type; 757750397Sobrien } 757850397Sobrien 757950397Sobrien equate_type_number_to_die (type, mod_type_die); 758050397Sobrien if (item_type) 758150397Sobrien /* We must do this after the equate_type_number_to_die call, in case 758250397Sobrien this is a recursive type. This ensures that the modified_type_die 758350397Sobrien recursion will terminate even if the type is recursive. Recursive 758450397Sobrien types are possible in Ada. */ 758550397Sobrien sub_die = modified_type_die (item_type, 758650397Sobrien TYPE_READONLY (item_type), 758750397Sobrien TYPE_VOLATILE (item_type), 758850397Sobrien context_die); 758950397Sobrien 759050397Sobrien if (sub_die != NULL) 759150397Sobrien add_AT_die_ref (mod_type_die, DW_AT_type, sub_die); 759250397Sobrien 759350397Sobrien return mod_type_die; 759450397Sobrien} 759550397Sobrien 759650397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is 759790075Sobrien an enumerated type. */ 759850397Sobrien 759950397Sobrienstatic inline int 760050397Sobrientype_is_enum (type) 760190075Sobrien tree type; 760250397Sobrien{ 760350397Sobrien return TREE_CODE (type) == ENUMERAL_TYPE; 760450397Sobrien} 760550397Sobrien 760690075Sobrien/* Return the register number described by a given RTL node. */ 760750397Sobrien 760890075Sobrienstatic unsigned int 760990075Sobrienreg_number (rtl) 761090075Sobrien rtx rtl; 761190075Sobrien{ 761290075Sobrien unsigned regno = REGNO (rtl); 761390075Sobrien 761490075Sobrien if (regno >= FIRST_PSEUDO_REGISTER) 761590075Sobrien abort (); 761690075Sobrien 761790075Sobrien return DBX_REGISTER_NUMBER (regno); 761890075Sobrien} 761990075Sobrien 762090075Sobrien/* Return a location descriptor that designates a machine register or 762190075Sobrien zero if there is no such. */ 762290075Sobrien 762350397Sobrienstatic dw_loc_descr_ref 762450397Sobrienreg_loc_descriptor (rtl) 762590075Sobrien rtx rtl; 762650397Sobrien{ 762790075Sobrien dw_loc_descr_ref loc_result = NULL; 762890075Sobrien unsigned reg; 762950397Sobrien 763090075Sobrien if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER) 763190075Sobrien return 0; 763290075Sobrien 763390075Sobrien reg = reg_number (rtl); 763450397Sobrien if (reg <= 31) 763550397Sobrien loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0); 763650397Sobrien else 763750397Sobrien loc_result = new_loc_descr (DW_OP_regx, reg, 0); 763850397Sobrien 763950397Sobrien return loc_result; 764050397Sobrien} 764150397Sobrien 764290075Sobrien/* Return a location descriptor that designates a constant. */ 764390075Sobrien 764490075Sobrienstatic dw_loc_descr_ref 764590075Sobrienint_loc_descriptor (i) 764690075Sobrien HOST_WIDE_INT i; 764790075Sobrien{ 764890075Sobrien enum dwarf_location_atom op; 764990075Sobrien 765090075Sobrien /* Pick the smallest representation of a constant, rather than just 765190075Sobrien defaulting to the LEB encoding. */ 765290075Sobrien if (i >= 0) 765390075Sobrien { 765490075Sobrien if (i <= 31) 765590075Sobrien op = DW_OP_lit0 + i; 765690075Sobrien else if (i <= 0xff) 765790075Sobrien op = DW_OP_const1u; 765890075Sobrien else if (i <= 0xffff) 765990075Sobrien op = DW_OP_const2u; 766090075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 766190075Sobrien || i <= 0xffffffff) 766290075Sobrien op = DW_OP_const4u; 766390075Sobrien else 766490075Sobrien op = DW_OP_constu; 766590075Sobrien } 766690075Sobrien else 766790075Sobrien { 766890075Sobrien if (i >= -0x80) 766990075Sobrien op = DW_OP_const1s; 767090075Sobrien else if (i >= -0x8000) 767190075Sobrien op = DW_OP_const2s; 767290075Sobrien else if (HOST_BITS_PER_WIDE_INT == 32 767390075Sobrien || i >= -0x80000000) 767490075Sobrien op = DW_OP_const4s; 767590075Sobrien else 767690075Sobrien op = DW_OP_consts; 767790075Sobrien } 767890075Sobrien 767990075Sobrien return new_loc_descr (op, i, 0); 768090075Sobrien} 768190075Sobrien 768250397Sobrien/* Return a location descriptor that designates a base+offset location. */ 768350397Sobrien 768450397Sobrienstatic dw_loc_descr_ref 768550397Sobrienbased_loc_descr (reg, offset) 768650397Sobrien unsigned reg; 768750397Sobrien long int offset; 768850397Sobrien{ 768990075Sobrien dw_loc_descr_ref loc_result; 769050397Sobrien /* For the "frame base", we use the frame pointer or stack pointer 769150397Sobrien registers, since the RTL for local variables is relative to one of 769250397Sobrien them. */ 769390075Sobrien unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed 769490075Sobrien ? HARD_FRAME_POINTER_REGNUM 769590075Sobrien : STACK_POINTER_REGNUM); 769650397Sobrien 769750397Sobrien if (reg == fp_reg) 769850397Sobrien loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); 769950397Sobrien else if (reg <= 31) 770050397Sobrien loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); 770150397Sobrien else 770250397Sobrien loc_result = new_loc_descr (DW_OP_bregx, reg, offset); 770350397Sobrien 770450397Sobrien return loc_result; 770550397Sobrien} 770650397Sobrien 770750397Sobrien/* Return true if this RTL expression describes a base+offset calculation. */ 770850397Sobrien 770950397Sobrienstatic inline int 771050397Sobrienis_based_loc (rtl) 771190075Sobrien rtx rtl; 771250397Sobrien{ 771390075Sobrien return (GET_CODE (rtl) == PLUS 771490075Sobrien && ((GET_CODE (XEXP (rtl, 0)) == REG 771590075Sobrien && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER 771690075Sobrien && GET_CODE (XEXP (rtl, 1)) == CONST_INT))); 771750397Sobrien} 771850397Sobrien 771950397Sobrien/* The following routine converts the RTL for a variable or parameter 772050397Sobrien (resident in memory) into an equivalent Dwarf representation of a 772150397Sobrien mechanism for getting the address of that same variable onto the top of a 772250397Sobrien hypothetical "address evaluation" stack. 772350397Sobrien 772450397Sobrien When creating memory location descriptors, we are effectively transforming 772550397Sobrien the RTL for a memory-resident object into its Dwarf postfix expression 772650397Sobrien equivalent. This routine recursively descends an RTL tree, turning 772790075Sobrien it into Dwarf postfix code as it goes. 772850397Sobrien 772990075Sobrien MODE is the mode of the memory reference, needed to handle some 773090075Sobrien autoincrement addressing modes. 773190075Sobrien 773290075Sobrien Return 0 if we can't represent the location. */ 773390075Sobrien 773450397Sobrienstatic dw_loc_descr_ref 773590075Sobrienmem_loc_descriptor (rtl, mode) 773690075Sobrien rtx rtl; 773790075Sobrien enum machine_mode mode; 773850397Sobrien{ 773950397Sobrien dw_loc_descr_ref mem_loc_result = NULL; 774090075Sobrien 774190075Sobrien /* Note that for a dynamically sized array, the location we will generate a 774250397Sobrien description of here will be the lowest numbered location which is 774350397Sobrien actually within the array. That's *not* necessarily the same as the 774450397Sobrien zeroth element of the array. */ 774550397Sobrien 774690075Sobrien#ifdef ASM_SIMPLIFY_DWARF_ADDR 774790075Sobrien rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); 774890075Sobrien#endif 774990075Sobrien 775050397Sobrien switch (GET_CODE (rtl)) 775150397Sobrien { 775290075Sobrien case POST_INC: 775390075Sobrien case POST_DEC: 775490075Sobrien case POST_MODIFY: 775590075Sobrien /* POST_INC and POST_DEC can be handled just like a SUBREG. So we 775690075Sobrien just fall into the SUBREG code. */ 775790075Sobrien 775890075Sobrien /* ... fall through ... */ 775990075Sobrien 776050397Sobrien case SUBREG: 776150397Sobrien /* The case of a subreg may arise when we have a local (register) 776250397Sobrien variable or a formal (register) parameter which doesn't quite fill 776350397Sobrien up an entire register. For now, just assume that it is 776450397Sobrien legitimate to make the Dwarf info refer to the whole register which 776550397Sobrien contains the given subreg. */ 776690075Sobrien rtl = SUBREG_REG (rtl); 776750397Sobrien 776890075Sobrien /* ... fall through ... */ 776950397Sobrien 777050397Sobrien case REG: 777150397Sobrien /* Whenever a register number forms a part of the description of the 777250397Sobrien method for calculating the (dynamic) address of a memory resident 777390075Sobrien object, DWARF rules require the register number be referred to as 777450397Sobrien a "base register". This distinction is not based in any way upon 777550397Sobrien what category of register the hardware believes the given register 777650397Sobrien belongs to. This is strictly DWARF terminology we're dealing with 777750397Sobrien here. Note that in cases where the location of a memory-resident 777850397Sobrien data object could be expressed as: OP_ADD (OP_BASEREG (basereg), 777950397Sobrien OP_CONST (0)) the actual DWARF location descriptor that we generate 778050397Sobrien may just be OP_BASEREG (basereg). This may look deceptively like 778150397Sobrien the object in question was allocated to a register (rather than in 778250397Sobrien memory) so DWARF consumers need to be aware of the subtle 778350397Sobrien distinction between OP_REG and OP_BASEREG. */ 778490075Sobrien if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) 778590075Sobrien mem_loc_result = based_loc_descr (reg_number (rtl), 0); 778650397Sobrien break; 778750397Sobrien 778850397Sobrien case MEM: 778990075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 779090075Sobrien if (mem_loc_result != 0) 779190075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); 779250397Sobrien break; 779350397Sobrien 779490075Sobrien case LABEL_REF: 779590075Sobrien /* Some ports can transform a symbol ref into a label ref, because 779690075Sobrien the symbol ref is too far away and has to be dumped into a constant 779790075Sobrien pool. */ 779850397Sobrien case CONST: 779950397Sobrien case SYMBOL_REF: 780090075Sobrien /* Alternatively, the symbol in the constant pool might be referenced 780190075Sobrien by a different symbol. */ 780290075Sobrien if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl)) 780390075Sobrien { 780490075Sobrien rtx tmp = get_pool_constant (rtl); 780590075Sobrien 780690075Sobrien if (GET_CODE (tmp) == SYMBOL_REF) 780790075Sobrien rtl = tmp; 780890075Sobrien } 780990075Sobrien 781050397Sobrien mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); 781150397Sobrien mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; 781290075Sobrien mem_loc_result->dw_loc_oprnd1.v.val_addr = rtl; 781390075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 781450397Sobrien break; 781550397Sobrien 781690075Sobrien case PRE_MODIFY: 781790075Sobrien /* Extract the PLUS expression nested inside and fall into 781890075Sobrien PLUS code below. */ 781990075Sobrien rtl = XEXP (rtl, 1); 782090075Sobrien goto plus; 782190075Sobrien 782290075Sobrien case PRE_INC: 782390075Sobrien case PRE_DEC: 782490075Sobrien /* Turn these into a PLUS expression and fall into the PLUS code 782590075Sobrien below. */ 782690075Sobrien rtl = gen_rtx_PLUS (word_mode, XEXP (rtl, 0), 782790075Sobrien GEN_INT (GET_CODE (rtl) == PRE_INC 782890075Sobrien ? GET_MODE_UNIT_SIZE (mode) 782990075Sobrien : -GET_MODE_UNIT_SIZE (mode))); 783090075Sobrien 783190075Sobrien /* ... fall through ... */ 783290075Sobrien 783350397Sobrien case PLUS: 783490075Sobrien plus: 783550397Sobrien if (is_based_loc (rtl)) 783650397Sobrien mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), 783750397Sobrien INTVAL (XEXP (rtl, 1))); 783850397Sobrien else 783950397Sobrien { 784090075Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode); 784190075Sobrien if (mem_loc_result == 0) 784290075Sobrien break; 784390075Sobrien 784490075Sobrien if (GET_CODE (XEXP (rtl, 1)) == CONST_INT 784590075Sobrien && INTVAL (XEXP (rtl, 1)) >= 0) 784690075Sobrien add_loc_descr (&mem_loc_result, 784790075Sobrien new_loc_descr (DW_OP_plus_uconst, 784890075Sobrien INTVAL (XEXP (rtl, 1)), 0)); 784990075Sobrien else 785090075Sobrien { 785190075Sobrien add_loc_descr (&mem_loc_result, 785290075Sobrien mem_loc_descriptor (XEXP (rtl, 1), mode)); 785390075Sobrien add_loc_descr (&mem_loc_result, 785490075Sobrien new_loc_descr (DW_OP_plus, 0, 0)); 785590075Sobrien } 785650397Sobrien } 785750397Sobrien break; 785850397Sobrien 785950397Sobrien case MULT: 786090075Sobrien { 786190075Sobrien /* If a pseudo-reg is optimized away, it is possible for it to 786290075Sobrien be replaced with a MEM containing a multiply. */ 786390075Sobrien dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); 786490075Sobrien dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); 786550397Sobrien 786690075Sobrien if (op0 == 0 || op1 == 0) 786790075Sobrien break; 786890075Sobrien 786990075Sobrien mem_loc_result = op0; 787090075Sobrien add_loc_descr (&mem_loc_result, op1); 787190075Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); 787290075Sobrien break; 787390075Sobrien } 787490075Sobrien 787550397Sobrien case CONST_INT: 787690075Sobrien mem_loc_result = int_loc_descriptor (INTVAL (rtl)); 787750397Sobrien break; 787850397Sobrien 787990075Sobrien case ADDRESSOF: 788090075Sobrien /* If this is a MEM, return its address. Otherwise, we can't 788190075Sobrien represent this. */ 788290075Sobrien if (GET_CODE (XEXP (rtl, 0)) == MEM) 788390075Sobrien return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode); 788490075Sobrien else 788590075Sobrien return 0; 788690075Sobrien 788750397Sobrien default: 788850397Sobrien abort (); 788950397Sobrien } 789050397Sobrien 789150397Sobrien return mem_loc_result; 789250397Sobrien} 789350397Sobrien 789450397Sobrien/* Return a descriptor that describes the concatenation of two locations. 789550397Sobrien This is typically a complex variable. */ 789650397Sobrien 789750397Sobrienstatic dw_loc_descr_ref 789850397Sobrienconcat_loc_descriptor (x0, x1) 789990075Sobrien rtx x0, x1; 790050397Sobrien{ 790150397Sobrien dw_loc_descr_ref cc_loc_result = NULL; 790290075Sobrien dw_loc_descr_ref x0_ref = loc_descriptor (x0); 790390075Sobrien dw_loc_descr_ref x1_ref = loc_descriptor (x1); 790450397Sobrien 790590075Sobrien if (x0_ref == 0 || x1_ref == 0) 790690075Sobrien return 0; 790790075Sobrien 790890075Sobrien cc_loc_result = x0_ref; 790950397Sobrien add_loc_descr (&cc_loc_result, 791090075Sobrien new_loc_descr (DW_OP_piece, 791190075Sobrien GET_MODE_SIZE (GET_MODE (x0)), 0)); 791250397Sobrien 791390075Sobrien add_loc_descr (&cc_loc_result, x1_ref); 791450397Sobrien add_loc_descr (&cc_loc_result, 791590075Sobrien new_loc_descr (DW_OP_piece, 791690075Sobrien GET_MODE_SIZE (GET_MODE (x1)), 0)); 791750397Sobrien 791850397Sobrien return cc_loc_result; 791950397Sobrien} 792050397Sobrien 792150397Sobrien/* Output a proper Dwarf location descriptor for a variable or parameter 792250397Sobrien which is either allocated in a register or in a memory location. For a 792350397Sobrien register, we just generate an OP_REG and the register number. For a 792450397Sobrien memory location we provide a Dwarf postfix expression describing how to 792590075Sobrien generate the (dynamic) address of the object onto the address stack. 792650397Sobrien 792790075Sobrien If we don't know how to describe it, return 0. */ 792890075Sobrien 792950397Sobrienstatic dw_loc_descr_ref 793050397Sobrienloc_descriptor (rtl) 793190075Sobrien rtx rtl; 793250397Sobrien{ 793350397Sobrien dw_loc_descr_ref loc_result = NULL; 793490075Sobrien 793550397Sobrien switch (GET_CODE (rtl)) 793650397Sobrien { 793750397Sobrien case SUBREG: 793850397Sobrien /* The case of a subreg may arise when we have a local (register) 793950397Sobrien variable or a formal (register) parameter which doesn't quite fill 794050397Sobrien up an entire register. For now, just assume that it is 794150397Sobrien legitimate to make the Dwarf info refer to the whole register which 794250397Sobrien contains the given subreg. */ 794390075Sobrien rtl = SUBREG_REG (rtl); 794450397Sobrien 794590075Sobrien /* ... fall through ... */ 794650397Sobrien 794750397Sobrien case REG: 794850397Sobrien loc_result = reg_loc_descriptor (rtl); 794950397Sobrien break; 795050397Sobrien 795150397Sobrien case MEM: 795290075Sobrien loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); 795350397Sobrien break; 795450397Sobrien 795550397Sobrien case CONCAT: 795650397Sobrien loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); 795750397Sobrien break; 795850397Sobrien 795950397Sobrien default: 796050397Sobrien abort (); 796150397Sobrien } 796250397Sobrien 796350397Sobrien return loc_result; 796450397Sobrien} 796550397Sobrien 796690075Sobrien/* Similar, but generate the descriptor from trees instead of rtl. This comes 796790075Sobrien up particularly with variable length arrays. If ADDRESSP is nonzero, we are 796890075Sobrien looking for an address. Otherwise, we return a value. If we can't make a 796990075Sobrien descriptor, return 0. */ 797090075Sobrien 797190075Sobrienstatic dw_loc_descr_ref 797290075Sobrienloc_descriptor_from_tree (loc, addressp) 797390075Sobrien tree loc; 797490075Sobrien int addressp; 797590075Sobrien{ 797690075Sobrien dw_loc_descr_ref ret, ret1; 797790075Sobrien int indirect_p = 0; 797890075Sobrien int unsignedp = TREE_UNSIGNED (TREE_TYPE (loc)); 797990075Sobrien enum dwarf_location_atom op; 798090075Sobrien 798190075Sobrien /* ??? Most of the time we do not take proper care for sign/zero 798290075Sobrien extending the values properly. Hopefully this won't be a real 798390075Sobrien problem... */ 798490075Sobrien 798590075Sobrien switch (TREE_CODE (loc)) 798690075Sobrien { 798790075Sobrien case ERROR_MARK: 798890075Sobrien return 0; 798990075Sobrien 799090075Sobrien case WITH_RECORD_EXPR: 799190075Sobrien case PLACEHOLDER_EXPR: 799290075Sobrien /* This case involves extracting fields from an object to determine the 799390075Sobrien position of other fields. We don't try to encode this here. The 799490075Sobrien only user of this is Ada, which encodes the needed information using 799590075Sobrien the names of types. */ 799690075Sobrien return 0; 799790075Sobrien 799890075Sobrien case CALL_EXPR: 799990075Sobrien return 0; 800090075Sobrien 800190075Sobrien case ADDR_EXPR: 800290075Sobrien /* We can support this only if we can look through conversions and 800390075Sobrien find an INDIRECT_EXPR. */ 800490075Sobrien for (loc = TREE_OPERAND (loc, 0); 800590075Sobrien TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR 800690075Sobrien || TREE_CODE (loc) == NON_LVALUE_EXPR 800790075Sobrien || TREE_CODE (loc) == VIEW_CONVERT_EXPR 800890075Sobrien || TREE_CODE (loc) == SAVE_EXPR; 800990075Sobrien loc = TREE_OPERAND (loc, 0)) 801090075Sobrien ; 801190075Sobrien 801290075Sobrien return (TREE_CODE (loc) == INDIRECT_REF 801390075Sobrien ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp) 801490075Sobrien : 0); 801590075Sobrien 801690075Sobrien case VAR_DECL: 801790075Sobrien case PARM_DECL: 801890075Sobrien { 801990075Sobrien rtx rtl = rtl_for_decl_location (loc); 802090075Sobrien 802190075Sobrien if (rtl == NULL_RTX) 802290075Sobrien return 0; 802390075Sobrien else if (CONSTANT_P (rtl)) 802490075Sobrien { 802590075Sobrien ret = new_loc_descr (DW_OP_addr, 0, 0); 802690075Sobrien ret->dw_loc_oprnd1.val_class = dw_val_class_addr; 802790075Sobrien ret->dw_loc_oprnd1.v.val_addr = rtl; 802890075Sobrien indirect_p = 1; 802990075Sobrien } 803090075Sobrien else 803190075Sobrien { 803290075Sobrien enum machine_mode mode = GET_MODE (rtl); 803390075Sobrien 803490075Sobrien if (GET_CODE (rtl) == MEM) 803590075Sobrien { 803690075Sobrien indirect_p = 1; 803790075Sobrien rtl = XEXP (rtl, 0); 803890075Sobrien } 803990075Sobrien 804090075Sobrien ret = mem_loc_descriptor (rtl, mode); 804190075Sobrien } 804290075Sobrien } 804390075Sobrien break; 804490075Sobrien 804590075Sobrien case INDIRECT_REF: 804690075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 804790075Sobrien indirect_p = 1; 804890075Sobrien break; 804990075Sobrien 805090075Sobrien case COMPOUND_EXPR: 805190075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 1), addressp); 805290075Sobrien 805390075Sobrien case NOP_EXPR: 805490075Sobrien case CONVERT_EXPR: 805590075Sobrien case NON_LVALUE_EXPR: 805690075Sobrien case VIEW_CONVERT_EXPR: 805790075Sobrien case SAVE_EXPR: 805890075Sobrien return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); 805990075Sobrien 806090075Sobrien case COMPONENT_REF: 806190075Sobrien case BIT_FIELD_REF: 806290075Sobrien case ARRAY_REF: 806390075Sobrien case ARRAY_RANGE_REF: 806490075Sobrien { 806590075Sobrien tree obj, offset; 806690075Sobrien HOST_WIDE_INT bitsize, bitpos, bytepos; 806790075Sobrien enum machine_mode mode; 806890075Sobrien int volatilep; 806990075Sobrien 807090075Sobrien obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode, 807190075Sobrien &unsignedp, &volatilep); 807290075Sobrien 807390075Sobrien if (obj == loc) 807490075Sobrien return 0; 807590075Sobrien 807690075Sobrien ret = loc_descriptor_from_tree (obj, 1); 807790075Sobrien if (ret == 0 807890075Sobrien || bitpos % BITS_PER_UNIT != 0 || bitsize % BITS_PER_UNIT != 0) 807990075Sobrien return 0; 808090075Sobrien 808190075Sobrien if (offset != NULL_TREE) 808290075Sobrien { 808390075Sobrien /* Variable offset. */ 808490075Sobrien add_loc_descr (&ret, loc_descriptor_from_tree (offset, 0)); 808590075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 808690075Sobrien } 808790075Sobrien 808890075Sobrien if (!addressp) 808990075Sobrien indirect_p = 1; 809090075Sobrien 809190075Sobrien bytepos = bitpos / BITS_PER_UNIT; 809290075Sobrien if (bytepos > 0) 809390075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); 809490075Sobrien else if (bytepos < 0) 809590075Sobrien { 809690075Sobrien add_loc_descr (&ret, int_loc_descriptor (bytepos)); 809790075Sobrien add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); 809890075Sobrien } 809990075Sobrien break; 810090075Sobrien } 810190075Sobrien 810290075Sobrien case INTEGER_CST: 810390075Sobrien if (host_integerp (loc, 0)) 810490075Sobrien ret = int_loc_descriptor (tree_low_cst (loc, 0)); 810590075Sobrien else 810690075Sobrien return 0; 810790075Sobrien break; 810890075Sobrien 810990075Sobrien case TRUTH_AND_EXPR: 811090075Sobrien case TRUTH_ANDIF_EXPR: 811190075Sobrien case BIT_AND_EXPR: 811290075Sobrien op = DW_OP_and; 811390075Sobrien goto do_binop; 811490075Sobrien 811590075Sobrien case TRUTH_XOR_EXPR: 811690075Sobrien case BIT_XOR_EXPR: 811790075Sobrien op = DW_OP_xor; 811890075Sobrien goto do_binop; 811990075Sobrien 812090075Sobrien case TRUTH_OR_EXPR: 812190075Sobrien case TRUTH_ORIF_EXPR: 812290075Sobrien case BIT_IOR_EXPR: 812390075Sobrien op = DW_OP_or; 812490075Sobrien goto do_binop; 812590075Sobrien 812690075Sobrien case TRUNC_DIV_EXPR: 812790075Sobrien op = DW_OP_div; 812890075Sobrien goto do_binop; 812990075Sobrien 813090075Sobrien case MINUS_EXPR: 813190075Sobrien op = DW_OP_minus; 813290075Sobrien goto do_binop; 813390075Sobrien 813490075Sobrien case TRUNC_MOD_EXPR: 813590075Sobrien op = DW_OP_mod; 813690075Sobrien goto do_binop; 813790075Sobrien 813890075Sobrien case MULT_EXPR: 813990075Sobrien op = DW_OP_mul; 814090075Sobrien goto do_binop; 814190075Sobrien 814290075Sobrien case LSHIFT_EXPR: 814390075Sobrien op = DW_OP_shl; 814490075Sobrien goto do_binop; 814590075Sobrien 814690075Sobrien case RSHIFT_EXPR: 814790075Sobrien op = (unsignedp ? DW_OP_shr : DW_OP_shra); 814890075Sobrien goto do_binop; 814990075Sobrien 815090075Sobrien case PLUS_EXPR: 815190075Sobrien if (TREE_CODE (TREE_OPERAND (loc, 1)) == INTEGER_CST 815290075Sobrien && host_integerp (TREE_OPERAND (loc, 1), 0)) 815390075Sobrien { 815490075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 815590075Sobrien if (ret == 0) 815690075Sobrien return 0; 815790075Sobrien 815890075Sobrien add_loc_descr (&ret, 815990075Sobrien new_loc_descr (DW_OP_plus_uconst, 816090075Sobrien tree_low_cst (TREE_OPERAND (loc, 1), 816190075Sobrien 0), 816290075Sobrien 0)); 816390075Sobrien break; 816490075Sobrien } 816590075Sobrien 816690075Sobrien op = DW_OP_plus; 816790075Sobrien goto do_binop; 816890075Sobrien 816990075Sobrien case LE_EXPR: 817090075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 817190075Sobrien return 0; 817290075Sobrien 817390075Sobrien op = DW_OP_le; 817490075Sobrien goto do_binop; 817590075Sobrien 817690075Sobrien case GE_EXPR: 817790075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 817890075Sobrien return 0; 817990075Sobrien 818090075Sobrien op = DW_OP_ge; 818190075Sobrien goto do_binop; 818290075Sobrien 818390075Sobrien case LT_EXPR: 818490075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 818590075Sobrien return 0; 818690075Sobrien 818790075Sobrien op = DW_OP_lt; 818890075Sobrien goto do_binop; 818990075Sobrien 819090075Sobrien case GT_EXPR: 819190075Sobrien if (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (loc, 0)))) 819290075Sobrien return 0; 819390075Sobrien 819490075Sobrien op = DW_OP_gt; 819590075Sobrien goto do_binop; 819690075Sobrien 819790075Sobrien case EQ_EXPR: 819890075Sobrien op = DW_OP_eq; 819990075Sobrien goto do_binop; 820090075Sobrien 820190075Sobrien case NE_EXPR: 820290075Sobrien op = DW_OP_ne; 820390075Sobrien goto do_binop; 820490075Sobrien 820590075Sobrien do_binop: 820690075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 820790075Sobrien ret1 = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 820890075Sobrien if (ret == 0 || ret1 == 0) 820990075Sobrien return 0; 821090075Sobrien 821190075Sobrien add_loc_descr (&ret, ret1); 821290075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 821390075Sobrien break; 821490075Sobrien 821590075Sobrien case TRUTH_NOT_EXPR: 821690075Sobrien case BIT_NOT_EXPR: 821790075Sobrien op = DW_OP_not; 821890075Sobrien goto do_unop; 821990075Sobrien 822090075Sobrien case ABS_EXPR: 822190075Sobrien op = DW_OP_abs; 822290075Sobrien goto do_unop; 822390075Sobrien 822490075Sobrien case NEGATE_EXPR: 822590075Sobrien op = DW_OP_neg; 822690075Sobrien goto do_unop; 822790075Sobrien 822890075Sobrien do_unop: 822990075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 823090075Sobrien if (ret == 0) 823190075Sobrien return 0; 823290075Sobrien 823390075Sobrien add_loc_descr (&ret, new_loc_descr (op, 0, 0)); 823490075Sobrien break; 823590075Sobrien 823690075Sobrien case MAX_EXPR: 823790075Sobrien loc = build (COND_EXPR, TREE_TYPE (loc), 823890075Sobrien build (LT_EXPR, integer_type_node, 823990075Sobrien TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)), 824090075Sobrien TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0)); 824190075Sobrien 824290075Sobrien /* ... fall through ... */ 824390075Sobrien 824490075Sobrien case COND_EXPR: 824590075Sobrien { 824690075Sobrien dw_loc_descr_ref lhs 824790075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0); 824890075Sobrien dw_loc_descr_ref rhs 824990075Sobrien = loc_descriptor_from_tree (TREE_OPERAND (loc, 2), 0); 825090075Sobrien dw_loc_descr_ref bra_node, jump_node, tmp; 825190075Sobrien 825290075Sobrien ret = loc_descriptor_from_tree (TREE_OPERAND (loc, 0), 0); 825390075Sobrien if (ret == 0 || lhs == 0 || rhs == 0) 825490075Sobrien return 0; 825590075Sobrien 825690075Sobrien bra_node = new_loc_descr (DW_OP_bra, 0, 0); 825790075Sobrien add_loc_descr (&ret, bra_node); 825890075Sobrien 825990075Sobrien add_loc_descr (&ret, rhs); 826090075Sobrien jump_node = new_loc_descr (DW_OP_skip, 0, 0); 826190075Sobrien add_loc_descr (&ret, jump_node); 826290075Sobrien 826390075Sobrien add_loc_descr (&ret, lhs); 826490075Sobrien bra_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 826590075Sobrien bra_node->dw_loc_oprnd1.v.val_loc = lhs; 826690075Sobrien 826790075Sobrien /* ??? Need a node to point the skip at. Use a nop. */ 826890075Sobrien tmp = new_loc_descr (DW_OP_nop, 0, 0); 826990075Sobrien add_loc_descr (&ret, tmp); 827090075Sobrien jump_node->dw_loc_oprnd1.val_class = dw_val_class_loc; 827190075Sobrien jump_node->dw_loc_oprnd1.v.val_loc = tmp; 827290075Sobrien } 827390075Sobrien break; 827490075Sobrien 827590075Sobrien default: 827690075Sobrien abort (); 827790075Sobrien } 827890075Sobrien 827990075Sobrien /* Show if we can't fill the request for an address. */ 828090075Sobrien if (addressp && indirect_p == 0) 828190075Sobrien return 0; 828290075Sobrien 828390075Sobrien /* If we've got an address and don't want one, dereference. */ 828490075Sobrien if (!addressp && indirect_p > 0) 828590075Sobrien { 828690075Sobrien HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (loc)); 828790075Sobrien 828890075Sobrien if (size > DWARF2_ADDR_SIZE || size == -1) 828990075Sobrien return 0; 829090075Sobrien else if (size == DWARF2_ADDR_SIZE) 829190075Sobrien op = DW_OP_deref; 829290075Sobrien else 829390075Sobrien op = DW_OP_deref_size; 829490075Sobrien 829590075Sobrien add_loc_descr (&ret, new_loc_descr (op, size, 0)); 829690075Sobrien } 829790075Sobrien 829890075Sobrien return ret; 829990075Sobrien} 830090075Sobrien 830190075Sobrien/* Given a value, round it up to the lowest multiple of `boundary' 830250397Sobrien which is not less than the value itself. */ 830350397Sobrien 830490075Sobrienstatic inline HOST_WIDE_INT 830550397Sobrienceiling (value, boundary) 830690075Sobrien HOST_WIDE_INT value; 830790075Sobrien unsigned int boundary; 830850397Sobrien{ 830950397Sobrien return (((value + boundary - 1) / boundary) * boundary); 831050397Sobrien} 831150397Sobrien 831250397Sobrien/* Given a pointer to what is assumed to be a FIELD_DECL node, return a 831350397Sobrien pointer to the declared type for the relevant field variable, or return 831450397Sobrien `integer_type_node' if the given node turns out to be an 831550397Sobrien ERROR_MARK node. */ 831650397Sobrien 831750397Sobrienstatic inline tree 831850397Sobrienfield_type (decl) 831990075Sobrien tree decl; 832050397Sobrien{ 832190075Sobrien tree type; 832250397Sobrien 832350397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 832450397Sobrien return integer_type_node; 832550397Sobrien 832650397Sobrien type = DECL_BIT_FIELD_TYPE (decl); 832750397Sobrien if (type == NULL_TREE) 832850397Sobrien type = TREE_TYPE (decl); 832950397Sobrien 833050397Sobrien return type; 833150397Sobrien} 833250397Sobrien 833390075Sobrien/* Given a pointer to a tree node, return the alignment in bits for 833490075Sobrien it, or else return BITS_PER_WORD if the node actually turns out to 833590075Sobrien be an ERROR_MARK node. */ 833650397Sobrien 833750397Sobrienstatic inline unsigned 833850397Sobriensimple_type_align_in_bits (type) 833990075Sobrien tree type; 834050397Sobrien{ 834150397Sobrien return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; 834250397Sobrien} 834350397Sobrien 834490075Sobrienstatic inline unsigned 834590075Sobriensimple_decl_align_in_bits (decl) 834690075Sobrien tree decl; 834790075Sobrien{ 834890075Sobrien return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD; 834990075Sobrien} 835090075Sobrien 835150397Sobrien/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE 835250397Sobrien node, return the size in bits for the type if it is a constant, or else 835350397Sobrien return the alignment for the type if the type's size is not constant, or 835450397Sobrien else return BITS_PER_WORD if the type actually turns out to be an 835550397Sobrien ERROR_MARK node. */ 835650397Sobrien 835790075Sobrienstatic inline unsigned HOST_WIDE_INT 835850397Sobriensimple_type_size_in_bits (type) 835990075Sobrien tree type; 836050397Sobrien{ 836190075Sobrien 836250397Sobrien if (TREE_CODE (type) == ERROR_MARK) 836350397Sobrien return BITS_PER_WORD; 836490075Sobrien else if (TYPE_SIZE (type) == NULL_TREE) 836590075Sobrien return 0; 836690075Sobrien else if (host_integerp (TYPE_SIZE (type), 1)) 836790075Sobrien return tree_low_cst (TYPE_SIZE (type), 1); 836850397Sobrien else 836990075Sobrien return TYPE_ALIGN (type); 837050397Sobrien} 837150397Sobrien 837290075Sobrien/* Given a pointer to a FIELD_DECL, compute and return the byte offset of the 837390075Sobrien lowest addressed byte of the "containing object" for the given FIELD_DECL, 837490075Sobrien or return 0 if we are unable to determine what that offset is, either 837590075Sobrien because the argument turns out to be a pointer to an ERROR_MARK node, or 837690075Sobrien because the offset is actually variable. (We can't handle the latter case 837790075Sobrien just yet). */ 837850397Sobrien 837990075Sobrienstatic HOST_WIDE_INT 838050397Sobrienfield_byte_offset (decl) 838190075Sobrien tree decl; 838250397Sobrien{ 838390075Sobrien unsigned int type_align_in_bits; 838490075Sobrien unsigned int decl_align_in_bits; 838590075Sobrien unsigned HOST_WIDE_INT type_size_in_bits; 838690075Sobrien HOST_WIDE_INT object_offset_in_bits; 838790075Sobrien tree type; 838890075Sobrien tree field_size_tree; 838990075Sobrien HOST_WIDE_INT bitpos_int; 839090075Sobrien HOST_WIDE_INT deepest_bitpos; 839190075Sobrien unsigned HOST_WIDE_INT field_size_in_bits; 839250397Sobrien 839350397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 839450397Sobrien return 0; 839590075Sobrien else if (TREE_CODE (decl) != FIELD_DECL) 839650397Sobrien abort (); 839750397Sobrien 839850397Sobrien type = field_type (decl); 839950397Sobrien field_size_tree = DECL_SIZE (decl); 840050397Sobrien 840190075Sobrien /* The size could be unspecified if there was an error, or for 840290075Sobrien a flexible array member. */ 840390075Sobrien if (! field_size_tree) 840490075Sobrien field_size_tree = bitsize_zero_node; 840590075Sobrien 840690075Sobrien /* We cannot yet cope with fields whose positions are variable, so 840750397Sobrien for now, when we see such things, we simply return 0. Someday, we may 840850397Sobrien be able to handle such cases, but it will be damn difficult. */ 840990075Sobrien if (! host_integerp (bit_position (decl), 0)) 841050397Sobrien return 0; 841150397Sobrien 841290075Sobrien bitpos_int = int_bit_position (decl); 841350397Sobrien 841490075Sobrien /* If we don't know the size of the field, pretend it's a full word. */ 841590075Sobrien if (host_integerp (field_size_tree, 1)) 841690075Sobrien field_size_in_bits = tree_low_cst (field_size_tree, 1); 841790075Sobrien else 841890075Sobrien field_size_in_bits = BITS_PER_WORD; 841990075Sobrien 842050397Sobrien type_size_in_bits = simple_type_size_in_bits (type); 842150397Sobrien type_align_in_bits = simple_type_align_in_bits (type); 842290075Sobrien decl_align_in_bits = simple_decl_align_in_bits (decl); 842350397Sobrien 842490075Sobrien /* The GCC front-end doesn't make any attempt to keep track of the starting 842590075Sobrien bit offset (relative to the start of the containing structure type) of the 842690075Sobrien hypothetical "containing object" for a bit-field. Thus, when computing 842790075Sobrien the byte offset value for the start of the "containing object" of a 842890075Sobrien bit-field, we must deduce this information on our own. This can be rather 842990075Sobrien tricky to do in some cases. For example, handling the following structure 843090075Sobrien type definition when compiling for an i386/i486 target (which only aligns 843190075Sobrien long long's to 32-bit boundaries) can be very tricky: 843250397Sobrien 843350397Sobrien struct S { int field1; long long field2:31; }; 843450397Sobrien 843590075Sobrien Fortunately, there is a simple rule-of-thumb which can be used in such 843690075Sobrien cases. When compiling for an i386/i486, GCC will allocate 8 bytes for the 843790075Sobrien structure shown above. It decides to do this based upon one simple rule 843890075Sobrien for bit-field allocation. GCC allocates each "containing object" for each 843990075Sobrien bit-field at the first (i.e. lowest addressed) legitimate alignment 844090075Sobrien boundary (based upon the required minimum alignment for the declared type 844190075Sobrien of the field) which it can possibly use, subject to the condition that 844290075Sobrien there is still enough available space remaining in the containing object 844390075Sobrien (when allocated at the selected point) to fully accommodate all of the 844490075Sobrien bits of the bit-field itself. 844550397Sobrien 844690075Sobrien This simple rule makes it obvious why GCC allocates 8 bytes for each 844790075Sobrien object of the structure type shown above. When looking for a place to 844890075Sobrien allocate the "containing object" for `field2', the compiler simply tries 844990075Sobrien to allocate a 64-bit "containing object" at each successive 32-bit 845090075Sobrien boundary (starting at zero) until it finds a place to allocate that 64- 845190075Sobrien bit field such that at least 31 contiguous (and previously unallocated) 845290075Sobrien bits remain within that selected 64 bit field. (As it turns out, for the 845390075Sobrien example above, the compiler finds it is OK to allocate the "containing 845490075Sobrien object" 64-bit field at bit-offset zero within the structure type.) 845590075Sobrien 845690075Sobrien Here we attempt to work backwards from the limited set of facts we're 845790075Sobrien given, and we try to deduce from those facts, where GCC must have believed 845890075Sobrien that the containing object started (within the structure type). The value 845990075Sobrien we deduce is then used (by the callers of this routine) to generate 846090075Sobrien DW_AT_location and DW_AT_bit_offset attributes for fields (both bit-fields 846190075Sobrien and, in the case of DW_AT_location, regular fields as well). */ 846290075Sobrien 846350397Sobrien /* Figure out the bit-distance from the start of the structure to the 846450397Sobrien "deepest" bit of the bit-field. */ 846550397Sobrien deepest_bitpos = bitpos_int + field_size_in_bits; 846650397Sobrien 846750397Sobrien /* This is the tricky part. Use some fancy footwork to deduce where the 846850397Sobrien lowest addressed bit of the containing object must be. */ 846990075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 847050397Sobrien 847190075Sobrien /* Round up to type_align by default. This works best for bitfields. */ 847290075Sobrien object_offset_in_bits += type_align_in_bits - 1; 847390075Sobrien object_offset_in_bits /= type_align_in_bits; 847490075Sobrien object_offset_in_bits *= type_align_in_bits; 847550397Sobrien 847690075Sobrien if (object_offset_in_bits > bitpos_int) 847790075Sobrien { 847890075Sobrien /* Sigh, the decl must be packed. */ 847990075Sobrien object_offset_in_bits = deepest_bitpos - type_size_in_bits; 848050397Sobrien 848190075Sobrien /* Round up to decl_align instead. */ 848290075Sobrien object_offset_in_bits += decl_align_in_bits - 1; 848390075Sobrien object_offset_in_bits /= decl_align_in_bits; 848490075Sobrien object_offset_in_bits *= decl_align_in_bits; 848590075Sobrien } 848690075Sobrien 848790075Sobrien return object_offset_in_bits / BITS_PER_UNIT; 848850397Sobrien} 848950397Sobrien 849050397Sobrien/* The following routines define various Dwarf attributes and any data 849150397Sobrien associated with them. */ 849250397Sobrien 849350397Sobrien/* Add a location description attribute value to a DIE. 849450397Sobrien 849550397Sobrien This emits location attributes suitable for whole variables and 849650397Sobrien whole parameters. Note that the location attributes for struct fields are 849750397Sobrien generated by the routine `data_member_location_attribute' below. */ 849850397Sobrien 849950397Sobrienstatic void 850050397Sobrienadd_AT_location_description (die, attr_kind, rtl) 850150397Sobrien dw_die_ref die; 850250397Sobrien enum dwarf_attribute attr_kind; 850390075Sobrien rtx rtl; 850450397Sobrien{ 850590075Sobrien dw_loc_descr_ref descr = loc_descriptor (rtl); 850650397Sobrien 850790075Sobrien if (descr != 0) 850890075Sobrien add_AT_loc (die, attr_kind, descr); 850950397Sobrien} 851050397Sobrien 851190075Sobrien/* Attach the specialized form of location attribute used for data members of 851290075Sobrien struct and union types. In the special case of a FIELD_DECL node which 851390075Sobrien represents a bit-field, the "offset" part of this special location 851490075Sobrien descriptor must indicate the distance in bytes from the lowest-addressed 851590075Sobrien byte of the containing struct or union type to the lowest-addressed byte of 851690075Sobrien the "containing object" for the bit-field. (See the `field_byte_offset' 851790075Sobrien function above). 851850397Sobrien 851990075Sobrien For any given bit-field, the "containing object" is a hypothetical object 852090075Sobrien (of some integral or enum type) within which the given bit-field lives. The 852190075Sobrien type of this hypothetical "containing object" is always the same as the 852290075Sobrien declared type of the individual bit-field itself (for GCC anyway... the 852390075Sobrien DWARF spec doesn't actually mandate this). Note that it is the size (in 852490075Sobrien bytes) of the hypothetical "containing object" which will be given in the 852590075Sobrien DW_AT_byte_size attribute for this bit-field. (See the 852690075Sobrien `byte_size_attribute' function below.) It is also used when calculating the 852790075Sobrien value of the DW_AT_bit_offset attribute. (See the `bit_offset_attribute' 852890075Sobrien function below.) */ 852990075Sobrien 853050397Sobrienstatic void 853150397Sobrienadd_data_member_location_attribute (die, decl) 853290075Sobrien dw_die_ref die; 853390075Sobrien tree decl; 853450397Sobrien{ 853590075Sobrien long offset; 853690075Sobrien dw_loc_descr_ref loc_descr = 0; 853750397Sobrien 853850397Sobrien if (TREE_CODE (decl) == TREE_VEC) 853990075Sobrien { 854090075Sobrien /* We're working on the TAG_inheritance for a base class. */ 854190075Sobrien if (TREE_VIA_VIRTUAL (decl) && is_cxx ()) 854290075Sobrien { 854390075Sobrien /* For C++ virtual bases we can't just use BINFO_OFFSET, as they 854490075Sobrien aren't at a fixed offset from all (sub)objects of the same 854590075Sobrien type. We need to extract the appropriate offset from our 854690075Sobrien vtable. The following dwarf expression means 854790075Sobrien 854890075Sobrien BaseAddr = ObAddr + *((*ObAddr) - Offset) 854990075Sobrien 855090075Sobrien This is specific to the V3 ABI, of course. */ 855190075Sobrien 855290075Sobrien dw_loc_descr_ref tmp; 855390075Sobrien 855490075Sobrien /* Make a copy of the object address. */ 855590075Sobrien tmp = new_loc_descr (DW_OP_dup, 0, 0); 855690075Sobrien add_loc_descr (&loc_descr, tmp); 855790075Sobrien 855890075Sobrien /* Extract the vtable address. */ 855990075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 856090075Sobrien add_loc_descr (&loc_descr, tmp); 856190075Sobrien 856290075Sobrien /* Calculate the address of the offset. */ 856390075Sobrien offset = tree_low_cst (BINFO_VPTR_FIELD (decl), 0); 856490075Sobrien if (offset >= 0) 856590075Sobrien abort (); 856690075Sobrien 856790075Sobrien tmp = int_loc_descriptor (-offset); 856890075Sobrien add_loc_descr (&loc_descr, tmp); 856990075Sobrien tmp = new_loc_descr (DW_OP_minus, 0, 0); 857090075Sobrien add_loc_descr (&loc_descr, tmp); 857190075Sobrien 857290075Sobrien /* Extract the offset. */ 857390075Sobrien tmp = new_loc_descr (DW_OP_deref, 0, 0); 857490075Sobrien add_loc_descr (&loc_descr, tmp); 857590075Sobrien 857690075Sobrien /* Add it to the object address. */ 857790075Sobrien tmp = new_loc_descr (DW_OP_plus, 0, 0); 857890075Sobrien add_loc_descr (&loc_descr, tmp); 857990075Sobrien } 858090075Sobrien else 858190075Sobrien offset = tree_low_cst (BINFO_OFFSET (decl), 0); 858290075Sobrien } 858350397Sobrien else 858450397Sobrien offset = field_byte_offset (decl); 858550397Sobrien 858690075Sobrien if (! loc_descr) 858790075Sobrien { 858890075Sobrien enum dwarf_location_atom op; 858950397Sobrien 859090075Sobrien /* The DWARF2 standard says that we should assume that the structure 859190075Sobrien address is already on the stack, so we can specify a structure field 859290075Sobrien address by using DW_OP_plus_uconst. */ 859390075Sobrien 859450397Sobrien#ifdef MIPS_DEBUGGING_INFO 859590075Sobrien /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst 859690075Sobrien operator correctly. It works only if we leave the offset on the 859790075Sobrien stack. */ 859890075Sobrien op = DW_OP_constu; 859950397Sobrien#else 860090075Sobrien op = DW_OP_plus_uconst; 860150397Sobrien#endif 860250397Sobrien 860390075Sobrien loc_descr = new_loc_descr (op, offset, 0); 860490075Sobrien } 860590075Sobrien 860650397Sobrien add_AT_loc (die, DW_AT_data_member_location, loc_descr); 860750397Sobrien} 860850397Sobrien 860950397Sobrien/* Attach an DW_AT_const_value attribute for a variable or a parameter which 861050397Sobrien does not have a "location" either in memory or in a register. These 861150397Sobrien things can arise in GNU C when a constant is passed as an actual parameter 861250397Sobrien to an inlined function. They can also arise in C++ where declared 861350397Sobrien constants do not necessarily get memory "homes". */ 861450397Sobrien 861550397Sobrienstatic void 861650397Sobrienadd_const_value_attribute (die, rtl) 861790075Sobrien dw_die_ref die; 861890075Sobrien rtx rtl; 861950397Sobrien{ 862050397Sobrien switch (GET_CODE (rtl)) 862150397Sobrien { 862250397Sobrien case CONST_INT: 862390075Sobrien /* Note that a CONST_INT rtx could represent either an integer 862490075Sobrien or a floating-point constant. A CONST_INT is used whenever 862590075Sobrien the constant will fit into a single word. In all such 862690075Sobrien cases, the original mode of the constant value is wiped 862790075Sobrien out, and the CONST_INT rtx is assigned VOIDmode. */ 862890075Sobrien { 862990075Sobrien HOST_WIDE_INT val = INTVAL (rtl); 863090075Sobrien 863190075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 863290075Sobrien if (val < 0 && (long) val == val) 863390075Sobrien add_AT_int (die, DW_AT_const_value, (long) val); 863490075Sobrien else if ((unsigned long) val == (unsigned HOST_WIDE_INT) val) 863590075Sobrien add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val); 863690075Sobrien else 863790075Sobrien { 863890075Sobrien#if HOST_BITS_PER_LONG * 2 == HOST_BITS_PER_WIDE_INT 863990075Sobrien add_AT_long_long (die, DW_AT_const_value, 864090075Sobrien val >> HOST_BITS_PER_LONG, val); 864190075Sobrien#else 864290075Sobrien abort (); 864390075Sobrien#endif 864490075Sobrien } 864590075Sobrien } 864650397Sobrien break; 864750397Sobrien 864850397Sobrien case CONST_DOUBLE: 864950397Sobrien /* Note that a CONST_DOUBLE rtx could represent either an integer or a 865050397Sobrien floating-point constant. A CONST_DOUBLE is used whenever the 865150397Sobrien constant requires more than one word in order to be adequately 865250397Sobrien represented. We output CONST_DOUBLEs as blocks. */ 865350397Sobrien { 865490075Sobrien enum machine_mode mode = GET_MODE (rtl); 865550397Sobrien 865650397Sobrien if (GET_MODE_CLASS (mode) == MODE_FLOAT) 865750397Sobrien { 865890075Sobrien unsigned length = GET_MODE_SIZE (mode) / 4; 865990075Sobrien long *array = (long *) xmalloc (sizeof (long) * length); 866050397Sobrien REAL_VALUE_TYPE rv; 866150397Sobrien 866250397Sobrien REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); 866350397Sobrien switch (mode) 866450397Sobrien { 866550397Sobrien case SFmode: 866650397Sobrien REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); 866750397Sobrien break; 866850397Sobrien 866950397Sobrien case DFmode: 867050397Sobrien REAL_VALUE_TO_TARGET_DOUBLE (rv, array); 867150397Sobrien break; 867250397Sobrien 867350397Sobrien case XFmode: 867450397Sobrien case TFmode: 867550397Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); 867650397Sobrien break; 867750397Sobrien 867850397Sobrien default: 867950397Sobrien abort (); 868050397Sobrien } 868150397Sobrien 868250397Sobrien add_AT_float (die, DW_AT_const_value, length, array); 868350397Sobrien } 868450397Sobrien else 868590075Sobrien { 868690075Sobrien /* ??? We really should be using HOST_WIDE_INT throughout. */ 868790075Sobrien if (HOST_BITS_PER_LONG != HOST_BITS_PER_WIDE_INT) 868890075Sobrien abort (); 868990075Sobrien 869090075Sobrien add_AT_long_long (die, DW_AT_const_value, 869190075Sobrien CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl)); 869290075Sobrien } 869350397Sobrien } 869450397Sobrien break; 869550397Sobrien 869650397Sobrien case CONST_STRING: 869750397Sobrien add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); 869850397Sobrien break; 869950397Sobrien 870050397Sobrien case SYMBOL_REF: 870150397Sobrien case LABEL_REF: 870250397Sobrien case CONST: 870390075Sobrien add_AT_addr (die, DW_AT_const_value, rtl); 870490075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, rtl); 870550397Sobrien break; 870650397Sobrien 870750397Sobrien case PLUS: 870850397Sobrien /* In cases where an inlined instance of an inline function is passed 870950397Sobrien the address of an `auto' variable (which is local to the caller) we 871050397Sobrien can get a situation where the DECL_RTL of the artificial local 871150397Sobrien variable (for the inlining) which acts as a stand-in for the 871250397Sobrien corresponding formal parameter (of the inline function) will look 871350397Sobrien like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not 871490075Sobrien exactly a compile-time constant expression, but it isn't the address 871590075Sobrien of the (artificial) local variable either. Rather, it represents the 871650397Sobrien *value* which the artificial local variable always has during its 871790075Sobrien lifetime. We currently have no way to represent such quasi-constant 871850397Sobrien values in Dwarf, so for now we just punt and generate nothing. */ 871950397Sobrien break; 872050397Sobrien 872150397Sobrien default: 872250397Sobrien /* No other kinds of rtx should be possible here. */ 872350397Sobrien abort (); 872450397Sobrien } 872550397Sobrien 872650397Sobrien} 872750397Sobrien 872890075Sobrienstatic rtx 872990075Sobrienrtl_for_decl_location (decl) 873090075Sobrien tree decl; 873150397Sobrien{ 873290075Sobrien rtx rtl; 873350397Sobrien 873450397Sobrien /* Here we have to decide where we are going to say the parameter "lives" 873550397Sobrien (as far as the debugger is concerned). We only have a couple of 873650397Sobrien choices. GCC provides us with DECL_RTL and with DECL_INCOMING_RTL. 873750397Sobrien 873890075Sobrien DECL_RTL normally indicates where the parameter lives during most of the 873950397Sobrien activation of the function. If optimization is enabled however, this 874090075Sobrien could be either NULL or else a pseudo-reg. Both of those cases indicate 874150397Sobrien that the parameter doesn't really live anywhere (as far as the code 874250397Sobrien generation parts of GCC are concerned) during most of the function's 874350397Sobrien activation. That will happen (for example) if the parameter is never 874450397Sobrien referenced within the function. 874550397Sobrien 874650397Sobrien We could just generate a location descriptor here for all non-NULL 874750397Sobrien non-pseudo values of DECL_RTL and ignore all of the rest, but we can be 874850397Sobrien a little nicer than that if we also consider DECL_INCOMING_RTL in cases 874950397Sobrien where DECL_RTL is NULL or is a pseudo-reg. 875050397Sobrien 875150397Sobrien Note however that we can only get away with using DECL_INCOMING_RTL as 875250397Sobrien a backup substitute for DECL_RTL in certain limited cases. In cases 875350397Sobrien where DECL_ARG_TYPE (decl) indicates the same type as TREE_TYPE (decl), 875450397Sobrien we can be sure that the parameter was passed using the same type as it is 875550397Sobrien declared to have within the function, and that its DECL_INCOMING_RTL 875650397Sobrien points us to a place where a value of that type is passed. 875750397Sobrien 875850397Sobrien In cases where DECL_ARG_TYPE (decl) and TREE_TYPE (decl) are different, 875950397Sobrien we cannot (in general) use DECL_INCOMING_RTL as a substitute for DECL_RTL 876050397Sobrien because in these cases DECL_INCOMING_RTL points us to a value of some 876150397Sobrien type which is *different* from the type of the parameter itself. Thus, 876250397Sobrien if we tried to use DECL_INCOMING_RTL to generate a location attribute in 876350397Sobrien such cases, the debugger would end up (for example) trying to fetch a 876450397Sobrien `float' from a place which actually contains the first part of a 876550397Sobrien `double'. That would lead to really incorrect and confusing 876650397Sobrien output at debug-time. 876750397Sobrien 876850397Sobrien So, in general, we *do not* use DECL_INCOMING_RTL as a backup for DECL_RTL 876950397Sobrien in cases where DECL_ARG_TYPE (decl) != TREE_TYPE (decl). There 877050397Sobrien are a couple of exceptions however. On little-endian machines we can 877150397Sobrien get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE (decl) is 877250397Sobrien not the same as TREE_TYPE (decl), but only when DECL_ARG_TYPE (decl) is 877350397Sobrien an integral type that is smaller than TREE_TYPE (decl). These cases arise 877450397Sobrien when (on a little-endian machine) a non-prototyped function has a 877550397Sobrien parameter declared to be of type `short' or `char'. In such cases, 877650397Sobrien TREE_TYPE (decl) will be `short' or `char', DECL_ARG_TYPE (decl) will 877750397Sobrien be `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the 877850397Sobrien passed `int' value. If the debugger then uses that address to fetch 877950397Sobrien a `short' or a `char' (on a little-endian machine) the result will be 878050397Sobrien the correct data, so we allow for such exceptional cases below. 878150397Sobrien 878250397Sobrien Note that our goal here is to describe the place where the given formal 878390075Sobrien parameter lives during most of the function's activation (i.e. between the 878490075Sobrien end of the prologue and the start of the epilogue). We'll do that as best 878590075Sobrien as we can. Note however that if the given formal parameter is modified 878690075Sobrien sometime during the execution of the function, then a stack backtrace (at 878790075Sobrien debug-time) will show the function as having been called with the *new* 878890075Sobrien value rather than the value which was originally passed in. This happens 878990075Sobrien rarely enough that it is not a major problem, but it *is* a problem, and 879090075Sobrien I'd like to fix it. 879150397Sobrien 879290075Sobrien A future version of dwarf2out.c may generate two additional attributes for 879390075Sobrien any given DW_TAG_formal_parameter DIE which will describe the "passed 879490075Sobrien type" and the "passed location" for the given formal parameter in addition 879590075Sobrien to the attributes we now generate to indicate the "declared type" and the 879690075Sobrien "active location" for each parameter. This additional set of attributes 879790075Sobrien could be used by debuggers for stack backtraces. Separately, note that 879890075Sobrien sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL can be NULL also. 879990075Sobrien This happens (for example) for inlined-instances of inline function formal 880090075Sobrien parameters which are never referenced. This really shouldn't be 880190075Sobrien happening. All PARM_DECL nodes should get valid non-NULL 880290075Sobrien DECL_INCOMING_RTL values, but integrate.c doesn't currently generate these 880390075Sobrien values for inlined instances of inline function parameters, so when we see 880490075Sobrien such cases, we are just out-of-luck for the time being (until integrate.c 880550397Sobrien gets fixed). */ 880650397Sobrien 880750397Sobrien /* Use DECL_RTL as the "location" unless we find something better. */ 880890075Sobrien rtl = DECL_RTL_IF_SET (decl); 880950397Sobrien 881090075Sobrien /* When generating abstract instances, ignore everything except 881190075Sobrien constants and symbols living in memory. */ 881290075Sobrien if (! reload_completed) 881350397Sobrien { 881490075Sobrien if (rtl 881590075Sobrien && (CONSTANT_P (rtl) 881690075Sobrien || (GET_CODE (rtl) == MEM 881790075Sobrien && CONSTANT_P (XEXP (rtl, 0))))) 881890075Sobrien return rtl; 881990075Sobrien rtl = NULL_RTX; 882090075Sobrien } 882190075Sobrien else if (TREE_CODE (decl) == PARM_DECL) 882290075Sobrien { 882350397Sobrien if (rtl == NULL_RTX || is_pseudo_reg (rtl)) 882450397Sobrien { 882590075Sobrien tree declared_type = type_main_variant (TREE_TYPE (decl)); 882690075Sobrien tree passed_type = type_main_variant (DECL_ARG_TYPE (decl)); 882750397Sobrien 882850397Sobrien /* This decl represents a formal parameter which was optimized out. 882950397Sobrien Note that DECL_INCOMING_RTL may be NULL in here, but we handle 883090075Sobrien all cases where (rtl == NULL_RTX) just below. */ 883150397Sobrien if (declared_type == passed_type) 883250397Sobrien rtl = DECL_INCOMING_RTL (decl); 883350397Sobrien else if (! BYTES_BIG_ENDIAN 883450397Sobrien && TREE_CODE (declared_type) == INTEGER_TYPE 883552284Sobrien && (GET_MODE_SIZE (TYPE_MODE (declared_type)) 883652284Sobrien <= GET_MODE_SIZE (TYPE_MODE (passed_type)))) 883790075Sobrien rtl = DECL_INCOMING_RTL (decl); 883850397Sobrien } 883952284Sobrien 884052284Sobrien /* If the parm was passed in registers, but lives on the stack, then 884152284Sobrien make a big endian correction if the mode of the type of the 884252284Sobrien parameter is not the same as the mode of the rtl. */ 884352284Sobrien /* ??? This is the same series of checks that are made in dbxout.c before 884452284Sobrien we reach the big endian correction code there. It isn't clear if all 884552284Sobrien of these checks are necessary here, but keeping them all is the safe 884652284Sobrien thing to do. */ 884752284Sobrien else if (GET_CODE (rtl) == MEM 884852284Sobrien && XEXP (rtl, 0) != const0_rtx 884952284Sobrien && ! CONSTANT_P (XEXP (rtl, 0)) 885052284Sobrien /* Not passed in memory. */ 885152284Sobrien && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM 885252284Sobrien /* Not passed by invisible reference. */ 885352284Sobrien && (GET_CODE (XEXP (rtl, 0)) != REG 885452284Sobrien || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM 885552284Sobrien || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM 885652284Sobrien#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 885752284Sobrien || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM 885852284Sobrien#endif 885952284Sobrien ) 886052284Sobrien /* Big endian correction check. */ 886152284Sobrien && BYTES_BIG_ENDIAN 886252284Sobrien && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl) 886352284Sobrien && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))) 886452284Sobrien < UNITS_PER_WORD)) 886552284Sobrien { 886652284Sobrien int offset = (UNITS_PER_WORD 886752284Sobrien - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))); 886890075Sobrien 886952284Sobrien rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)), 887052284Sobrien plus_constant (XEXP (rtl, 0), offset)); 887152284Sobrien } 887250397Sobrien } 887350397Sobrien 887490075Sobrien if (rtl != NULL_RTX) 887590075Sobrien { 887690075Sobrien rtl = eliminate_regs (rtl, 0, NULL_RTX); 887790075Sobrien#ifdef LEAF_REG_REMAP 887890075Sobrien if (current_function_uses_only_leaf_regs) 887990075Sobrien leaf_renumber_regs_insn (rtl); 888090075Sobrien#endif 888190075Sobrien } 888290075Sobrien 888390075Sobrien /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant, 888490075Sobrien and will have been substituted directly into all expressions that use it. 888590075Sobrien C does not have such a concept, but C++ and other languages do. */ 888690075Sobrien else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) 888790075Sobrien rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode, 888890075Sobrien EXPAND_INITIALIZER); 888990075Sobrien 889090075Sobrien return rtl; 889190075Sobrien} 889290075Sobrien 889390075Sobrien/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value 889490075Sobrien data attribute for a variable or a parameter. We generate the 889590075Sobrien DW_AT_const_value attribute only in those cases where the given variable 889690075Sobrien or parameter does not have a true "location" either in memory or in a 889790075Sobrien register. This can happen (for example) when a constant is passed as an 889890075Sobrien actual argument in a call to an inline function. (It's possible that 889990075Sobrien these things can crop up in other ways also.) Note that one type of 890090075Sobrien constant value which can be passed into an inlined function is a constant 890190075Sobrien pointer. This can happen for example if an actual argument in an inlined 890290075Sobrien function call evaluates to a compile-time constant address. */ 890390075Sobrien 890490075Sobrienstatic void 890590075Sobrienadd_location_or_const_value_attribute (die, decl) 890690075Sobrien dw_die_ref die; 890790075Sobrien tree decl; 890890075Sobrien{ 890990075Sobrien rtx rtl; 891090075Sobrien 891190075Sobrien if (TREE_CODE (decl) == ERROR_MARK) 891290075Sobrien return; 891390075Sobrien else if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 891490075Sobrien abort (); 891590075Sobrien 891690075Sobrien rtl = rtl_for_decl_location (decl); 891750397Sobrien if (rtl == NULL_RTX) 891850397Sobrien return; 891950397Sobrien 892090075Sobrien /* If we don't look past the constant pool, we risk emitting a 892190075Sobrien reference to a constant pool entry that isn't referenced from 892290075Sobrien code, and thus is not emitted. */ 892390075Sobrien rtl = avoid_constant_pool_reference (rtl); 892450397Sobrien 892550397Sobrien switch (GET_CODE (rtl)) 892650397Sobrien { 892750397Sobrien case ADDRESSOF: 892850397Sobrien /* The address of a variable that was optimized away; don't emit 892950397Sobrien anything. */ 893050397Sobrien break; 893150397Sobrien 893250397Sobrien case CONST_INT: 893350397Sobrien case CONST_DOUBLE: 893450397Sobrien case CONST_STRING: 893550397Sobrien case SYMBOL_REF: 893650397Sobrien case LABEL_REF: 893750397Sobrien case CONST: 893850397Sobrien case PLUS: 893950397Sobrien /* DECL_RTL could be (plus (reg ...) (const_int ...)) */ 894050397Sobrien add_const_value_attribute (die, rtl); 894150397Sobrien break; 894250397Sobrien 894350397Sobrien case MEM: 894450397Sobrien case REG: 894550397Sobrien case SUBREG: 894650397Sobrien case CONCAT: 894750397Sobrien add_AT_location_description (die, DW_AT_location, rtl); 894850397Sobrien break; 894950397Sobrien 895050397Sobrien default: 895150397Sobrien abort (); 895250397Sobrien } 895350397Sobrien} 895450397Sobrien 895590075Sobrien/* If we don't have a copy of this variable in memory for some reason (such 895690075Sobrien as a C++ member constant that doesn't have an out-of-line definition), 895790075Sobrien we should tell the debugger about the constant value. */ 895890075Sobrien 895990075Sobrienstatic void 896090075Sobrientree_add_const_value_attribute (var_die, decl) 896190075Sobrien dw_die_ref var_die; 896290075Sobrien tree decl; 896390075Sobrien{ 896490075Sobrien tree init = DECL_INITIAL (decl); 896590075Sobrien tree type = TREE_TYPE (decl); 896690075Sobrien 896790075Sobrien if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && init 896890075Sobrien && initializer_constant_valid_p (init, type) == null_pointer_node) 896990075Sobrien /* OK */; 897090075Sobrien else 897190075Sobrien return; 897290075Sobrien 897390075Sobrien switch (TREE_CODE (type)) 897490075Sobrien { 897590075Sobrien case INTEGER_TYPE: 897690075Sobrien if (host_integerp (init, 0)) 897790075Sobrien add_AT_unsigned (var_die, DW_AT_const_value, 897890075Sobrien tree_low_cst (init, 0)); 897990075Sobrien else 898090075Sobrien add_AT_long_long (var_die, DW_AT_const_value, 898190075Sobrien TREE_INT_CST_HIGH (init), 898290075Sobrien TREE_INT_CST_LOW (init)); 898390075Sobrien break; 898490075Sobrien 898590075Sobrien default:; 898690075Sobrien } 898790075Sobrien} 898890075Sobrien 898950397Sobrien/* Generate an DW_AT_name attribute given some string value to be included as 899050397Sobrien the value of the attribute. */ 899150397Sobrien 899250397Sobrienstatic inline void 899350397Sobrienadd_name_attribute (die, name_string) 899490075Sobrien dw_die_ref die; 899590075Sobrien const char *name_string; 899650397Sobrien{ 899750397Sobrien if (name_string != NULL && *name_string != 0) 899890075Sobrien { 899990075Sobrien if (demangle_name_func) 900090075Sobrien name_string = (*demangle_name_func) (name_string); 900190075Sobrien 900290075Sobrien add_AT_string (die, DW_AT_name, name_string); 900390075Sobrien } 900450397Sobrien} 900550397Sobrien 900650397Sobrien/* Given a tree node describing an array bound (either lower or upper) output 900750397Sobrien a representation for that bound. */ 900850397Sobrien 900950397Sobrienstatic void 901050397Sobrienadd_bound_info (subrange_die, bound_attr, bound) 901190075Sobrien dw_die_ref subrange_die; 901290075Sobrien enum dwarf_attribute bound_attr; 901390075Sobrien tree bound; 901450397Sobrien{ 901550397Sobrien switch (TREE_CODE (bound)) 901650397Sobrien { 901750397Sobrien case ERROR_MARK: 901850397Sobrien return; 901950397Sobrien 902090075Sobrien /* All fixed-bounds are represented by INTEGER_CST nodes. */ 902150397Sobrien case INTEGER_CST: 902290075Sobrien if (! host_integerp (bound, 0) 902390075Sobrien || (bound_attr == DW_AT_lower_bound 902490075Sobrien && (((is_c_family () || is_java ()) && integer_zerop (bound)) 902590075Sobrien || (is_fortran () && integer_onep (bound))))) 902690075Sobrien /* use the default */ 902790075Sobrien ; 902850397Sobrien else 902990075Sobrien add_AT_unsigned (subrange_die, bound_attr, tree_low_cst (bound, 0)); 903050397Sobrien break; 903150397Sobrien 903250397Sobrien case CONVERT_EXPR: 903350397Sobrien case NOP_EXPR: 903450397Sobrien case NON_LVALUE_EXPR: 903590075Sobrien case VIEW_CONVERT_EXPR: 903650397Sobrien add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); 903750397Sobrien break; 903890075Sobrien 903950397Sobrien case SAVE_EXPR: 904050397Sobrien /* If optimization is turned on, the SAVE_EXPRs that describe how to 904150397Sobrien access the upper bound values may be bogus. If they refer to a 904250397Sobrien register, they may only describe how to get at these values at the 904350397Sobrien points in the generated code right after they have just been 904450397Sobrien computed. Worse yet, in the typical case, the upper bound values 904550397Sobrien will not even *be* computed in the optimized code (though the 904650397Sobrien number of elements will), so these SAVE_EXPRs are entirely 904750397Sobrien bogus. In order to compensate for this fact, we check here to see 904850397Sobrien if optimization is enabled, and if so, we don't add an attribute 904950397Sobrien for the (unknown and unknowable) upper bound. This should not 905050397Sobrien cause too much trouble for existing (stupid?) debuggers because 905150397Sobrien they have to deal with empty upper bounds location descriptions 905250397Sobrien anyway in order to be able to deal with incomplete array types. 905350397Sobrien Of course an intelligent debugger (GDB?) should be able to 905490075Sobrien comprehend that a missing upper bound specification in an array 905550397Sobrien type used for a storage class `auto' local array variable 905650397Sobrien indicates that the upper bound is both unknown (at compile- time) 905750397Sobrien and unknowable (at run-time) due to optimization. 905850397Sobrien 905950397Sobrien We assume that a MEM rtx is safe because gcc wouldn't put the 906050397Sobrien value there unless it was going to be used repeatedly in the 906150397Sobrien function, i.e. for cleanups. */ 906290075Sobrien if (SAVE_EXPR_RTL (bound) 906390075Sobrien && (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM)) 906450397Sobrien { 906590075Sobrien dw_die_ref ctx = lookup_decl_die (current_function_decl); 906690075Sobrien dw_die_ref decl_die = new_die (DW_TAG_variable, ctx, bound); 906790075Sobrien rtx loc = SAVE_EXPR_RTL (bound); 906850397Sobrien 906950397Sobrien /* If the RTL for the SAVE_EXPR is memory, handle the case where 907050397Sobrien it references an outer function's frame. */ 907150397Sobrien if (GET_CODE (loc) == MEM) 907250397Sobrien { 907350397Sobrien rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound); 907450397Sobrien 907550397Sobrien if (XEXP (loc, 0) != new_addr) 907690075Sobrien loc = gen_rtx_MEM (GET_MODE (loc), new_addr); 907750397Sobrien } 907850397Sobrien 907950397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 908050397Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 908150397Sobrien add_AT_location_description (decl_die, DW_AT_location, loc); 908250397Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 908350397Sobrien } 908450397Sobrien 908550397Sobrien /* Else leave out the attribute. */ 908650397Sobrien break; 908750397Sobrien 908850397Sobrien case VAR_DECL: 908990075Sobrien case PARM_DECL: 909090075Sobrien { 909190075Sobrien dw_die_ref decl_die = lookup_decl_die (bound); 909250397Sobrien 909390075Sobrien /* ??? Can this happen, or should the variable have been bound 909490075Sobrien first? Probably it can, since I imagine that we try to create 909590075Sobrien the types of parameters in the order in which they exist in 909690075Sobrien the list, and won't have created a forward reference to a 909790075Sobrien later parameter. */ 909890075Sobrien if (decl_die != NULL) 909990075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 910090075Sobrien break; 910190075Sobrien } 910290075Sobrien 910350397Sobrien default: 910490075Sobrien { 910590075Sobrien /* Otherwise try to create a stack operation procedure to 910690075Sobrien evaluate the value of the array bound. */ 910790075Sobrien 910890075Sobrien dw_die_ref ctx, decl_die; 910990075Sobrien dw_loc_descr_ref loc; 911090075Sobrien 911190075Sobrien loc = loc_descriptor_from_tree (bound, 0); 911290075Sobrien if (loc == NULL) 911390075Sobrien break; 911490075Sobrien 911590075Sobrien if (current_function_decl == 0) 911690075Sobrien ctx = comp_unit_die; 911790075Sobrien else 911890075Sobrien ctx = lookup_decl_die (current_function_decl); 911990075Sobrien 912090075Sobrien /* If we weren't able to find a context, it's most likely the case 912190075Sobrien that we are processing the return type of the function. So 912290075Sobrien make a SAVE_EXPR to point to it and have the limbo DIE code 912390075Sobrien find the proper die. The save_expr function doesn't always 912490075Sobrien make a SAVE_EXPR, so do it ourselves. */ 912590075Sobrien if (ctx == 0) 912690075Sobrien bound = build (SAVE_EXPR, TREE_TYPE (bound), bound, 912790075Sobrien current_function_decl, NULL_TREE); 912890075Sobrien 912990075Sobrien decl_die = new_die (DW_TAG_variable, ctx, bound); 913090075Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 913190075Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 913290075Sobrien add_AT_loc (decl_die, DW_AT_location, loc); 913390075Sobrien 913490075Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 913590075Sobrien break; 913690075Sobrien } 913750397Sobrien } 913850397Sobrien} 913950397Sobrien 914050397Sobrien/* Note that the block of subscript information for an array type also 914150397Sobrien includes information about the element type of type given array type. */ 914250397Sobrien 914350397Sobrienstatic void 914450397Sobrienadd_subscript_info (type_die, type) 914590075Sobrien dw_die_ref type_die; 914690075Sobrien tree type; 914750397Sobrien{ 914850397Sobrien#ifndef MIPS_DEBUGGING_INFO 914990075Sobrien unsigned dimension_number; 915050397Sobrien#endif 915190075Sobrien tree lower, upper; 915290075Sobrien dw_die_ref subrange_die; 915350397Sobrien 915490075Sobrien /* The GNU compilers represent multidimensional array types as sequences of 915550397Sobrien one dimensional array types whose element types are themselves array 915650397Sobrien types. Here we squish that down, so that each multidimensional array 915790075Sobrien type gets only one array_type DIE in the Dwarf debugging info. The draft 915850397Sobrien Dwarf specification say that we are allowed to do this kind of 915950397Sobrien compression in C (because there is no difference between an array or 916090075Sobrien arrays and a multidimensional array in C) but for other source languages 916150397Sobrien (e.g. Ada) we probably shouldn't do this. */ 916250397Sobrien 916350397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 916450397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 916550397Sobrien We work around this by disabling this feature. See also 916650397Sobrien gen_array_type_die. */ 916750397Sobrien#ifndef MIPS_DEBUGGING_INFO 916850397Sobrien for (dimension_number = 0; 916950397Sobrien TREE_CODE (type) == ARRAY_TYPE; 917050397Sobrien type = TREE_TYPE (type), dimension_number++) 917190075Sobrien#endif 917250397Sobrien { 917390075Sobrien tree domain = TYPE_DOMAIN (type); 917450397Sobrien 917550397Sobrien /* Arrays come in three flavors: Unspecified bounds, fixed bounds, 917690075Sobrien and (in GNU C only) variable bounds. Handle all three forms 917750397Sobrien here. */ 917890075Sobrien subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL); 917950397Sobrien if (domain) 918050397Sobrien { 918150397Sobrien /* We have an array type with specified bounds. */ 918250397Sobrien lower = TYPE_MIN_VALUE (domain); 918350397Sobrien upper = TYPE_MAX_VALUE (domain); 918450397Sobrien 918550397Sobrien /* define the index type. */ 918650397Sobrien if (TREE_TYPE (domain)) 918750397Sobrien { 918850397Sobrien /* ??? This is probably an Ada unnamed subrange type. Ignore the 918950397Sobrien TREE_TYPE field. We can't emit debug info for this 919050397Sobrien because it is an unnamed integral type. */ 919150397Sobrien if (TREE_CODE (domain) == INTEGER_TYPE 919250397Sobrien && TYPE_NAME (domain) == NULL_TREE 919350397Sobrien && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE 919450397Sobrien && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE) 919590075Sobrien ; 919650397Sobrien else 919750397Sobrien add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0, 919850397Sobrien type_die); 919950397Sobrien } 920050397Sobrien 920150397Sobrien /* ??? If upper is NULL, the array has unspecified length, 920250397Sobrien but it does have a lower bound. This happens with Fortran 920350397Sobrien dimension arr(N:*) 920450397Sobrien Since the debugger is definitely going to need to know N 920550397Sobrien to produce useful results, go ahead and output the lower 920650397Sobrien bound solo, and hope the debugger can cope. */ 920750397Sobrien 920850397Sobrien add_bound_info (subrange_die, DW_AT_lower_bound, lower); 920950397Sobrien if (upper) 921050397Sobrien add_bound_info (subrange_die, DW_AT_upper_bound, upper); 921150397Sobrien } 921250397Sobrien 921390075Sobrien /* Otherwise we have an array type with an unspecified length. The 921490075Sobrien DWARF-2 spec does not say how to handle this; let's just leave out the 921590075Sobrien bounds. */ 921650397Sobrien } 921750397Sobrien} 921850397Sobrien 921950397Sobrienstatic void 922050397Sobrienadd_byte_size_attribute (die, tree_node) 922150397Sobrien dw_die_ref die; 922290075Sobrien tree tree_node; 922350397Sobrien{ 922490075Sobrien unsigned size; 922550397Sobrien 922650397Sobrien switch (TREE_CODE (tree_node)) 922750397Sobrien { 922850397Sobrien case ERROR_MARK: 922950397Sobrien size = 0; 923050397Sobrien break; 923150397Sobrien case ENUMERAL_TYPE: 923250397Sobrien case RECORD_TYPE: 923350397Sobrien case UNION_TYPE: 923450397Sobrien case QUAL_UNION_TYPE: 923550397Sobrien size = int_size_in_bytes (tree_node); 923650397Sobrien break; 923750397Sobrien case FIELD_DECL: 923850397Sobrien /* For a data member of a struct or union, the DW_AT_byte_size is 923950397Sobrien generally given as the number of bytes normally allocated for an 924050397Sobrien object of the *declared* type of the member itself. This is true 924150397Sobrien even for bit-fields. */ 924250397Sobrien size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT; 924350397Sobrien break; 924450397Sobrien default: 924550397Sobrien abort (); 924650397Sobrien } 924750397Sobrien 924850397Sobrien /* Note that `size' might be -1 when we get to this point. If it is, that 924950397Sobrien indicates that the byte size of the entity in question is variable. We 925050397Sobrien have no good way of expressing this fact in Dwarf at the present time, 925150397Sobrien so just let the -1 pass on through. */ 925250397Sobrien add_AT_unsigned (die, DW_AT_byte_size, size); 925350397Sobrien} 925450397Sobrien 925550397Sobrien/* For a FIELD_DECL node which represents a bit-field, output an attribute 925650397Sobrien which specifies the distance in bits from the highest order bit of the 925750397Sobrien "containing object" for the bit-field to the highest order bit of the 925850397Sobrien bit-field itself. 925950397Sobrien 926090075Sobrien For any given bit-field, the "containing object" is a hypothetical object 926190075Sobrien (of some integral or enum type) within which the given bit-field lives. The 926290075Sobrien type of this hypothetical "containing object" is always the same as the 926390075Sobrien declared type of the individual bit-field itself. The determination of the 926490075Sobrien exact location of the "containing object" for a bit-field is rather 926590075Sobrien complicated. It's handled by the `field_byte_offset' function (above). 926650397Sobrien 926750397Sobrien Note that it is the size (in bytes) of the hypothetical "containing object" 926850397Sobrien which will be given in the DW_AT_byte_size attribute for this bit-field. 926950397Sobrien (See `byte_size_attribute' above). */ 927050397Sobrien 927150397Sobrienstatic inline void 927250397Sobrienadd_bit_offset_attribute (die, decl) 927390075Sobrien dw_die_ref die; 927490075Sobrien tree decl; 927550397Sobrien{ 927690075Sobrien HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl); 927790075Sobrien tree type = DECL_BIT_FIELD_TYPE (decl); 927890075Sobrien HOST_WIDE_INT bitpos_int; 927990075Sobrien HOST_WIDE_INT highest_order_object_bit_offset; 928090075Sobrien HOST_WIDE_INT highest_order_field_bit_offset; 928190075Sobrien HOST_WIDE_INT unsigned bit_offset; 928250397Sobrien 928350397Sobrien /* Must be a field and a bit field. */ 928450397Sobrien if (!type 928550397Sobrien || TREE_CODE (decl) != FIELD_DECL) 928650397Sobrien abort (); 928750397Sobrien 928850397Sobrien /* We can't yet handle bit-fields whose offsets are variable, so if we 928950397Sobrien encounter such things, just return without generating any attribute 929090075Sobrien whatsoever. Likewise for variable or too large size. */ 929190075Sobrien if (! host_integerp (bit_position (decl), 0) 929290075Sobrien || ! host_integerp (DECL_SIZE (decl), 1)) 929350397Sobrien return; 929450397Sobrien 929590075Sobrien bitpos_int = int_bit_position (decl); 929650397Sobrien 929750397Sobrien /* Note that the bit offset is always the distance (in bits) from the 929890075Sobrien highest-order bit of the "containing object" to the highest-order bit of 929990075Sobrien the bit-field itself. Since the "high-order end" of any object or field 930050397Sobrien is different on big-endian and little-endian machines, the computation 930150397Sobrien below must take account of these differences. */ 930250397Sobrien highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT; 930350397Sobrien highest_order_field_bit_offset = bitpos_int; 930450397Sobrien 930550397Sobrien if (! BYTES_BIG_ENDIAN) 930650397Sobrien { 930790075Sobrien highest_order_field_bit_offset += tree_low_cst (DECL_SIZE (decl), 0); 930850397Sobrien highest_order_object_bit_offset += simple_type_size_in_bits (type); 930950397Sobrien } 931050397Sobrien 931150397Sobrien bit_offset 931250397Sobrien = (! BYTES_BIG_ENDIAN 931350397Sobrien ? highest_order_object_bit_offset - highest_order_field_bit_offset 931450397Sobrien : highest_order_field_bit_offset - highest_order_object_bit_offset); 931550397Sobrien 931650397Sobrien add_AT_unsigned (die, DW_AT_bit_offset, bit_offset); 931750397Sobrien} 931850397Sobrien 931950397Sobrien/* For a FIELD_DECL node which represents a bit field, output an attribute 932050397Sobrien which specifies the length in bits of the given field. */ 932150397Sobrien 932250397Sobrienstatic inline void 932350397Sobrienadd_bit_size_attribute (die, decl) 932490075Sobrien dw_die_ref die; 932590075Sobrien tree decl; 932650397Sobrien{ 932750397Sobrien /* Must be a field and a bit field. */ 932850397Sobrien if (TREE_CODE (decl) != FIELD_DECL 932950397Sobrien || ! DECL_BIT_FIELD_TYPE (decl)) 933050397Sobrien abort (); 933190075Sobrien 933290075Sobrien if (host_integerp (DECL_SIZE (decl), 1)) 933390075Sobrien add_AT_unsigned (die, DW_AT_bit_size, tree_low_cst (DECL_SIZE (decl), 1)); 933450397Sobrien} 933550397Sobrien 933650397Sobrien/* If the compiled language is ANSI C, then add a 'prototyped' 933750397Sobrien attribute, if arg types are given for the parameters of a function. */ 933850397Sobrien 933950397Sobrienstatic inline void 934050397Sobrienadd_prototyped_attribute (die, func_type) 934190075Sobrien dw_die_ref die; 934290075Sobrien tree func_type; 934350397Sobrien{ 934450397Sobrien if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 934550397Sobrien && TYPE_ARG_TYPES (func_type) != NULL) 934650397Sobrien add_AT_flag (die, DW_AT_prototyped, 1); 934750397Sobrien} 934850397Sobrien 934950397Sobrien/* Add an 'abstract_origin' attribute below a given DIE. The DIE is found 935050397Sobrien by looking in either the type declaration or object declaration 935150397Sobrien equate table. */ 935250397Sobrien 935350397Sobrienstatic inline void 935450397Sobrienadd_abstract_origin_attribute (die, origin) 935590075Sobrien dw_die_ref die; 935690075Sobrien tree origin; 935750397Sobrien{ 935850397Sobrien dw_die_ref origin_die = NULL; 935990075Sobrien 936090075Sobrien if (TREE_CODE (origin) != FUNCTION_DECL) 936190075Sobrien { 936290075Sobrien /* We may have gotten separated from the block for the inlined 936390075Sobrien function, if we're in an exception handler or some such; make 936490075Sobrien sure that the abstract function has been written out. 936590075Sobrien 936690075Sobrien Doing this for nested functions is wrong, however; functions are 936790075Sobrien distinct units, and our context might not even be inline. */ 936890075Sobrien tree fn = origin; 936990075Sobrien 937090075Sobrien if (TYPE_P (fn)) 937190075Sobrien fn = TYPE_STUB_DECL (fn); 937290075Sobrien 937390075Sobrien fn = decl_function_context (fn); 937490075Sobrien if (fn) 937590075Sobrien dwarf2out_abstract_function (fn); 937690075Sobrien } 937790075Sobrien 937890075Sobrien if (DECL_P (origin)) 937950397Sobrien origin_die = lookup_decl_die (origin); 938090075Sobrien else if (TYPE_P (origin)) 938150397Sobrien origin_die = lookup_type_die (origin); 938250397Sobrien 938390075Sobrien if (origin_die == NULL) 938490075Sobrien abort (); 938590075Sobrien 938650397Sobrien add_AT_die_ref (die, DW_AT_abstract_origin, origin_die); 938750397Sobrien} 938850397Sobrien 938950397Sobrien/* We do not currently support the pure_virtual attribute. */ 939050397Sobrien 939150397Sobrienstatic inline void 939250397Sobrienadd_pure_or_virtual_attribute (die, func_decl) 939390075Sobrien dw_die_ref die; 939490075Sobrien tree func_decl; 939550397Sobrien{ 939650397Sobrien if (DECL_VINDEX (func_decl)) 939750397Sobrien { 939850397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 939950397Sobrien 940090075Sobrien if (host_integerp (DECL_VINDEX (func_decl), 0)) 940190075Sobrien add_AT_loc (die, DW_AT_vtable_elem_location, 940290075Sobrien new_loc_descr (DW_OP_constu, 940390075Sobrien tree_low_cst (DECL_VINDEX (func_decl), 0), 940490075Sobrien 0)); 940590075Sobrien 940650397Sobrien /* GNU extension: Record what type this method came from originally. */ 940750397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 940850397Sobrien add_AT_die_ref (die, DW_AT_containing_type, 940950397Sobrien lookup_type_die (DECL_CONTEXT (func_decl))); 941050397Sobrien } 941150397Sobrien} 941250397Sobrien 941350397Sobrien/* Add source coordinate attributes for the given decl. */ 941450397Sobrien 941550397Sobrienstatic void 941650397Sobrienadd_src_coords_attributes (die, decl) 941790075Sobrien dw_die_ref die; 941890075Sobrien tree decl; 941950397Sobrien{ 942090075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 942150397Sobrien 942250397Sobrien add_AT_unsigned (die, DW_AT_decl_file, file_index); 942350397Sobrien add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 942450397Sobrien} 942550397Sobrien 942650397Sobrien/* Add an DW_AT_name attribute and source coordinate attribute for the 942750397Sobrien given decl, but only if it actually has a name. */ 942850397Sobrien 942950397Sobrienstatic void 943050397Sobrienadd_name_and_src_coords_attributes (die, decl) 943190075Sobrien dw_die_ref die; 943290075Sobrien tree decl; 943350397Sobrien{ 943490075Sobrien tree decl_name; 943550397Sobrien 943690075Sobrien decl_name = DECL_NAME (decl); 943750397Sobrien if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) 943850397Sobrien { 943950397Sobrien add_name_attribute (die, dwarf2_name (decl, 0)); 944090075Sobrien if (! DECL_ARTIFICIAL (decl)) 944190075Sobrien add_src_coords_attributes (die, decl); 944290075Sobrien 944350397Sobrien if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) 944490075Sobrien && TREE_PUBLIC (decl) 944590075Sobrien && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) 944690075Sobrien && !DECL_ABSTRACT (decl)) 944750397Sobrien add_AT_string (die, DW_AT_MIPS_linkage_name, 944850397Sobrien IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 944950397Sobrien } 945090075Sobrien 945190075Sobrien#ifdef VMS_DEBUGGING_INFO 945290075Sobrien /* Get the function's name, as described by its RTL. This may be different 945390075Sobrien from the DECL_NAME name used in the source file. */ 945490075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) 945590075Sobrien { 945690075Sobrien add_AT_addr (die, DW_AT_VMS_rtnbeg_pd_address, 945790075Sobrien XEXP (DECL_RTL (decl), 0)); 945890075Sobrien VARRAY_PUSH_RTX (used_rtx_varray, XEXP (DECL_RTL (decl), 0)); 945990075Sobrien } 946090075Sobrien#endif 946150397Sobrien} 946250397Sobrien 946390075Sobrien/* Push a new declaration scope. */ 946450397Sobrien 946550397Sobrienstatic void 946650397Sobrienpush_decl_scope (scope) 946750397Sobrien tree scope; 946850397Sobrien{ 946990075Sobrien VARRAY_PUSH_TREE (decl_scope_table, scope); 947090075Sobrien} 947150397Sobrien 947290075Sobrien/* Pop a declaration scope. */ 947350397Sobrien 947490075Sobrienstatic inline void 947590075Sobrienpop_decl_scope () 947690075Sobrien{ 947790075Sobrien if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0) 947890075Sobrien abort (); 947950397Sobrien 948090075Sobrien VARRAY_POP (decl_scope_table); 948150397Sobrien} 948250397Sobrien 948390075Sobrien/* Return the DIE for the scope that immediately contains this type. 948490075Sobrien Non-named types get global scope. Named types nested in other 948590075Sobrien types get their containing scope if it's open, or global scope 948690075Sobrien otherwise. All other types (i.e. function-local named types) get 948790075Sobrien the current active scope. */ 948850397Sobrien 948950397Sobrienstatic dw_die_ref 949050397Sobrienscope_die_for (t, context_die) 949190075Sobrien tree t; 949290075Sobrien dw_die_ref context_die; 949350397Sobrien{ 949490075Sobrien dw_die_ref scope_die = NULL; 949590075Sobrien tree containing_scope; 949690075Sobrien int i; 949750397Sobrien 949890075Sobrien /* Non-types always go in the current scope. */ 949990075Sobrien if (! TYPE_P (t)) 950090075Sobrien abort (); 950150397Sobrien 950290075Sobrien containing_scope = TYPE_CONTEXT (t); 950390075Sobrien 950450397Sobrien /* Ignore namespaces for the moment. */ 950550397Sobrien if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL) 950650397Sobrien containing_scope = NULL_TREE; 950750397Sobrien 950852284Sobrien /* Ignore function type "scopes" from the C frontend. They mean that 950952284Sobrien a tagged type is local to a parmlist of a function declarator, but 951052284Sobrien that isn't useful to DWARF. */ 951152284Sobrien if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE) 951252284Sobrien containing_scope = NULL_TREE; 951352284Sobrien 951450397Sobrien if (containing_scope == NULL_TREE) 951550397Sobrien scope_die = comp_unit_die; 951690075Sobrien else if (TYPE_P (containing_scope)) 951750397Sobrien { 951890075Sobrien /* For types, we can just look up the appropriate DIE. But 951990075Sobrien first we check to see if we're in the middle of emitting it 952090075Sobrien so we know where the new DIE should go. */ 952190075Sobrien for (i = VARRAY_ACTIVE_SIZE (decl_scope_table) - 1; i >= 0; --i) 952290075Sobrien if (VARRAY_TREE (decl_scope_table, i) == containing_scope) 952390075Sobrien break; 952450397Sobrien 952550397Sobrien if (i < 0) 952650397Sobrien { 952750397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE 952850397Sobrien && !TREE_ASM_WRITTEN (containing_scope)) 952950397Sobrien abort (); 953052284Sobrien 953152284Sobrien /* If none of the current dies are suitable, we get file scope. */ 953252284Sobrien scope_die = comp_unit_die; 953350397Sobrien } 953490075Sobrien else 953590075Sobrien scope_die = lookup_type_die (containing_scope); 953650397Sobrien } 953790075Sobrien else 953890075Sobrien scope_die = context_die; 953950397Sobrien 954050397Sobrien return scope_die; 954150397Sobrien} 954250397Sobrien 954390075Sobrien/* Returns nonzero if CONTEXT_DIE is internal to a function. */ 954490075Sobrien 954590075Sobrienstatic inline int 954690075Sobrienlocal_scope_p (context_die) 954790075Sobrien dw_die_ref context_die; 954850397Sobrien{ 954990075Sobrien for (; context_die; context_die = context_die->die_parent) 955090075Sobrien if (context_die->die_tag == DW_TAG_inlined_subroutine 955190075Sobrien || context_die->die_tag == DW_TAG_subprogram) 955290075Sobrien return 1; 955390075Sobrien 955490075Sobrien return 0; 955550397Sobrien} 955650397Sobrien 955790075Sobrien/* Returns nonzero if CONTEXT_DIE is a class. */ 955890075Sobrien 955990075Sobrienstatic inline int 956090075Sobrienclass_scope_p (context_die) 956190075Sobrien dw_die_ref context_die; 956290075Sobrien{ 956390075Sobrien return (context_die 956490075Sobrien && (context_die->die_tag == DW_TAG_structure_type 956590075Sobrien || context_die->die_tag == DW_TAG_union_type)); 956690075Sobrien} 956790075Sobrien 956850397Sobrien/* Many forms of DIEs require a "type description" attribute. This 956950397Sobrien routine locates the proper "type descriptor" die for the type given 957050397Sobrien by 'type', and adds an DW_AT_type attribute below the given die. */ 957150397Sobrien 957250397Sobrienstatic void 957350397Sobrienadd_type_attribute (object_die, type, decl_const, decl_volatile, context_die) 957490075Sobrien dw_die_ref object_die; 957590075Sobrien tree type; 957690075Sobrien int decl_const; 957790075Sobrien int decl_volatile; 957890075Sobrien dw_die_ref context_die; 957950397Sobrien{ 958090075Sobrien enum tree_code code = TREE_CODE (type); 958190075Sobrien dw_die_ref type_die = NULL; 958250397Sobrien 958350397Sobrien /* ??? If this type is an unnamed subrange type of an integral or 958450397Sobrien floating-point type, use the inner type. This is because we have no 958550397Sobrien support for unnamed types in base_type_die. This can happen if this is 958650397Sobrien an Ada subrange type. Correct solution is emit a subrange type die. */ 958750397Sobrien if ((code == INTEGER_TYPE || code == REAL_TYPE) 958850397Sobrien && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0) 958950397Sobrien type = TREE_TYPE (type), code = TREE_CODE (type); 959050397Sobrien 959190075Sobrien if (code == ERROR_MARK 959290075Sobrien /* Handle a special case. For functions whose return type is void, we 959390075Sobrien generate *no* type attribute. (Note that no object may have type 959490075Sobrien `void', so this only applies to function return types). */ 959590075Sobrien || code == VOID_TYPE) 959650397Sobrien return; 959750397Sobrien 959850397Sobrien type_die = modified_type_die (type, 959950397Sobrien decl_const || TYPE_READONLY (type), 960050397Sobrien decl_volatile || TYPE_VOLATILE (type), 960150397Sobrien context_die); 960290075Sobrien 960350397Sobrien if (type_die != NULL) 960450397Sobrien add_AT_die_ref (object_die, DW_AT_type, type_die); 960550397Sobrien} 960650397Sobrien 960750397Sobrien/* Given a tree pointer to a struct, class, union, or enum type node, return 960850397Sobrien a pointer to the (string) tag name for the given type, or zero if the type 960950397Sobrien was declared without a tag. */ 961050397Sobrien 961190075Sobrienstatic const char * 961250397Sobrientype_tag (type) 961390075Sobrien tree type; 961450397Sobrien{ 961590075Sobrien const char *name = 0; 961650397Sobrien 961750397Sobrien if (TYPE_NAME (type) != 0) 961850397Sobrien { 961990075Sobrien tree t = 0; 962050397Sobrien 962150397Sobrien /* Find the IDENTIFIER_NODE for the type name. */ 962250397Sobrien if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 962350397Sobrien t = TYPE_NAME (type); 962450397Sobrien 962590075Sobrien /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 962650397Sobrien a TYPE_DECL node, regardless of whether or not a `typedef' was 962750397Sobrien involved. */ 962850397Sobrien else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 962950397Sobrien && ! DECL_IGNORED_P (TYPE_NAME (type))) 963050397Sobrien t = DECL_NAME (TYPE_NAME (type)); 963150397Sobrien 963250397Sobrien /* Now get the name as a string, or invent one. */ 963350397Sobrien if (t != 0) 963450397Sobrien name = IDENTIFIER_POINTER (t); 963550397Sobrien } 963650397Sobrien 963750397Sobrien return (name == 0 || *name == '\0') ? 0 : name; 963850397Sobrien} 963950397Sobrien 964050397Sobrien/* Return the type associated with a data member, make a special check 964150397Sobrien for bit field types. */ 964250397Sobrien 964350397Sobrienstatic inline tree 964450397Sobrienmember_declared_type (member) 964590075Sobrien tree member; 964650397Sobrien{ 964750397Sobrien return (DECL_BIT_FIELD_TYPE (member) 964890075Sobrien ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member)); 964950397Sobrien} 965050397Sobrien 965150397Sobrien/* Get the decl's label, as described by its RTL. This may be different 965250397Sobrien from the DECL_NAME name used in the source file. */ 965350397Sobrien 965450397Sobrien#if 0 965590075Sobrienstatic const char * 965650397Sobriendecl_start_label (decl) 965790075Sobrien tree decl; 965850397Sobrien{ 965950397Sobrien rtx x; 966090075Sobrien const char *fnname; 966190075Sobrien 966250397Sobrien x = DECL_RTL (decl); 966350397Sobrien if (GET_CODE (x) != MEM) 966450397Sobrien abort (); 966550397Sobrien 966650397Sobrien x = XEXP (x, 0); 966750397Sobrien if (GET_CODE (x) != SYMBOL_REF) 966850397Sobrien abort (); 966950397Sobrien 967050397Sobrien fnname = XSTR (x, 0); 967150397Sobrien return fnname; 967250397Sobrien} 967350397Sobrien#endif 967450397Sobrien 967550397Sobrien/* These routines generate the internal representation of the DIE's for 967650397Sobrien the compilation unit. Debugging information is collected by walking 967750397Sobrien the declaration trees passed in from dwarf2out_decl(). */ 967850397Sobrien 967950397Sobrienstatic void 968050397Sobriengen_array_type_die (type, context_die) 968190075Sobrien tree type; 968290075Sobrien dw_die_ref context_die; 968350397Sobrien{ 968490075Sobrien dw_die_ref scope_die = scope_die_for (type, context_die); 968590075Sobrien dw_die_ref array_die; 968690075Sobrien tree element_type; 968750397Sobrien 968850397Sobrien /* ??? The SGI dwarf reader fails for array of array of enum types unless 968950397Sobrien the inner array type comes before the outer array type. Thus we must 969050397Sobrien call gen_type_die before we call new_die. See below also. */ 969150397Sobrien#ifdef MIPS_DEBUGGING_INFO 969250397Sobrien gen_type_die (TREE_TYPE (type), context_die); 969350397Sobrien#endif 969450397Sobrien 969590075Sobrien array_die = new_die (DW_TAG_array_type, scope_die, type); 969650397Sobrien 969750397Sobrien#if 0 969850397Sobrien /* We default the array ordering. SDB will probably do 969950397Sobrien the right things even if DW_AT_ordering is not present. It's not even 970050397Sobrien an issue until we start to get into multidimensional arrays anyway. If 970150397Sobrien SDB is ever caught doing the Wrong Thing for multi-dimensional arrays, 970250397Sobrien then we'll have to put the DW_AT_ordering attribute back in. (But if 970350397Sobrien and when we find out that we need to put these in, we will only do so 970450397Sobrien for multidimensional arrays. */ 970550397Sobrien add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major); 970650397Sobrien#endif 970750397Sobrien 970850397Sobrien#ifdef MIPS_DEBUGGING_INFO 970950397Sobrien /* The SGI compilers handle arrays of unknown bound by setting 971050397Sobrien AT_declaration and not emitting any subrange DIEs. */ 971150397Sobrien if (! TYPE_DOMAIN (type)) 971250397Sobrien add_AT_unsigned (array_die, DW_AT_declaration, 1); 971350397Sobrien else 971450397Sobrien#endif 971550397Sobrien add_subscript_info (array_die, type); 971650397Sobrien 971790075Sobrien add_name_attribute (array_die, type_tag (type)); 971850397Sobrien equate_type_number_to_die (type, array_die); 971950397Sobrien 972050397Sobrien /* Add representation of the type of the elements of this array type. */ 972150397Sobrien element_type = TREE_TYPE (type); 972250397Sobrien 972350397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 972450397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 972550397Sobrien We work around this by disabling this feature. See also 972650397Sobrien add_subscript_info. */ 972750397Sobrien#ifndef MIPS_DEBUGGING_INFO 972850397Sobrien while (TREE_CODE (element_type) == ARRAY_TYPE) 972950397Sobrien element_type = TREE_TYPE (element_type); 973050397Sobrien 973150397Sobrien gen_type_die (element_type, context_die); 973250397Sobrien#endif 973350397Sobrien 973450397Sobrien add_type_attribute (array_die, element_type, 0, 0, context_die); 973550397Sobrien} 973650397Sobrien 973750397Sobrienstatic void 973850397Sobriengen_set_type_die (type, context_die) 973990075Sobrien tree type; 974090075Sobrien dw_die_ref context_die; 974150397Sobrien{ 974290075Sobrien dw_die_ref type_die 974390075Sobrien = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type); 974450397Sobrien 974550397Sobrien equate_type_number_to_die (type, type_die); 974650397Sobrien add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die); 974750397Sobrien} 974850397Sobrien 974950397Sobrien#if 0 975050397Sobrienstatic void 975150397Sobriengen_entry_point_die (decl, context_die) 975290075Sobrien tree decl; 975390075Sobrien dw_die_ref context_die; 975450397Sobrien{ 975590075Sobrien tree origin = decl_ultimate_origin (decl); 975690075Sobrien dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl); 975790075Sobrien 975850397Sobrien if (origin != NULL) 975950397Sobrien add_abstract_origin_attribute (decl_die, origin); 976050397Sobrien else 976150397Sobrien { 976250397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 976350397Sobrien add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)), 976450397Sobrien 0, 0, context_die); 976550397Sobrien } 976650397Sobrien 976750397Sobrien if (DECL_ABSTRACT (decl)) 976850397Sobrien equate_decl_number_to_die (decl, decl_die); 976950397Sobrien else 977050397Sobrien add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl)); 977150397Sobrien} 977250397Sobrien#endif 977350397Sobrien 977452284Sobrien/* Walk through the list of incomplete types again, trying once more to 977552284Sobrien emit full debugging info for them. */ 977652284Sobrien 977752284Sobrienstatic void 977852284Sobrienretry_incomplete_types () 977952284Sobrien{ 978090075Sobrien int i; 978152284Sobrien 978290075Sobrien for (i = VARRAY_ACTIVE_SIZE (incomplete_types) - 1; i >= 0; i--) 978390075Sobrien gen_type_die (VARRAY_TREE (incomplete_types, i), comp_unit_die); 978452284Sobrien} 978552284Sobrien 978650397Sobrien/* Generate a DIE to represent an inlined instance of an enumeration type. */ 978750397Sobrien 978850397Sobrienstatic void 978950397Sobriengen_inlined_enumeration_type_die (type, context_die) 979090075Sobrien tree type; 979190075Sobrien dw_die_ref context_die; 979250397Sobrien{ 979390075Sobrien dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type); 979450397Sobrien 979590075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 979690075Sobrien be incomplete and such types are not marked. */ 979750397Sobrien add_abstract_origin_attribute (type_die, type); 979850397Sobrien} 979950397Sobrien 980050397Sobrien/* Generate a DIE to represent an inlined instance of a structure type. */ 980150397Sobrien 980250397Sobrienstatic void 980350397Sobriengen_inlined_structure_type_die (type, context_die) 980490075Sobrien tree type; 980590075Sobrien dw_die_ref context_die; 980650397Sobrien{ 980790075Sobrien dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type); 980850397Sobrien 980990075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 981090075Sobrien be incomplete and such types are not marked. */ 981150397Sobrien add_abstract_origin_attribute (type_die, type); 981250397Sobrien} 981350397Sobrien 981450397Sobrien/* Generate a DIE to represent an inlined instance of a union type. */ 981550397Sobrien 981650397Sobrienstatic void 981750397Sobriengen_inlined_union_type_die (type, context_die) 981890075Sobrien tree type; 981990075Sobrien dw_die_ref context_die; 982050397Sobrien{ 982190075Sobrien dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type); 982250397Sobrien 982390075Sobrien /* We do not check for TREE_ASM_WRITTEN (type) being set, as the type may 982490075Sobrien be incomplete and such types are not marked. */ 982550397Sobrien add_abstract_origin_attribute (type_die, type); 982650397Sobrien} 982750397Sobrien 982850397Sobrien/* Generate a DIE to represent an enumeration type. Note that these DIEs 982950397Sobrien include all of the information about the enumeration values also. Each 983050397Sobrien enumerated type name/value is listed as a child of the enumerated type 983150397Sobrien DIE. */ 983250397Sobrien 983350397Sobrienstatic void 983450397Sobriengen_enumeration_type_die (type, context_die) 983590075Sobrien tree type; 983690075Sobrien dw_die_ref context_die; 983750397Sobrien{ 983890075Sobrien dw_die_ref type_die = lookup_type_die (type); 983950397Sobrien 984050397Sobrien if (type_die == NULL) 984150397Sobrien { 984250397Sobrien type_die = new_die (DW_TAG_enumeration_type, 984390075Sobrien scope_die_for (type, context_die), type); 984450397Sobrien equate_type_number_to_die (type, type_die); 984550397Sobrien add_name_attribute (type_die, type_tag (type)); 984650397Sobrien } 984750397Sobrien else if (! TYPE_SIZE (type)) 984850397Sobrien return; 984950397Sobrien else 985050397Sobrien remove_AT (type_die, DW_AT_declaration); 985150397Sobrien 985250397Sobrien /* Handle a GNU C/C++ extension, i.e. incomplete enum types. If the 985350397Sobrien given enum type is incomplete, do not generate the DW_AT_byte_size 985450397Sobrien attribute or the DW_AT_element_list attribute. */ 985550397Sobrien if (TYPE_SIZE (type)) 985650397Sobrien { 985790075Sobrien tree link; 985850397Sobrien 985950397Sobrien TREE_ASM_WRITTEN (type) = 1; 986050397Sobrien add_byte_size_attribute (type_die, type); 986150397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 986250397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 986350397Sobrien 986450397Sobrien /* If the first reference to this type was as the return type of an 986550397Sobrien inline function, then it may not have a parent. Fix this now. */ 986650397Sobrien if (type_die->die_parent == NULL) 986750397Sobrien add_child_die (scope_die_for (type, context_die), type_die); 986850397Sobrien 986950397Sobrien for (link = TYPE_FIELDS (type); 987050397Sobrien link != NULL; link = TREE_CHAIN (link)) 987150397Sobrien { 987290075Sobrien dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link); 987350397Sobrien 987450397Sobrien add_name_attribute (enum_die, 987550397Sobrien IDENTIFIER_POINTER (TREE_PURPOSE (link))); 987690075Sobrien 987790075Sobrien if (host_integerp (TREE_VALUE (link), 0)) 987890075Sobrien { 987990075Sobrien if (tree_int_cst_sgn (TREE_VALUE (link)) < 0) 988090075Sobrien add_AT_int (enum_die, DW_AT_const_value, 988190075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 988290075Sobrien else 988390075Sobrien add_AT_unsigned (enum_die, DW_AT_const_value, 988490075Sobrien tree_low_cst (TREE_VALUE (link), 0)); 988590075Sobrien } 988650397Sobrien } 988750397Sobrien } 988850397Sobrien else 988950397Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 989050397Sobrien} 989150397Sobrien 989250397Sobrien/* Generate a DIE to represent either a real live formal parameter decl or to 989350397Sobrien represent just the type of some formal parameter position in some function 989450397Sobrien type. 989550397Sobrien 989650397Sobrien Note that this routine is a bit unusual because its argument may be a 989750397Sobrien ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which 989850397Sobrien represents an inlining of some PARM_DECL) or else some sort of a ..._TYPE 989950397Sobrien node. If it's the former then this function is being called to output a 990050397Sobrien DIE to represent a formal parameter object (or some inlining thereof). If 990150397Sobrien it's the latter, then this function is only being called to output a 990250397Sobrien DW_TAG_formal_parameter DIE to stand as a placeholder for some formal 990350397Sobrien argument type of some subprogram type. */ 990450397Sobrien 990550397Sobrienstatic dw_die_ref 990650397Sobriengen_formal_parameter_die (node, context_die) 990790075Sobrien tree node; 990890075Sobrien dw_die_ref context_die; 990950397Sobrien{ 991090075Sobrien dw_die_ref parm_die 991190075Sobrien = new_die (DW_TAG_formal_parameter, context_die, node); 991290075Sobrien tree origin; 991350397Sobrien 991450397Sobrien switch (TREE_CODE_CLASS (TREE_CODE (node))) 991550397Sobrien { 991650397Sobrien case 'd': 991750397Sobrien origin = decl_ultimate_origin (node); 991850397Sobrien if (origin != NULL) 991950397Sobrien add_abstract_origin_attribute (parm_die, origin); 992050397Sobrien else 992150397Sobrien { 992250397Sobrien add_name_and_src_coords_attributes (parm_die, node); 992350397Sobrien add_type_attribute (parm_die, TREE_TYPE (node), 992450397Sobrien TREE_READONLY (node), 992550397Sobrien TREE_THIS_VOLATILE (node), 992650397Sobrien context_die); 992750397Sobrien if (DECL_ARTIFICIAL (node)) 992850397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 992950397Sobrien } 993050397Sobrien 993150397Sobrien equate_decl_number_to_die (node, parm_die); 993250397Sobrien if (! DECL_ABSTRACT (node)) 993350397Sobrien add_location_or_const_value_attribute (parm_die, node); 993450397Sobrien 993550397Sobrien break; 993650397Sobrien 993750397Sobrien case 't': 993850397Sobrien /* We were called with some kind of a ..._TYPE node. */ 993950397Sobrien add_type_attribute (parm_die, node, 0, 0, context_die); 994050397Sobrien break; 994150397Sobrien 994250397Sobrien default: 994350397Sobrien abort (); 994450397Sobrien } 994550397Sobrien 994650397Sobrien return parm_die; 994750397Sobrien} 994850397Sobrien 994950397Sobrien/* Generate a special type of DIE used as a stand-in for a trailing ellipsis 995050397Sobrien at the end of an (ANSI prototyped) formal parameters list. */ 995150397Sobrien 995250397Sobrienstatic void 995350397Sobriengen_unspecified_parameters_die (decl_or_type, context_die) 995490075Sobrien tree decl_or_type; 995590075Sobrien dw_die_ref context_die; 995650397Sobrien{ 995790075Sobrien new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type); 995850397Sobrien} 995950397Sobrien 996050397Sobrien/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a 996150397Sobrien DW_TAG_unspecified_parameters DIE) to represent the types of the formal 996250397Sobrien parameters as specified in some function type specification (except for 996390075Sobrien those which appear as part of a function *definition*). */ 996450397Sobrien 996550397Sobrienstatic void 996650397Sobriengen_formal_types_die (function_or_method_type, context_die) 996790075Sobrien tree function_or_method_type; 996890075Sobrien dw_die_ref context_die; 996950397Sobrien{ 997090075Sobrien tree link; 997190075Sobrien tree formal_type = NULL; 997290075Sobrien tree first_parm_type; 997390075Sobrien tree arg; 997450397Sobrien 997590075Sobrien if (TREE_CODE (function_or_method_type) == FUNCTION_DECL) 997690075Sobrien { 997790075Sobrien arg = DECL_ARGUMENTS (function_or_method_type); 997890075Sobrien function_or_method_type = TREE_TYPE (function_or_method_type); 997990075Sobrien } 998090075Sobrien else 998190075Sobrien arg = NULL_TREE; 998290075Sobrien 998390075Sobrien first_parm_type = TYPE_ARG_TYPES (function_or_method_type); 998450397Sobrien 998590075Sobrien /* Make our first pass over the list of formal parameter types and output a 998650397Sobrien DW_TAG_formal_parameter DIE for each one. */ 998790075Sobrien for (link = first_parm_type; link; ) 998850397Sobrien { 998990075Sobrien dw_die_ref parm_die; 999090075Sobrien 999150397Sobrien formal_type = TREE_VALUE (link); 999250397Sobrien if (formal_type == void_type_node) 999350397Sobrien break; 999450397Sobrien 999550397Sobrien /* Output a (nameless) DIE to represent the formal parameter itself. */ 999650397Sobrien parm_die = gen_formal_parameter_die (formal_type, context_die); 999790075Sobrien if ((TREE_CODE (function_or_method_type) == METHOD_TYPE 999890075Sobrien && link == first_parm_type) 999990075Sobrien || (arg && DECL_ARTIFICIAL (arg))) 1000050397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 1000190075Sobrien 1000290075Sobrien link = TREE_CHAIN (link); 1000390075Sobrien if (arg) 1000490075Sobrien arg = TREE_CHAIN (arg); 1000550397Sobrien } 1000650397Sobrien 1000750397Sobrien /* If this function type has an ellipsis, add a 1000850397Sobrien DW_TAG_unspecified_parameters DIE to the end of the parameter list. */ 1000950397Sobrien if (formal_type != void_type_node) 1001050397Sobrien gen_unspecified_parameters_die (function_or_method_type, context_die); 1001150397Sobrien 1001290075Sobrien /* Make our second (and final) pass over the list of formal parameter types 1001350397Sobrien and output DIEs to represent those types (as necessary). */ 1001450397Sobrien for (link = TYPE_ARG_TYPES (function_or_method_type); 1001590075Sobrien link && TREE_VALUE (link); 1001650397Sobrien link = TREE_CHAIN (link)) 1001790075Sobrien gen_type_die (TREE_VALUE (link), context_die); 1001890075Sobrien} 1001990075Sobrien 1002090075Sobrien/* We want to generate the DIE for TYPE so that we can generate the 1002190075Sobrien die for MEMBER, which has been defined; we will need to refer back 1002290075Sobrien to the member declaration nested within TYPE. If we're trying to 1002390075Sobrien generate minimal debug info for TYPE, processing TYPE won't do the 1002490075Sobrien trick; we need to attach the member declaration by hand. */ 1002590075Sobrien 1002690075Sobrienstatic void 1002790075Sobriengen_type_die_for_member (type, member, context_die) 1002890075Sobrien tree type, member; 1002990075Sobrien dw_die_ref context_die; 1003090075Sobrien{ 1003190075Sobrien gen_type_die (type, context_die); 1003290075Sobrien 1003390075Sobrien /* If we're trying to avoid duplicate debug info, we may not have 1003490075Sobrien emitted the member decl for this function. Emit it now. */ 1003590075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) 1003690075Sobrien && ! lookup_decl_die (member)) 1003750397Sobrien { 1003890075Sobrien if (decl_ultimate_origin (member)) 1003990075Sobrien abort (); 1004050397Sobrien 1004190075Sobrien push_decl_scope (type); 1004290075Sobrien if (TREE_CODE (member) == FUNCTION_DECL) 1004390075Sobrien gen_subprogram_die (member, lookup_type_die (type)); 1004490075Sobrien else 1004590075Sobrien gen_variable_die (member, lookup_type_die (type)); 1004690075Sobrien 1004790075Sobrien pop_decl_scope (); 1004850397Sobrien } 1004950397Sobrien} 1005050397Sobrien 1005190075Sobrien/* Generate the DWARF2 info for the "abstract" instance of a function which we 1005290075Sobrien may later generate inlined and/or out-of-line instances of. */ 1005390075Sobrien 1005490075Sobrienstatic void 1005590075Sobriendwarf2out_abstract_function (decl) 1005690075Sobrien tree decl; 1005790075Sobrien{ 1005890075Sobrien dw_die_ref old_die; 1005990075Sobrien tree save_fn; 1006090075Sobrien tree context; 1006190075Sobrien int was_abstract = DECL_ABSTRACT (decl); 1006290075Sobrien 1006390075Sobrien /* Make sure we have the actual abstract inline, not a clone. */ 1006490075Sobrien decl = DECL_ORIGIN (decl); 1006590075Sobrien 1006690075Sobrien old_die = lookup_decl_die (decl); 1006790075Sobrien if (old_die && get_AT_unsigned (old_die, DW_AT_inline)) 1006890075Sobrien /* We've already generated the abstract instance. */ 1006990075Sobrien return; 1007090075Sobrien 1007190075Sobrien /* Be sure we've emitted the in-class declaration DIE (if any) first, so 1007290075Sobrien we don't get confused by DECL_ABSTRACT. */ 1007390075Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1007490075Sobrien { 1007590075Sobrien context = decl_class_context (decl); 1007690075Sobrien if (context) 1007790075Sobrien gen_type_die_for_member 1007890075Sobrien (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); 1007990075Sobrien } 1008090075Sobrien 1008190075Sobrien /* Pretend we've just finished compiling this function. */ 1008290075Sobrien save_fn = current_function_decl; 1008390075Sobrien current_function_decl = decl; 1008490075Sobrien 1008590075Sobrien set_decl_abstract_flags (decl, 1); 1008690075Sobrien dwarf2out_decl (decl); 1008790075Sobrien if (! was_abstract) 1008890075Sobrien set_decl_abstract_flags (decl, 0); 1008990075Sobrien 1009090075Sobrien current_function_decl = save_fn; 1009190075Sobrien} 1009290075Sobrien 1009350397Sobrien/* Generate a DIE to represent a declared function (either file-scope or 1009450397Sobrien block-local). */ 1009550397Sobrien 1009650397Sobrienstatic void 1009750397Sobriengen_subprogram_die (decl, context_die) 1009890075Sobrien tree decl; 1009990075Sobrien dw_die_ref context_die; 1010050397Sobrien{ 1010150397Sobrien char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 1010290075Sobrien tree origin = decl_ultimate_origin (decl); 1010390075Sobrien dw_die_ref subr_die; 1010490075Sobrien rtx fp_reg; 1010590075Sobrien tree fn_arg_types; 1010690075Sobrien tree outer_scope; 1010790075Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1010890075Sobrien int declaration = (current_function_decl != decl 1010990075Sobrien || class_scope_p (context_die)); 1011050397Sobrien 1011190075Sobrien /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we 1011290075Sobrien started to generate the abstract instance of an inline, decided to output 1011390075Sobrien its containing class, and proceeded to emit the declaration of the inline 1011490075Sobrien from the member list for the class. If so, DECLARATION takes priority; 1011590075Sobrien we'll get back to the abstract instance when done with the class. */ 1011690075Sobrien 1011790075Sobrien /* The class-scope declaration DIE must be the primary DIE. */ 1011890075Sobrien if (origin && declaration && class_scope_p (context_die)) 1011950397Sobrien { 1012090075Sobrien origin = NULL; 1012190075Sobrien if (old_die) 1012290075Sobrien abort (); 1012350397Sobrien } 1012490075Sobrien 1012590075Sobrien if (origin != NULL) 1012650397Sobrien { 1012790075Sobrien if (declaration && ! local_scope_p (context_die)) 1012890075Sobrien abort (); 1012950397Sobrien 1013090075Sobrien /* Fixup die_parent for the abstract instance of a nested 1013190075Sobrien inline function. */ 1013290075Sobrien if (old_die && old_die->die_parent == NULL) 1013390075Sobrien add_child_die (context_die, old_die); 1013490075Sobrien 1013590075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1013690075Sobrien add_abstract_origin_attribute (subr_die, origin); 1013750397Sobrien } 1013850397Sobrien else if (old_die) 1013950397Sobrien { 1014090075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1014150397Sobrien 1014290075Sobrien if (!get_AT_flag (old_die, DW_AT_declaration) 1014390075Sobrien /* We can have a normal definition following an inline one in the 1014490075Sobrien case of redefinition of GNU C extern inlines. 1014590075Sobrien It seems reasonable to use AT_specification in this case. */ 1014690075Sobrien && !get_AT_unsigned (old_die, DW_AT_inline)) 1014752284Sobrien { 1014852284Sobrien /* ??? This can happen if there is a bug in the program, for 1014952284Sobrien instance, if it has duplicate function definitions. Ideally, 1015052284Sobrien we should detect this case and ignore it. For now, if we have 1015152284Sobrien already reported an error, any error at all, then assume that 1015290075Sobrien we got here because of an input error, not a dwarf2 bug. */ 1015352284Sobrien if (errorcount) 1015452284Sobrien return; 1015552284Sobrien abort (); 1015652284Sobrien } 1015750397Sobrien 1015850397Sobrien /* If the definition comes from the same place as the declaration, 1015950397Sobrien maybe use the old DIE. We always want the DIE for this function 1016050397Sobrien that has the *_pc attributes to be under comp_unit_die so the 1016190075Sobrien debugger can find it. We also need to do this for abstract 1016290075Sobrien instances of inlines, since the spec requires the out-of-line copy 1016390075Sobrien to have the same parent. For local class methods, this doesn't 1016490075Sobrien apply; we just use the old DIE. */ 1016590075Sobrien if ((old_die->die_parent == comp_unit_die || context_die == NULL) 1016690075Sobrien && (DECL_ARTIFICIAL (decl) 1016790075Sobrien || (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index 1016890075Sobrien && (get_AT_unsigned (old_die, DW_AT_decl_line) 1016990075Sobrien == (unsigned) DECL_SOURCE_LINE (decl))))) 1017050397Sobrien { 1017150397Sobrien subr_die = old_die; 1017250397Sobrien 1017350397Sobrien /* Clear out the declaration attribute and the parm types. */ 1017450397Sobrien remove_AT (subr_die, DW_AT_declaration); 1017550397Sobrien remove_children (subr_die); 1017650397Sobrien } 1017750397Sobrien else 1017850397Sobrien { 1017990075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1018050397Sobrien add_AT_die_ref (subr_die, DW_AT_specification, old_die); 1018150397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1018250397Sobrien add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); 1018350397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1018490075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1018550397Sobrien add_AT_unsigned 1018650397Sobrien (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 1018750397Sobrien } 1018850397Sobrien } 1018950397Sobrien else 1019050397Sobrien { 1019190075Sobrien subr_die = new_die (DW_TAG_subprogram, context_die, decl); 1019250397Sobrien 1019350397Sobrien if (TREE_PUBLIC (decl)) 1019450397Sobrien add_AT_flag (subr_die, DW_AT_external, 1); 1019550397Sobrien 1019650397Sobrien add_name_and_src_coords_attributes (subr_die, decl); 1019750397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1019850397Sobrien { 1019990075Sobrien add_prototyped_attribute (subr_die, TREE_TYPE (decl)); 1020090075Sobrien add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)), 1020190075Sobrien 0, 0, context_die); 1020250397Sobrien } 1020350397Sobrien 1020450397Sobrien add_pure_or_virtual_attribute (subr_die, decl); 1020550397Sobrien if (DECL_ARTIFICIAL (decl)) 1020650397Sobrien add_AT_flag (subr_die, DW_AT_artificial, 1); 1020790075Sobrien 1020850397Sobrien if (TREE_PROTECTED (decl)) 1020950397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected); 1021050397Sobrien else if (TREE_PRIVATE (decl)) 1021150397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private); 1021250397Sobrien } 1021350397Sobrien 1021450397Sobrien if (declaration) 1021550397Sobrien { 1021690075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1021790075Sobrien { 1021890075Sobrien add_AT_flag (subr_die, DW_AT_declaration, 1); 1021950397Sobrien 1022090075Sobrien /* The first time we see a member function, it is in the context of 1022190075Sobrien the class to which it belongs. We make sure of this by emitting 1022290075Sobrien the class first. The next time is the definition, which is 1022390075Sobrien handled above. The two may come from the same source text. */ 1022490075Sobrien if (DECL_CONTEXT (decl) || DECL_ABSTRACT (decl)) 1022590075Sobrien equate_decl_number_to_die (decl, subr_die); 1022690075Sobrien } 1022750397Sobrien } 1022850397Sobrien else if (DECL_ABSTRACT (decl)) 1022950397Sobrien { 1023090075Sobrien if (DECL_INLINE (decl) && !flag_no_inline) 1023150397Sobrien { 1023290075Sobrien /* ??? Checking DECL_DEFER_OUTPUT is correct for static 1023390075Sobrien inline functions, but not for extern inline functions. 1023490075Sobrien We can't get this completely correct because information 1023590075Sobrien about whether the function was declared inline is not 1023690075Sobrien saved anywhere. */ 1023790075Sobrien if (DECL_DEFER_OUTPUT (decl)) 1023850397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined); 1023950397Sobrien else 1024090075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); 1024150397Sobrien } 1024250397Sobrien else 1024390075Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined); 1024450397Sobrien 1024550397Sobrien equate_decl_number_to_die (decl, subr_die); 1024650397Sobrien } 1024750397Sobrien else if (!DECL_EXTERNAL (decl)) 1024850397Sobrien { 1024990075Sobrien if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) 1025050397Sobrien equate_decl_number_to_die (decl, subr_die); 1025150397Sobrien 1025250397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, 1025350397Sobrien current_funcdef_number); 1025450397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); 1025550397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, 1025650397Sobrien current_funcdef_number); 1025750397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); 1025850397Sobrien 1025950397Sobrien add_pubname (decl, subr_die); 1026050397Sobrien add_arange (decl, subr_die); 1026150397Sobrien 1026250397Sobrien#ifdef MIPS_DEBUGGING_INFO 1026350397Sobrien /* Add a reference to the FDE for this routine. */ 1026450397Sobrien add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); 1026550397Sobrien#endif 1026650397Sobrien 1026750397Sobrien /* Define the "frame base" location for this routine. We use the 1026850397Sobrien frame pointer or stack pointer registers, since the RTL for local 1026950397Sobrien variables is relative to one of them. */ 1027050397Sobrien fp_reg 1027150397Sobrien = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; 1027250397Sobrien add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); 1027350397Sobrien 1027450397Sobrien#if 0 1027550397Sobrien /* ??? This fails for nested inline functions, because context_display 1027650397Sobrien is not part of the state saved/restored for inline functions. */ 1027750397Sobrien if (current_function_needs_context) 1027850397Sobrien add_AT_location_description (subr_die, DW_AT_static_link, 1027950397Sobrien lookup_static_chain (decl)); 1028050397Sobrien#endif 1028150397Sobrien } 1028250397Sobrien 1028350397Sobrien /* Now output descriptions of the arguments for this function. This gets 1028490075Sobrien (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list 1028550397Sobrien for a FUNCTION_DECL doesn't indicate cases where there was a trailing 1028650397Sobrien `...' at the end of the formal parameter list. In order to find out if 1028750397Sobrien there was a trailing ellipsis or not, we must instead look at the type 1028850397Sobrien associated with the FUNCTION_DECL. This will be a node of type 1028950397Sobrien FUNCTION_TYPE. If the chain of type nodes hanging off of this 1029090075Sobrien FUNCTION_TYPE node ends with a void_type_node then there should *not* be 1029150397Sobrien an ellipsis at the end. */ 1029250397Sobrien 1029350397Sobrien /* In the case where we are describing a mere function declaration, all we 1029490075Sobrien need to do here (and all we *can* do here) is to describe the *types* of 1029550397Sobrien its formal parameters. */ 1029650397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1029750397Sobrien ; 1029850397Sobrien else if (declaration) 1029990075Sobrien gen_formal_types_die (decl, subr_die); 1030050397Sobrien else 1030150397Sobrien { 1030250397Sobrien /* Generate DIEs to represent all known formal parameters */ 1030390075Sobrien tree arg_decls = DECL_ARGUMENTS (decl); 1030490075Sobrien tree parm; 1030550397Sobrien 1030650397Sobrien /* When generating DIEs, generate the unspecified_parameters DIE 1030750397Sobrien instead if we come across the arg "__builtin_va_alist" */ 1030850397Sobrien for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) 1030950397Sobrien if (TREE_CODE (parm) == PARM_DECL) 1031050397Sobrien { 1031150397Sobrien if (DECL_NAME (parm) 1031250397Sobrien && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), 1031350397Sobrien "__builtin_va_alist")) 1031450397Sobrien gen_unspecified_parameters_die (parm, subr_die); 1031550397Sobrien else 1031650397Sobrien gen_decl_die (parm, subr_die); 1031750397Sobrien } 1031850397Sobrien 1031990075Sobrien /* Decide whether we need an unspecified_parameters DIE at the end. 1032090075Sobrien There are 2 more cases to do this for: 1) the ansi ... declaration - 1032150397Sobrien this is detectable when the end of the arg list is not a 1032250397Sobrien void_type_node 2) an unprototyped function declaration (not a 1032350397Sobrien definition). This just means that we have no info about the 1032450397Sobrien parameters at all. */ 1032550397Sobrien fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); 1032650397Sobrien if (fn_arg_types != NULL) 1032750397Sobrien { 1032850397Sobrien /* this is the prototyped case, check for ... */ 1032950397Sobrien if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) 1033050397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1033150397Sobrien } 1033250397Sobrien else if (DECL_INITIAL (decl) == NULL_TREE) 1033350397Sobrien gen_unspecified_parameters_die (decl, subr_die); 1033450397Sobrien } 1033550397Sobrien 1033650397Sobrien /* Output Dwarf info for all of the stuff within the body of the function 1033750397Sobrien (if it has one - it may be just a declaration). */ 1033850397Sobrien outer_scope = DECL_INITIAL (decl); 1033950397Sobrien 1034090075Sobrien /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent 1034190075Sobrien a function. This BLOCK actually represents the outermost binding contour 1034290075Sobrien for the function, i.e. the contour in which the function's formal 1034390075Sobrien parameters and labels get declared. Curiously, it appears that the front 1034490075Sobrien end doesn't actually put the PARM_DECL nodes for the current function onto 1034590075Sobrien the BLOCK_VARS list for this outer scope, but are strung off of the 1034690075Sobrien DECL_ARGUMENTS list for the function instead. 1034790075Sobrien 1034890075Sobrien The BLOCK_VARS list for the `outer_scope' does provide us with a list of 1034990075Sobrien the LABEL_DECL nodes for the function however, and we output DWARF info 1035090075Sobrien for those in decls_for_scope. Just within the `outer_scope' there will be 1035190075Sobrien a BLOCK node representing the function's outermost pair of curly braces, 1035290075Sobrien and any blocks used for the base and member initializers of a C++ 1035350397Sobrien constructor function. */ 1035450397Sobrien if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK) 1035550397Sobrien { 1035650397Sobrien current_function_has_inlines = 0; 1035750397Sobrien decls_for_scope (outer_scope, subr_die, 0); 1035850397Sobrien 1035950397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 1036050397Sobrien if (current_function_has_inlines) 1036150397Sobrien { 1036250397Sobrien add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1); 1036350397Sobrien if (! comp_unit_has_inlines) 1036450397Sobrien { 1036550397Sobrien add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1); 1036650397Sobrien comp_unit_has_inlines = 1; 1036750397Sobrien } 1036850397Sobrien } 1036950397Sobrien#endif 1037050397Sobrien } 1037150397Sobrien} 1037250397Sobrien 1037350397Sobrien/* Generate a DIE to represent a declared data object. */ 1037450397Sobrien 1037550397Sobrienstatic void 1037650397Sobriengen_variable_die (decl, context_die) 1037790075Sobrien tree decl; 1037890075Sobrien dw_die_ref context_die; 1037950397Sobrien{ 1038090075Sobrien tree origin = decl_ultimate_origin (decl); 1038190075Sobrien dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl); 1038250397Sobrien 1038350397Sobrien dw_die_ref old_die = lookup_decl_die (decl); 1038490075Sobrien int declaration = (DECL_EXTERNAL (decl) 1038590075Sobrien || class_scope_p (context_die)); 1038650397Sobrien 1038750397Sobrien if (origin != NULL) 1038850397Sobrien add_abstract_origin_attribute (var_die, origin); 1038990075Sobrien 1039050397Sobrien /* Loop unrolling can create multiple blocks that refer to the same 1039190075Sobrien static variable, so we must test for the DW_AT_declaration flag. 1039290075Sobrien 1039390075Sobrien ??? Loop unrolling/reorder_blocks should perhaps be rewritten to 1039450397Sobrien copy decls and set the DECL_ABSTRACT flag on them instead of 1039590075Sobrien sharing them. 1039690075Sobrien 1039790075Sobrien ??? Duplicated blocks have been rewritten to use .debug_ranges. */ 1039850397Sobrien else if (old_die && TREE_STATIC (decl) 1039950397Sobrien && get_AT_flag (old_die, DW_AT_declaration) == 1) 1040050397Sobrien { 1040190075Sobrien /* This is a definition of a C++ class level static. */ 1040250397Sobrien add_AT_die_ref (var_die, DW_AT_specification, old_die); 1040350397Sobrien if (DECL_NAME (decl)) 1040450397Sobrien { 1040590075Sobrien unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 1040650397Sobrien 1040750397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 1040850397Sobrien add_AT_unsigned (var_die, DW_AT_decl_file, file_index); 1040950397Sobrien 1041050397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 1041190075Sobrien != (unsigned) DECL_SOURCE_LINE (decl)) 1041250397Sobrien 1041350397Sobrien add_AT_unsigned (var_die, DW_AT_decl_line, 1041450397Sobrien DECL_SOURCE_LINE (decl)); 1041550397Sobrien } 1041650397Sobrien } 1041750397Sobrien else 1041850397Sobrien { 1041950397Sobrien add_name_and_src_coords_attributes (var_die, decl); 1042090075Sobrien add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl), 1042150397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1042250397Sobrien 1042350397Sobrien if (TREE_PUBLIC (decl)) 1042450397Sobrien add_AT_flag (var_die, DW_AT_external, 1); 1042550397Sobrien 1042650397Sobrien if (DECL_ARTIFICIAL (decl)) 1042750397Sobrien add_AT_flag (var_die, DW_AT_artificial, 1); 1042850397Sobrien 1042950397Sobrien if (TREE_PROTECTED (decl)) 1043050397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); 1043150397Sobrien else if (TREE_PRIVATE (decl)) 1043250397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); 1043350397Sobrien } 1043450397Sobrien 1043550397Sobrien if (declaration) 1043650397Sobrien add_AT_flag (var_die, DW_AT_declaration, 1); 1043790075Sobrien 1043890075Sobrien if (class_scope_p (context_die) || DECL_ABSTRACT (decl)) 1043950397Sobrien equate_decl_number_to_die (decl, var_die); 1044050397Sobrien 1044150397Sobrien if (! declaration && ! DECL_ABSTRACT (decl)) 1044250397Sobrien { 1044350397Sobrien add_location_or_const_value_attribute (var_die, decl); 1044450397Sobrien add_pubname (decl, var_die); 1044550397Sobrien } 1044690075Sobrien else 1044790075Sobrien tree_add_const_value_attribute (var_die, decl); 1044850397Sobrien} 1044950397Sobrien 1045050397Sobrien/* Generate a DIE to represent a label identifier. */ 1045150397Sobrien 1045250397Sobrienstatic void 1045350397Sobriengen_label_die (decl, context_die) 1045490075Sobrien tree decl; 1045590075Sobrien dw_die_ref context_die; 1045650397Sobrien{ 1045790075Sobrien tree origin = decl_ultimate_origin (decl); 1045890075Sobrien dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl); 1045990075Sobrien rtx insn; 1046050397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1046150397Sobrien 1046250397Sobrien if (origin != NULL) 1046350397Sobrien add_abstract_origin_attribute (lbl_die, origin); 1046450397Sobrien else 1046550397Sobrien add_name_and_src_coords_attributes (lbl_die, decl); 1046650397Sobrien 1046750397Sobrien if (DECL_ABSTRACT (decl)) 1046850397Sobrien equate_decl_number_to_die (decl, lbl_die); 1046950397Sobrien else 1047050397Sobrien { 1047150397Sobrien insn = DECL_RTL (decl); 1047252284Sobrien 1047352284Sobrien /* Deleted labels are programmer specified labels which have been 1047452284Sobrien eliminated because of various optimisations. We still emit them 1047552284Sobrien here so that it is possible to put breakpoints on them. */ 1047652284Sobrien if (GET_CODE (insn) == CODE_LABEL 1047752284Sobrien || ((GET_CODE (insn) == NOTE 1047852284Sobrien && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))) 1047950397Sobrien { 1048090075Sobrien /* When optimization is enabled (via -O) some parts of the compiler 1048190075Sobrien (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which 1048250397Sobrien represent source-level labels which were explicitly declared by 1048350397Sobrien the user. This really shouldn't be happening though, so catch 1048450397Sobrien it if it ever does happen. */ 1048550397Sobrien if (INSN_DELETED_P (insn)) 1048650397Sobrien abort (); 1048750397Sobrien 1048890075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn)); 1048950397Sobrien add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); 1049050397Sobrien } 1049150397Sobrien } 1049250397Sobrien} 1049350397Sobrien 1049450397Sobrien/* Generate a DIE for a lexical block. */ 1049550397Sobrien 1049650397Sobrienstatic void 1049750397Sobriengen_lexical_block_die (stmt, context_die, depth) 1049890075Sobrien tree stmt; 1049990075Sobrien dw_die_ref context_die; 1050050397Sobrien int depth; 1050150397Sobrien{ 1050290075Sobrien dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); 1050350397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1050450397Sobrien 1050550397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1050650397Sobrien { 1050790075Sobrien if (BLOCK_FRAGMENT_CHAIN (stmt)) 1050890075Sobrien { 1050990075Sobrien tree chain; 1051090075Sobrien 1051190075Sobrien add_AT_range_list (stmt_die, DW_AT_ranges, add_ranges (stmt)); 1051290075Sobrien 1051390075Sobrien chain = BLOCK_FRAGMENT_CHAIN (stmt); 1051490075Sobrien do 1051590075Sobrien { 1051690075Sobrien add_ranges (chain); 1051790075Sobrien chain = BLOCK_FRAGMENT_CHAIN (chain); 1051890075Sobrien } 1051990075Sobrien while (chain); 1052090075Sobrien add_ranges (NULL); 1052190075Sobrien } 1052290075Sobrien else 1052390075Sobrien { 1052490075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1052590075Sobrien BLOCK_NUMBER (stmt)); 1052690075Sobrien add_AT_lbl_id (stmt_die, DW_AT_low_pc, label); 1052790075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1052890075Sobrien BLOCK_NUMBER (stmt)); 1052990075Sobrien add_AT_lbl_id (stmt_die, DW_AT_high_pc, label); 1053090075Sobrien } 1053150397Sobrien } 1053250397Sobrien 1053350397Sobrien decls_for_scope (stmt, stmt_die, depth); 1053450397Sobrien} 1053550397Sobrien 1053650397Sobrien/* Generate a DIE for an inlined subprogram. */ 1053750397Sobrien 1053850397Sobrienstatic void 1053950397Sobriengen_inlined_subroutine_die (stmt, context_die, depth) 1054090075Sobrien tree stmt; 1054190075Sobrien dw_die_ref context_die; 1054250397Sobrien int depth; 1054350397Sobrien{ 1054450397Sobrien if (! BLOCK_ABSTRACT (stmt)) 1054550397Sobrien { 1054690075Sobrien dw_die_ref subr_die 1054790075Sobrien = new_die (DW_TAG_inlined_subroutine, context_die, stmt); 1054890075Sobrien tree decl = block_ultimate_origin (stmt); 1054950397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1055050397Sobrien 1055190075Sobrien /* Emit info for the abstract instance first, if we haven't yet. */ 1055290075Sobrien dwarf2out_abstract_function (decl); 1055390075Sobrien 1055450397Sobrien add_abstract_origin_attribute (subr_die, decl); 1055550397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 1055690075Sobrien BLOCK_NUMBER (stmt)); 1055750397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label); 1055890075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, 1055990075Sobrien BLOCK_NUMBER (stmt)); 1056050397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label); 1056150397Sobrien decls_for_scope (stmt, subr_die, depth); 1056250397Sobrien current_function_has_inlines = 1; 1056350397Sobrien } 1056450397Sobrien} 1056550397Sobrien 1056650397Sobrien/* Generate a DIE for a field in a record, or structure. */ 1056750397Sobrien 1056850397Sobrienstatic void 1056950397Sobriengen_field_die (decl, context_die) 1057090075Sobrien tree decl; 1057190075Sobrien dw_die_ref context_die; 1057250397Sobrien{ 1057390075Sobrien dw_die_ref decl_die = new_die (DW_TAG_member, context_die, decl); 1057450397Sobrien 1057550397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 1057650397Sobrien add_type_attribute (decl_die, member_declared_type (decl), 1057750397Sobrien TREE_READONLY (decl), TREE_THIS_VOLATILE (decl), 1057850397Sobrien context_die); 1057950397Sobrien 1058050397Sobrien if (DECL_BIT_FIELD_TYPE (decl)) 1058150397Sobrien { 1058250397Sobrien add_byte_size_attribute (decl_die, decl); 1058350397Sobrien add_bit_size_attribute (decl_die, decl); 1058450397Sobrien add_bit_offset_attribute (decl_die, decl); 1058550397Sobrien } 1058650397Sobrien 1058750397Sobrien if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE) 1058850397Sobrien add_data_member_location_attribute (decl_die, decl); 1058950397Sobrien 1059050397Sobrien if (DECL_ARTIFICIAL (decl)) 1059150397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 1059250397Sobrien 1059350397Sobrien if (TREE_PROTECTED (decl)) 1059450397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected); 1059550397Sobrien else if (TREE_PRIVATE (decl)) 1059650397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private); 1059750397Sobrien} 1059850397Sobrien 1059950397Sobrien#if 0 1060050397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1060150397Sobrien Use modified_type_die instead. 1060250397Sobrien We keep this code here just in case these types of DIEs may be needed to 1060350397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1060490075Sobrien 1060550397Sobrienstatic void 1060650397Sobriengen_pointer_type_die (type, context_die) 1060790075Sobrien tree type; 1060890075Sobrien dw_die_ref context_die; 1060950397Sobrien{ 1061090075Sobrien dw_die_ref ptr_die 1061190075Sobrien = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type); 1061250397Sobrien 1061350397Sobrien equate_type_number_to_die (type, ptr_die); 1061450397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1061550397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1061650397Sobrien} 1061750397Sobrien 1061850397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 1061950397Sobrien Use modified_type_die instead. 1062050397Sobrien We keep this code here just in case these types of DIEs may be needed to 1062150397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 1062290075Sobrien 1062350397Sobrienstatic void 1062450397Sobriengen_reference_type_die (type, context_die) 1062590075Sobrien tree type; 1062690075Sobrien dw_die_ref context_die; 1062750397Sobrien{ 1062890075Sobrien dw_die_ref ref_die 1062990075Sobrien = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type); 1063050397Sobrien 1063150397Sobrien equate_type_number_to_die (type, ref_die); 1063250397Sobrien add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die); 1063350397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 1063450397Sobrien} 1063550397Sobrien#endif 1063650397Sobrien 1063750397Sobrien/* Generate a DIE for a pointer to a member type. */ 1063890075Sobrien 1063950397Sobrienstatic void 1064050397Sobriengen_ptr_to_mbr_type_die (type, context_die) 1064190075Sobrien tree type; 1064290075Sobrien dw_die_ref context_die; 1064350397Sobrien{ 1064490075Sobrien dw_die_ref ptr_die 1064590075Sobrien = new_die (DW_TAG_ptr_to_member_type, 1064690075Sobrien scope_die_for (type, context_die), type); 1064750397Sobrien 1064850397Sobrien equate_type_number_to_die (type, ptr_die); 1064950397Sobrien add_AT_die_ref (ptr_die, DW_AT_containing_type, 1065050397Sobrien lookup_type_die (TYPE_OFFSET_BASETYPE (type))); 1065150397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 1065250397Sobrien} 1065350397Sobrien 1065450397Sobrien/* Generate the DIE for the compilation unit. */ 1065550397Sobrien 1065690075Sobrienstatic dw_die_ref 1065790075Sobriengen_compile_unit_die (filename) 1065890075Sobrien const char *filename; 1065950397Sobrien{ 1066090075Sobrien dw_die_ref die; 1066150397Sobrien char producer[250]; 1066290075Sobrien const char *wd = getpwd (); 1066390075Sobrien const char *language_string = lang_hooks.name; 1066490075Sobrien int language; 1066550397Sobrien 1066690075Sobrien die = new_die (DW_TAG_compile_unit, NULL, NULL); 1066790075Sobrien add_name_attribute (die, filename); 1066850397Sobrien 1066990075Sobrien if (wd != NULL && filename[0] != DIR_SEPARATOR) 1067090075Sobrien add_AT_string (die, DW_AT_comp_dir, wd); 1067150397Sobrien 1067250397Sobrien sprintf (producer, "%s %s", language_string, version_string); 1067350397Sobrien 1067450397Sobrien#ifdef MIPS_DEBUGGING_INFO 1067550397Sobrien /* The MIPS/SGI compilers place the 'cc' command line options in the producer 1067650397Sobrien string. The SGI debugger looks for -g, -g1, -g2, or -g3; if they do 1067750397Sobrien not appear in the producer string, the debugger reaches the conclusion 1067850397Sobrien that the object file is stripped and has no debugging information. 1067950397Sobrien To get the MIPS/SGI debugger to believe that there is debugging 1068050397Sobrien information in the object file, we add a -g to the producer string. */ 1068150397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1068250397Sobrien strcat (producer, " -g"); 1068350397Sobrien#endif 1068450397Sobrien 1068590075Sobrien add_AT_string (die, DW_AT_producer, producer); 1068650397Sobrien 1068750397Sobrien if (strcmp (language_string, "GNU C++") == 0) 1068890075Sobrien language = DW_LANG_C_plus_plus; 1068950397Sobrien else if (strcmp (language_string, "GNU Ada") == 0) 1069090075Sobrien language = DW_LANG_Ada83; 1069150397Sobrien else if (strcmp (language_string, "GNU F77") == 0) 1069290075Sobrien language = DW_LANG_Fortran77; 1069350397Sobrien else if (strcmp (language_string, "GNU Pascal") == 0) 1069490075Sobrien language = DW_LANG_Pascal83; 1069590075Sobrien else if (strcmp (language_string, "GNU Java") == 0) 1069690075Sobrien language = DW_LANG_Java; 1069750397Sobrien else if (flag_traditional) 1069890075Sobrien language = DW_LANG_C; 1069950397Sobrien else 1070090075Sobrien language = DW_LANG_C89; 1070150397Sobrien 1070290075Sobrien add_AT_unsigned (die, DW_AT_language, language); 1070390075Sobrien return die; 1070450397Sobrien} 1070550397Sobrien 1070650397Sobrien/* Generate a DIE for a string type. */ 1070750397Sobrien 1070850397Sobrienstatic void 1070950397Sobriengen_string_type_die (type, context_die) 1071090075Sobrien tree type; 1071190075Sobrien dw_die_ref context_die; 1071250397Sobrien{ 1071390075Sobrien dw_die_ref type_die 1071490075Sobrien = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type); 1071550397Sobrien 1071650397Sobrien equate_type_number_to_die (type, type_die); 1071750397Sobrien 1071890075Sobrien /* ??? Fudge the string length attribute for now. 1071990075Sobrien TODO: add string length info. */ 1072090075Sobrien#if 0 1072190075Sobrien string_length_attribute (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 1072290075Sobrien bound_representation (upper_bound, 0, 'u'); 1072390075Sobrien#endif 1072450397Sobrien} 1072550397Sobrien 1072650397Sobrien/* Generate the DIE for a base class. */ 1072750397Sobrien 1072850397Sobrienstatic void 1072950397Sobriengen_inheritance_die (binfo, context_die) 1073090075Sobrien tree binfo; 1073190075Sobrien dw_die_ref context_die; 1073250397Sobrien{ 1073390075Sobrien dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo); 1073450397Sobrien 1073550397Sobrien add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die); 1073650397Sobrien add_data_member_location_attribute (die, binfo); 1073750397Sobrien 1073850397Sobrien if (TREE_VIA_VIRTUAL (binfo)) 1073950397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 1074090075Sobrien 1074150397Sobrien if (TREE_VIA_PUBLIC (binfo)) 1074250397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); 1074350397Sobrien else if (TREE_VIA_PROTECTED (binfo)) 1074450397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); 1074550397Sobrien} 1074650397Sobrien 1074750397Sobrien/* Generate a DIE for a class member. */ 1074850397Sobrien 1074950397Sobrienstatic void 1075050397Sobriengen_member_die (type, context_die) 1075190075Sobrien tree type; 1075290075Sobrien dw_die_ref context_die; 1075350397Sobrien{ 1075490075Sobrien tree member; 1075590075Sobrien dw_die_ref child; 1075650397Sobrien 1075750397Sobrien /* If this is not an incomplete type, output descriptions of each of its 1075850397Sobrien members. Note that as we output the DIEs necessary to represent the 1075950397Sobrien members of this record or union type, we will also be trying to output 1076050397Sobrien DIEs to represent the *types* of those members. However the `type' 1076190075Sobrien function (above) will specifically avoid generating type DIEs for member 1076290075Sobrien types *within* the list of member DIEs for this (containing) type except 1076350397Sobrien for those types (of members) which are explicitly marked as also being 1076450397Sobrien members of this (containing) type themselves. The g++ front- end can 1076590075Sobrien force any given type to be treated as a member of some other (containing) 1076690075Sobrien type by setting the TYPE_CONTEXT of the given (member) type to point to 1076790075Sobrien the TREE node representing the appropriate (containing) type. */ 1076850397Sobrien 1076950397Sobrien /* First output info about the base classes. */ 1077050397Sobrien if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) 1077150397Sobrien { 1077290075Sobrien tree bases = TYPE_BINFO_BASETYPES (type); 1077390075Sobrien int n_bases = TREE_VEC_LENGTH (bases); 1077490075Sobrien int i; 1077550397Sobrien 1077650397Sobrien for (i = 0; i < n_bases; i++) 1077750397Sobrien gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die); 1077850397Sobrien } 1077950397Sobrien 1078050397Sobrien /* Now output info about the data members and type members. */ 1078150397Sobrien for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) 1078290075Sobrien { 1078390075Sobrien /* If we thought we were generating minimal debug info for TYPE 1078490075Sobrien and then changed our minds, some of the member declarations 1078590075Sobrien may have already been defined. Don't define them again, but 1078690075Sobrien do put them in the right order. */ 1078750397Sobrien 1078890075Sobrien child = lookup_decl_die (member); 1078990075Sobrien if (child) 1079090075Sobrien splice_child_die (context_die, child); 1079190075Sobrien else 1079290075Sobrien gen_decl_die (member, context_die); 1079390075Sobrien } 1079490075Sobrien 1079550397Sobrien /* Now output info about the function members (if any). */ 1079650397Sobrien for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member)) 1079790075Sobrien { 1079890075Sobrien /* Don't include clones in the member list. */ 1079990075Sobrien if (DECL_ABSTRACT_ORIGIN (member)) 1080090075Sobrien continue; 1080190075Sobrien 1080290075Sobrien child = lookup_decl_die (member); 1080390075Sobrien if (child) 1080490075Sobrien splice_child_die (context_die, child); 1080590075Sobrien else 1080690075Sobrien gen_decl_die (member, context_die); 1080790075Sobrien } 1080850397Sobrien} 1080950397Sobrien 1081090075Sobrien/* Generate a DIE for a structure or union type. If TYPE_DECL_SUPPRESS_DEBUG 1081190075Sobrien is set, we pretend that the type was never defined, so we only get the 1081290075Sobrien member DIEs needed by later specification DIEs. */ 1081350397Sobrien 1081450397Sobrienstatic void 1081550397Sobriengen_struct_or_union_type_die (type, context_die) 1081690075Sobrien tree type; 1081790075Sobrien dw_die_ref context_die; 1081850397Sobrien{ 1081990075Sobrien dw_die_ref type_die = lookup_type_die (type); 1082090075Sobrien dw_die_ref scope_die = 0; 1082190075Sobrien int nested = 0; 1082290075Sobrien int complete = (TYPE_SIZE (type) 1082390075Sobrien && (! TYPE_STUB_DECL (type) 1082490075Sobrien || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)))); 1082550397Sobrien 1082690075Sobrien if (type_die && ! complete) 1082750397Sobrien return; 1082850397Sobrien 1082950397Sobrien if (TYPE_CONTEXT (type) != NULL_TREE 1083052284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))) 1083150397Sobrien nested = 1; 1083250397Sobrien 1083350397Sobrien scope_die = scope_die_for (type, context_die); 1083450397Sobrien 1083550397Sobrien if (! type_die || (nested && scope_die == comp_unit_die)) 1083650397Sobrien /* First occurrence of type or toplevel definition of nested class. */ 1083750397Sobrien { 1083890075Sobrien dw_die_ref old_die = type_die; 1083950397Sobrien 1084050397Sobrien type_die = new_die (TREE_CODE (type) == RECORD_TYPE 1084150397Sobrien ? DW_TAG_structure_type : DW_TAG_union_type, 1084290075Sobrien scope_die, type); 1084350397Sobrien equate_type_number_to_die (type, type_die); 1084450397Sobrien if (old_die) 1084550397Sobrien add_AT_die_ref (type_die, DW_AT_specification, old_die); 1084690075Sobrien else 1084790075Sobrien add_name_attribute (type_die, type_tag (type)); 1084850397Sobrien } 1084950397Sobrien else 1085050397Sobrien remove_AT (type_die, DW_AT_declaration); 1085150397Sobrien 1085250397Sobrien /* If this type has been completed, then give it a byte_size attribute and 1085350397Sobrien then give a list of members. */ 1085490075Sobrien if (complete) 1085550397Sobrien { 1085690075Sobrien /* Prevent infinite recursion in cases where the type of some member of 1085750397Sobrien this type is expressed in terms of this type itself. */ 1085850397Sobrien TREE_ASM_WRITTEN (type) = 1; 1085950397Sobrien add_byte_size_attribute (type_die, type); 1086050397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 1086150397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 1086250397Sobrien 1086350397Sobrien /* If the first reference to this type was as the return type of an 1086450397Sobrien inline function, then it may not have a parent. Fix this now. */ 1086550397Sobrien if (type_die->die_parent == NULL) 1086650397Sobrien add_child_die (scope_die, type_die); 1086750397Sobrien 1086850397Sobrien push_decl_scope (type); 1086950397Sobrien gen_member_die (type, type_die); 1087050397Sobrien pop_decl_scope (); 1087150397Sobrien 1087250397Sobrien /* GNU extension: Record what type our vtable lives in. */ 1087350397Sobrien if (TYPE_VFIELD (type)) 1087450397Sobrien { 1087550397Sobrien tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type)); 1087650397Sobrien 1087750397Sobrien gen_type_die (vtype, context_die); 1087850397Sobrien add_AT_die_ref (type_die, DW_AT_containing_type, 1087950397Sobrien lookup_type_die (vtype)); 1088050397Sobrien } 1088150397Sobrien } 1088250397Sobrien else 1088352284Sobrien { 1088452284Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 1088552284Sobrien 1088690075Sobrien /* We don't need to do this for function-local types. */ 1088790075Sobrien if (TYPE_STUB_DECL (type) 1088890075Sobrien && ! decl_function_context (TYPE_STUB_DECL (type))) 1088990075Sobrien VARRAY_PUSH_TREE (incomplete_types, type); 1089052284Sobrien } 1089150397Sobrien} 1089250397Sobrien 1089350397Sobrien/* Generate a DIE for a subroutine _type_. */ 1089450397Sobrien 1089550397Sobrienstatic void 1089650397Sobriengen_subroutine_type_die (type, context_die) 1089790075Sobrien tree type; 1089890075Sobrien dw_die_ref context_die; 1089950397Sobrien{ 1090090075Sobrien tree return_type = TREE_TYPE (type); 1090190075Sobrien dw_die_ref subr_die 1090290075Sobrien = new_die (DW_TAG_subroutine_type, 1090390075Sobrien scope_die_for (type, context_die), type); 1090450397Sobrien 1090550397Sobrien equate_type_number_to_die (type, subr_die); 1090650397Sobrien add_prototyped_attribute (subr_die, type); 1090750397Sobrien add_type_attribute (subr_die, return_type, 0, 0, context_die); 1090850397Sobrien gen_formal_types_die (type, subr_die); 1090950397Sobrien} 1091050397Sobrien 1091150397Sobrien/* Generate a DIE for a type definition */ 1091250397Sobrien 1091350397Sobrienstatic void 1091450397Sobriengen_typedef_die (decl, context_die) 1091590075Sobrien tree decl; 1091690075Sobrien dw_die_ref context_die; 1091750397Sobrien{ 1091890075Sobrien dw_die_ref type_die; 1091990075Sobrien tree origin; 1092050397Sobrien 1092150397Sobrien if (TREE_ASM_WRITTEN (decl)) 1092250397Sobrien return; 1092390075Sobrien 1092450397Sobrien TREE_ASM_WRITTEN (decl) = 1; 1092590075Sobrien type_die = new_die (DW_TAG_typedef, context_die, decl); 1092650397Sobrien origin = decl_ultimate_origin (decl); 1092750397Sobrien if (origin != NULL) 1092850397Sobrien add_abstract_origin_attribute (type_die, origin); 1092950397Sobrien else 1093050397Sobrien { 1093190075Sobrien tree type; 1093290075Sobrien 1093350397Sobrien add_name_and_src_coords_attributes (type_die, decl); 1093450397Sobrien if (DECL_ORIGINAL_TYPE (decl)) 1093550397Sobrien { 1093650397Sobrien type = DECL_ORIGINAL_TYPE (decl); 1093790075Sobrien 1093890075Sobrien if (type == TREE_TYPE (decl)) 1093990075Sobrien abort (); 1094090075Sobrien else 1094190075Sobrien equate_type_number_to_die (TREE_TYPE (decl), type_die); 1094250397Sobrien } 1094350397Sobrien else 1094450397Sobrien type = TREE_TYPE (decl); 1094590075Sobrien 1094650397Sobrien add_type_attribute (type_die, type, TREE_READONLY (decl), 1094750397Sobrien TREE_THIS_VOLATILE (decl), context_die); 1094850397Sobrien } 1094950397Sobrien 1095050397Sobrien if (DECL_ABSTRACT (decl)) 1095150397Sobrien equate_decl_number_to_die (decl, type_die); 1095250397Sobrien} 1095350397Sobrien 1095450397Sobrien/* Generate a type description DIE. */ 1095550397Sobrien 1095650397Sobrienstatic void 1095750397Sobriengen_type_die (type, context_die) 1095890075Sobrien tree type; 1095990075Sobrien dw_die_ref context_die; 1096050397Sobrien{ 1096190075Sobrien int need_pop; 1096290075Sobrien 1096350397Sobrien if (type == NULL_TREE || type == error_mark_node) 1096450397Sobrien return; 1096550397Sobrien 1096650397Sobrien /* We are going to output a DIE to represent the unqualified version of 1096750397Sobrien this type (i.e. without any const or volatile qualifiers) so get the 1096850397Sobrien main variant (i.e. the unqualified version) of this type now. */ 1096950397Sobrien type = type_main_variant (type); 1097050397Sobrien 1097150397Sobrien if (TREE_ASM_WRITTEN (type)) 1097250397Sobrien return; 1097350397Sobrien 1097450397Sobrien if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 1097550397Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 1097690075Sobrien { 1097750397Sobrien TREE_ASM_WRITTEN (type) = 1; 1097850397Sobrien gen_decl_die (TYPE_NAME (type), context_die); 1097950397Sobrien return; 1098050397Sobrien } 1098150397Sobrien 1098250397Sobrien switch (TREE_CODE (type)) 1098350397Sobrien { 1098450397Sobrien case ERROR_MARK: 1098550397Sobrien break; 1098650397Sobrien 1098750397Sobrien case POINTER_TYPE: 1098850397Sobrien case REFERENCE_TYPE: 1098950397Sobrien /* We must set TREE_ASM_WRITTEN in case this is a recursive type. This 1099050397Sobrien ensures that the gen_type_die recursion will terminate even if the 1099150397Sobrien type is recursive. Recursive types are possible in Ada. */ 1099250397Sobrien /* ??? We could perhaps do this for all types before the switch 1099350397Sobrien statement. */ 1099450397Sobrien TREE_ASM_WRITTEN (type) = 1; 1099550397Sobrien 1099650397Sobrien /* For these types, all that is required is that we output a DIE (or a 1099750397Sobrien set of DIEs) to represent the "basis" type. */ 1099850397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1099950397Sobrien break; 1100050397Sobrien 1100150397Sobrien case OFFSET_TYPE: 1100290075Sobrien /* This code is used for C++ pointer-to-data-member types. 1100350397Sobrien Output a description of the relevant class type. */ 1100450397Sobrien gen_type_die (TYPE_OFFSET_BASETYPE (type), context_die); 1100550397Sobrien 1100650397Sobrien /* Output a description of the type of the object pointed to. */ 1100750397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1100850397Sobrien 1100950397Sobrien /* Now output a DIE to represent this pointer-to-data-member type 1101050397Sobrien itself. */ 1101150397Sobrien gen_ptr_to_mbr_type_die (type, context_die); 1101250397Sobrien break; 1101350397Sobrien 1101450397Sobrien case SET_TYPE: 1101550397Sobrien gen_type_die (TYPE_DOMAIN (type), context_die); 1101650397Sobrien gen_set_type_die (type, context_die); 1101750397Sobrien break; 1101850397Sobrien 1101950397Sobrien case FILE_TYPE: 1102050397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1102150397Sobrien abort (); /* No way to represent these in Dwarf yet! */ 1102250397Sobrien break; 1102350397Sobrien 1102450397Sobrien case FUNCTION_TYPE: 1102550397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1102650397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1102750397Sobrien gen_subroutine_type_die (type, context_die); 1102850397Sobrien break; 1102950397Sobrien 1103050397Sobrien case METHOD_TYPE: 1103150397Sobrien /* Force out return type (in case it wasn't forced out already). */ 1103250397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1103350397Sobrien gen_subroutine_type_die (type, context_die); 1103450397Sobrien break; 1103550397Sobrien 1103650397Sobrien case ARRAY_TYPE: 1103750397Sobrien if (TYPE_STRING_FLAG (type) && TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) 1103850397Sobrien { 1103950397Sobrien gen_type_die (TREE_TYPE (type), context_die); 1104050397Sobrien gen_string_type_die (type, context_die); 1104150397Sobrien } 1104250397Sobrien else 1104350397Sobrien gen_array_type_die (type, context_die); 1104450397Sobrien break; 1104550397Sobrien 1104690075Sobrien case VECTOR_TYPE: 1104790075Sobrien gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die); 1104890075Sobrien break; 1104990075Sobrien 1105050397Sobrien case ENUMERAL_TYPE: 1105150397Sobrien case RECORD_TYPE: 1105250397Sobrien case UNION_TYPE: 1105350397Sobrien case QUAL_UNION_TYPE: 1105490075Sobrien /* If this is a nested type whose containing class hasn't been written 1105590075Sobrien out yet, writing it out will cover this one, too. This does not apply 1105690075Sobrien to instantiations of member class templates; they need to be added to 1105790075Sobrien the containing class as they are generated. FIXME: This hurts the 1105890075Sobrien idea of combining type decls from multiple TUs, since we can't predict 1105990075Sobrien what set of template instantiations we'll get. */ 1106050397Sobrien if (TYPE_CONTEXT (type) 1106152284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) 1106250397Sobrien && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 1106350397Sobrien { 1106450397Sobrien gen_type_die (TYPE_CONTEXT (type), context_die); 1106550397Sobrien 1106690075Sobrien if (TREE_ASM_WRITTEN (type)) 1106750397Sobrien return; 1106850397Sobrien 1106950397Sobrien /* If that failed, attach ourselves to the stub. */ 1107050397Sobrien push_decl_scope (TYPE_CONTEXT (type)); 1107150397Sobrien context_die = lookup_type_die (TYPE_CONTEXT (type)); 1107290075Sobrien need_pop = 1; 1107350397Sobrien } 1107490075Sobrien else 1107590075Sobrien need_pop = 0; 1107650397Sobrien 1107750397Sobrien if (TREE_CODE (type) == ENUMERAL_TYPE) 1107850397Sobrien gen_enumeration_type_die (type, context_die); 1107950397Sobrien else 1108050397Sobrien gen_struct_or_union_type_die (type, context_die); 1108150397Sobrien 1108290075Sobrien if (need_pop) 1108350397Sobrien pop_decl_scope (); 1108450397Sobrien 1108550397Sobrien /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix 1108650397Sobrien it up if it is ever completed. gen_*_type_die will set it for us 1108750397Sobrien when appropriate. */ 1108850397Sobrien return; 1108950397Sobrien 1109050397Sobrien case VOID_TYPE: 1109150397Sobrien case INTEGER_TYPE: 1109250397Sobrien case REAL_TYPE: 1109350397Sobrien case COMPLEX_TYPE: 1109450397Sobrien case BOOLEAN_TYPE: 1109550397Sobrien case CHAR_TYPE: 1109650397Sobrien /* No DIEs needed for fundamental types. */ 1109750397Sobrien break; 1109850397Sobrien 1109950397Sobrien case LANG_TYPE: 1110050397Sobrien /* No Dwarf representation currently defined. */ 1110150397Sobrien break; 1110250397Sobrien 1110350397Sobrien default: 1110450397Sobrien abort (); 1110550397Sobrien } 1110650397Sobrien 1110750397Sobrien TREE_ASM_WRITTEN (type) = 1; 1110850397Sobrien} 1110950397Sobrien 1111050397Sobrien/* Generate a DIE for a tagged type instantiation. */ 1111150397Sobrien 1111250397Sobrienstatic void 1111350397Sobriengen_tagged_type_instantiation_die (type, context_die) 1111490075Sobrien tree type; 1111590075Sobrien dw_die_ref context_die; 1111650397Sobrien{ 1111750397Sobrien if (type == NULL_TREE || type == error_mark_node) 1111850397Sobrien return; 1111950397Sobrien 1112050397Sobrien /* We are going to output a DIE to represent the unqualified version of 1112150397Sobrien this type (i.e. without any const or volatile qualifiers) so make sure 1112250397Sobrien that we have the main variant (i.e. the unqualified version) of this 1112350397Sobrien type now. */ 1112490075Sobrien if (type != type_main_variant (type)) 1112550397Sobrien abort (); 1112650397Sobrien 1112790075Sobrien /* Do not check TREE_ASM_WRITTEN (type) as it may not be set if this is 1112890075Sobrien an instance of an unresolved type. */ 1112990075Sobrien 1113050397Sobrien switch (TREE_CODE (type)) 1113150397Sobrien { 1113250397Sobrien case ERROR_MARK: 1113350397Sobrien break; 1113450397Sobrien 1113550397Sobrien case ENUMERAL_TYPE: 1113650397Sobrien gen_inlined_enumeration_type_die (type, context_die); 1113750397Sobrien break; 1113850397Sobrien 1113950397Sobrien case RECORD_TYPE: 1114050397Sobrien gen_inlined_structure_type_die (type, context_die); 1114150397Sobrien break; 1114250397Sobrien 1114350397Sobrien case UNION_TYPE: 1114450397Sobrien case QUAL_UNION_TYPE: 1114550397Sobrien gen_inlined_union_type_die (type, context_die); 1114650397Sobrien break; 1114750397Sobrien 1114850397Sobrien default: 1114950397Sobrien abort (); 1115050397Sobrien } 1115150397Sobrien} 1115250397Sobrien 1115350397Sobrien/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the 1115450397Sobrien things which are local to the given block. */ 1115550397Sobrien 1115650397Sobrienstatic void 1115750397Sobriengen_block_die (stmt, context_die, depth) 1115890075Sobrien tree stmt; 1115990075Sobrien dw_die_ref context_die; 1116050397Sobrien int depth; 1116150397Sobrien{ 1116290075Sobrien int must_output_die = 0; 1116390075Sobrien tree origin; 1116490075Sobrien tree decl; 1116590075Sobrien enum tree_code origin_code; 1116650397Sobrien 1116750397Sobrien /* Ignore blocks never really used to make RTL. */ 1116890075Sobrien if (stmt == NULL_TREE || !TREE_USED (stmt) 1116990075Sobrien || (!TREE_ASM_WRITTEN (stmt) && !BLOCK_ABSTRACT (stmt))) 1117050397Sobrien return; 1117150397Sobrien 1117290075Sobrien /* If the block is one fragment of a non-contiguous block, do not 1117390075Sobrien process the variables, since they will have been done by the 1117490075Sobrien origin block. Do process subblocks. */ 1117590075Sobrien if (BLOCK_FRAGMENT_ORIGIN (stmt)) 1117690075Sobrien { 1117790075Sobrien tree sub; 1117890075Sobrien 1117990075Sobrien for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub)) 1118090075Sobrien gen_block_die (sub, context_die, depth + 1); 1118190075Sobrien 1118290075Sobrien return; 1118390075Sobrien } 1118490075Sobrien 1118550397Sobrien /* Determine the "ultimate origin" of this block. This block may be an 1118650397Sobrien inlined instance of an inlined instance of inline function, so we have 1118750397Sobrien to trace all of the way back through the origin chain to find out what 1118850397Sobrien sort of node actually served as the original seed for the creation of 1118950397Sobrien the current block. */ 1119050397Sobrien origin = block_ultimate_origin (stmt); 1119150397Sobrien origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK; 1119250397Sobrien 1119350397Sobrien /* Determine if we need to output any Dwarf DIEs at all to represent this 1119450397Sobrien block. */ 1119550397Sobrien if (origin_code == FUNCTION_DECL) 1119650397Sobrien /* The outer scopes for inlinings *must* always be represented. We 1119750397Sobrien generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */ 1119850397Sobrien must_output_die = 1; 1119950397Sobrien else 1120050397Sobrien { 1120150397Sobrien /* In the case where the current block represents an inlining of the 1120290075Sobrien "body block" of an inline function, we must *NOT* output any DIE for 1120390075Sobrien this block because we have already output a DIE to represent the whole 1120490075Sobrien inlined function scope and the "body block" of any function doesn't 1120590075Sobrien really represent a different scope according to ANSI C rules. So we 1120690075Sobrien check here to make sure that this block does not represent a "body 1120790075Sobrien block inlining" before trying to set the MUST_OUTPUT_DIE flag. */ 1120850397Sobrien if (! is_body_block (origin ? origin : stmt)) 1120950397Sobrien { 1121050397Sobrien /* Determine if this block directly contains any "significant" 1121150397Sobrien local declarations which we will need to output DIEs for. */ 1121250397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 1121350397Sobrien /* We are not in terse mode so *any* local declaration counts 1121450397Sobrien as being a "significant" one. */ 1121550397Sobrien must_output_die = (BLOCK_VARS (stmt) != NULL); 1121650397Sobrien else 1121750397Sobrien /* We are in terse mode, so only local (nested) function 1121850397Sobrien definitions count as "significant" local declarations. */ 1121950397Sobrien for (decl = BLOCK_VARS (stmt); 1122050397Sobrien decl != NULL; decl = TREE_CHAIN (decl)) 1122150397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1122250397Sobrien && DECL_INITIAL (decl)) 1122350397Sobrien { 1122450397Sobrien must_output_die = 1; 1122550397Sobrien break; 1122650397Sobrien } 1122750397Sobrien } 1122850397Sobrien } 1122950397Sobrien 1123050397Sobrien /* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block 1123150397Sobrien DIE for any block which contains no significant local declarations at 1123250397Sobrien all. Rather, in such cases we just call `decls_for_scope' so that any 1123350397Sobrien needed Dwarf info for any sub-blocks will get properly generated. Note 1123450397Sobrien that in terse mode, our definition of what constitutes a "significant" 1123550397Sobrien local declaration gets restricted to include only inlined function 1123650397Sobrien instances and local (nested) function definitions. */ 1123750397Sobrien if (must_output_die) 1123850397Sobrien { 1123950397Sobrien if (origin_code == FUNCTION_DECL) 1124050397Sobrien gen_inlined_subroutine_die (stmt, context_die, depth); 1124150397Sobrien else 1124250397Sobrien gen_lexical_block_die (stmt, context_die, depth); 1124350397Sobrien } 1124450397Sobrien else 1124550397Sobrien decls_for_scope (stmt, context_die, depth); 1124650397Sobrien} 1124750397Sobrien 1124850397Sobrien/* Generate all of the decls declared within a given scope and (recursively) 1124950397Sobrien all of its sub-blocks. */ 1125050397Sobrien 1125150397Sobrienstatic void 1125250397Sobriendecls_for_scope (stmt, context_die, depth) 1125390075Sobrien tree stmt; 1125490075Sobrien dw_die_ref context_die; 1125550397Sobrien int depth; 1125650397Sobrien{ 1125790075Sobrien tree decl; 1125890075Sobrien tree subblocks; 1125950397Sobrien 1126050397Sobrien /* Ignore blocks never really used to make RTL. */ 1126150397Sobrien if (stmt == NULL_TREE || ! TREE_USED (stmt)) 1126250397Sobrien return; 1126350397Sobrien 1126450397Sobrien /* Output the DIEs to represent all of the data objects and typedefs 1126550397Sobrien declared directly within this block but not within any nested 1126650397Sobrien sub-blocks. Also, nested function and tag DIEs have been 1126750397Sobrien generated with a parent of NULL; fix that up now. */ 1126890075Sobrien for (decl = BLOCK_VARS (stmt); decl != NULL; decl = TREE_CHAIN (decl)) 1126950397Sobrien { 1127090075Sobrien dw_die_ref die; 1127150397Sobrien 1127250397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 1127350397Sobrien die = lookup_decl_die (decl); 1127450397Sobrien else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)) 1127550397Sobrien die = lookup_type_die (TREE_TYPE (decl)); 1127650397Sobrien else 1127750397Sobrien die = NULL; 1127850397Sobrien 1127950397Sobrien if (die != NULL && die->die_parent == NULL) 1128050397Sobrien add_child_die (context_die, die); 1128150397Sobrien else 1128250397Sobrien gen_decl_die (decl, context_die); 1128350397Sobrien } 1128450397Sobrien 1128550397Sobrien /* Output the DIEs to represent all sub-blocks (and the items declared 1128650397Sobrien therein) of this block. */ 1128750397Sobrien for (subblocks = BLOCK_SUBBLOCKS (stmt); 1128850397Sobrien subblocks != NULL; 1128950397Sobrien subblocks = BLOCK_CHAIN (subblocks)) 1129050397Sobrien gen_block_die (subblocks, context_die, depth + 1); 1129150397Sobrien} 1129250397Sobrien 1129350397Sobrien/* Is this a typedef we can avoid emitting? */ 1129450397Sobrien 1129550397Sobrienstatic inline int 1129650397Sobrienis_redundant_typedef (decl) 1129790075Sobrien tree decl; 1129850397Sobrien{ 1129950397Sobrien if (TYPE_DECL_IS_STUB (decl)) 1130050397Sobrien return 1; 1130150397Sobrien 1130250397Sobrien if (DECL_ARTIFICIAL (decl) 1130350397Sobrien && DECL_CONTEXT (decl) 1130450397Sobrien && is_tagged_type (DECL_CONTEXT (decl)) 1130550397Sobrien && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL 1130650397Sobrien && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))) 1130750397Sobrien /* Also ignore the artificial member typedef for the class name. */ 1130850397Sobrien return 1; 1130950397Sobrien 1131050397Sobrien return 0; 1131150397Sobrien} 1131250397Sobrien 1131350397Sobrien/* Generate Dwarf debug information for a decl described by DECL. */ 1131450397Sobrien 1131550397Sobrienstatic void 1131650397Sobriengen_decl_die (decl, context_die) 1131790075Sobrien tree decl; 1131890075Sobrien dw_die_ref context_die; 1131950397Sobrien{ 1132090075Sobrien tree origin; 1132150397Sobrien 1132290075Sobrien if (DECL_P (decl) && DECL_IGNORED_P (decl)) 1132350397Sobrien return; 1132450397Sobrien 1132550397Sobrien switch (TREE_CODE (decl)) 1132650397Sobrien { 1132790075Sobrien case ERROR_MARK: 1132890075Sobrien break; 1132990075Sobrien 1133050397Sobrien case CONST_DECL: 1133190075Sobrien /* The individual enumerators of an enum type get output when we output 1133250397Sobrien the Dwarf representation of the relevant enum type itself. */ 1133350397Sobrien break; 1133450397Sobrien 1133550397Sobrien case FUNCTION_DECL: 1133650397Sobrien /* Don't output any DIEs to represent mere function declarations, 1133750397Sobrien unless they are class members or explicit block externs. */ 1133850397Sobrien if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE 1133990075Sobrien && (current_function_decl == NULL_TREE || DECL_ARTIFICIAL (decl))) 1134050397Sobrien break; 1134150397Sobrien 1134290075Sobrien /* If we're emitting a clone, emit info for the abstract instance. */ 1134390075Sobrien if (DECL_ORIGIN (decl) != decl) 1134490075Sobrien dwarf2out_abstract_function (DECL_ABSTRACT_ORIGIN (decl)); 1134590075Sobrien 1134690075Sobrien /* If we're emitting an out-of-line copy of an inline function, 1134790075Sobrien emit info for the abstract instance and set up to refer to it. */ 1134890075Sobrien else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl) 1134990075Sobrien && ! class_scope_p (context_die) 1135090075Sobrien /* dwarf2out_abstract_function won't emit a die if this is just 1135190075Sobrien a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in 1135290075Sobrien that case, because that works only if we have a die. */ 1135390075Sobrien && DECL_INITIAL (decl) != NULL_TREE) 1135450397Sobrien { 1135590075Sobrien dwarf2out_abstract_function (decl); 1135690075Sobrien set_decl_origin_self (decl); 1135790075Sobrien } 1135890075Sobrien 1135990075Sobrien /* Otherwise we're emitting the primary DIE for this decl. */ 1136090075Sobrien else if (debug_info_level > DINFO_LEVEL_TERSE) 1136190075Sobrien { 1136250397Sobrien /* Before we describe the FUNCTION_DECL itself, make sure that we 1136350397Sobrien have described its return type. */ 1136450397Sobrien gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die); 1136550397Sobrien 1136690075Sobrien /* And its virtual context. */ 1136790075Sobrien if (DECL_VINDEX (decl) != NULL_TREE) 1136890075Sobrien gen_type_die (DECL_CONTEXT (decl), context_die); 1136990075Sobrien 1137050397Sobrien /* And its containing type. */ 1137150397Sobrien origin = decl_class_context (decl); 1137250397Sobrien if (origin != NULL_TREE) 1137390075Sobrien gen_type_die_for_member (origin, decl, context_die); 1137450397Sobrien } 1137550397Sobrien 1137650397Sobrien /* Now output a DIE to represent the function itself. */ 1137750397Sobrien gen_subprogram_die (decl, context_die); 1137850397Sobrien break; 1137950397Sobrien 1138050397Sobrien case TYPE_DECL: 1138150397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1138250397Sobrien actual typedefs. */ 1138350397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1138450397Sobrien break; 1138550397Sobrien 1138690075Sobrien /* In the special case of a TYPE_DECL node representing the declaration 1138790075Sobrien of some type tag, if the given TYPE_DECL is marked as having been 1138890075Sobrien instantiated from some other (original) TYPE_DECL node (e.g. one which 1138990075Sobrien was generated within the original definition of an inline function) we 1139090075Sobrien have to generate a special (abbreviated) DW_TAG_structure_type, 1139190075Sobrien DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */ 1139290075Sobrien if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE) 1139350397Sobrien { 1139450397Sobrien gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die); 1139550397Sobrien break; 1139650397Sobrien } 1139750397Sobrien 1139850397Sobrien if (is_redundant_typedef (decl)) 1139950397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1140050397Sobrien else 1140150397Sobrien /* Output a DIE to represent the typedef itself. */ 1140250397Sobrien gen_typedef_die (decl, context_die); 1140350397Sobrien break; 1140450397Sobrien 1140550397Sobrien case LABEL_DECL: 1140650397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1140750397Sobrien gen_label_die (decl, context_die); 1140850397Sobrien break; 1140950397Sobrien 1141050397Sobrien case VAR_DECL: 1141150397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1141250397Sobrien variable declarations or definitions. */ 1141350397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1141450397Sobrien break; 1141550397Sobrien 1141650397Sobrien /* Output any DIEs that are needed to specify the type of this data 1141750397Sobrien object. */ 1141850397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1141950397Sobrien 1142050397Sobrien /* And its containing type. */ 1142150397Sobrien origin = decl_class_context (decl); 1142250397Sobrien if (origin != NULL_TREE) 1142390075Sobrien gen_type_die_for_member (origin, decl, context_die); 1142450397Sobrien 1142550397Sobrien /* Now output the DIE to represent the data object itself. This gets 1142650397Sobrien complicated because of the possibility that the VAR_DECL really 1142750397Sobrien represents an inlined instance of a formal parameter for an inline 1142850397Sobrien function. */ 1142950397Sobrien origin = decl_ultimate_origin (decl); 1143050397Sobrien if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) 1143150397Sobrien gen_formal_parameter_die (decl, context_die); 1143250397Sobrien else 1143350397Sobrien gen_variable_die (decl, context_die); 1143450397Sobrien break; 1143550397Sobrien 1143650397Sobrien case FIELD_DECL: 1143790075Sobrien /* Ignore the nameless fields that are used to skip bits but handle C++ 1143890075Sobrien anonymous unions. */ 1143950397Sobrien if (DECL_NAME (decl) != NULL_TREE 1144050397Sobrien || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE) 1144150397Sobrien { 1144250397Sobrien gen_type_die (member_declared_type (decl), context_die); 1144350397Sobrien gen_field_die (decl, context_die); 1144450397Sobrien } 1144550397Sobrien break; 1144650397Sobrien 1144750397Sobrien case PARM_DECL: 1144850397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 1144950397Sobrien gen_formal_parameter_die (decl, context_die); 1145050397Sobrien break; 1145150397Sobrien 1145290075Sobrien case NAMESPACE_DECL: 1145390075Sobrien /* Ignore for now. */ 1145490075Sobrien break; 1145590075Sobrien 1145650397Sobrien default: 1145750397Sobrien abort (); 1145850397Sobrien } 1145950397Sobrien} 1146090075Sobrien 1146190075Sobrienstatic void 1146290075Sobrienmark_limbo_die_list (ptr) 1146390075Sobrien void *ptr ATTRIBUTE_UNUSED; 1146490075Sobrien{ 1146590075Sobrien limbo_die_node *node; 1146690075Sobrien for (node = limbo_die_list; node ; node = node->next) 1146790075Sobrien ggc_mark_tree (node->created_for); 1146890075Sobrien} 1146950397Sobrien 1147090075Sobrien/* Add Ada "use" clause information for SGI Workshop debugger. */ 1147150397Sobrien 1147250397Sobrienvoid 1147390075Sobriendwarf2out_add_library_unit_info (filename, context_list) 1147490075Sobrien const char *filename; 1147590075Sobrien const char *context_list; 1147650397Sobrien{ 1147790075Sobrien unsigned int file_index; 1147850397Sobrien 1147990075Sobrien if (filename != NULL) 1148050397Sobrien { 1148190075Sobrien dw_die_ref unit_die = new_die (DW_TAG_module, comp_unit_die, NULL); 1148290075Sobrien tree context_list_decl 1148390075Sobrien = build_decl (LABEL_DECL, get_identifier (context_list), 1148490075Sobrien void_type_node); 1148550397Sobrien 1148690075Sobrien TREE_PUBLIC (context_list_decl) = TRUE; 1148790075Sobrien add_name_attribute (unit_die, context_list); 1148890075Sobrien file_index = lookup_filename (filename); 1148990075Sobrien add_AT_unsigned (unit_die, DW_AT_decl_file, file_index); 1149090075Sobrien add_pubname (context_list_decl, unit_die); 1149150397Sobrien } 1149290075Sobrien} 1149350397Sobrien 1149490075Sobrien/* Output debug information for global decl DECL. Called from toplev.c after 1149590075Sobrien compilation proper has finished. */ 1149690075Sobrien 1149790075Sobrienstatic void 1149890075Sobriendwarf2out_global_decl (decl) 1149990075Sobrien tree decl; 1150090075Sobrien{ 1150190075Sobrien /* Output DWARF2 information for file-scope tentative data object 1150290075Sobrien declarations, file-scope (extern) function declarations (which had no 1150390075Sobrien corresponding body) and file-scope tagged type declarations and 1150490075Sobrien definitions which have not yet been forced out. */ 1150590075Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) 1150690075Sobrien dwarf2out_decl (decl); 1150790075Sobrien} 1150890075Sobrien 1150990075Sobrien/* Write the debugging output for DECL. */ 1151090075Sobrien 1151190075Sobrienvoid 1151290075Sobriendwarf2out_decl (decl) 1151390075Sobrien tree decl; 1151490075Sobrien{ 1151590075Sobrien dw_die_ref context_die = comp_unit_die; 1151690075Sobrien 1151750397Sobrien switch (TREE_CODE (decl)) 1151850397Sobrien { 1151990075Sobrien case ERROR_MARK: 1152090075Sobrien return; 1152190075Sobrien 1152250397Sobrien case FUNCTION_DECL: 1152390075Sobrien /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a 1152450397Sobrien builtin function. Explicit programmer-supplied declarations of 1152550397Sobrien these same functions should NOT be ignored however. */ 1152690075Sobrien if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl)) 1152750397Sobrien return; 1152850397Sobrien 1152950397Sobrien /* What we would really like to do here is to filter out all mere 1153050397Sobrien file-scope declarations of file-scope functions which are never 1153150397Sobrien referenced later within this translation unit (and keep all of ones 1153290075Sobrien that *are* referenced later on) but we aren't clairvoyant, so we have 1153390075Sobrien no idea which functions will be referenced in the future (i.e. later 1153450397Sobrien on within the current translation unit). So here we just ignore all 1153590075Sobrien file-scope function declarations which are not also definitions. If 1153650397Sobrien and when the debugger needs to know something about these functions, 1153790075Sobrien it will have to hunt around and find the DWARF information associated 1153890075Sobrien with the definition of the function. 1153990075Sobrien 1154090075Sobrien We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL 1154190075Sobrien nodes represent definitions and which ones represent mere 1154290075Sobrien declarations. We have to check DECL_INITIAL instead. That's because 1154390075Sobrien the C front-end supports some weird semantics for "extern inline" 1154490075Sobrien function definitions. These can get inlined within the current 1154590075Sobrien translation unit (an thus, we need to generate Dwarf info for their 1154690075Sobrien abstract instances so that the Dwarf info for the concrete inlined 1154790075Sobrien instances can have something to refer to) but the compiler never 1154890075Sobrien generates any out-of-lines instances of such things (despite the fact 1154990075Sobrien that they *are* definitions). 1155090075Sobrien 1155190075Sobrien The important point is that the C front-end marks these "extern 1155290075Sobrien inline" functions as DECL_EXTERNAL, but we need to generate DWARF for 1155390075Sobrien them anyway. Note that the C++ front-end also plays some similar games 1155490075Sobrien for inline function definitions appearing within include files which 1155590075Sobrien also contain `#pragma interface' pragmas. */ 1155650397Sobrien if (DECL_INITIAL (decl) == NULL_TREE) 1155750397Sobrien return; 1155850397Sobrien 1155950397Sobrien /* If we're a nested function, initially use a parent of NULL; if we're 1156050397Sobrien a plain function, this will be fixed up in decls_for_scope. If 1156150397Sobrien we're a method, it will be ignored, since we already have a DIE. */ 1156250397Sobrien if (decl_function_context (decl)) 1156350397Sobrien context_die = NULL; 1156450397Sobrien break; 1156550397Sobrien 1156650397Sobrien case VAR_DECL: 1156790075Sobrien /* Ignore this VAR_DECL if it refers to a file-scope extern data object 1156850397Sobrien declaration and if the declaration was never even referenced from 1156950397Sobrien within this entire compilation unit. We suppress these DIEs in 1157050397Sobrien order to save space in the .debug section (by eliminating entries 1157150397Sobrien which are probably useless). Note that we must not suppress 1157250397Sobrien block-local extern declarations (whether used or not) because that 1157350397Sobrien would screw-up the debugger's name lookup mechanism and cause it to 1157450397Sobrien miss things which really ought to be in scope at a given point. */ 1157550397Sobrien if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) 1157650397Sobrien return; 1157750397Sobrien 1157850397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 1157950397Sobrien variable declarations or definitions. */ 1158050397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1158150397Sobrien return; 1158250397Sobrien break; 1158350397Sobrien 1158450397Sobrien case TYPE_DECL: 1158590075Sobrien /* Don't emit stubs for types unless they are needed by other DIEs. */ 1158690075Sobrien if (TYPE_DECL_SUPPRESS_DEBUG (decl)) 1158790075Sobrien return; 1158890075Sobrien 1158950397Sobrien /* Don't bother trying to generate any DIEs to represent any of the 1159050397Sobrien normal built-in types for the language we are compiling. */ 1159150397Sobrien if (DECL_SOURCE_LINE (decl) == 0) 1159250397Sobrien { 1159350397Sobrien /* OK, we need to generate one for `bool' so GDB knows what type 1159450397Sobrien comparisons have. */ 1159550397Sobrien if ((get_AT_unsigned (comp_unit_die, DW_AT_language) 1159650397Sobrien == DW_LANG_C_plus_plus) 1159790075Sobrien && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE 1159890075Sobrien && ! DECL_IGNORED_P (decl)) 1159950397Sobrien modified_type_die (TREE_TYPE (decl), 0, 0, NULL); 1160050397Sobrien 1160150397Sobrien return; 1160250397Sobrien } 1160350397Sobrien 1160450397Sobrien /* If we are in terse mode, don't generate any DIEs for types. */ 1160550397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 1160650397Sobrien return; 1160750397Sobrien 1160850397Sobrien /* If we're a function-scope tag, initially use a parent of NULL; 1160950397Sobrien this will be fixed up in decls_for_scope. */ 1161050397Sobrien if (decl_function_context (decl)) 1161150397Sobrien context_die = NULL; 1161250397Sobrien 1161350397Sobrien break; 1161450397Sobrien 1161550397Sobrien default: 1161650397Sobrien return; 1161750397Sobrien } 1161850397Sobrien 1161950397Sobrien gen_decl_die (decl, context_die); 1162050397Sobrien} 1162150397Sobrien 1162250397Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for 1162350397Sobrien a lexical block. */ 1162450397Sobrien 1162590075Sobrienstatic void 1162690075Sobriendwarf2out_begin_block (line, blocknum) 1162790075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1162890075Sobrien unsigned int blocknum; 1162950397Sobrien{ 1163050397Sobrien function_section (current_function_decl); 1163190075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 1163250397Sobrien} 1163350397Sobrien 1163450397Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a 1163550397Sobrien lexical block. */ 1163650397Sobrien 1163790075Sobrienstatic void 1163890075Sobriendwarf2out_end_block (line, blocknum) 1163990075Sobrien unsigned int line ATTRIBUTE_UNUSED; 1164090075Sobrien unsigned int blocknum; 1164150397Sobrien{ 1164250397Sobrien function_section (current_function_decl); 1164390075Sobrien ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); 1164450397Sobrien} 1164550397Sobrien 1164690075Sobrien/* Returns nonzero if it is appropriate not to emit any debugging 1164790075Sobrien information for BLOCK, because it doesn't contain any instructions. 1164850397Sobrien 1164990075Sobrien Don't allow this for blocks with nested functions or local classes 1165090075Sobrien as we would end up with orphans, and in the presence of scheduling 1165190075Sobrien we may end up calling them anyway. */ 1165290075Sobrien 1165390075Sobrienstatic bool 1165490075Sobriendwarf2out_ignore_block (block) 1165590075Sobrien tree block; 1165650397Sobrien{ 1165790075Sobrien tree decl; 1165850397Sobrien 1165990075Sobrien for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl)) 1166090075Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 1166190075Sobrien || (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))) 1166290075Sobrien return 0; 1166390075Sobrien 1166490075Sobrien return 1; 1166550397Sobrien} 1166650397Sobrien 1166790075Sobrien/* Lookup FILE_NAME (in the list of filenames that we know about here in 1166850397Sobrien dwarf2out.c) and return its "index". The index of each (known) filename is 1166990075Sobrien just a unique number which is associated with only that one filename. We 1167090075Sobrien need such numbers for the sake of generating labels (in the .debug_sfnames 1167190075Sobrien section) and references to those files numbers (in the .debug_srcinfo 1167290075Sobrien and.debug_macinfo sections). If the filename given as an argument is not 1167390075Sobrien found in our current list, add it to the list and assign it the next 1167490075Sobrien available unique index number. In order to speed up searches, we remember 1167590075Sobrien the index of the filename was looked up last. This handles the majority of 1167690075Sobrien all searches. */ 1167750397Sobrien 1167850397Sobrienstatic unsigned 1167950397Sobrienlookup_filename (file_name) 1168090075Sobrien const char *file_name; 1168150397Sobrien{ 1168290075Sobrien unsigned i; 1168350397Sobrien 1168490075Sobrien /* ??? Why isn't DECL_SOURCE_FILE left null instead. */ 1168590075Sobrien if (strcmp (file_name, "<internal>") == 0 1168690075Sobrien || strcmp (file_name, "<built-in>") == 0) 1168790075Sobrien return 0; 1168850397Sobrien 1168990075Sobrien /* Check to see if the file name that was searched on the previous 1169090075Sobrien call matches this file name. If so, return the index. */ 1169190075Sobrien if (file_table.last_lookup_index != 0) 1169290075Sobrien if (0 == strcmp (file_name, 1169390075Sobrien file_table.table[file_table.last_lookup_index])) 1169490075Sobrien return file_table.last_lookup_index; 1169590075Sobrien 1169650397Sobrien /* Didn't match the previous lookup, search the table */ 1169790075Sobrien for (i = 1; i < file_table.in_use; i++) 1169890075Sobrien if (strcmp (file_name, file_table.table[i]) == 0) 1169950397Sobrien { 1170090075Sobrien file_table.last_lookup_index = i; 1170150397Sobrien return i; 1170250397Sobrien } 1170350397Sobrien 1170490075Sobrien /* Prepare to add a new table entry by making sure there is enough space in 1170550397Sobrien the table to do so. If not, expand the current table. */ 1170690075Sobrien if (i == file_table.allocated) 1170750397Sobrien { 1170890075Sobrien file_table.allocated = i + FILE_TABLE_INCREMENT; 1170990075Sobrien file_table.table = (char **) 1171090075Sobrien xrealloc (file_table.table, file_table.allocated * sizeof (char *)); 1171150397Sobrien } 1171250397Sobrien 1171350397Sobrien /* Add the new entry to the end of the filename table. */ 1171490075Sobrien file_table.table[i] = xstrdup (file_name); 1171590075Sobrien file_table.in_use = i + 1; 1171690075Sobrien file_table.last_lookup_index = i; 1171750397Sobrien 1171890075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1171990075Sobrien fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name); 1172090075Sobrien 1172190075Sobrien return i; 1172250397Sobrien} 1172350397Sobrien 1172490075Sobrienstatic void 1172590075Sobrieninit_file_table () 1172690075Sobrien{ 1172790075Sobrien /* Allocate the initial hunk of the file_table. */ 1172890075Sobrien file_table.table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *)); 1172990075Sobrien file_table.allocated = FILE_TABLE_INCREMENT; 1173090075Sobrien 1173190075Sobrien /* Skip the first entry - file numbers begin at 1. */ 1173290075Sobrien file_table.in_use = 1; 1173390075Sobrien file_table.last_lookup_index = 0; 1173490075Sobrien} 1173590075Sobrien 1173650397Sobrien/* Output a label to mark the beginning of a source code line entry 1173750397Sobrien and record information relating to this source line, in 1173850397Sobrien 'line_info_table' for later output of the .debug_line section. */ 1173950397Sobrien 1174090075Sobrienstatic void 1174190075Sobriendwarf2out_source_line (line, filename) 1174290075Sobrien unsigned int line; 1174390075Sobrien const char *filename; 1174450397Sobrien{ 1174550397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1174650397Sobrien { 1174750397Sobrien function_section (current_function_decl); 1174850397Sobrien 1174990075Sobrien /* If requested, emit something human-readable. */ 1175090075Sobrien if (flag_debug_asm) 1175190075Sobrien fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, 1175290075Sobrien filename, line); 1175390075Sobrien 1175490075Sobrien if (DWARF2_ASM_LINE_DEBUG_INFO) 1175550397Sobrien { 1175690075Sobrien unsigned file_num = lookup_filename (filename); 1175790075Sobrien 1175890075Sobrien /* Emit the .loc directive understood by GNU as. */ 1175990075Sobrien fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); 1176090075Sobrien 1176190075Sobrien /* Indicate that line number info exists. */ 1176290075Sobrien line_info_table_in_use++; 1176390075Sobrien 1176490075Sobrien /* Indicate that multiple line number tables exist. */ 1176590075Sobrien if (DECL_SECTION_NAME (current_function_decl)) 1176690075Sobrien separate_line_info_table_in_use++; 1176790075Sobrien } 1176890075Sobrien else if (DECL_SECTION_NAME (current_function_decl)) 1176990075Sobrien { 1177090075Sobrien dw_separate_line_info_ref line_info; 1177150397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, 1177250397Sobrien separate_line_info_table_in_use); 1177350397Sobrien 1177450397Sobrien /* expand the line info table if necessary */ 1177550397Sobrien if (separate_line_info_table_in_use 1177650397Sobrien == separate_line_info_table_allocated) 1177750397Sobrien { 1177850397Sobrien separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1177950397Sobrien separate_line_info_table 1178050397Sobrien = (dw_separate_line_info_ref) 1178150397Sobrien xrealloc (separate_line_info_table, 1178250397Sobrien separate_line_info_table_allocated 1178350397Sobrien * sizeof (dw_separate_line_info_entry)); 1178450397Sobrien } 1178550397Sobrien 1178650397Sobrien /* Add the new entry at the end of the line_info_table. */ 1178750397Sobrien line_info 1178850397Sobrien = &separate_line_info_table[separate_line_info_table_in_use++]; 1178950397Sobrien line_info->dw_file_num = lookup_filename (filename); 1179050397Sobrien line_info->dw_line_num = line; 1179150397Sobrien line_info->function = current_funcdef_number; 1179250397Sobrien } 1179350397Sobrien else 1179450397Sobrien { 1179590075Sobrien dw_line_info_ref line_info; 1179650397Sobrien 1179750397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, 1179850397Sobrien line_info_table_in_use); 1179950397Sobrien 1180050397Sobrien /* Expand the line info table if necessary. */ 1180150397Sobrien if (line_info_table_in_use == line_info_table_allocated) 1180250397Sobrien { 1180350397Sobrien line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1180450397Sobrien line_info_table 1180550397Sobrien = (dw_line_info_ref) 1180650397Sobrien xrealloc (line_info_table, 1180750397Sobrien (line_info_table_allocated 1180850397Sobrien * sizeof (dw_line_info_entry))); 1180950397Sobrien } 1181050397Sobrien 1181150397Sobrien /* Add the new entry at the end of the line_info_table. */ 1181250397Sobrien line_info = &line_info_table[line_info_table_in_use++]; 1181350397Sobrien line_info->dw_file_num = lookup_filename (filename); 1181450397Sobrien line_info->dw_line_num = line; 1181550397Sobrien } 1181650397Sobrien } 1181750397Sobrien} 1181850397Sobrien 1181990075Sobrien/* Record the beginning of a new source file. */ 1182050397Sobrien 1182190075Sobrienstatic void 1182290075Sobriendwarf2out_start_source_file (lineno, filename) 1182390075Sobrien unsigned int lineno; 1182490075Sobrien const char *filename; 1182550397Sobrien{ 1182690075Sobrien if (flag_eliminate_dwarf2_dups) 1182790075Sobrien { 1182890075Sobrien /* Record the beginning of the file for break_out_includes. */ 1182990075Sobrien dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); 1183090075Sobrien add_AT_string (bincl_die, DW_AT_name, filename); 1183190075Sobrien } 1183290075Sobrien 1183390075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1183490075Sobrien { 1183590075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1183690075Sobrien dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); 1183790075Sobrien dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", 1183890075Sobrien lineno); 1183990075Sobrien dw2_asm_output_data_uleb128 (lookup_filename (filename), 1184090075Sobrien "Filename we just started"); 1184190075Sobrien } 1184250397Sobrien} 1184350397Sobrien 1184490075Sobrien/* Record the end of a source file. */ 1184550397Sobrien 1184690075Sobrienstatic void 1184790075Sobriendwarf2out_end_source_file (lineno) 1184890075Sobrien unsigned int lineno ATTRIBUTE_UNUSED; 1184950397Sobrien{ 1185090075Sobrien if (flag_eliminate_dwarf2_dups) 1185190075Sobrien /* Record the end of the file for break_out_includes. */ 1185290075Sobrien new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL); 1185390075Sobrien 1185490075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1185590075Sobrien { 1185690075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1185790075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1185890075Sobrien } 1185950397Sobrien} 1186050397Sobrien 1186190075Sobrien/* Called from debug_define in toplev.c. The `buffer' parameter contains 1186250397Sobrien the tail part of the directive line, i.e. the part which is past the 1186350397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1186450397Sobrien 1186590075Sobrienstatic void 1186650397Sobriendwarf2out_define (lineno, buffer) 1186790075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1186890075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1186950397Sobrien{ 1187050397Sobrien static int initialized = 0; 1187150397Sobrien if (!initialized) 1187250397Sobrien { 1187390075Sobrien dwarf2out_start_source_file (0, primary_filename); 1187450397Sobrien initialized = 1; 1187550397Sobrien } 1187690075Sobrien 1187790075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1187890075Sobrien { 1187990075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1188090075Sobrien dw2_asm_output_data (1, DW_MACINFO_define, "Define macro"); 1188190075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1188290075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1188390075Sobrien } 1188450397Sobrien} 1188550397Sobrien 1188690075Sobrien/* Called from debug_undef in toplev.c. The `buffer' parameter contains 1188750397Sobrien the tail part of the directive line, i.e. the part which is past the 1188850397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 1188950397Sobrien 1189090075Sobrienstatic void 1189150397Sobriendwarf2out_undef (lineno, buffer) 1189290075Sobrien unsigned lineno ATTRIBUTE_UNUSED; 1189390075Sobrien const char *buffer ATTRIBUTE_UNUSED; 1189450397Sobrien{ 1189590075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1189690075Sobrien { 1189790075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1189890075Sobrien dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro"); 1189990075Sobrien dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); 1190090075Sobrien dw2_asm_output_nstring (buffer, -1, "The macro"); 1190190075Sobrien } 1190250397Sobrien} 1190350397Sobrien 1190450397Sobrien/* Set up for Dwarf output at the start of compilation. */ 1190550397Sobrien 1190690075Sobrienstatic void 1190790075Sobriendwarf2out_init (main_input_filename) 1190890075Sobrien const char *main_input_filename; 1190950397Sobrien{ 1191090075Sobrien init_file_table (); 1191190075Sobrien 1191250397Sobrien /* Remember the name of the primary input file. */ 1191350397Sobrien primary_filename = main_input_filename; 1191450397Sobrien 1191590075Sobrien /* Add it to the file table first, under the assumption that we'll 1191690075Sobrien be emitting line number data for it first, which avoids having 1191790075Sobrien to add an initial DW_LNS_set_file. */ 1191890075Sobrien lookup_filename (main_input_filename); 1191950397Sobrien 1192050397Sobrien /* Allocate the initial hunk of the decl_die_table. */ 1192150397Sobrien decl_die_table 1192290075Sobrien = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref)); 1192350397Sobrien decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT; 1192450397Sobrien decl_die_table_in_use = 0; 1192550397Sobrien 1192650397Sobrien /* Allocate the initial hunk of the decl_scope_table. */ 1192790075Sobrien VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table"); 1192890075Sobrien ggc_add_tree_varray_root (&decl_scope_table, 1); 1192950397Sobrien 1193050397Sobrien /* Allocate the initial hunk of the abbrev_die_table. */ 1193150397Sobrien abbrev_die_table 1193290075Sobrien = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT, 1193390075Sobrien sizeof (dw_die_ref)); 1193450397Sobrien abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; 1193550397Sobrien /* Zero-th entry is allocated, but unused */ 1193650397Sobrien abbrev_die_table_in_use = 1; 1193750397Sobrien 1193850397Sobrien /* Allocate the initial hunk of the line_info_table. */ 1193950397Sobrien line_info_table 1194090075Sobrien = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, 1194190075Sobrien sizeof (dw_line_info_entry)); 1194250397Sobrien line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 1194390075Sobrien 1194450397Sobrien /* Zero-th entry is allocated, but unused */ 1194550397Sobrien line_info_table_in_use = 1; 1194650397Sobrien 1194790075Sobrien /* Generate the initial DIE for the .debug section. Note that the (string) 1194850397Sobrien value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE 1194990075Sobrien will (typically) be a relative pathname and that this pathname should be 1195050397Sobrien taken as being relative to the directory from which the compiler was 1195150397Sobrien invoked when the given (base) source file was compiled. */ 1195290075Sobrien comp_unit_die = gen_compile_unit_die (main_input_filename); 1195350397Sobrien 1195490075Sobrien VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types"); 1195590075Sobrien ggc_add_tree_varray_root (&incomplete_types, 1); 1195690075Sobrien 1195790075Sobrien VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray"); 1195890075Sobrien ggc_add_rtx_varray_root (&used_rtx_varray, 1); 1195990075Sobrien 1196090075Sobrien ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list); 1196190075Sobrien 1196250397Sobrien ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1196390075Sobrien ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, 1196490075Sobrien DEBUG_ABBREV_SECTION_LABEL, 0); 1196590075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1196690075Sobrien ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0); 1196790075Sobrien else 1196890075Sobrien strcpy (text_section_label, stripattributes (TEXT_SECTION_NAME)); 1196990075Sobrien 1197090075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, 1197152284Sobrien DEBUG_INFO_SECTION_LABEL, 0); 1197290075Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, 1197352284Sobrien DEBUG_LINE_SECTION_LABEL, 0); 1197490075Sobrien ASM_GENERATE_INTERNAL_LABEL (ranges_section_label, 1197590075Sobrien DEBUG_RANGES_SECTION_LABEL, 0); 1197690075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1197752284Sobrien ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); 1197890075Sobrien named_section_flags (DEBUG_INFO_SECTION, SECTION_DEBUG); 1197952284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label); 1198090075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1198152284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); 1198290075Sobrien 1198390075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1198490075Sobrien { 1198590075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1198690075Sobrien ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label, 1198790075Sobrien DEBUG_MACINFO_SECTION_LABEL, 0); 1198890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label); 1198990075Sobrien } 1199090075Sobrien 1199190075Sobrien if (DWARF2_GENERATE_TEXT_SECTION_LABEL) 1199290075Sobrien { 1199390075Sobrien text_section (); 1199490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, text_section_label); 1199590075Sobrien } 1199650397Sobrien} 1199750397Sobrien 1199890075Sobrien/* Allocate a string in .debug_str hash table. */ 1199990075Sobrien 1200090075Sobrienstatic hashnode 1200190075Sobrienindirect_string_alloc (tab) 1200290075Sobrien hash_table *tab ATTRIBUTE_UNUSED; 1200390075Sobrien{ 1200490075Sobrien struct indirect_string_node *node; 1200590075Sobrien 1200690075Sobrien node = xmalloc (sizeof (struct indirect_string_node)); 1200790075Sobrien node->refcount = 0; 1200890075Sobrien node->form = 0; 1200990075Sobrien node->label = NULL; 1201090075Sobrien 1201190075Sobrien return (hashnode) node; 1201290075Sobrien} 1201390075Sobrien 1201490075Sobrien/* A helper function for dwarf2out_finish called through 1201590075Sobrien ht_forall. Emit one queued .debug_str string. */ 1201690075Sobrien 1201790075Sobrienstatic int 1201890075Sobrienoutput_indirect_string (pfile, h, v) 1201990075Sobrien struct cpp_reader *pfile ATTRIBUTE_UNUSED; 1202090075Sobrien hashnode h; 1202190075Sobrien const PTR v ATTRIBUTE_UNUSED; 1202290075Sobrien{ 1202390075Sobrien struct indirect_string_node *node = (struct indirect_string_node *) h; 1202490075Sobrien 1202590075Sobrien if (node->form == DW_FORM_strp) 1202690075Sobrien { 1202790075Sobrien named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS); 1202890075Sobrien ASM_OUTPUT_LABEL (asm_out_file, node->label); 1202990075Sobrien assemble_string ((const char *) HT_STR (&node->id), 1203090075Sobrien HT_LEN (&node->id) + 1); 1203190075Sobrien } 1203290075Sobrien 1203390075Sobrien return 1; 1203490075Sobrien} 1203590075Sobrien 1203650397Sobrien/* Output stuff that dwarf requires at the end of every file, 1203750397Sobrien and generate the DWARF-2 debugging info. */ 1203850397Sobrien 1203990075Sobrienstatic void 1204090075Sobriendwarf2out_finish (input_filename) 1204190075Sobrien const char *input_filename ATTRIBUTE_UNUSED; 1204250397Sobrien{ 1204350397Sobrien limbo_die_node *node, *next_node; 1204490075Sobrien dw_die_ref die = 0; 1204550397Sobrien 1204650397Sobrien /* Traverse the limbo die list, and add parent/child links. The only 1204750397Sobrien dies without parents that should be here are concrete instances of 1204850397Sobrien inline functions, and the comp_unit_die. We can ignore the comp_unit_die. 1204950397Sobrien For concrete instances, we can get the parent die from the abstract 1205050397Sobrien instance. */ 1205150397Sobrien for (node = limbo_die_list; node; node = next_node) 1205250397Sobrien { 1205350397Sobrien next_node = node->next; 1205450397Sobrien die = node->die; 1205550397Sobrien 1205650397Sobrien if (die->die_parent == NULL) 1205750397Sobrien { 1205890075Sobrien dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); 1205990075Sobrien tree context; 1206090075Sobrien 1206190075Sobrien if (origin) 1206290075Sobrien add_child_die (origin->die_parent, die); 1206350397Sobrien else if (die == comp_unit_die) 1206490075Sobrien ; 1206590075Sobrien /* If this was an expression for a bound involved in a function 1206690075Sobrien return type, it may be a SAVE_EXPR for which we weren't able 1206790075Sobrien to find a DIE previously. So try now. */ 1206890075Sobrien else if (node->created_for 1206990075Sobrien && TREE_CODE (node->created_for) == SAVE_EXPR 1207090075Sobrien && 0 != (origin = (lookup_decl_die 1207190075Sobrien (SAVE_EXPR_CONTEXT 1207290075Sobrien (node->created_for))))) 1207390075Sobrien add_child_die (origin, die); 1207490075Sobrien else if (errorcount > 0 || sorrycount > 0) 1207590075Sobrien /* It's OK to be confused by errors in the input. */ 1207690075Sobrien add_child_die (comp_unit_die, die); 1207790075Sobrien else if (node->created_for 1207890075Sobrien && ((DECL_P (node->created_for) 1207990075Sobrien && (context = DECL_CONTEXT (node->created_for))) 1208090075Sobrien || (TYPE_P (node->created_for) 1208190075Sobrien && (context = TYPE_CONTEXT (node->created_for)))) 1208290075Sobrien && TREE_CODE (context) == FUNCTION_DECL) 1208390075Sobrien { 1208490075Sobrien /* In certain situations, the lexical block containing a 1208590075Sobrien nested function can be optimized away, which results 1208690075Sobrien in the nested function die being orphaned. Likewise 1208790075Sobrien with the return type of that nested function. Force 1208890075Sobrien this to be a child of the containing function. */ 1208990075Sobrien origin = lookup_decl_die (context); 1209090075Sobrien if (! origin) 1209190075Sobrien abort (); 1209290075Sobrien add_child_die (origin, die); 1209390075Sobrien } 1209450397Sobrien else 1209550397Sobrien abort (); 1209650397Sobrien } 1209790075Sobrien 1209850397Sobrien free (node); 1209950397Sobrien } 1210050397Sobrien 1210190075Sobrien limbo_die_list = NULL; 1210290075Sobrien 1210352284Sobrien /* Walk through the list of incomplete types again, trying once more to 1210452284Sobrien emit full debugging info for them. */ 1210552284Sobrien retry_incomplete_types (); 1210652284Sobrien 1210790075Sobrien /* We need to reverse all the dies before break_out_includes, or 1210890075Sobrien we'll see the end of an include file before the beginning. */ 1210990075Sobrien reverse_all_dies (comp_unit_die); 1211090075Sobrien 1211190075Sobrien /* Generate separate CUs for each of the include files we've seen. 1211290075Sobrien They will go into limbo_die_list. */ 1211390075Sobrien if (flag_eliminate_dwarf2_dups) 1211490075Sobrien break_out_includes (comp_unit_die); 1211590075Sobrien 1211690075Sobrien /* Traverse the DIE's and add add sibling attributes to those DIE's 1211750397Sobrien that have children. */ 1211850397Sobrien add_sibling_attributes (comp_unit_die); 1211990075Sobrien for (node = limbo_die_list; node; node = node->next) 1212090075Sobrien add_sibling_attributes (node->die); 1212150397Sobrien 1212250397Sobrien /* Output a terminator label for the .text section. */ 1212390075Sobrien text_section (); 1212450397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); 1212550397Sobrien 1212690075Sobrien /* Output the source line correspondence table. We must do this 1212790075Sobrien even if there is no line information. Otherwise, on an empty 1212890075Sobrien translation unit, we will generate a present, but empty, 1212990075Sobrien .debug_info section. IRIX 6.5 `nm' will then complain when 1213090075Sobrien examining the file. */ 1213190075Sobrien if (! DWARF2_ASM_LINE_DEBUG_INFO) 1213250397Sobrien { 1213390075Sobrien named_section_flags (DEBUG_LINE_SECTION, SECTION_DEBUG); 1213450397Sobrien output_line_info (); 1213590075Sobrien } 1213650397Sobrien 1213790075Sobrien /* Output location list section if necessary. */ 1213890075Sobrien if (have_location_lists) 1213990075Sobrien { 1214090075Sobrien /* Output the location lists info. */ 1214190075Sobrien named_section_flags (DEBUG_LOC_SECTION, SECTION_DEBUG); 1214290075Sobrien ASM_GENERATE_INTERNAL_LABEL (loc_section_label, 1214390075Sobrien DEBUG_LOC_SECTION_LABEL, 0); 1214490075Sobrien ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); 1214590075Sobrien output_location_lists (die); 1214690075Sobrien have_location_lists = 0; 1214790075Sobrien } 1214850397Sobrien 1214990075Sobrien /* We can only use the low/high_pc attributes if all of the code was 1215090075Sobrien in .text. */ 1215190075Sobrien if (separate_line_info_table_in_use == 0) 1215290075Sobrien { 1215390075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); 1215490075Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); 1215550397Sobrien } 1215650397Sobrien 1215790075Sobrien /* If it wasn't, we need to give .debug_loc and .debug_ranges an appropriate 1215890075Sobrien "base address". Use zero so that these addresses become absolute. */ 1215990075Sobrien else if (have_location_lists || ranges_table_in_use) 1216090075Sobrien add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); 1216190075Sobrien 1216290075Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 1216390075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, 1216490075Sobrien debug_line_section_label); 1216590075Sobrien 1216690075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1216790075Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_macro_info, macinfo_section_label); 1216890075Sobrien 1216990075Sobrien /* Output all of the compilation units. We put the main one last so that 1217090075Sobrien the offsets are available to output_pubnames. */ 1217190075Sobrien for (node = limbo_die_list; node; node = node->next) 1217290075Sobrien output_comp_unit (node->die); 1217390075Sobrien 1217490075Sobrien output_comp_unit (comp_unit_die); 1217590075Sobrien 1217650397Sobrien /* Output the abbreviation table. */ 1217790075Sobrien named_section_flags (DEBUG_ABBREV_SECTION, SECTION_DEBUG); 1217850397Sobrien output_abbrev_section (); 1217950397Sobrien 1218090075Sobrien /* Output public names table if necessary. */ 1218150397Sobrien if (pubname_table_in_use) 1218250397Sobrien { 1218390075Sobrien named_section_flags (DEBUG_PUBNAMES_SECTION, SECTION_DEBUG); 1218450397Sobrien output_pubnames (); 1218550397Sobrien } 1218650397Sobrien 1218790075Sobrien /* Output the address range information. We only put functions in the arange 1218890075Sobrien table, so don't write it out if we don't have any. */ 1218950397Sobrien if (fde_table_in_use) 1219050397Sobrien { 1219190075Sobrien named_section_flags (DEBUG_ARANGES_SECTION, SECTION_DEBUG); 1219250397Sobrien output_aranges (); 1219350397Sobrien } 1219490075Sobrien 1219590075Sobrien /* Output ranges section if necessary. */ 1219690075Sobrien if (ranges_table_in_use) 1219790075Sobrien { 1219890075Sobrien named_section_flags (DEBUG_RANGES_SECTION, SECTION_DEBUG); 1219990075Sobrien ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label); 1220090075Sobrien output_ranges (); 1220190075Sobrien } 1220290075Sobrien 1220390075Sobrien /* Have to end the primary source file. */ 1220490075Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 1220590075Sobrien { 1220690075Sobrien named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); 1220790075Sobrien dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); 1220890075Sobrien } 1220990075Sobrien 1221090075Sobrien /* If we emitted any DW_FORM_strp form attribute, output the string 1221190075Sobrien table too. */ 1221290075Sobrien if (debug_str_hash) 1221390075Sobrien ht_forall (debug_str_hash, output_indirect_string, NULL); 1221450397Sobrien} 1221590075Sobrien#endif /* DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO */ 12216