dwarf2out.c revision 52284
150397Sobrien/* Output Dwarf2 format symbol table information from the GNU C compiler. 252284Sobrien Copyright (C) 1992, 93, 95-98, 1999 Free Software Foundation, Inc. 350397Sobrien Contributed by Gary Funck (gary@intrepid.com). 450397Sobrien Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). 550397Sobrien Extensively modified by Jason Merrill (jason@cygnus.com). 650397Sobrien 750397SobrienThis file is part of GNU CC. 850397Sobrien 950397SobrienGNU CC is free software; you can redistribute it and/or modify 1050397Sobrienit under the terms of the GNU General Public License as published by 1150397Sobrienthe Free Software Foundation; either version 2, or (at your option) 1250397Sobrienany later version. 1350397Sobrien 1450397SobrienGNU CC is distributed in the hope that it will be useful, 1550397Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1650397SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1750397SobrienGNU General Public License for more details. 1850397Sobrien 1950397SobrienYou should have received a copy of the GNU General Public License 2050397Sobrienalong with GNU CC; see the file COPYING. If not, write to 2152284Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330, 2252284SobrienBoston, MA 02111-1307, USA. */ 2350397Sobrien 2450397Sobrien/* The first part of this file deals with the DWARF 2 frame unwind 2550397Sobrien information, which is also used by the GCC efficient exception handling 2650397Sobrien mechanism. The second part, controlled only by an #ifdef 2750397Sobrien DWARF2_DEBUGGING_INFO, deals with the other DWARF 2 debugging 2850397Sobrien information. */ 2950397Sobrien 3050397Sobrien#include "config.h" 3150397Sobrien#include "system.h" 3250397Sobrien#include "defaults.h" 3350397Sobrien#include "tree.h" 3450397Sobrien#include "flags.h" 3550397Sobrien#include "rtl.h" 3650397Sobrien#include "hard-reg-set.h" 3750397Sobrien#include "regs.h" 3850397Sobrien#include "insn-config.h" 3950397Sobrien#include "reload.h" 4050397Sobrien#include "output.h" 4150397Sobrien#include "expr.h" 4250397Sobrien#include "except.h" 4350397Sobrien#include "dwarf2.h" 4450397Sobrien#include "dwarf2out.h" 4550397Sobrien#include "toplev.h" 4650397Sobrien#include "dyn-string.h" 4750397Sobrien 4850397Sobrien/* We cannot use <assert.h> in GCC source, since that would include 4950397Sobrien GCC's assert.h, which may not be compatible with the host compiler. */ 5050397Sobrien#undef assert 5150397Sobrien#ifdef NDEBUG 5250397Sobrien# define assert(e) 5350397Sobrien#else 5450397Sobrien# define assert(e) do { if (! (e)) abort (); } while (0) 5550397Sobrien#endif 5650397Sobrien 5750397Sobrien/* Decide whether we want to emit frame unwind information for the current 5850397Sobrien translation unit. */ 5950397Sobrien 6050397Sobrienint 6150397Sobriendwarf2out_do_frame () 6250397Sobrien{ 6350397Sobrien return (write_symbols == DWARF2_DEBUG 6450397Sobrien#ifdef DWARF2_FRAME_INFO 6550397Sobrien || DWARF2_FRAME_INFO 6650397Sobrien#endif 6750397Sobrien#ifdef DWARF2_UNWIND_INFO 6850397Sobrien || (flag_exceptions && ! exceptions_via_longjmp) 6950397Sobrien#endif 7050397Sobrien ); 7150397Sobrien} 7250397Sobrien 7350397Sobrien#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) 7450397Sobrien 7550397Sobrien/* How to start an assembler comment. */ 7650397Sobrien#ifndef ASM_COMMENT_START 7750397Sobrien#define ASM_COMMENT_START ";#" 7850397Sobrien#endif 7950397Sobrien 8050397Sobrientypedef struct dw_cfi_struct *dw_cfi_ref; 8150397Sobrientypedef struct dw_fde_struct *dw_fde_ref; 8250397Sobrientypedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref; 8350397Sobrien 8450397Sobrien/* Call frames are described using a sequence of Call Frame 8550397Sobrien Information instructions. The register number, offset 8650397Sobrien and address fields are provided as possible operands; 8750397Sobrien their use is selected by the opcode field. */ 8850397Sobrien 8950397Sobrientypedef union dw_cfi_oprnd_struct 9050397Sobrien{ 9150397Sobrien unsigned long dw_cfi_reg_num; 9250397Sobrien long int dw_cfi_offset; 9350397Sobrien char *dw_cfi_addr; 9450397Sobrien} 9550397Sobriendw_cfi_oprnd; 9650397Sobrien 9750397Sobrientypedef struct dw_cfi_struct 9850397Sobrien{ 9950397Sobrien dw_cfi_ref dw_cfi_next; 10050397Sobrien enum dwarf_call_frame_info dw_cfi_opc; 10150397Sobrien dw_cfi_oprnd dw_cfi_oprnd1; 10250397Sobrien dw_cfi_oprnd dw_cfi_oprnd2; 10350397Sobrien} 10450397Sobriendw_cfi_node; 10550397Sobrien 10650397Sobrien/* All call frame descriptions (FDE's) in the GCC generated DWARF 10750397Sobrien refer to a single Common Information Entry (CIE), defined at 10850397Sobrien the beginning of the .debug_frame section. This used of a single 10950397Sobrien CIE obviates the need to keep track of multiple CIE's 11050397Sobrien in the DWARF generation routines below. */ 11150397Sobrien 11250397Sobrientypedef struct dw_fde_struct 11350397Sobrien{ 11450397Sobrien char *dw_fde_begin; 11550397Sobrien char *dw_fde_current_label; 11650397Sobrien char *dw_fde_end; 11750397Sobrien dw_cfi_ref dw_fde_cfi; 11850397Sobrien} 11950397Sobriendw_fde_node; 12050397Sobrien 12150397Sobrien/* Maximum size (in bytes) of an artificially generated label. */ 12250397Sobrien#define MAX_ARTIFICIAL_LABEL_BYTES 30 12350397Sobrien 12450397Sobrien/* Make sure we know the sizes of the various types dwarf can describe. These 12550397Sobrien are only defaults. If the sizes are different for your target, you should 12650397Sobrien override these values by defining the appropriate symbols in your tm.h 12750397Sobrien file. */ 12850397Sobrien 12950397Sobrien#ifndef CHAR_TYPE_SIZE 13050397Sobrien#define CHAR_TYPE_SIZE BITS_PER_UNIT 13150397Sobrien#endif 13250397Sobrien#ifndef PTR_SIZE 13350397Sobrien#define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT) 13450397Sobrien#endif 13550397Sobrien 13650397Sobrien/* The size in bytes of a DWARF field indicating an offset or length 13750397Sobrien relative to a debug info section, specified to be 4 bytes in the DWARF-2 13850397Sobrien specification. The SGI/MIPS ABI defines it to be the same as PTR_SIZE. */ 13950397Sobrien 14050397Sobrien#ifndef DWARF_OFFSET_SIZE 14150397Sobrien#define DWARF_OFFSET_SIZE 4 14250397Sobrien#endif 14350397Sobrien 14450397Sobrien#define DWARF_VERSION 2 14550397Sobrien 14650397Sobrien/* Round SIZE up to the nearest BOUNDARY. */ 14750397Sobrien#define DWARF_ROUND(SIZE,BOUNDARY) \ 14850397Sobrien (((SIZE) + (BOUNDARY) - 1) & ~((BOUNDARY) - 1)) 14950397Sobrien 15050397Sobrien/* Offsets recorded in opcodes are a multiple of this alignment factor. */ 15150397Sobrien#ifdef STACK_GROWS_DOWNWARD 15250397Sobrien#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_WORD) 15350397Sobrien#else 15450397Sobrien#define DWARF_CIE_DATA_ALIGNMENT UNITS_PER_WORD 15550397Sobrien#endif 15650397Sobrien 15750397Sobrien/* A pointer to the base of a table that contains frame description 15850397Sobrien information for each routine. */ 15950397Sobrienstatic dw_fde_ref fde_table; 16050397Sobrien 16150397Sobrien/* Number of elements currently allocated for fde_table. */ 16250397Sobrienstatic unsigned fde_table_allocated; 16350397Sobrien 16450397Sobrien/* Number of elements in fde_table currently in use. */ 16550397Sobrienstatic unsigned fde_table_in_use; 16650397Sobrien 16750397Sobrien/* Size (in elements) of increments by which we may expand the 16850397Sobrien fde_table. */ 16950397Sobrien#define FDE_TABLE_INCREMENT 256 17050397Sobrien 17150397Sobrien/* A list of call frame insns for the CIE. */ 17250397Sobrienstatic dw_cfi_ref cie_cfi_head; 17350397Sobrien 17450397Sobrien/* The number of the current function definition for which debugging 17550397Sobrien information is being generated. These numbers range from 1 up to the 17650397Sobrien maximum number of function definitions contained within the current 17750397Sobrien compilation unit. These numbers are used to create unique label id's 17850397Sobrien unique to each function definition. */ 17950397Sobrienstatic unsigned current_funcdef_number = 0; 18050397Sobrien 18150397Sobrien/* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram 18250397Sobrien attribute that accelerates the lookup of the FDE associated 18350397Sobrien with the subprogram. This variable holds the table index of the FDE 18450397Sobrien associated with the current function (body) definition. */ 18550397Sobrienstatic unsigned current_funcdef_fde; 18650397Sobrien 18750397Sobrien/* Forward declarations for functions defined in this file. */ 18850397Sobrien 18950397Sobrienstatic char *stripattributes PROTO((char *)); 19050397Sobrienstatic char *dwarf_cfi_name PROTO((unsigned)); 19150397Sobrienstatic dw_cfi_ref new_cfi PROTO((void)); 19250397Sobrienstatic void add_cfi PROTO((dw_cfi_ref *, dw_cfi_ref)); 19350397Sobrienstatic unsigned long size_of_uleb128 PROTO((unsigned long)); 19450397Sobrienstatic unsigned long size_of_sleb128 PROTO((long)); 19550397Sobrienstatic void output_uleb128 PROTO((unsigned long)); 19650397Sobrienstatic void output_sleb128 PROTO((long)); 19750397Sobrienstatic void add_fde_cfi PROTO((char *, dw_cfi_ref)); 19850397Sobrienstatic void lookup_cfa_1 PROTO((dw_cfi_ref, unsigned long *, 19950397Sobrien long *)); 20050397Sobrienstatic void lookup_cfa PROTO((unsigned long *, long *)); 20150397Sobrienstatic void reg_save PROTO((char *, unsigned, unsigned, 20250397Sobrien long)); 20350397Sobrienstatic void initial_return_save PROTO((rtx)); 20450397Sobrienstatic void output_cfi PROTO((dw_cfi_ref, dw_fde_ref)); 20550397Sobrienstatic void output_call_frame_info PROTO((int)); 20650397Sobrienstatic unsigned reg_number PROTO((rtx)); 20750397Sobrienstatic void dwarf2out_stack_adjust PROTO((rtx)); 20850397Sobrien 20950397Sobrien/* Definitions of defaults for assembler-dependent names of various 21050397Sobrien pseudo-ops and section names. 21150397Sobrien Theses may be overridden in the tm.h file (if necessary) for a particular 21250397Sobrien assembler. */ 21350397Sobrien 21450397Sobrien#ifdef OBJECT_FORMAT_ELF 21550397Sobrien#ifndef UNALIGNED_SHORT_ASM_OP 21650397Sobrien#define UNALIGNED_SHORT_ASM_OP ".2byte" 21750397Sobrien#endif 21850397Sobrien#ifndef UNALIGNED_INT_ASM_OP 21950397Sobrien#define UNALIGNED_INT_ASM_OP ".4byte" 22050397Sobrien#endif 22150397Sobrien#ifndef UNALIGNED_DOUBLE_INT_ASM_OP 22250397Sobrien#define UNALIGNED_DOUBLE_INT_ASM_OP ".8byte" 22350397Sobrien#endif 22450397Sobrien#endif /* OBJECT_FORMAT_ELF */ 22550397Sobrien 22650397Sobrien#ifndef ASM_BYTE_OP 22750397Sobrien#define ASM_BYTE_OP ".byte" 22850397Sobrien#endif 22950397Sobrien 23050397Sobrien/* Data and reference forms for relocatable data. */ 23150397Sobrien#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4) 23250397Sobrien#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4) 23350397Sobrien 23450397Sobrien/* Pseudo-op for defining a new section. */ 23550397Sobrien#ifndef SECTION_ASM_OP 23650397Sobrien#define SECTION_ASM_OP ".section" 23750397Sobrien#endif 23850397Sobrien 23950397Sobrien/* The default format used by the ASM_OUTPUT_SECTION macro (see below) to 24050397Sobrien print the SECTION_ASM_OP and the section name. The default here works for 24150397Sobrien almost all svr4 assemblers, except for the sparc, where the section name 24250397Sobrien must be enclosed in double quotes. (See sparcv4.h). */ 24350397Sobrien#ifndef SECTION_FORMAT 24450397Sobrien#ifdef PUSHSECTION_FORMAT 24550397Sobrien#define SECTION_FORMAT PUSHSECTION_FORMAT 24650397Sobrien#else 24750397Sobrien#define SECTION_FORMAT "\t%s\t%s\n" 24850397Sobrien#endif 24950397Sobrien#endif 25050397Sobrien 25150397Sobrien#ifndef FRAME_SECTION 25250397Sobrien#define FRAME_SECTION ".debug_frame" 25350397Sobrien#endif 25450397Sobrien 25550397Sobrien#ifndef FUNC_BEGIN_LABEL 25650397Sobrien#define FUNC_BEGIN_LABEL "LFB" 25750397Sobrien#endif 25850397Sobrien#ifndef FUNC_END_LABEL 25950397Sobrien#define FUNC_END_LABEL "LFE" 26050397Sobrien#endif 26150397Sobrien#define CIE_AFTER_SIZE_LABEL "LSCIE" 26250397Sobrien#define CIE_END_LABEL "LECIE" 26350397Sobrien#define CIE_LENGTH_LABEL "LLCIE" 26450397Sobrien#define FDE_AFTER_SIZE_LABEL "LSFDE" 26550397Sobrien#define FDE_END_LABEL "LEFDE" 26650397Sobrien#define FDE_LENGTH_LABEL "LLFDE" 26750397Sobrien 26850397Sobrien/* Definitions of defaults for various types of primitive assembly language 26950397Sobrien output operations. These may be overridden from within the tm.h file, 27050397Sobrien but typically, that is unnecessary. */ 27150397Sobrien 27250397Sobrien#ifndef ASM_OUTPUT_SECTION 27350397Sobrien#define ASM_OUTPUT_SECTION(FILE, SECTION) \ 27450397Sobrien fprintf ((FILE), SECTION_FORMAT, SECTION_ASM_OP, SECTION) 27550397Sobrien#endif 27650397Sobrien 27750397Sobrien#ifndef ASM_OUTPUT_DWARF_DATA1 27850397Sobrien#define ASM_OUTPUT_DWARF_DATA1(FILE,VALUE) \ 27950397Sobrien fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) (VALUE)) 28050397Sobrien#endif 28150397Sobrien 28250397Sobrien#ifndef ASM_OUTPUT_DWARF_DELTA1 28350397Sobrien#define ASM_OUTPUT_DWARF_DELTA1(FILE,LABEL1,LABEL2) \ 28450397Sobrien do { fprintf ((FILE), "\t%s\t", ASM_BYTE_OP); \ 28550397Sobrien assemble_name (FILE, LABEL1); \ 28650397Sobrien fprintf (FILE, "-"); \ 28750397Sobrien assemble_name (FILE, LABEL2); \ 28850397Sobrien } while (0) 28950397Sobrien#endif 29050397Sobrien 29150397Sobrien#ifdef UNALIGNED_INT_ASM_OP 29250397Sobrien 29350397Sobrien#ifndef UNALIGNED_OFFSET_ASM_OP 29450397Sobrien#define UNALIGNED_OFFSET_ASM_OP \ 29550397Sobrien (DWARF_OFFSET_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP) 29650397Sobrien#endif 29750397Sobrien 29850397Sobrien#ifndef UNALIGNED_WORD_ASM_OP 29950397Sobrien#define UNALIGNED_WORD_ASM_OP \ 30050397Sobrien (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP) 30150397Sobrien#endif 30250397Sobrien 30350397Sobrien#ifndef ASM_OUTPUT_DWARF_DELTA2 30450397Sobrien#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \ 30550397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \ 30650397Sobrien assemble_name (FILE, LABEL1); \ 30750397Sobrien fprintf (FILE, "-"); \ 30850397Sobrien assemble_name (FILE, LABEL2); \ 30950397Sobrien } while (0) 31050397Sobrien#endif 31150397Sobrien 31250397Sobrien#ifndef ASM_OUTPUT_DWARF_DELTA4 31350397Sobrien#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \ 31450397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ 31550397Sobrien assemble_name (FILE, LABEL1); \ 31650397Sobrien fprintf (FILE, "-"); \ 31750397Sobrien assemble_name (FILE, LABEL2); \ 31850397Sobrien } while (0) 31950397Sobrien#endif 32050397Sobrien 32150397Sobrien#ifndef ASM_OUTPUT_DWARF_DELTA 32250397Sobrien#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \ 32350397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP); \ 32450397Sobrien assemble_name (FILE, LABEL1); \ 32550397Sobrien fprintf (FILE, "-"); \ 32650397Sobrien assemble_name (FILE, LABEL2); \ 32750397Sobrien } while (0) 32850397Sobrien#endif 32950397Sobrien 33050397Sobrien#ifndef ASM_OUTPUT_DWARF_ADDR_DELTA 33150397Sobrien#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \ 33250397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP); \ 33350397Sobrien assemble_name (FILE, LABEL1); \ 33450397Sobrien fprintf (FILE, "-"); \ 33550397Sobrien assemble_name (FILE, LABEL2); \ 33650397Sobrien } while (0) 33750397Sobrien#endif 33850397Sobrien 33950397Sobrien#ifndef ASM_OUTPUT_DWARF_ADDR 34050397Sobrien#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \ 34150397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP); \ 34250397Sobrien assemble_name (FILE, LABEL); \ 34350397Sobrien } while (0) 34450397Sobrien#endif 34550397Sobrien 34652284Sobrien/* ??? This macro takes an RTX in dwarfout.c and a string in dwarf2out.c. 34752284Sobrien We resolve the conflict by creating a new macro ASM_OUTPUT_DWARF2_ADDR_CONST 34852284Sobrien for ports that want to support both DWARF1 and DWARF2. This needs a better 34952284Sobrien solution. See also the comments in sparc/sp64-elf.h. */ 35052284Sobrien#ifdef ASM_OUTPUT_DWARF2_ADDR_CONST 35152284Sobrien#undef ASM_OUTPUT_DWARF_ADDR_CONST 35252284Sobrien#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \ 35352284Sobrien ASM_OUTPUT_DWARF2_ADDR_CONST (FILE, ADDR) 35452284Sobrien#endif 35552284Sobrien 35650397Sobrien#ifndef ASM_OUTPUT_DWARF_ADDR_CONST 35750397Sobrien#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,ADDR) \ 35850397Sobrien fprintf ((FILE), "\t%s\t%s", UNALIGNED_WORD_ASM_OP, (ADDR)) 35950397Sobrien#endif 36050397Sobrien 36150397Sobrien#ifndef ASM_OUTPUT_DWARF_OFFSET4 36250397Sobrien#define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \ 36350397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ 36450397Sobrien assemble_name (FILE, LABEL); \ 36550397Sobrien } while (0) 36650397Sobrien#endif 36750397Sobrien 36850397Sobrien#ifndef ASM_OUTPUT_DWARF_OFFSET 36950397Sobrien#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \ 37050397Sobrien do { fprintf ((FILE), "\t%s\t", UNALIGNED_OFFSET_ASM_OP); \ 37150397Sobrien assemble_name (FILE, LABEL); \ 37250397Sobrien } while (0) 37350397Sobrien#endif 37450397Sobrien 37550397Sobrien#ifndef ASM_OUTPUT_DWARF_DATA2 37650397Sobrien#define ASM_OUTPUT_DWARF_DATA2(FILE,VALUE) \ 37750397Sobrien fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, (unsigned) (VALUE)) 37850397Sobrien#endif 37950397Sobrien 38050397Sobrien#ifndef ASM_OUTPUT_DWARF_DATA4 38150397Sobrien#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \ 38250397Sobrien fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_INT_ASM_OP, (unsigned) (VALUE)) 38350397Sobrien#endif 38450397Sobrien 38550397Sobrien#ifndef ASM_OUTPUT_DWARF_DATA 38650397Sobrien#define ASM_OUTPUT_DWARF_DATA(FILE,VALUE) \ 38750397Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP, \ 38850397Sobrien (unsigned long) (VALUE)) 38950397Sobrien#endif 39050397Sobrien 39150397Sobrien#ifndef ASM_OUTPUT_DWARF_ADDR_DATA 39250397Sobrien#define ASM_OUTPUT_DWARF_ADDR_DATA(FILE,VALUE) \ 39350397Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_WORD_ASM_OP, \ 39450397Sobrien (unsigned long) (VALUE)) 39550397Sobrien#endif 39650397Sobrien 39750397Sobrien#ifndef ASM_OUTPUT_DWARF_DATA8 39850397Sobrien#define ASM_OUTPUT_DWARF_DATA8(FILE,HIGH_VALUE,LOW_VALUE) \ 39950397Sobrien do { \ 40050397Sobrien if (WORDS_BIG_ENDIAN) \ 40150397Sobrien { \ 40250397Sobrien fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (HIGH_VALUE));\ 40350397Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (LOW_VALUE));\ 40450397Sobrien } \ 40550397Sobrien else \ 40650397Sobrien { \ 40750397Sobrien fprintf ((FILE), "\t%s\t0x%lx\n", UNALIGNED_INT_ASM_OP, (LOW_VALUE)); \ 40850397Sobrien fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (HIGH_VALUE)); \ 40950397Sobrien } \ 41050397Sobrien } while (0) 41150397Sobrien#endif 41250397Sobrien 41350397Sobrien#else /* UNALIGNED_INT_ASM_OP */ 41450397Sobrien 41550397Sobrien/* We don't have unaligned support, let's hope the normal output works for 41650397Sobrien .debug_frame. */ 41750397Sobrien 41850397Sobrien#define ASM_OUTPUT_DWARF_ADDR(FILE,LABEL) \ 41950397Sobrien assemble_integer (gen_rtx_SYMBOL_REF (Pmode, LABEL), PTR_SIZE, 1) 42050397Sobrien 42150397Sobrien#define ASM_OUTPUT_DWARF_OFFSET4(FILE,LABEL) \ 42250397Sobrien assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1) 42350397Sobrien 42450397Sobrien#define ASM_OUTPUT_DWARF_OFFSET(FILE,LABEL) \ 42550397Sobrien assemble_integer (gen_rtx_SYMBOL_REF (SImode, LABEL), 4, 1) 42650397Sobrien 42750397Sobrien#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \ 42850397Sobrien assemble_integer (gen_rtx_MINUS (HImode, \ 42950397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL1), \ 43050397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \ 43150397Sobrien 2, 1) 43250397Sobrien 43350397Sobrien#define ASM_OUTPUT_DWARF_DELTA4(FILE,LABEL1,LABEL2) \ 43450397Sobrien assemble_integer (gen_rtx_MINUS (SImode, \ 43550397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL1), \ 43650397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \ 43750397Sobrien 4, 1) 43850397Sobrien 43950397Sobrien#define ASM_OUTPUT_DWARF_ADDR_DELTA(FILE,LABEL1,LABEL2) \ 44050397Sobrien assemble_integer (gen_rtx_MINUS (Pmode, \ 44150397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL1), \ 44250397Sobrien gen_rtx_SYMBOL_REF (Pmode, LABEL2)), \ 44350397Sobrien PTR_SIZE, 1) 44450397Sobrien 44550397Sobrien#define ASM_OUTPUT_DWARF_DELTA(FILE,LABEL1,LABEL2) \ 44650397Sobrien ASM_OUTPUT_DWARF_DELTA4 (FILE,LABEL1,LABEL2) 44750397Sobrien 44850397Sobrien#define ASM_OUTPUT_DWARF_DATA4(FILE,VALUE) \ 44950397Sobrien assemble_integer (GEN_INT (VALUE), 4, 1) 45050397Sobrien 45150397Sobrien#endif /* UNALIGNED_INT_ASM_OP */ 45250397Sobrien 45350397Sobrien#ifdef SET_ASM_OP 45450397Sobrien#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 45550397Sobrien#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \ 45650397Sobrien do { \ 45750397Sobrien fprintf (FILE, "\t%s\t", SET_ASM_OP); \ 45850397Sobrien assemble_name (FILE, SY); \ 45950397Sobrien fputc (',', FILE); \ 46050397Sobrien assemble_name (FILE, HI); \ 46150397Sobrien fputc ('-', FILE); \ 46250397Sobrien assemble_name (FILE, LO); \ 46350397Sobrien } while (0) 46450397Sobrien#endif 46550397Sobrien#endif /* SET_ASM_OP */ 46650397Sobrien 46750397Sobrien/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing 46850397Sobrien newline is produced. When flag_debug_asm is asserted, we add commentary 46950397Sobrien at the end of the line, so we must avoid output of a newline here. */ 47050397Sobrien#ifndef ASM_OUTPUT_DWARF_STRING 47150397Sobrien#define ASM_OUTPUT_DWARF_STRING(FILE,P) \ 47250397Sobrien do { \ 47350397Sobrien register int slen = strlen(P); \ 47450397Sobrien register char *p = (P); \ 47550397Sobrien register int i; \ 47650397Sobrien fprintf (FILE, "\t.ascii \""); \ 47750397Sobrien for (i = 0; i < slen; i++) \ 47850397Sobrien { \ 47950397Sobrien register int c = p[i]; \ 48050397Sobrien if (c == '\"' || c == '\\') \ 48150397Sobrien putc ('\\', FILE); \ 48250397Sobrien if (c >= ' ' && c < 0177) \ 48350397Sobrien putc (c, FILE); \ 48450397Sobrien else \ 48550397Sobrien { \ 48650397Sobrien fprintf (FILE, "\\%o", c); \ 48750397Sobrien } \ 48850397Sobrien } \ 48950397Sobrien fprintf (FILE, "\\0\""); \ 49050397Sobrien } \ 49150397Sobrien while (0) 49250397Sobrien#endif 49350397Sobrien 49450397Sobrien/* The DWARF 2 CFA column which tracks the return address. Normally this 49550397Sobrien is the column for PC, or the first column after all of the hard 49650397Sobrien registers. */ 49750397Sobrien#ifndef DWARF_FRAME_RETURN_COLUMN 49850397Sobrien#ifdef PC_REGNUM 49950397Sobrien#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM) 50050397Sobrien#else 50150397Sobrien#define DWARF_FRAME_RETURN_COLUMN FIRST_PSEUDO_REGISTER 50250397Sobrien#endif 50350397Sobrien#endif 50450397Sobrien 50550397Sobrien/* The mapping from gcc register number to DWARF 2 CFA column number. By 50650397Sobrien default, we just provide columns for all registers. */ 50750397Sobrien#ifndef DWARF_FRAME_REGNUM 50850397Sobrien#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) 50950397Sobrien#endif 51050397Sobrien 51150397Sobrien/* Hook used by __throw. */ 51250397Sobrien 51350397Sobrienrtx 51450397Sobrienexpand_builtin_dwarf_fp_regnum () 51550397Sobrien{ 51650397Sobrien return GEN_INT (DWARF_FRAME_REGNUM (HARD_FRAME_POINTER_REGNUM)); 51750397Sobrien} 51850397Sobrien 51950397Sobrien/* The offset from the incoming value of %sp to the top of the stack frame 52050397Sobrien for the current function. */ 52150397Sobrien#ifndef INCOMING_FRAME_SP_OFFSET 52250397Sobrien#define INCOMING_FRAME_SP_OFFSET 0 52350397Sobrien#endif 52450397Sobrien 52550397Sobrien/* Return a pointer to a copy of the section string name S with all 52650397Sobrien attributes stripped off, and an asterisk prepended (for assemble_name). */ 52750397Sobrien 52850397Sobrienstatic inline char * 52950397Sobrienstripattributes (s) 53050397Sobrien char *s; 53150397Sobrien{ 53250397Sobrien char *stripped = xmalloc (strlen (s) + 2); 53350397Sobrien char *p = stripped; 53450397Sobrien 53550397Sobrien *p++ = '*'; 53650397Sobrien 53750397Sobrien while (*s && *s != ',') 53850397Sobrien *p++ = *s++; 53950397Sobrien 54050397Sobrien *p = '\0'; 54150397Sobrien return stripped; 54250397Sobrien} 54350397Sobrien 54450397Sobrien/* Return the register number described by a given RTL node. */ 54550397Sobrien 54650397Sobrienstatic unsigned 54750397Sobrienreg_number (rtl) 54850397Sobrien register rtx rtl; 54950397Sobrien{ 55050397Sobrien register unsigned regno = REGNO (rtl); 55150397Sobrien 55250397Sobrien if (regno >= FIRST_PSEUDO_REGISTER) 55350397Sobrien { 55450397Sobrien warning ("internal regno botch: regno = %d\n", regno); 55550397Sobrien regno = 0; 55650397Sobrien } 55750397Sobrien 55850397Sobrien regno = DBX_REGISTER_NUMBER (regno); 55950397Sobrien return regno; 56050397Sobrien} 56150397Sobrien 56250397Sobrienstruct reg_size_range 56350397Sobrien{ 56450397Sobrien int beg; 56550397Sobrien int end; 56650397Sobrien int size; 56750397Sobrien}; 56850397Sobrien 56950397Sobrien/* Given a register number in REG_TREE, return an rtx for its size in bytes. 57050397Sobrien We do this in kind of a roundabout way, by building up a list of 57150397Sobrien register size ranges and seeing where our register falls in one of those 57250397Sobrien ranges. We need to do it this way because REG_TREE is not a constant, 57350397Sobrien and the target macros were not designed to make this task easy. */ 57450397Sobrien 57550397Sobrienrtx 57650397Sobrienexpand_builtin_dwarf_reg_size (reg_tree, target) 57750397Sobrien tree reg_tree; 57850397Sobrien rtx target; 57950397Sobrien{ 58050397Sobrien enum machine_mode mode; 58150397Sobrien int size; 58250397Sobrien struct reg_size_range ranges[5]; 58350397Sobrien tree t, t2; 58450397Sobrien 58550397Sobrien int i = 0; 58650397Sobrien int n_ranges = 0; 58750397Sobrien int last_size = -1; 58850397Sobrien 58950397Sobrien for (; i < FIRST_PSEUDO_REGISTER; ++i) 59050397Sobrien { 59150397Sobrien /* The return address is out of order on the MIPS, and we don't use 59250397Sobrien copy_reg for it anyway, so we don't care here how large it is. */ 59350397Sobrien if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN) 59450397Sobrien continue; 59550397Sobrien 59650397Sobrien mode = reg_raw_mode[i]; 59750397Sobrien 59850397Sobrien /* CCmode is arbitrarily given a size of 4 bytes. It is more useful 59950397Sobrien to use the same size as word_mode, since that reduces the number 60050397Sobrien of ranges we need. It should not matter, since the result should 60150397Sobrien never be used for a condition code register anyways. */ 60250397Sobrien if (GET_MODE_CLASS (mode) == MODE_CC) 60350397Sobrien mode = word_mode; 60450397Sobrien 60550397Sobrien size = GET_MODE_SIZE (mode); 60650397Sobrien 60750397Sobrien /* If this register is not valid in the specified mode and 60850397Sobrien we have a previous size, use that for the size of this 60950397Sobrien register to avoid making junk tiny ranges. */ 61050397Sobrien if (! HARD_REGNO_MODE_OK (i, mode) && last_size != -1) 61150397Sobrien size = last_size; 61250397Sobrien 61350397Sobrien if (size != last_size) 61450397Sobrien { 61550397Sobrien ranges[n_ranges].beg = i; 61650397Sobrien ranges[n_ranges].size = last_size = size; 61750397Sobrien ++n_ranges; 61850397Sobrien if (n_ranges >= 5) 61950397Sobrien abort (); 62050397Sobrien } 62150397Sobrien ranges[n_ranges-1].end = i; 62250397Sobrien } 62350397Sobrien 62450397Sobrien /* The usual case: fp regs surrounded by general regs. */ 62550397Sobrien if (n_ranges == 3 && ranges[0].size == ranges[2].size) 62650397Sobrien { 62750397Sobrien if ((DWARF_FRAME_REGNUM (ranges[1].end) 62850397Sobrien - DWARF_FRAME_REGNUM (ranges[1].beg)) 62950397Sobrien != ranges[1].end - ranges[1].beg) 63050397Sobrien abort (); 63150397Sobrien t = fold (build (GE_EXPR, integer_type_node, reg_tree, 63250397Sobrien build_int_2 (DWARF_FRAME_REGNUM (ranges[1].beg), 0))); 63350397Sobrien t2 = fold (build (LE_EXPR, integer_type_node, reg_tree, 63450397Sobrien build_int_2 (DWARF_FRAME_REGNUM (ranges[1].end), 0))); 63550397Sobrien t = fold (build (TRUTH_ANDIF_EXPR, integer_type_node, t, t2)); 63650397Sobrien t = fold (build (COND_EXPR, integer_type_node, t, 63750397Sobrien build_int_2 (ranges[1].size, 0), 63850397Sobrien build_int_2 (ranges[0].size, 0))); 63950397Sobrien } 64050397Sobrien else 64150397Sobrien { 64252284Sobrien /* Initialize last_end to be larger than any possible 64352284Sobrien DWARF_FRAME_REGNUM. */ 64452284Sobrien int last_end = 0x7fffffff; 64550397Sobrien --n_ranges; 64650397Sobrien t = build_int_2 (ranges[n_ranges].size, 0); 64752284Sobrien do 64850397Sobrien { 64952284Sobrien int beg = DWARF_FRAME_REGNUM (ranges[n_ranges].beg); 65052284Sobrien int end = DWARF_FRAME_REGNUM (ranges[n_ranges].end); 65152284Sobrien if (beg < 0) 65252284Sobrien continue; 65352284Sobrien if (end >= last_end) 65450397Sobrien abort (); 65552284Sobrien last_end = end; 65652284Sobrien if (end - beg != ranges[n_ranges].end - ranges[n_ranges].beg) 65750397Sobrien abort (); 65850397Sobrien t2 = fold (build (LE_EXPR, integer_type_node, reg_tree, 65952284Sobrien build_int_2 (end, 0))); 66050397Sobrien t = fold (build (COND_EXPR, integer_type_node, t2, 66150397Sobrien build_int_2 (ranges[n_ranges].size, 0), t)); 66250397Sobrien } 66352284Sobrien while (--n_ranges >= 0); 66450397Sobrien } 66550397Sobrien return expand_expr (t, target, Pmode, 0); 66650397Sobrien} 66750397Sobrien 66850397Sobrien/* Convert a DWARF call frame info. operation to its string name */ 66950397Sobrien 67050397Sobrienstatic char * 67150397Sobriendwarf_cfi_name (cfi_opc) 67250397Sobrien register unsigned cfi_opc; 67350397Sobrien{ 67450397Sobrien switch (cfi_opc) 67550397Sobrien { 67650397Sobrien case DW_CFA_advance_loc: 67750397Sobrien return "DW_CFA_advance_loc"; 67850397Sobrien case DW_CFA_offset: 67950397Sobrien return "DW_CFA_offset"; 68050397Sobrien case DW_CFA_restore: 68150397Sobrien return "DW_CFA_restore"; 68250397Sobrien case DW_CFA_nop: 68350397Sobrien return "DW_CFA_nop"; 68450397Sobrien case DW_CFA_set_loc: 68550397Sobrien return "DW_CFA_set_loc"; 68650397Sobrien case DW_CFA_advance_loc1: 68750397Sobrien return "DW_CFA_advance_loc1"; 68850397Sobrien case DW_CFA_advance_loc2: 68950397Sobrien return "DW_CFA_advance_loc2"; 69050397Sobrien case DW_CFA_advance_loc4: 69150397Sobrien return "DW_CFA_advance_loc4"; 69250397Sobrien case DW_CFA_offset_extended: 69350397Sobrien return "DW_CFA_offset_extended"; 69450397Sobrien case DW_CFA_restore_extended: 69550397Sobrien return "DW_CFA_restore_extended"; 69650397Sobrien case DW_CFA_undefined: 69750397Sobrien return "DW_CFA_undefined"; 69850397Sobrien case DW_CFA_same_value: 69950397Sobrien return "DW_CFA_same_value"; 70050397Sobrien case DW_CFA_register: 70150397Sobrien return "DW_CFA_register"; 70250397Sobrien case DW_CFA_remember_state: 70350397Sobrien return "DW_CFA_remember_state"; 70450397Sobrien case DW_CFA_restore_state: 70550397Sobrien return "DW_CFA_restore_state"; 70650397Sobrien case DW_CFA_def_cfa: 70750397Sobrien return "DW_CFA_def_cfa"; 70850397Sobrien case DW_CFA_def_cfa_register: 70950397Sobrien return "DW_CFA_def_cfa_register"; 71050397Sobrien case DW_CFA_def_cfa_offset: 71150397Sobrien return "DW_CFA_def_cfa_offset"; 71250397Sobrien 71350397Sobrien /* SGI/MIPS specific */ 71450397Sobrien case DW_CFA_MIPS_advance_loc8: 71550397Sobrien return "DW_CFA_MIPS_advance_loc8"; 71650397Sobrien 71750397Sobrien /* GNU extensions */ 71850397Sobrien case DW_CFA_GNU_window_save: 71950397Sobrien return "DW_CFA_GNU_window_save"; 72050397Sobrien case DW_CFA_GNU_args_size: 72150397Sobrien return "DW_CFA_GNU_args_size"; 72250397Sobrien 72350397Sobrien default: 72450397Sobrien return "DW_CFA_<unknown>"; 72550397Sobrien } 72650397Sobrien} 72750397Sobrien 72850397Sobrien/* Return a pointer to a newly allocated Call Frame Instruction. */ 72950397Sobrien 73050397Sobrienstatic inline dw_cfi_ref 73150397Sobriennew_cfi () 73250397Sobrien{ 73350397Sobrien register dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node)); 73450397Sobrien 73550397Sobrien cfi->dw_cfi_next = NULL; 73650397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0; 73750397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0; 73850397Sobrien 73950397Sobrien return cfi; 74050397Sobrien} 74150397Sobrien 74250397Sobrien/* Add a Call Frame Instruction to list of instructions. */ 74350397Sobrien 74450397Sobrienstatic inline void 74550397Sobrienadd_cfi (list_head, cfi) 74650397Sobrien register dw_cfi_ref *list_head; 74750397Sobrien register dw_cfi_ref cfi; 74850397Sobrien{ 74950397Sobrien register dw_cfi_ref *p; 75050397Sobrien 75150397Sobrien /* Find the end of the chain. */ 75250397Sobrien for (p = list_head; (*p) != NULL; p = &(*p)->dw_cfi_next) 75350397Sobrien ; 75450397Sobrien 75550397Sobrien *p = cfi; 75650397Sobrien} 75750397Sobrien 75850397Sobrien/* Generate a new label for the CFI info to refer to. */ 75950397Sobrien 76050397Sobrienchar * 76150397Sobriendwarf2out_cfi_label () 76250397Sobrien{ 76350397Sobrien static char label[20]; 76450397Sobrien static unsigned long label_num = 0; 76550397Sobrien 76650397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++); 76750397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 76850397Sobrien 76950397Sobrien return label; 77050397Sobrien} 77150397Sobrien 77250397Sobrien/* Add CFI to the current fde at the PC value indicated by LABEL if specified, 77350397Sobrien or to the CIE if LABEL is NULL. */ 77450397Sobrien 77550397Sobrienstatic void 77650397Sobrienadd_fde_cfi (label, cfi) 77750397Sobrien register char *label; 77850397Sobrien register dw_cfi_ref cfi; 77950397Sobrien{ 78050397Sobrien if (label) 78150397Sobrien { 78250397Sobrien register dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 78350397Sobrien 78450397Sobrien if (*label == 0) 78550397Sobrien label = dwarf2out_cfi_label (); 78650397Sobrien 78750397Sobrien if (fde->dw_fde_current_label == NULL 78850397Sobrien || strcmp (label, fde->dw_fde_current_label) != 0) 78950397Sobrien { 79050397Sobrien register dw_cfi_ref xcfi; 79150397Sobrien 79250397Sobrien fde->dw_fde_current_label = label = xstrdup (label); 79350397Sobrien 79450397Sobrien /* Set the location counter to the new label. */ 79550397Sobrien xcfi = new_cfi (); 79650397Sobrien xcfi->dw_cfi_opc = DW_CFA_advance_loc4; 79750397Sobrien xcfi->dw_cfi_oprnd1.dw_cfi_addr = label; 79850397Sobrien add_cfi (&fde->dw_fde_cfi, xcfi); 79950397Sobrien } 80050397Sobrien 80150397Sobrien add_cfi (&fde->dw_fde_cfi, cfi); 80250397Sobrien } 80350397Sobrien 80450397Sobrien else 80550397Sobrien add_cfi (&cie_cfi_head, cfi); 80650397Sobrien} 80750397Sobrien 80850397Sobrien/* Subroutine of lookup_cfa. */ 80950397Sobrien 81050397Sobrienstatic inline void 81150397Sobrienlookup_cfa_1 (cfi, regp, offsetp) 81250397Sobrien register dw_cfi_ref cfi; 81350397Sobrien register unsigned long *regp; 81450397Sobrien register long *offsetp; 81550397Sobrien{ 81650397Sobrien switch (cfi->dw_cfi_opc) 81750397Sobrien { 81850397Sobrien case DW_CFA_def_cfa_offset: 81950397Sobrien *offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset; 82050397Sobrien break; 82150397Sobrien case DW_CFA_def_cfa_register: 82250397Sobrien *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 82350397Sobrien break; 82450397Sobrien case DW_CFA_def_cfa: 82550397Sobrien *regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num; 82650397Sobrien *offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset; 82750397Sobrien break; 82850397Sobrien default: 82950397Sobrien break; 83050397Sobrien } 83150397Sobrien} 83250397Sobrien 83350397Sobrien/* Find the previous value for the CFA. */ 83450397Sobrien 83550397Sobrienstatic void 83650397Sobrienlookup_cfa (regp, offsetp) 83750397Sobrien register unsigned long *regp; 83850397Sobrien register long *offsetp; 83950397Sobrien{ 84050397Sobrien register dw_cfi_ref cfi; 84150397Sobrien 84250397Sobrien *regp = (unsigned long) -1; 84350397Sobrien *offsetp = 0; 84450397Sobrien 84550397Sobrien for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next) 84650397Sobrien lookup_cfa_1 (cfi, regp, offsetp); 84750397Sobrien 84850397Sobrien if (fde_table_in_use) 84950397Sobrien { 85050397Sobrien register dw_fde_ref fde = &fde_table[fde_table_in_use - 1]; 85150397Sobrien for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) 85250397Sobrien lookup_cfa_1 (cfi, regp, offsetp); 85350397Sobrien } 85450397Sobrien} 85550397Sobrien 85650397Sobrien/* The current rule for calculating the DWARF2 canonical frame address. */ 85750397Sobrienstatic unsigned long cfa_reg; 85850397Sobrienstatic long cfa_offset; 85950397Sobrien 86050397Sobrien/* The register used for saving registers to the stack, and its offset 86150397Sobrien from the CFA. */ 86250397Sobrienstatic unsigned cfa_store_reg; 86350397Sobrienstatic long cfa_store_offset; 86450397Sobrien 86550397Sobrien/* The running total of the size of arguments pushed onto the stack. */ 86650397Sobrienstatic long args_size; 86750397Sobrien 86850397Sobrien/* The last args_size we actually output. */ 86950397Sobrienstatic long old_args_size; 87050397Sobrien 87150397Sobrien/* Entry point to update the canonical frame address (CFA). 87250397Sobrien LABEL is passed to add_fde_cfi. The value of CFA is now to be 87350397Sobrien calculated from REG+OFFSET. */ 87450397Sobrien 87550397Sobrienvoid 87650397Sobriendwarf2out_def_cfa (label, reg, offset) 87750397Sobrien register char *label; 87850397Sobrien register unsigned reg; 87950397Sobrien register long offset; 88050397Sobrien{ 88150397Sobrien register dw_cfi_ref cfi; 88250397Sobrien unsigned long old_reg; 88350397Sobrien long old_offset; 88450397Sobrien 88550397Sobrien cfa_reg = reg; 88650397Sobrien cfa_offset = offset; 88750397Sobrien if (cfa_store_reg == reg) 88850397Sobrien cfa_store_offset = offset; 88950397Sobrien 89050397Sobrien reg = DWARF_FRAME_REGNUM (reg); 89150397Sobrien lookup_cfa (&old_reg, &old_offset); 89250397Sobrien 89350397Sobrien if (reg == old_reg && offset == old_offset) 89450397Sobrien return; 89550397Sobrien 89650397Sobrien cfi = new_cfi (); 89750397Sobrien 89850397Sobrien if (reg == old_reg) 89950397Sobrien { 90050397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_offset; 90150397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = offset; 90250397Sobrien } 90350397Sobrien 90450397Sobrien#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ 90550397Sobrien else if (offset == old_offset && old_reg != (unsigned long) -1) 90650397Sobrien { 90750397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa_register; 90850397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 90950397Sobrien } 91050397Sobrien#endif 91150397Sobrien 91250397Sobrien else 91350397Sobrien { 91450397Sobrien cfi->dw_cfi_opc = DW_CFA_def_cfa; 91550397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 91650397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; 91750397Sobrien } 91850397Sobrien 91950397Sobrien add_fde_cfi (label, cfi); 92050397Sobrien} 92150397Sobrien 92250397Sobrien/* Add the CFI for saving a register. REG is the CFA column number. 92350397Sobrien LABEL is passed to add_fde_cfi. 92450397Sobrien If SREG is -1, the register is saved at OFFSET from the CFA; 92550397Sobrien otherwise it is saved in SREG. */ 92650397Sobrien 92750397Sobrienstatic void 92850397Sobrienreg_save (label, reg, sreg, offset) 92950397Sobrien register char * label; 93050397Sobrien register unsigned reg; 93150397Sobrien register unsigned sreg; 93250397Sobrien register long offset; 93350397Sobrien{ 93450397Sobrien register dw_cfi_ref cfi = new_cfi (); 93550397Sobrien 93650397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg; 93750397Sobrien 93850397Sobrien /* The following comparison is correct. -1 is used to indicate that 93950397Sobrien the value isn't a register number. */ 94050397Sobrien if (sreg == (unsigned int) -1) 94150397Sobrien { 94250397Sobrien if (reg & ~0x3f) 94350397Sobrien /* The register number won't fit in 6 bits, so we have to use 94450397Sobrien the long form. */ 94550397Sobrien cfi->dw_cfi_opc = DW_CFA_offset_extended; 94650397Sobrien else 94750397Sobrien cfi->dw_cfi_opc = DW_CFA_offset; 94850397Sobrien 94950397Sobrien offset /= DWARF_CIE_DATA_ALIGNMENT; 95050397Sobrien if (offset < 0) 95150397Sobrien abort (); 95250397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_offset = offset; 95350397Sobrien } 95450397Sobrien else 95550397Sobrien { 95650397Sobrien cfi->dw_cfi_opc = DW_CFA_register; 95750397Sobrien cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg; 95850397Sobrien } 95950397Sobrien 96050397Sobrien add_fde_cfi (label, cfi); 96150397Sobrien} 96250397Sobrien 96350397Sobrien/* Add the CFI for saving a register window. LABEL is passed to reg_save. 96450397Sobrien This CFI tells the unwinder that it needs to restore the window registers 96550397Sobrien from the previous frame's window save area. 96650397Sobrien 96750397Sobrien ??? Perhaps we should note in the CIE where windows are saved (instead of 96850397Sobrien assuming 0(cfa)) and what registers are in the window. */ 96950397Sobrien 97050397Sobrienvoid 97150397Sobriendwarf2out_window_save (label) 97250397Sobrien register char * label; 97350397Sobrien{ 97450397Sobrien register dw_cfi_ref cfi = new_cfi (); 97550397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_window_save; 97650397Sobrien add_fde_cfi (label, cfi); 97750397Sobrien} 97850397Sobrien 97950397Sobrien/* Add a CFI to update the running total of the size of arguments 98050397Sobrien pushed onto the stack. */ 98150397Sobrien 98250397Sobrienvoid 98350397Sobriendwarf2out_args_size (label, size) 98450397Sobrien char *label; 98550397Sobrien long size; 98650397Sobrien{ 98750397Sobrien register dw_cfi_ref cfi; 98850397Sobrien 98950397Sobrien if (size == old_args_size) 99050397Sobrien return; 99150397Sobrien old_args_size = size; 99250397Sobrien 99350397Sobrien cfi = new_cfi (); 99450397Sobrien cfi->dw_cfi_opc = DW_CFA_GNU_args_size; 99550397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_offset = size; 99650397Sobrien add_fde_cfi (label, cfi); 99750397Sobrien} 99850397Sobrien 99950397Sobrien/* Entry point for saving a register to the stack. REG is the GCC register 100050397Sobrien number. LABEL and OFFSET are passed to reg_save. */ 100150397Sobrien 100250397Sobrienvoid 100350397Sobriendwarf2out_reg_save (label, reg, offset) 100450397Sobrien register char * label; 100550397Sobrien register unsigned reg; 100650397Sobrien register long offset; 100750397Sobrien{ 100850397Sobrien reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset); 100950397Sobrien} 101050397Sobrien 101150397Sobrien/* Entry point for saving the return address in the stack. 101250397Sobrien LABEL and OFFSET are passed to reg_save. */ 101350397Sobrien 101450397Sobrienvoid 101550397Sobriendwarf2out_return_save (label, offset) 101650397Sobrien register char * label; 101750397Sobrien register long offset; 101850397Sobrien{ 101950397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset); 102050397Sobrien} 102150397Sobrien 102250397Sobrien/* Entry point for saving the return address in a register. 102350397Sobrien LABEL and SREG are passed to reg_save. */ 102450397Sobrien 102550397Sobrienvoid 102650397Sobriendwarf2out_return_reg (label, sreg) 102750397Sobrien register char * label; 102850397Sobrien register unsigned sreg; 102950397Sobrien{ 103050397Sobrien reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0); 103150397Sobrien} 103250397Sobrien 103350397Sobrien/* Record the initial position of the return address. RTL is 103450397Sobrien INCOMING_RETURN_ADDR_RTX. */ 103550397Sobrien 103650397Sobrienstatic void 103750397Sobrieninitial_return_save (rtl) 103850397Sobrien register rtx rtl; 103950397Sobrien{ 104052284Sobrien unsigned int reg = (unsigned int) -1; 104150397Sobrien long offset = 0; 104250397Sobrien 104350397Sobrien switch (GET_CODE (rtl)) 104450397Sobrien { 104550397Sobrien case REG: 104650397Sobrien /* RA is in a register. */ 104750397Sobrien reg = reg_number (rtl); 104850397Sobrien break; 104950397Sobrien case MEM: 105050397Sobrien /* RA is on the stack. */ 105150397Sobrien rtl = XEXP (rtl, 0); 105250397Sobrien switch (GET_CODE (rtl)) 105350397Sobrien { 105450397Sobrien case REG: 105550397Sobrien if (REGNO (rtl) != STACK_POINTER_REGNUM) 105650397Sobrien abort (); 105750397Sobrien offset = 0; 105850397Sobrien break; 105950397Sobrien case PLUS: 106050397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 106150397Sobrien abort (); 106250397Sobrien offset = INTVAL (XEXP (rtl, 1)); 106350397Sobrien break; 106450397Sobrien case MINUS: 106550397Sobrien if (REGNO (XEXP (rtl, 0)) != STACK_POINTER_REGNUM) 106650397Sobrien abort (); 106750397Sobrien offset = -INTVAL (XEXP (rtl, 1)); 106850397Sobrien break; 106950397Sobrien default: 107050397Sobrien abort (); 107150397Sobrien } 107250397Sobrien break; 107350397Sobrien case PLUS: 107450397Sobrien /* The return address is at some offset from any value we can 107550397Sobrien actually load. For instance, on the SPARC it is in %i7+8. Just 107650397Sobrien ignore the offset for now; it doesn't matter for unwinding frames. */ 107750397Sobrien if (GET_CODE (XEXP (rtl, 1)) != CONST_INT) 107850397Sobrien abort (); 107950397Sobrien initial_return_save (XEXP (rtl, 0)); 108050397Sobrien return; 108150397Sobrien default: 108250397Sobrien abort (); 108350397Sobrien } 108450397Sobrien 108550397Sobrien reg_save (NULL, DWARF_FRAME_RETURN_COLUMN, reg, offset - cfa_offset); 108650397Sobrien} 108750397Sobrien 108850397Sobrien/* Check INSN to see if it looks like a push or a stack adjustment, and 108950397Sobrien make a note of it if it does. EH uses this information to find out how 109050397Sobrien much extra space it needs to pop off the stack. */ 109150397Sobrien 109250397Sobrienstatic void 109350397Sobriendwarf2out_stack_adjust (insn) 109450397Sobrien rtx insn; 109550397Sobrien{ 109650397Sobrien long offset; 109750397Sobrien char *label; 109850397Sobrien 109950397Sobrien if (! asynchronous_exceptions && GET_CODE (insn) == CALL_INSN) 110050397Sobrien { 110150397Sobrien /* Extract the size of the args from the CALL rtx itself. */ 110250397Sobrien 110350397Sobrien insn = PATTERN (insn); 110450397Sobrien if (GET_CODE (insn) == PARALLEL) 110550397Sobrien insn = XVECEXP (insn, 0, 0); 110650397Sobrien if (GET_CODE (insn) == SET) 110750397Sobrien insn = SET_SRC (insn); 110850397Sobrien assert (GET_CODE (insn) == CALL); 110950397Sobrien dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); 111050397Sobrien return; 111150397Sobrien } 111250397Sobrien 111350397Sobrien /* If only calls can throw, and we have a frame pointer, 111450397Sobrien save up adjustments until we see the CALL_INSN. */ 111550397Sobrien else if (! asynchronous_exceptions 111650397Sobrien && cfa_reg != STACK_POINTER_REGNUM) 111750397Sobrien return; 111850397Sobrien 111950397Sobrien if (GET_CODE (insn) == BARRIER) 112050397Sobrien { 112150397Sobrien /* When we see a BARRIER, we know to reset args_size to 0. Usually 112250397Sobrien the compiler will have already emitted a stack adjustment, but 112350397Sobrien doesn't bother for calls to noreturn functions. */ 112450397Sobrien#ifdef STACK_GROWS_DOWNWARD 112550397Sobrien offset = -args_size; 112650397Sobrien#else 112750397Sobrien offset = args_size; 112850397Sobrien#endif 112950397Sobrien } 113050397Sobrien else if (GET_CODE (PATTERN (insn)) == SET) 113150397Sobrien { 113250397Sobrien rtx src, dest; 113350397Sobrien enum rtx_code code; 113450397Sobrien 113550397Sobrien insn = PATTERN (insn); 113650397Sobrien src = SET_SRC (insn); 113750397Sobrien dest = SET_DEST (insn); 113850397Sobrien 113950397Sobrien if (dest == stack_pointer_rtx) 114050397Sobrien { 114150397Sobrien /* (set (reg sp) (plus (reg sp) (const_int))) */ 114250397Sobrien code = GET_CODE (src); 114350397Sobrien if (! (code == PLUS || code == MINUS) 114450397Sobrien || XEXP (src, 0) != stack_pointer_rtx 114550397Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 114650397Sobrien return; 114750397Sobrien 114850397Sobrien offset = INTVAL (XEXP (src, 1)); 114950397Sobrien } 115050397Sobrien else if (GET_CODE (dest) == MEM) 115150397Sobrien { 115250397Sobrien /* (set (mem (pre_dec (reg sp))) (foo)) */ 115350397Sobrien src = XEXP (dest, 0); 115450397Sobrien code = GET_CODE (src); 115550397Sobrien 115650397Sobrien if (! (code == PRE_DEC || code == PRE_INC) 115750397Sobrien || XEXP (src, 0) != stack_pointer_rtx) 115850397Sobrien return; 115950397Sobrien 116050397Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 116150397Sobrien } 116250397Sobrien else 116350397Sobrien return; 116450397Sobrien 116550397Sobrien if (code == PLUS || code == PRE_INC) 116650397Sobrien offset = -offset; 116750397Sobrien } 116850397Sobrien else 116950397Sobrien return; 117050397Sobrien 117150397Sobrien if (offset == 0) 117250397Sobrien return; 117350397Sobrien 117450397Sobrien if (cfa_reg == STACK_POINTER_REGNUM) 117550397Sobrien cfa_offset += offset; 117650397Sobrien 117750397Sobrien#ifndef STACK_GROWS_DOWNWARD 117850397Sobrien offset = -offset; 117950397Sobrien#endif 118050397Sobrien args_size += offset; 118150397Sobrien if (args_size < 0) 118250397Sobrien args_size = 0; 118350397Sobrien 118450397Sobrien label = dwarf2out_cfi_label (); 118550397Sobrien dwarf2out_def_cfa (label, cfa_reg, cfa_offset); 118650397Sobrien dwarf2out_args_size (label, args_size); 118750397Sobrien} 118850397Sobrien 118952284Sobrien/* A temporary register used in adjusting SP or setting up the store_reg. */ 119052284Sobrienstatic unsigned cfa_temp_reg; 119152284Sobrien 119252284Sobrien/* A temporary value used in adjusting SP or setting up the store_reg. */ 119352284Sobrienstatic long cfa_temp_value; 119452284Sobrien 119552284Sobrien/* Record call frame debugging information for an expression, which either 119650397Sobrien sets SP or FP (adjusting how we calculate the frame address) or saves a 119752284Sobrien register to the stack. */ 119850397Sobrien 119952284Sobrienstatic void 120052284Sobriendwarf2out_frame_debug_expr (expr, label) 120152284Sobrien rtx expr; 120252284Sobrien char *label; 120350397Sobrien{ 120450397Sobrien rtx src, dest; 120550397Sobrien long offset; 120652284Sobrien 120752284Sobrien /* If RTX_FRAME_RELATED_P is set on a PARALLEL, process each member of 120852284Sobrien the PARALLEL independantly. The first element is always processed if 120952284Sobrien it is a SET. This is for backward compatability. Other elements 121052284Sobrien are processed only if they are SETs and the RTX_FRAME_RELATED_P 121152284Sobrien flag is set in them. */ 121250397Sobrien 121352284Sobrien if (GET_CODE (expr) == PARALLEL) 121452284Sobrien { 121552284Sobrien int par_index; 121652284Sobrien int limit = XVECLEN (expr, 0); 121750397Sobrien 121852284Sobrien for (par_index = 0; par_index < limit; par_index++) 121952284Sobrien { 122052284Sobrien rtx x = XVECEXP (expr, 0, par_index); 122152284Sobrien 122252284Sobrien if (GET_CODE (x) == SET && 122352284Sobrien (RTX_FRAME_RELATED_P (x) || par_index == 0)) 122452284Sobrien dwarf2out_frame_debug_expr (x, label); 122552284Sobrien } 122650397Sobrien return; 122750397Sobrien } 122852284Sobrien 122952284Sobrien if (GET_CODE (expr) != SET) 123050397Sobrien abort (); 123150397Sobrien 123252284Sobrien src = SET_SRC (expr); 123352284Sobrien dest = SET_DEST (expr); 123450397Sobrien 123550397Sobrien switch (GET_CODE (dest)) 123650397Sobrien { 123750397Sobrien case REG: 123850397Sobrien /* Update the CFA rule wrt SP or FP. Make sure src is 123952284Sobrien relative to the current CFA register. */ 124050397Sobrien switch (GET_CODE (src)) 124152284Sobrien { 124252284Sobrien /* Setting FP from SP. */ 124352284Sobrien case REG: 124452284Sobrien if (cfa_reg != (unsigned) REGNO (src)) 124552284Sobrien abort (); 124652284Sobrien if (REGNO (dest) != STACK_POINTER_REGNUM 124752284Sobrien && !(frame_pointer_needed 124852284Sobrien && REGNO (dest) == HARD_FRAME_POINTER_REGNUM)) 124952284Sobrien abort (); 125052284Sobrien cfa_reg = REGNO (dest); 125152284Sobrien break; 125250397Sobrien 125352284Sobrien case PLUS: 125452284Sobrien case MINUS: 125552284Sobrien if (dest == stack_pointer_rtx) 125652284Sobrien { 125752284Sobrien /* Adjusting SP. */ 125852284Sobrien switch (GET_CODE (XEXP (src, 1))) 125952284Sobrien { 126052284Sobrien case CONST_INT: 126152284Sobrien offset = INTVAL (XEXP (src, 1)); 126252284Sobrien break; 126352284Sobrien case REG: 126452284Sobrien if ((unsigned) REGNO (XEXP (src, 1)) != cfa_temp_reg) 126552284Sobrien abort (); 126652284Sobrien offset = cfa_temp_value; 126752284Sobrien break; 126852284Sobrien default: 126952284Sobrien abort (); 127052284Sobrien } 127150397Sobrien 127252284Sobrien if (XEXP (src, 0) == hard_frame_pointer_rtx) 127352284Sobrien { 127452284Sobrien /* Restoring SP from FP in the epilogue. */ 127552284Sobrien if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM) 127652284Sobrien abort (); 127752284Sobrien cfa_reg = STACK_POINTER_REGNUM; 127852284Sobrien } 127952284Sobrien else if (XEXP (src, 0) != stack_pointer_rtx) 128052284Sobrien abort (); 128150397Sobrien 128252284Sobrien if (GET_CODE (src) == PLUS) 128352284Sobrien offset = -offset; 128452284Sobrien if (cfa_reg == STACK_POINTER_REGNUM) 128552284Sobrien cfa_offset += offset; 128652284Sobrien if (cfa_store_reg == STACK_POINTER_REGNUM) 128752284Sobrien cfa_store_offset += offset; 128852284Sobrien } 128950397Sobrien else if (dest == hard_frame_pointer_rtx) 129050397Sobrien { 129152284Sobrien /* Either setting the FP from an offset of the SP, 129252284Sobrien or adjusting the FP */ 129352284Sobrien if (! frame_pointer_needed 129452284Sobrien || REGNO (dest) != HARD_FRAME_POINTER_REGNUM) 129552284Sobrien abort (); 129650397Sobrien 129752284Sobrien if (XEXP (src, 0) == stack_pointer_rtx 129852284Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 129952284Sobrien { 130052284Sobrien if (cfa_reg != STACK_POINTER_REGNUM) 130152284Sobrien abort (); 130252284Sobrien offset = INTVAL (XEXP (src, 1)); 130352284Sobrien if (GET_CODE (src) == PLUS) 130452284Sobrien offset = -offset; 130552284Sobrien cfa_offset += offset; 130652284Sobrien cfa_reg = HARD_FRAME_POINTER_REGNUM; 130752284Sobrien } 130852284Sobrien else if (XEXP (src, 0) == hard_frame_pointer_rtx 130952284Sobrien && GET_CODE (XEXP (src, 1)) == CONST_INT) 131052284Sobrien { 131152284Sobrien if (cfa_reg != (unsigned) HARD_FRAME_POINTER_REGNUM) 131252284Sobrien abort (); 131352284Sobrien offset = INTVAL (XEXP (src, 1)); 131452284Sobrien if (GET_CODE (src) == PLUS) 131552284Sobrien offset = -offset; 131652284Sobrien cfa_offset += offset; 131752284Sobrien } 131850397Sobrien 131952284Sobrien else 132052284Sobrien abort(); 132150397Sobrien } 132252284Sobrien else 132352284Sobrien { 132452284Sobrien if (GET_CODE (src) != PLUS 132552284Sobrien || XEXP (src, 1) != stack_pointer_rtx) 132652284Sobrien abort (); 132752284Sobrien if (GET_CODE (XEXP (src, 0)) != REG 132852284Sobrien || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg) 132952284Sobrien abort (); 133052284Sobrien if (cfa_reg != STACK_POINTER_REGNUM) 133152284Sobrien abort (); 133252284Sobrien cfa_store_reg = REGNO (dest); 133352284Sobrien cfa_store_offset = cfa_offset - cfa_temp_value; 133452284Sobrien } 133552284Sobrien break; 133650397Sobrien 133752284Sobrien case CONST_INT: 133852284Sobrien cfa_temp_reg = REGNO (dest); 133952284Sobrien cfa_temp_value = INTVAL (src); 134052284Sobrien break; 134150397Sobrien 134252284Sobrien case IOR: 134352284Sobrien if (GET_CODE (XEXP (src, 0)) != REG 134452284Sobrien || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp_reg 134552284Sobrien || (unsigned) REGNO (dest) != cfa_temp_reg 134652284Sobrien || GET_CODE (XEXP (src, 1)) != CONST_INT) 134752284Sobrien abort (); 134852284Sobrien cfa_temp_value |= INTVAL (XEXP (src, 1)); 134952284Sobrien break; 135050397Sobrien 135152284Sobrien default: 135252284Sobrien abort (); 135352284Sobrien } 135450397Sobrien dwarf2out_def_cfa (label, cfa_reg, cfa_offset); 135552284Sobrien break; 135650397Sobrien 135752284Sobrien case MEM: 135852284Sobrien /* Saving a register to the stack. Make sure dest is relative to the 135952284Sobrien CFA register. */ 136052284Sobrien if (GET_CODE (src) != REG) 136152284Sobrien abort (); 136252284Sobrien switch (GET_CODE (XEXP (dest, 0))) 136352284Sobrien { 136452284Sobrien /* With a push. */ 136552284Sobrien case PRE_INC: 136652284Sobrien case PRE_DEC: 136752284Sobrien offset = GET_MODE_SIZE (GET_MODE (dest)); 136852284Sobrien if (GET_CODE (XEXP (dest, 0)) == PRE_INC) 136952284Sobrien offset = -offset; 137050397Sobrien 137152284Sobrien if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM 137252284Sobrien || cfa_store_reg != STACK_POINTER_REGNUM) 137352284Sobrien abort (); 137452284Sobrien cfa_store_offset += offset; 137552284Sobrien if (cfa_reg == STACK_POINTER_REGNUM) 137652284Sobrien cfa_offset = cfa_store_offset; 137750397Sobrien 137852284Sobrien offset = -cfa_store_offset; 137952284Sobrien break; 138050397Sobrien 138152284Sobrien /* With an offset. */ 138252284Sobrien case PLUS: 138352284Sobrien case MINUS: 138452284Sobrien offset = INTVAL (XEXP (XEXP (dest, 0), 1)); 138552284Sobrien if (GET_CODE (XEXP (dest, 0)) == MINUS) 138652284Sobrien offset = -offset; 138750397Sobrien 138852284Sobrien if (cfa_store_reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) 138952284Sobrien abort (); 139052284Sobrien offset -= cfa_store_offset; 139152284Sobrien break; 139250397Sobrien 139352284Sobrien /* Without an offset. */ 139452284Sobrien case REG: 139552284Sobrien if (cfa_store_reg != (unsigned) REGNO (XEXP (dest, 0))) 139652284Sobrien abort(); 139752284Sobrien offset = -cfa_store_offset; 139852284Sobrien break; 139950397Sobrien 140052284Sobrien default: 140152284Sobrien abort (); 140252284Sobrien } 140352284Sobrien dwarf2out_def_cfa (label, cfa_reg, cfa_offset); 140452284Sobrien dwarf2out_reg_save (label, REGNO (src), offset); 140552284Sobrien break; 140652284Sobrien 140752284Sobrien default: 140852284Sobrien abort (); 140952284Sobrien } 141052284Sobrien} 141152284Sobrien 141252284Sobrien 141352284Sobrien/* Record call frame debugging information for INSN, which either 141452284Sobrien sets SP or FP (adjusting how we calculate the frame address) or saves a 141552284Sobrien register to the stack. If INSN is NULL_RTX, initialize our state. */ 141652284Sobrien 141752284Sobrienvoid 141852284Sobriendwarf2out_frame_debug (insn) 141952284Sobrien rtx insn; 142052284Sobrien{ 142152284Sobrien char *label; 142252284Sobrien rtx src; 142352284Sobrien 142452284Sobrien if (insn == NULL_RTX) 142552284Sobrien { 142652284Sobrien /* Set up state for generating call frame debug info. */ 142752284Sobrien lookup_cfa (&cfa_reg, &cfa_offset); 142852284Sobrien if (cfa_reg != DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)) 142952284Sobrien abort (); 143052284Sobrien cfa_reg = STACK_POINTER_REGNUM; 143152284Sobrien cfa_store_reg = cfa_reg; 143252284Sobrien cfa_store_offset = cfa_offset; 143352284Sobrien cfa_temp_reg = -1; 143452284Sobrien cfa_temp_value = 0; 143552284Sobrien return; 143650397Sobrien } 143752284Sobrien 143852284Sobrien if (! RTX_FRAME_RELATED_P (insn)) 143952284Sobrien { 144052284Sobrien dwarf2out_stack_adjust (insn); 144152284Sobrien return; 144252284Sobrien } 144352284Sobrien 144452284Sobrien label = dwarf2out_cfi_label (); 144552284Sobrien 144652284Sobrien src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); 144752284Sobrien if (src) 144852284Sobrien insn = XEXP (src, 0); 144952284Sobrien else 145052284Sobrien insn = PATTERN (insn); 145152284Sobrien 145252284Sobrien dwarf2out_frame_debug_expr (insn, label); 145350397Sobrien} 145450397Sobrien 145550397Sobrien/* Return the size of an unsigned LEB128 quantity. */ 145650397Sobrien 145750397Sobrienstatic inline unsigned long 145850397Sobriensize_of_uleb128 (value) 145950397Sobrien register unsigned long value; 146050397Sobrien{ 146150397Sobrien register unsigned long size = 0; 146250397Sobrien register unsigned byte; 146350397Sobrien 146450397Sobrien do 146550397Sobrien { 146650397Sobrien byte = (value & 0x7f); 146750397Sobrien value >>= 7; 146850397Sobrien size += 1; 146950397Sobrien } 147050397Sobrien while (value != 0); 147150397Sobrien 147250397Sobrien return size; 147350397Sobrien} 147450397Sobrien 147550397Sobrien/* Return the size of a signed LEB128 quantity. */ 147650397Sobrien 147750397Sobrienstatic inline unsigned long 147850397Sobriensize_of_sleb128 (value) 147950397Sobrien register long value; 148050397Sobrien{ 148150397Sobrien register unsigned long size = 0; 148250397Sobrien register unsigned byte; 148350397Sobrien 148450397Sobrien do 148550397Sobrien { 148650397Sobrien byte = (value & 0x7f); 148750397Sobrien value >>= 7; 148850397Sobrien size += 1; 148950397Sobrien } 149050397Sobrien while (!(((value == 0) && ((byte & 0x40) == 0)) 149150397Sobrien || ((value == -1) && ((byte & 0x40) != 0)))); 149250397Sobrien 149350397Sobrien return size; 149450397Sobrien} 149550397Sobrien 149650397Sobrien/* Output an unsigned LEB128 quantity. */ 149750397Sobrien 149850397Sobrienstatic void 149950397Sobrienoutput_uleb128 (value) 150050397Sobrien register unsigned long value; 150150397Sobrien{ 150250397Sobrien unsigned long save_value = value; 150350397Sobrien 150450397Sobrien fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP); 150550397Sobrien do 150650397Sobrien { 150750397Sobrien register unsigned byte = (value & 0x7f); 150850397Sobrien value >>= 7; 150950397Sobrien if (value != 0) 151050397Sobrien /* More bytes to follow. */ 151150397Sobrien byte |= 0x80; 151250397Sobrien 151350397Sobrien fprintf (asm_out_file, "0x%x", byte); 151450397Sobrien if (value != 0) 151550397Sobrien fprintf (asm_out_file, ","); 151650397Sobrien } 151750397Sobrien while (value != 0); 151850397Sobrien 151950397Sobrien if (flag_debug_asm) 152050397Sobrien fprintf (asm_out_file, "\t%s ULEB128 0x%lx", ASM_COMMENT_START, save_value); 152150397Sobrien} 152250397Sobrien 152350397Sobrien/* Output an signed LEB128 quantity. */ 152450397Sobrien 152550397Sobrienstatic void 152650397Sobrienoutput_sleb128 (value) 152750397Sobrien register long value; 152850397Sobrien{ 152950397Sobrien register int more; 153050397Sobrien register unsigned byte; 153150397Sobrien long save_value = value; 153250397Sobrien 153350397Sobrien fprintf (asm_out_file, "\t%s\t", ASM_BYTE_OP); 153450397Sobrien do 153550397Sobrien { 153650397Sobrien byte = (value & 0x7f); 153750397Sobrien /* arithmetic shift */ 153850397Sobrien value >>= 7; 153950397Sobrien more = !((((value == 0) && ((byte & 0x40) == 0)) 154050397Sobrien || ((value == -1) && ((byte & 0x40) != 0)))); 154150397Sobrien if (more) 154250397Sobrien byte |= 0x80; 154350397Sobrien 154450397Sobrien fprintf (asm_out_file, "0x%x", byte); 154550397Sobrien if (more) 154650397Sobrien fprintf (asm_out_file, ","); 154750397Sobrien } 154850397Sobrien 154950397Sobrien while (more); 155050397Sobrien if (flag_debug_asm) 155150397Sobrien fprintf (asm_out_file, "\t%s SLEB128 %ld", ASM_COMMENT_START, save_value); 155250397Sobrien} 155350397Sobrien 155450397Sobrien/* Output a Call Frame Information opcode and its operand(s). */ 155550397Sobrien 155650397Sobrienstatic void 155750397Sobrienoutput_cfi (cfi, fde) 155850397Sobrien register dw_cfi_ref cfi; 155950397Sobrien register dw_fde_ref fde; 156050397Sobrien{ 156150397Sobrien if (cfi->dw_cfi_opc == DW_CFA_advance_loc) 156250397Sobrien { 156350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 156450397Sobrien cfi->dw_cfi_opc 156550397Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)); 156650397Sobrien if (flag_debug_asm) 156750397Sobrien fprintf (asm_out_file, "\t%s DW_CFA_advance_loc 0x%lx", 156850397Sobrien ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_offset); 156950397Sobrien fputc ('\n', asm_out_file); 157050397Sobrien } 157150397Sobrien 157250397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_offset) 157350397Sobrien { 157450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 157550397Sobrien cfi->dw_cfi_opc 157650397Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)); 157750397Sobrien if (flag_debug_asm) 157850397Sobrien fprintf (asm_out_file, "\t%s DW_CFA_offset, column 0x%lx", 157950397Sobrien ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 158050397Sobrien 158150397Sobrien fputc ('\n', asm_out_file); 158250397Sobrien output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset); 158350397Sobrien fputc ('\n', asm_out_file); 158450397Sobrien } 158550397Sobrien else if (cfi->dw_cfi_opc == DW_CFA_restore) 158650397Sobrien { 158750397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 158850397Sobrien cfi->dw_cfi_opc 158950397Sobrien | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)); 159050397Sobrien if (flag_debug_asm) 159150397Sobrien fprintf (asm_out_file, "\t%s DW_CFA_restore, column 0x%lx", 159250397Sobrien ASM_COMMENT_START, cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 159350397Sobrien 159450397Sobrien fputc ('\n', asm_out_file); 159550397Sobrien } 159650397Sobrien else 159750397Sobrien { 159850397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, cfi->dw_cfi_opc); 159950397Sobrien if (flag_debug_asm) 160050397Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, 160150397Sobrien dwarf_cfi_name (cfi->dw_cfi_opc)); 160250397Sobrien 160350397Sobrien fputc ('\n', asm_out_file); 160450397Sobrien switch (cfi->dw_cfi_opc) 160550397Sobrien { 160650397Sobrien case DW_CFA_set_loc: 160750397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, cfi->dw_cfi_oprnd1.dw_cfi_addr); 160850397Sobrien fputc ('\n', asm_out_file); 160950397Sobrien break; 161050397Sobrien case DW_CFA_advance_loc1: 161150397Sobrien ASM_OUTPUT_DWARF_DELTA1 (asm_out_file, 161250397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, 161350397Sobrien fde->dw_fde_current_label); 161450397Sobrien fputc ('\n', asm_out_file); 161550397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 161650397Sobrien break; 161750397Sobrien case DW_CFA_advance_loc2: 161850397Sobrien ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, 161950397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, 162050397Sobrien fde->dw_fde_current_label); 162150397Sobrien fputc ('\n', asm_out_file); 162250397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 162350397Sobrien break; 162450397Sobrien case DW_CFA_advance_loc4: 162550397Sobrien ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, 162650397Sobrien cfi->dw_cfi_oprnd1.dw_cfi_addr, 162750397Sobrien fde->dw_fde_current_label); 162850397Sobrien fputc ('\n', asm_out_file); 162950397Sobrien fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; 163050397Sobrien break; 163150397Sobrien#ifdef MIPS_DEBUGGING_INFO 163250397Sobrien case DW_CFA_MIPS_advance_loc8: 163350397Sobrien /* TODO: not currently implemented. */ 163450397Sobrien abort (); 163550397Sobrien break; 163650397Sobrien#endif 163750397Sobrien case DW_CFA_offset_extended: 163850397Sobrien case DW_CFA_def_cfa: 163950397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 164050397Sobrien fputc ('\n', asm_out_file); 164150397Sobrien output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset); 164250397Sobrien fputc ('\n', asm_out_file); 164350397Sobrien break; 164450397Sobrien case DW_CFA_restore_extended: 164550397Sobrien case DW_CFA_undefined: 164650397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 164750397Sobrien fputc ('\n', asm_out_file); 164850397Sobrien break; 164950397Sobrien case DW_CFA_same_value: 165050397Sobrien case DW_CFA_def_cfa_register: 165150397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 165250397Sobrien fputc ('\n', asm_out_file); 165350397Sobrien break; 165450397Sobrien case DW_CFA_register: 165550397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num); 165650397Sobrien fputc ('\n', asm_out_file); 165750397Sobrien output_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num); 165850397Sobrien fputc ('\n', asm_out_file); 165950397Sobrien break; 166050397Sobrien case DW_CFA_def_cfa_offset: 166150397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset); 166250397Sobrien fputc ('\n', asm_out_file); 166350397Sobrien break; 166450397Sobrien case DW_CFA_GNU_window_save: 166550397Sobrien break; 166650397Sobrien case DW_CFA_GNU_args_size: 166750397Sobrien output_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset); 166850397Sobrien fputc ('\n', asm_out_file); 166950397Sobrien break; 167050397Sobrien default: 167150397Sobrien break; 167250397Sobrien } 167350397Sobrien } 167450397Sobrien} 167550397Sobrien 167650397Sobrien#if !defined (EH_FRAME_SECTION) 167750397Sobrien#if defined (EH_FRAME_SECTION_ASM_OP) 167850397Sobrien#define EH_FRAME_SECTION() eh_frame_section(); 167950397Sobrien#else 168050397Sobrien#if defined (ASM_OUTPUT_SECTION_NAME) 168150397Sobrien#define EH_FRAME_SECTION() \ 168250397Sobrien do { \ 168350397Sobrien named_section (NULL_TREE, ".eh_frame", 0); \ 168450397Sobrien } while (0) 168550397Sobrien#endif 168650397Sobrien#endif 168750397Sobrien#endif 168850397Sobrien 168950397Sobrien/* If we aren't using crtstuff to run ctors, don't use it for EH. */ 169050397Sobrien#if !defined (HAS_INIT_SECTION) && !defined (INIT_SECTION_ASM_OP) 169150397Sobrien#undef EH_FRAME_SECTION 169250397Sobrien#endif 169350397Sobrien 169450397Sobrien/* Output the call frame information used to used to record information 169550397Sobrien that relates to calculating the frame pointer, and records the 169650397Sobrien location of saved registers. */ 169750397Sobrien 169850397Sobrienstatic void 169950397Sobrienoutput_call_frame_info (for_eh) 170050397Sobrien int for_eh; 170150397Sobrien{ 170250397Sobrien register unsigned long i; 170350397Sobrien register dw_fde_ref fde; 170450397Sobrien register dw_cfi_ref cfi; 170550397Sobrien char l1[20], l2[20]; 170650397Sobrien#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 170750397Sobrien char ld[20]; 170850397Sobrien#endif 170950397Sobrien 171050397Sobrien /* Do we want to include a pointer to the exception table? */ 171150397Sobrien int eh_ptr = for_eh && exception_table_p (); 171250397Sobrien 171350397Sobrien fputc ('\n', asm_out_file); 171450397Sobrien 171550397Sobrien /* We're going to be generating comments, so turn on app. */ 171650397Sobrien if (flag_debug_asm) 171750397Sobrien app_enable (); 171850397Sobrien 171950397Sobrien if (for_eh) 172050397Sobrien { 172150397Sobrien#ifdef EH_FRAME_SECTION 172250397Sobrien EH_FRAME_SECTION (); 172350397Sobrien#else 172450397Sobrien tree label = get_file_function_name ('F'); 172550397Sobrien 172652284Sobrien force_data_section (); 172750397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 172850397Sobrien ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 172950397Sobrien ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); 173050397Sobrien#endif 173150397Sobrien assemble_label ("__FRAME_BEGIN__"); 173250397Sobrien } 173350397Sobrien else 173450397Sobrien ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION); 173550397Sobrien 173650397Sobrien /* Output the CIE. */ 173750397Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); 173850397Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); 173950397Sobrien#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 174050397Sobrien ASM_GENERATE_INTERNAL_LABEL (ld, CIE_LENGTH_LABEL, for_eh); 174150397Sobrien if (for_eh) 174250397Sobrien ASM_OUTPUT_DWARF_OFFSET4 (asm_out_file, ld); 174350397Sobrien else 174450397Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, ld); 174550397Sobrien#else 174650397Sobrien if (for_eh) 174750397Sobrien ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l2, l1); 174850397Sobrien else 174950397Sobrien ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1); 175050397Sobrien#endif 175150397Sobrien if (flag_debug_asm) 175250397Sobrien fprintf (asm_out_file, "\t%s Length of Common Information Entry", 175350397Sobrien ASM_COMMENT_START); 175450397Sobrien 175550397Sobrien fputc ('\n', asm_out_file); 175650397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 175750397Sobrien 175850397Sobrien if (for_eh) 175950397Sobrien /* Now that the CIE pointer is PC-relative for EH, 176050397Sobrien use 0 to identify the CIE. */ 176150397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0); 176250397Sobrien else 176350397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID); 176450397Sobrien 176550397Sobrien if (flag_debug_asm) 176650397Sobrien fprintf (asm_out_file, "\t%s CIE Identifier Tag", ASM_COMMENT_START); 176750397Sobrien 176850397Sobrien fputc ('\n', asm_out_file); 176950397Sobrien if (! for_eh && DWARF_OFFSET_SIZE == 8) 177050397Sobrien { 177150397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, DW_CIE_ID); 177250397Sobrien fputc ('\n', asm_out_file); 177350397Sobrien } 177450397Sobrien 177550397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CIE_VERSION); 177650397Sobrien if (flag_debug_asm) 177750397Sobrien fprintf (asm_out_file, "\t%s CIE Version", ASM_COMMENT_START); 177850397Sobrien 177950397Sobrien fputc ('\n', asm_out_file); 178050397Sobrien if (eh_ptr) 178150397Sobrien { 178250397Sobrien /* The CIE contains a pointer to the exception region info for the 178350397Sobrien frame. Make the augmentation string three bytes (including the 178450397Sobrien trailing null) so the pointer is 4-byte aligned. The Solaris ld 178550397Sobrien can't handle unaligned relocs. */ 178650397Sobrien if (flag_debug_asm) 178750397Sobrien { 178850397Sobrien ASM_OUTPUT_DWARF_STRING (asm_out_file, "eh"); 178950397Sobrien fprintf (asm_out_file, "\t%s CIE Augmentation", ASM_COMMENT_START); 179050397Sobrien } 179150397Sobrien else 179250397Sobrien { 179350397Sobrien ASM_OUTPUT_ASCII (asm_out_file, "eh", 3); 179450397Sobrien } 179550397Sobrien fputc ('\n', asm_out_file); 179650397Sobrien 179750397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, "__EXCEPTION_TABLE__"); 179850397Sobrien if (flag_debug_asm) 179950397Sobrien fprintf (asm_out_file, "\t%s pointer to exception region info", 180050397Sobrien ASM_COMMENT_START); 180150397Sobrien } 180250397Sobrien else 180350397Sobrien { 180450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 180550397Sobrien if (flag_debug_asm) 180650397Sobrien fprintf (asm_out_file, "\t%s CIE Augmentation (none)", 180750397Sobrien ASM_COMMENT_START); 180850397Sobrien } 180950397Sobrien 181050397Sobrien fputc ('\n', asm_out_file); 181150397Sobrien output_uleb128 (1); 181250397Sobrien if (flag_debug_asm) 181350397Sobrien fprintf (asm_out_file, " (CIE Code Alignment Factor)"); 181450397Sobrien 181550397Sobrien fputc ('\n', asm_out_file); 181650397Sobrien output_sleb128 (DWARF_CIE_DATA_ALIGNMENT); 181750397Sobrien if (flag_debug_asm) 181850397Sobrien fprintf (asm_out_file, " (CIE Data Alignment Factor)"); 181950397Sobrien 182050397Sobrien fputc ('\n', asm_out_file); 182150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_FRAME_RETURN_COLUMN); 182250397Sobrien if (flag_debug_asm) 182350397Sobrien fprintf (asm_out_file, "\t%s CIE RA Column", ASM_COMMENT_START); 182450397Sobrien 182550397Sobrien fputc ('\n', asm_out_file); 182650397Sobrien 182750397Sobrien for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next) 182850397Sobrien output_cfi (cfi, NULL); 182950397Sobrien 183050397Sobrien /* Pad the CIE out to an address sized boundary. */ 183150397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 183250397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 183350397Sobrien#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 183450397Sobrien ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1); 183550397Sobrien if (flag_debug_asm) 183650397Sobrien fprintf (asm_out_file, "\t%s CIE Length Symbol", ASM_COMMENT_START); 183750397Sobrien fputc ('\n', asm_out_file); 183850397Sobrien#endif 183950397Sobrien 184050397Sobrien /* Loop through all of the FDE's. */ 184150397Sobrien for (i = 0; i < fde_table_in_use; ++i) 184250397Sobrien { 184350397Sobrien fde = &fde_table[i]; 184450397Sobrien 184550397Sobrien ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i*2); 184650397Sobrien ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i*2); 184750397Sobrien#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 184850397Sobrien ASM_GENERATE_INTERNAL_LABEL (ld, FDE_LENGTH_LABEL, for_eh + i*2); 184950397Sobrien if (for_eh) 185050397Sobrien ASM_OUTPUT_DWARF_OFFSET4 (asm_out_file, ld); 185150397Sobrien else 185250397Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, ld); 185350397Sobrien#else 185450397Sobrien if (for_eh) 185550397Sobrien ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l2, l1); 185650397Sobrien else 185750397Sobrien ASM_OUTPUT_DWARF_DELTA (asm_out_file, l2, l1); 185850397Sobrien#endif 185950397Sobrien if (flag_debug_asm) 186050397Sobrien fprintf (asm_out_file, "\t%s FDE Length", ASM_COMMENT_START); 186150397Sobrien fputc ('\n', asm_out_file); 186250397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l1); 186350397Sobrien 186452284Sobrien /* ??? This always emits a 4 byte offset when for_eh is true, but it 186552284Sobrien emits a target dependent sized offset when for_eh is not true. 186652284Sobrien This inconsistency may confuse gdb. The only case where we need a 186752284Sobrien non-4 byte offset is for the Irix6 N64 ABI, so we may lose SGI 186852284Sobrien compatibility if we emit a 4 byte offset. We need a 4 byte offset 186952284Sobrien though in order to be compatible with the dwarf_fde struct in frame.c. 187052284Sobrien If the for_eh case is changed, then the struct in frame.c has 187152284Sobrien to be adjusted appropriately. */ 187250397Sobrien if (for_eh) 187352284Sobrien ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, l1, "__FRAME_BEGIN__"); 187450397Sobrien else 187550397Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, stripattributes (FRAME_SECTION)); 187650397Sobrien if (flag_debug_asm) 187750397Sobrien fprintf (asm_out_file, "\t%s FDE CIE offset", ASM_COMMENT_START); 187850397Sobrien 187950397Sobrien fputc ('\n', asm_out_file); 188050397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, fde->dw_fde_begin); 188150397Sobrien if (flag_debug_asm) 188250397Sobrien fprintf (asm_out_file, "\t%s FDE initial location", ASM_COMMENT_START); 188350397Sobrien 188450397Sobrien fputc ('\n', asm_out_file); 188550397Sobrien ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, 188650397Sobrien fde->dw_fde_end, fde->dw_fde_begin); 188750397Sobrien if (flag_debug_asm) 188850397Sobrien fprintf (asm_out_file, "\t%s FDE address range", ASM_COMMENT_START); 188950397Sobrien 189050397Sobrien fputc ('\n', asm_out_file); 189150397Sobrien 189250397Sobrien /* Loop through the Call Frame Instructions associated with 189350397Sobrien this FDE. */ 189450397Sobrien fde->dw_fde_current_label = fde->dw_fde_begin; 189550397Sobrien for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) 189650397Sobrien output_cfi (cfi, fde); 189750397Sobrien 189850397Sobrien /* Pad the FDE out to an address sized boundary. */ 189950397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); 190050397Sobrien ASM_OUTPUT_LABEL (asm_out_file, l2); 190150397Sobrien#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL 190250397Sobrien ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1); 190350397Sobrien if (flag_debug_asm) 190450397Sobrien fprintf (asm_out_file, "\t%s FDE Length Symbol", ASM_COMMENT_START); 190550397Sobrien fputc ('\n', asm_out_file); 190650397Sobrien#endif 190750397Sobrien } 190850397Sobrien#ifndef EH_FRAME_SECTION 190950397Sobrien if (for_eh) 191050397Sobrien { 191150397Sobrien /* Emit terminating zero for table. */ 191250397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0); 191350397Sobrien fputc ('\n', asm_out_file); 191450397Sobrien } 191550397Sobrien#endif 191650397Sobrien#ifdef MIPS_DEBUGGING_INFO 191750397Sobrien /* Work around Irix 6 assembler bug whereby labels at the end of a section 191850397Sobrien get a value of 0. Putting .align 0 after the label fixes it. */ 191950397Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 0); 192050397Sobrien#endif 192150397Sobrien 192250397Sobrien /* Turn off app to make assembly quicker. */ 192350397Sobrien if (flag_debug_asm) 192450397Sobrien app_disable (); 192550397Sobrien} 192650397Sobrien 192750397Sobrien/* Output a marker (i.e. a label) for the beginning of a function, before 192850397Sobrien the prologue. */ 192950397Sobrien 193050397Sobrienvoid 193150397Sobriendwarf2out_begin_prologue () 193250397Sobrien{ 193350397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 193450397Sobrien register dw_fde_ref fde; 193550397Sobrien 193650397Sobrien ++current_funcdef_number; 193750397Sobrien 193850397Sobrien function_section (current_function_decl); 193950397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 194050397Sobrien current_funcdef_number); 194150397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 194250397Sobrien 194350397Sobrien /* Expand the fde table if necessary. */ 194450397Sobrien if (fde_table_in_use == fde_table_allocated) 194550397Sobrien { 194650397Sobrien fde_table_allocated += FDE_TABLE_INCREMENT; 194750397Sobrien fde_table 194850397Sobrien = (dw_fde_ref) xrealloc (fde_table, 194950397Sobrien fde_table_allocated * sizeof (dw_fde_node)); 195050397Sobrien } 195150397Sobrien 195250397Sobrien /* Record the FDE associated with this function. */ 195350397Sobrien current_funcdef_fde = fde_table_in_use; 195450397Sobrien 195550397Sobrien /* Add the new FDE at the end of the fde_table. */ 195650397Sobrien fde = &fde_table[fde_table_in_use++]; 195750397Sobrien fde->dw_fde_begin = xstrdup (label); 195850397Sobrien fde->dw_fde_current_label = NULL; 195950397Sobrien fde->dw_fde_end = NULL; 196050397Sobrien fde->dw_fde_cfi = NULL; 196150397Sobrien 196250397Sobrien args_size = old_args_size = 0; 196350397Sobrien} 196450397Sobrien 196550397Sobrien/* Output a marker (i.e. a label) for the absolute end of the generated code 196650397Sobrien for a function definition. This gets called *after* the epilogue code has 196750397Sobrien been generated. */ 196850397Sobrien 196950397Sobrienvoid 197050397Sobriendwarf2out_end_epilogue () 197150397Sobrien{ 197250397Sobrien dw_fde_ref fde; 197350397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 197450397Sobrien 197550397Sobrien /* Output a label to mark the endpoint of the code generated for this 197650397Sobrien function. */ 197750397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number); 197850397Sobrien ASM_OUTPUT_LABEL (asm_out_file, label); 197950397Sobrien fde = &fde_table[fde_table_in_use - 1]; 198050397Sobrien fde->dw_fde_end = xstrdup (label); 198150397Sobrien} 198250397Sobrien 198350397Sobrienvoid 198450397Sobriendwarf2out_frame_init () 198550397Sobrien{ 198650397Sobrien /* Allocate the initial hunk of the fde_table. */ 198750397Sobrien fde_table 198850397Sobrien = (dw_fde_ref) xmalloc (FDE_TABLE_INCREMENT * sizeof (dw_fde_node)); 198950397Sobrien bzero ((char *) fde_table, FDE_TABLE_INCREMENT * sizeof (dw_fde_node)); 199050397Sobrien fde_table_allocated = FDE_TABLE_INCREMENT; 199150397Sobrien fde_table_in_use = 0; 199250397Sobrien 199350397Sobrien /* Generate the CFA instructions common to all FDE's. Do it now for the 199450397Sobrien sake of lookup_cfa. */ 199550397Sobrien 199650397Sobrien#ifdef DWARF2_UNWIND_INFO 199750397Sobrien /* On entry, the Canonical Frame Address is at SP. */ 199850397Sobrien dwarf2out_def_cfa (NULL, STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); 199950397Sobrien initial_return_save (INCOMING_RETURN_ADDR_RTX); 200050397Sobrien#endif 200150397Sobrien} 200250397Sobrien 200350397Sobrienvoid 200450397Sobriendwarf2out_frame_finish () 200550397Sobrien{ 200650397Sobrien /* Output call frame information. */ 200750397Sobrien#ifdef MIPS_DEBUGGING_INFO 200850397Sobrien if (write_symbols == DWARF2_DEBUG) 200950397Sobrien output_call_frame_info (0); 201050397Sobrien if (flag_exceptions && ! exceptions_via_longjmp) 201150397Sobrien output_call_frame_info (1); 201250397Sobrien#else 201350397Sobrien if (write_symbols == DWARF2_DEBUG 201450397Sobrien || (flag_exceptions && ! exceptions_via_longjmp)) 201550397Sobrien output_call_frame_info (1); 201650397Sobrien#endif 201750397Sobrien} 201850397Sobrien 201950397Sobrien#endif /* .debug_frame support */ 202050397Sobrien 202150397Sobrien/* And now, the support for symbolic debugging information. */ 202250397Sobrien#ifdef DWARF2_DEBUGGING_INFO 202350397Sobrien 202450397Sobrienextern char *getpwd PROTO((void)); 202550397Sobrien 202650397Sobrien/* NOTE: In the comments in this file, many references are made to 202750397Sobrien "Debugging Information Entries". This term is abbreviated as `DIE' 202850397Sobrien throughout the remainder of this file. */ 202950397Sobrien 203050397Sobrien/* An internal representation of the DWARF output is built, and then 203150397Sobrien walked to generate the DWARF debugging info. The walk of the internal 203250397Sobrien representation is done after the entire program has been compiled. 203350397Sobrien The types below are used to describe the internal representation. */ 203450397Sobrien 203550397Sobrien/* Each DIE may have a series of attribute/value pairs. Values 203650397Sobrien can take on several forms. The forms that are used in this 203750397Sobrien implementation are listed below. */ 203850397Sobrien 203950397Sobrientypedef enum 204050397Sobrien{ 204150397Sobrien dw_val_class_addr, 204250397Sobrien dw_val_class_loc, 204350397Sobrien dw_val_class_const, 204450397Sobrien dw_val_class_unsigned_const, 204550397Sobrien dw_val_class_long_long, 204650397Sobrien dw_val_class_float, 204750397Sobrien dw_val_class_flag, 204850397Sobrien dw_val_class_die_ref, 204950397Sobrien dw_val_class_fde_ref, 205050397Sobrien dw_val_class_lbl_id, 205152284Sobrien dw_val_class_lbl_offset, 205250397Sobrien dw_val_class_str 205350397Sobrien} 205450397Sobriendw_val_class; 205550397Sobrien 205650397Sobrien/* Various DIE's use offsets relative to the beginning of the 205750397Sobrien .debug_info section to refer to each other. */ 205850397Sobrien 205950397Sobrientypedef long int dw_offset; 206050397Sobrien 206150397Sobrien/* Define typedefs here to avoid circular dependencies. */ 206250397Sobrien 206350397Sobrientypedef struct die_struct *dw_die_ref; 206450397Sobrientypedef struct dw_attr_struct *dw_attr_ref; 206550397Sobrientypedef struct dw_val_struct *dw_val_ref; 206650397Sobrientypedef struct dw_line_info_struct *dw_line_info_ref; 206750397Sobrientypedef struct dw_separate_line_info_struct *dw_separate_line_info_ref; 206850397Sobrientypedef struct dw_loc_descr_struct *dw_loc_descr_ref; 206950397Sobrientypedef struct pubname_struct *pubname_ref; 207050397Sobrientypedef dw_die_ref *arange_ref; 207150397Sobrien 207250397Sobrien/* Describe a double word constant value. */ 207350397Sobrien 207450397Sobrientypedef struct dw_long_long_struct 207550397Sobrien{ 207650397Sobrien unsigned long hi; 207750397Sobrien unsigned long low; 207850397Sobrien} 207950397Sobriendw_long_long_const; 208050397Sobrien 208150397Sobrien/* Describe a floating point constant value. */ 208250397Sobrien 208350397Sobrientypedef struct dw_fp_struct 208450397Sobrien{ 208550397Sobrien long *array; 208650397Sobrien unsigned length; 208750397Sobrien} 208850397Sobriendw_float_const; 208950397Sobrien 209050397Sobrien/* Each entry in the line_info_table maintains the file and 209150397Sobrien line number associated with the label generated for that 209250397Sobrien entry. The label gives the PC value associated with 209350397Sobrien the line number entry. */ 209450397Sobrien 209550397Sobrientypedef struct dw_line_info_struct 209650397Sobrien{ 209750397Sobrien unsigned long dw_file_num; 209850397Sobrien unsigned long dw_line_num; 209950397Sobrien} 210050397Sobriendw_line_info_entry; 210150397Sobrien 210250397Sobrien/* Line information for functions in separate sections; each one gets its 210350397Sobrien own sequence. */ 210450397Sobrientypedef struct dw_separate_line_info_struct 210550397Sobrien{ 210650397Sobrien unsigned long dw_file_num; 210750397Sobrien unsigned long dw_line_num; 210850397Sobrien unsigned long function; 210950397Sobrien} 211050397Sobriendw_separate_line_info_entry; 211150397Sobrien 211250397Sobrien/* The dw_val_node describes an attribute's value, as it is 211350397Sobrien represented internally. */ 211450397Sobrien 211550397Sobrientypedef struct dw_val_struct 211650397Sobrien{ 211750397Sobrien dw_val_class val_class; 211850397Sobrien union 211950397Sobrien { 212050397Sobrien char *val_addr; 212150397Sobrien dw_loc_descr_ref val_loc; 212250397Sobrien long int val_int; 212350397Sobrien long unsigned val_unsigned; 212450397Sobrien dw_long_long_const val_long_long; 212550397Sobrien dw_float_const val_float; 212650397Sobrien dw_die_ref val_die_ref; 212750397Sobrien unsigned val_fde_index; 212850397Sobrien char *val_str; 212950397Sobrien char *val_lbl_id; 213050397Sobrien unsigned char val_flag; 213150397Sobrien } 213250397Sobrien v; 213350397Sobrien} 213450397Sobriendw_val_node; 213550397Sobrien 213650397Sobrien/* Locations in memory are described using a sequence of stack machine 213750397Sobrien operations. */ 213850397Sobrien 213950397Sobrientypedef struct dw_loc_descr_struct 214050397Sobrien{ 214150397Sobrien dw_loc_descr_ref dw_loc_next; 214250397Sobrien enum dwarf_location_atom dw_loc_opc; 214350397Sobrien dw_val_node dw_loc_oprnd1; 214450397Sobrien dw_val_node dw_loc_oprnd2; 214550397Sobrien} 214650397Sobriendw_loc_descr_node; 214750397Sobrien 214850397Sobrien/* Each DIE attribute has a field specifying the attribute kind, 214950397Sobrien a link to the next attribute in the chain, and an attribute value. 215050397Sobrien Attributes are typically linked below the DIE they modify. */ 215150397Sobrien 215250397Sobrientypedef struct dw_attr_struct 215350397Sobrien{ 215450397Sobrien enum dwarf_attribute dw_attr; 215550397Sobrien dw_attr_ref dw_attr_next; 215650397Sobrien dw_val_node dw_attr_val; 215750397Sobrien} 215850397Sobriendw_attr_node; 215950397Sobrien 216050397Sobrien/* The Debugging Information Entry (DIE) structure */ 216150397Sobrien 216250397Sobrientypedef struct die_struct 216350397Sobrien{ 216450397Sobrien enum dwarf_tag die_tag; 216550397Sobrien dw_attr_ref die_attr; 216650397Sobrien dw_attr_ref die_attr_last; 216750397Sobrien dw_die_ref die_parent; 216850397Sobrien dw_die_ref die_child; 216950397Sobrien dw_die_ref die_child_last; 217050397Sobrien dw_die_ref die_sib; 217150397Sobrien dw_offset die_offset; 217250397Sobrien unsigned long die_abbrev; 217350397Sobrien} 217450397Sobriendie_node; 217550397Sobrien 217650397Sobrien/* The pubname structure */ 217750397Sobrien 217850397Sobrientypedef struct pubname_struct 217950397Sobrien{ 218050397Sobrien dw_die_ref die; 218150397Sobrien char * name; 218250397Sobrien} 218350397Sobrienpubname_entry; 218450397Sobrien 218550397Sobrien/* The limbo die list structure. */ 218650397Sobrientypedef struct limbo_die_struct 218750397Sobrien{ 218850397Sobrien dw_die_ref die; 218950397Sobrien struct limbo_die_struct *next; 219050397Sobrien} 219150397Sobrienlimbo_die_node; 219250397Sobrien 219350397Sobrien/* How to start an assembler comment. */ 219450397Sobrien#ifndef ASM_COMMENT_START 219550397Sobrien#define ASM_COMMENT_START ";#" 219650397Sobrien#endif 219750397Sobrien 219850397Sobrien/* Define a macro which returns non-zero for a TYPE_DECL which was 219950397Sobrien implicitly generated for a tagged type. 220050397Sobrien 220150397Sobrien Note that unlike the gcc front end (which generates a NULL named 220250397Sobrien TYPE_DECL node for each complete tagged type, each array type, and 220350397Sobrien each function type node created) the g++ front end generates a 220450397Sobrien _named_ TYPE_DECL node for each tagged type node created. 220550397Sobrien These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to 220650397Sobrien generate a DW_TAG_typedef DIE for them. */ 220750397Sobrien 220850397Sobrien#define TYPE_DECL_IS_STUB(decl) \ 220950397Sobrien (DECL_NAME (decl) == NULL_TREE \ 221050397Sobrien || (DECL_ARTIFICIAL (decl) \ 221150397Sobrien && is_tagged_type (TREE_TYPE (decl)) \ 221250397Sobrien && ((decl == TYPE_STUB_DECL (TREE_TYPE (decl))) \ 221350397Sobrien /* This is necessary for stub decls that \ 221450397Sobrien appear in nested inline functions. */ \ 221550397Sobrien || (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE \ 221650397Sobrien && (decl_ultimate_origin (decl) \ 221750397Sobrien == TYPE_STUB_DECL (TREE_TYPE (decl))))))) 221850397Sobrien 221950397Sobrien/* Information concerning the compilation unit's programming 222050397Sobrien language, and compiler version. */ 222150397Sobrien 222250397Sobrienextern int flag_traditional; 222350397Sobrienextern char *version_string; 222450397Sobrienextern char *language_string; 222550397Sobrien 222650397Sobrien/* Fixed size portion of the DWARF compilation unit header. */ 222750397Sobrien#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3) 222850397Sobrien 222950397Sobrien/* Fixed size portion of debugging line information prolog. */ 223050397Sobrien#define DWARF_LINE_PROLOG_HEADER_SIZE 5 223150397Sobrien 223250397Sobrien/* Fixed size portion of public names info. */ 223350397Sobrien#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2) 223450397Sobrien 223550397Sobrien/* Fixed size portion of the address range info. */ 223650397Sobrien#define DWARF_ARANGES_HEADER_SIZE \ 223750397Sobrien (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE) 223850397Sobrien 223950397Sobrien/* Define the architecture-dependent minimum instruction length (in bytes). 224050397Sobrien In this implementation of DWARF, this field is used for information 224150397Sobrien purposes only. Since GCC generates assembly language, we have 224250397Sobrien no a priori knowledge of how many instruction bytes are generated 224350397Sobrien for each source line, and therefore can use only the DW_LNE_set_address 224450397Sobrien and DW_LNS_fixed_advance_pc line information commands. */ 224550397Sobrien 224650397Sobrien#ifndef DWARF_LINE_MIN_INSTR_LENGTH 224750397Sobrien#define DWARF_LINE_MIN_INSTR_LENGTH 4 224850397Sobrien#endif 224950397Sobrien 225050397Sobrien/* Minimum line offset in a special line info. opcode. 225150397Sobrien This value was chosen to give a reasonable range of values. */ 225250397Sobrien#define DWARF_LINE_BASE -10 225350397Sobrien 225450397Sobrien/* First special line opcde - leave room for the standard opcodes. */ 225550397Sobrien#define DWARF_LINE_OPCODE_BASE 10 225650397Sobrien 225750397Sobrien/* Range of line offsets in a special line info. opcode. */ 225850397Sobrien#define DWARF_LINE_RANGE (254-DWARF_LINE_OPCODE_BASE+1) 225950397Sobrien 226050397Sobrien/* Flag that indicates the initial value of the is_stmt_start flag. 226150397Sobrien In the present implementation, we do not mark any lines as 226250397Sobrien the beginning of a source statement, because that information 226350397Sobrien is not made available by the GCC front-end. */ 226450397Sobrien#define DWARF_LINE_DEFAULT_IS_STMT_START 1 226550397Sobrien 226650397Sobrien/* This location is used by calc_die_sizes() to keep track 226750397Sobrien the offset of each DIE within the .debug_info section. */ 226850397Sobrienstatic unsigned long next_die_offset; 226950397Sobrien 227050397Sobrien/* Record the root of the DIE's built for the current compilation unit. */ 227150397Sobrienstatic dw_die_ref comp_unit_die; 227250397Sobrien 227350397Sobrien/* A list of DIEs with a NULL parent waiting to be relocated. */ 227450397Sobrienstatic limbo_die_node *limbo_die_list = 0; 227550397Sobrien 227650397Sobrien/* Pointer to an array of filenames referenced by this compilation unit. */ 227750397Sobrienstatic char **file_table; 227850397Sobrien 227950397Sobrien/* Total number of entries in the table (i.e. array) pointed to by 228050397Sobrien `file_table'. This is the *total* and includes both used and unused 228150397Sobrien slots. */ 228250397Sobrienstatic unsigned file_table_allocated; 228350397Sobrien 228450397Sobrien/* Number of entries in the file_table which are actually in use. */ 228550397Sobrienstatic unsigned file_table_in_use; 228650397Sobrien 228750397Sobrien/* Size (in elements) of increments by which we may expand the filename 228850397Sobrien table. */ 228950397Sobrien#define FILE_TABLE_INCREMENT 64 229050397Sobrien 229150397Sobrien/* Local pointer to the name of the main input file. Initialized in 229250397Sobrien dwarf2out_init. */ 229350397Sobrienstatic char *primary_filename; 229450397Sobrien 229550397Sobrien/* For Dwarf output, we must assign lexical-blocks id numbers in the order in 229650397Sobrien which their beginnings are encountered. We output Dwarf debugging info 229750397Sobrien that refers to the beginnings and ends of the ranges of code for each 229850397Sobrien lexical block. The labels themselves are generated in final.c, which 229950397Sobrien assigns numbers to the blocks in the same way. */ 230050397Sobrienstatic unsigned next_block_number = 2; 230150397Sobrien 230250397Sobrien/* A pointer to the base of a table of references to DIE's that describe 230350397Sobrien declarations. The table is indexed by DECL_UID() which is a unique 230450397Sobrien number identifying each decl. */ 230550397Sobrienstatic dw_die_ref *decl_die_table; 230650397Sobrien 230750397Sobrien/* Number of elements currently allocated for the decl_die_table. */ 230850397Sobrienstatic unsigned decl_die_table_allocated; 230950397Sobrien 231050397Sobrien/* Number of elements in decl_die_table currently in use. */ 231150397Sobrienstatic unsigned decl_die_table_in_use; 231250397Sobrien 231350397Sobrien/* Size (in elements) of increments by which we may expand the 231450397Sobrien decl_die_table. */ 231550397Sobrien#define DECL_DIE_TABLE_INCREMENT 256 231650397Sobrien 231750397Sobrien/* Structure used for the decl_scope table. scope is the current declaration 231850397Sobrien scope, and previous is the entry that is the parent of this scope. This 231950397Sobrien is usually but not always the immediately preceeding entry. */ 232050397Sobrien 232150397Sobrientypedef struct decl_scope_struct 232250397Sobrien{ 232350397Sobrien tree scope; 232450397Sobrien int previous; 232550397Sobrien} 232650397Sobriendecl_scope_node; 232750397Sobrien 232850397Sobrien/* A pointer to the base of a table of references to declaration 232950397Sobrien scopes. This table is a display which tracks the nesting 233050397Sobrien of declaration scopes at the current scope and containing 233150397Sobrien scopes. This table is used to find the proper place to 233250397Sobrien define type declaration DIE's. */ 233350397Sobrienstatic decl_scope_node *decl_scope_table; 233450397Sobrien 233550397Sobrien/* Number of elements currently allocated for the decl_scope_table. */ 233650397Sobrienstatic int decl_scope_table_allocated; 233750397Sobrien 233850397Sobrien/* Current level of nesting of declaration scopes. */ 233950397Sobrienstatic int decl_scope_depth; 234050397Sobrien 234150397Sobrien/* Size (in elements) of increments by which we may expand the 234250397Sobrien decl_scope_table. */ 234350397Sobrien#define DECL_SCOPE_TABLE_INCREMENT 64 234450397Sobrien 234550397Sobrien/* A pointer to the base of a list of references to DIE's that 234650397Sobrien are uniquely identified by their tag, presence/absence of 234750397Sobrien children DIE's, and list of attribute/value pairs. */ 234850397Sobrienstatic dw_die_ref *abbrev_die_table; 234950397Sobrien 235050397Sobrien/* Number of elements currently allocated for abbrev_die_table. */ 235150397Sobrienstatic unsigned abbrev_die_table_allocated; 235250397Sobrien 235350397Sobrien/* Number of elements in type_die_table currently in use. */ 235450397Sobrienstatic unsigned abbrev_die_table_in_use; 235550397Sobrien 235650397Sobrien/* Size (in elements) of increments by which we may expand the 235750397Sobrien abbrev_die_table. */ 235850397Sobrien#define ABBREV_DIE_TABLE_INCREMENT 256 235950397Sobrien 236050397Sobrien/* A pointer to the base of a table that contains line information 236150397Sobrien for each source code line in .text in the compilation unit. */ 236250397Sobrienstatic dw_line_info_ref line_info_table; 236350397Sobrien 236450397Sobrien/* Number of elements currently allocated for line_info_table. */ 236550397Sobrienstatic unsigned line_info_table_allocated; 236650397Sobrien 236750397Sobrien/* Number of elements in separate_line_info_table currently in use. */ 236850397Sobrienstatic unsigned separate_line_info_table_in_use; 236950397Sobrien 237050397Sobrien/* A pointer to the base of a table that contains line information 237150397Sobrien for each source code line outside of .text in the compilation unit. */ 237250397Sobrienstatic dw_separate_line_info_ref separate_line_info_table; 237350397Sobrien 237450397Sobrien/* Number of elements currently allocated for separate_line_info_table. */ 237550397Sobrienstatic unsigned separate_line_info_table_allocated; 237650397Sobrien 237750397Sobrien/* Number of elements in line_info_table currently in use. */ 237850397Sobrienstatic unsigned line_info_table_in_use; 237950397Sobrien 238050397Sobrien/* Size (in elements) of increments by which we may expand the 238150397Sobrien line_info_table. */ 238250397Sobrien#define LINE_INFO_TABLE_INCREMENT 1024 238350397Sobrien 238450397Sobrien/* A pointer to the base of a table that contains a list of publicly 238550397Sobrien accessible names. */ 238650397Sobrienstatic pubname_ref pubname_table; 238750397Sobrien 238850397Sobrien/* Number of elements currently allocated for pubname_table. */ 238950397Sobrienstatic unsigned pubname_table_allocated; 239050397Sobrien 239150397Sobrien/* Number of elements in pubname_table currently in use. */ 239250397Sobrienstatic unsigned pubname_table_in_use; 239350397Sobrien 239450397Sobrien/* Size (in elements) of increments by which we may expand the 239550397Sobrien pubname_table. */ 239650397Sobrien#define PUBNAME_TABLE_INCREMENT 64 239750397Sobrien 239850397Sobrien/* A pointer to the base of a table that contains a list of publicly 239950397Sobrien accessible names. */ 240050397Sobrienstatic arange_ref arange_table; 240150397Sobrien 240250397Sobrien/* Number of elements currently allocated for arange_table. */ 240350397Sobrienstatic unsigned arange_table_allocated; 240450397Sobrien 240550397Sobrien/* Number of elements in arange_table currently in use. */ 240650397Sobrienstatic unsigned arange_table_in_use; 240750397Sobrien 240850397Sobrien/* Size (in elements) of increments by which we may expand the 240950397Sobrien arange_table. */ 241050397Sobrien#define ARANGE_TABLE_INCREMENT 64 241150397Sobrien 241250397Sobrien/* A pointer to the base of a list of pending types which we haven't 241350397Sobrien generated DIEs for yet, but which we will have to come back to 241450397Sobrien later on. */ 241550397Sobrien 241650397Sobrienstatic tree *pending_types_list; 241750397Sobrien 241850397Sobrien/* Number of elements currently allocated for the pending_types_list. */ 241950397Sobrienstatic unsigned pending_types_allocated; 242050397Sobrien 242150397Sobrien/* Number of elements of pending_types_list currently in use. */ 242250397Sobrienstatic unsigned pending_types; 242350397Sobrien 242450397Sobrien/* Size (in elements) of increments by which we may expand the pending 242550397Sobrien types list. Actually, a single hunk of space of this size should 242650397Sobrien be enough for most typical programs. */ 242750397Sobrien#define PENDING_TYPES_INCREMENT 64 242850397Sobrien 242952284Sobrien/* A pointer to the base of a list of incomplete types which might be 243052284Sobrien completed at some later time. */ 243152284Sobrien 243252284Sobrienstatic tree *incomplete_types_list; 243352284Sobrien 243452284Sobrien/* Number of elements currently allocated for the incomplete_types_list. */ 243552284Sobrienstatic unsigned incomplete_types_allocated; 243652284Sobrien 243752284Sobrien/* Number of elements of incomplete_types_list currently in use. */ 243852284Sobrienstatic unsigned incomplete_types; 243952284Sobrien 244052284Sobrien/* Size (in elements) of increments by which we may expand the incomplete 244152284Sobrien types list. Actually, a single hunk of space of this size should 244252284Sobrien be enough for most typical programs. */ 244352284Sobrien#define INCOMPLETE_TYPES_INCREMENT 64 244452284Sobrien 244550397Sobrien/* Record whether the function being analyzed contains inlined functions. */ 244650397Sobrienstatic int current_function_has_inlines; 244750397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 244850397Sobrienstatic int comp_unit_has_inlines; 244950397Sobrien#endif 245050397Sobrien 245150397Sobrien/* A pointer to the ..._DECL node which we have most recently been working 245250397Sobrien on. We keep this around just in case something about it looks screwy and 245350397Sobrien we want to tell the user what the source coordinates for the actual 245450397Sobrien declaration are. */ 245550397Sobrienstatic tree dwarf_last_decl; 245650397Sobrien 245750397Sobrien/* Forward declarations for functions defined in this file. */ 245850397Sobrien 245950397Sobrienstatic void addr_const_to_string PROTO((dyn_string_t, rtx)); 246050397Sobrienstatic char *addr_to_string PROTO((rtx)); 246150397Sobrienstatic int is_pseudo_reg PROTO((rtx)); 246250397Sobrienstatic tree type_main_variant PROTO((tree)); 246350397Sobrienstatic int is_tagged_type PROTO((tree)); 246450397Sobrienstatic char *dwarf_tag_name PROTO((unsigned)); 246550397Sobrienstatic char *dwarf_attr_name PROTO((unsigned)); 246650397Sobrienstatic char *dwarf_form_name PROTO((unsigned)); 246750397Sobrienstatic char *dwarf_stack_op_name PROTO((unsigned)); 246850397Sobrien#if 0 246950397Sobrienstatic char *dwarf_type_encoding_name PROTO((unsigned)); 247050397Sobrien#endif 247150397Sobrienstatic tree decl_ultimate_origin PROTO((tree)); 247250397Sobrienstatic tree block_ultimate_origin PROTO((tree)); 247350397Sobrienstatic tree decl_class_context PROTO((tree)); 247450397Sobrienstatic void add_dwarf_attr PROTO((dw_die_ref, dw_attr_ref)); 247550397Sobrienstatic void add_AT_flag PROTO((dw_die_ref, 247650397Sobrien enum dwarf_attribute, 247750397Sobrien unsigned)); 247850397Sobrienstatic void add_AT_int PROTO((dw_die_ref, 247950397Sobrien enum dwarf_attribute, long)); 248050397Sobrienstatic void add_AT_unsigned PROTO((dw_die_ref, 248150397Sobrien enum dwarf_attribute, 248250397Sobrien unsigned long)); 248350397Sobrienstatic void add_AT_long_long PROTO((dw_die_ref, 248450397Sobrien enum dwarf_attribute, 248550397Sobrien unsigned long, unsigned long)); 248650397Sobrienstatic void add_AT_float PROTO((dw_die_ref, 248750397Sobrien enum dwarf_attribute, 248850397Sobrien unsigned, long *)); 248950397Sobrienstatic void add_AT_string PROTO((dw_die_ref, 249050397Sobrien enum dwarf_attribute, char *)); 249150397Sobrienstatic void add_AT_die_ref PROTO((dw_die_ref, 249250397Sobrien enum dwarf_attribute, 249350397Sobrien dw_die_ref)); 249450397Sobrienstatic void add_AT_fde_ref PROTO((dw_die_ref, 249550397Sobrien enum dwarf_attribute, 249650397Sobrien unsigned)); 249750397Sobrienstatic void add_AT_loc PROTO((dw_die_ref, 249850397Sobrien enum dwarf_attribute, 249950397Sobrien dw_loc_descr_ref)); 250050397Sobrienstatic void add_AT_addr PROTO((dw_die_ref, 250150397Sobrien enum dwarf_attribute, char *)); 250250397Sobrienstatic void add_AT_lbl_id PROTO((dw_die_ref, 250350397Sobrien enum dwarf_attribute, char *)); 250452284Sobrienstatic void add_AT_lbl_offset PROTO((dw_die_ref, 250550397Sobrien enum dwarf_attribute, char *)); 250650397Sobrienstatic int is_extern_subr_die PROTO((dw_die_ref)); 250750397Sobrienstatic dw_attr_ref get_AT PROTO((dw_die_ref, 250850397Sobrien enum dwarf_attribute)); 250950397Sobrienstatic char *get_AT_low_pc PROTO((dw_die_ref)); 251050397Sobrienstatic char *get_AT_hi_pc PROTO((dw_die_ref)); 251150397Sobrienstatic char *get_AT_string PROTO((dw_die_ref, 251250397Sobrien enum dwarf_attribute)); 251350397Sobrienstatic int get_AT_flag PROTO((dw_die_ref, 251450397Sobrien enum dwarf_attribute)); 251550397Sobrienstatic unsigned get_AT_unsigned PROTO((dw_die_ref, 251650397Sobrien enum dwarf_attribute)); 251750397Sobrienstatic int is_c_family PROTO((void)); 251850397Sobrienstatic int is_fortran PROTO((void)); 251950397Sobrienstatic void remove_AT PROTO((dw_die_ref, 252050397Sobrien enum dwarf_attribute)); 252150397Sobrienstatic void remove_children PROTO((dw_die_ref)); 252250397Sobrienstatic void add_child_die PROTO((dw_die_ref, dw_die_ref)); 252350397Sobrienstatic dw_die_ref new_die PROTO((enum dwarf_tag, dw_die_ref)); 252450397Sobrienstatic dw_die_ref lookup_type_die PROTO((tree)); 252550397Sobrienstatic void equate_type_number_to_die PROTO((tree, dw_die_ref)); 252650397Sobrienstatic dw_die_ref lookup_decl_die PROTO((tree)); 252750397Sobrienstatic void equate_decl_number_to_die PROTO((tree, dw_die_ref)); 252850397Sobrienstatic dw_loc_descr_ref new_loc_descr PROTO((enum dwarf_location_atom, 252950397Sobrien unsigned long, unsigned long)); 253050397Sobrienstatic void add_loc_descr PROTO((dw_loc_descr_ref *, 253150397Sobrien dw_loc_descr_ref)); 253250397Sobrienstatic void print_spaces PROTO((FILE *)); 253350397Sobrienstatic void print_die PROTO((dw_die_ref, FILE *)); 253450397Sobrienstatic void print_dwarf_line_table PROTO((FILE *)); 253550397Sobrienstatic void add_sibling_attributes PROTO((dw_die_ref)); 253650397Sobrienstatic void build_abbrev_table PROTO((dw_die_ref)); 253750397Sobrienstatic unsigned long size_of_string PROTO((char *)); 253850397Sobrienstatic unsigned long size_of_loc_descr PROTO((dw_loc_descr_ref)); 253950397Sobrienstatic unsigned long size_of_locs PROTO((dw_loc_descr_ref)); 254050397Sobrienstatic int constant_size PROTO((long unsigned)); 254150397Sobrienstatic unsigned long size_of_die PROTO((dw_die_ref)); 254250397Sobrienstatic void calc_die_sizes PROTO((dw_die_ref)); 254350397Sobrienstatic unsigned long size_of_line_prolog PROTO((void)); 254450397Sobrienstatic unsigned long size_of_line_info PROTO((void)); 254550397Sobrienstatic unsigned long size_of_pubnames PROTO((void)); 254650397Sobrienstatic unsigned long size_of_aranges PROTO((void)); 254750397Sobrienstatic enum dwarf_form value_format PROTO((dw_val_ref)); 254850397Sobrienstatic void output_value_format PROTO((dw_val_ref)); 254950397Sobrienstatic void output_abbrev_section PROTO((void)); 255050397Sobrienstatic void output_loc_operands PROTO((dw_loc_descr_ref)); 255150397Sobrienstatic unsigned long sibling_offset PROTO((dw_die_ref)); 255250397Sobrienstatic void output_die PROTO((dw_die_ref)); 255350397Sobrienstatic void output_compilation_unit_header PROTO((void)); 255450397Sobrienstatic char *dwarf2_name PROTO((tree, int)); 255550397Sobrienstatic void add_pubname PROTO((tree, dw_die_ref)); 255650397Sobrienstatic void output_pubnames PROTO((void)); 255750397Sobrienstatic void add_arange PROTO((tree, dw_die_ref)); 255850397Sobrienstatic void output_aranges PROTO((void)); 255950397Sobrienstatic void output_line_info PROTO((void)); 256050397Sobrienstatic int is_body_block PROTO((tree)); 256150397Sobrienstatic dw_die_ref base_type_die PROTO((tree)); 256250397Sobrienstatic tree root_type PROTO((tree)); 256350397Sobrienstatic int is_base_type PROTO((tree)); 256450397Sobrienstatic dw_die_ref modified_type_die PROTO((tree, int, int, dw_die_ref)); 256550397Sobrienstatic int type_is_enum PROTO((tree)); 256650397Sobrienstatic dw_loc_descr_ref reg_loc_descriptor PROTO((rtx)); 256750397Sobrienstatic dw_loc_descr_ref based_loc_descr PROTO((unsigned, long)); 256850397Sobrienstatic int is_based_loc PROTO((rtx)); 256950397Sobrienstatic dw_loc_descr_ref mem_loc_descriptor PROTO((rtx)); 257050397Sobrienstatic dw_loc_descr_ref concat_loc_descriptor PROTO((rtx, rtx)); 257150397Sobrienstatic dw_loc_descr_ref loc_descriptor PROTO((rtx)); 257250397Sobrienstatic unsigned ceiling PROTO((unsigned, unsigned)); 257350397Sobrienstatic tree field_type PROTO((tree)); 257450397Sobrienstatic unsigned simple_type_align_in_bits PROTO((tree)); 257550397Sobrienstatic unsigned simple_type_size_in_bits PROTO((tree)); 257650397Sobrienstatic unsigned field_byte_offset PROTO((tree)); 257750397Sobrienstatic void add_AT_location_description PROTO((dw_die_ref, 257850397Sobrien enum dwarf_attribute, rtx)); 257950397Sobrienstatic void add_data_member_location_attribute PROTO((dw_die_ref, tree)); 258050397Sobrienstatic void add_const_value_attribute PROTO((dw_die_ref, rtx)); 258150397Sobrienstatic void add_location_or_const_value_attribute PROTO((dw_die_ref, tree)); 258250397Sobrienstatic void add_name_attribute PROTO((dw_die_ref, char *)); 258350397Sobrienstatic void add_bound_info PROTO((dw_die_ref, 258450397Sobrien enum dwarf_attribute, tree)); 258550397Sobrienstatic void add_subscript_info PROTO((dw_die_ref, tree)); 258650397Sobrienstatic void add_byte_size_attribute PROTO((dw_die_ref, tree)); 258750397Sobrienstatic void add_bit_offset_attribute PROTO((dw_die_ref, tree)); 258850397Sobrienstatic void add_bit_size_attribute PROTO((dw_die_ref, tree)); 258950397Sobrienstatic void add_prototyped_attribute PROTO((dw_die_ref, tree)); 259050397Sobrienstatic void add_abstract_origin_attribute PROTO((dw_die_ref, tree)); 259150397Sobrienstatic void add_pure_or_virtual_attribute PROTO((dw_die_ref, tree)); 259250397Sobrienstatic void add_src_coords_attributes PROTO((dw_die_ref, tree)); 259350397Sobrienstatic void add_name_and_src_coords_attributes PROTO((dw_die_ref, tree)); 259450397Sobrienstatic void push_decl_scope PROTO((tree)); 259550397Sobrienstatic dw_die_ref scope_die_for PROTO((tree, dw_die_ref)); 259650397Sobrienstatic void pop_decl_scope PROTO((void)); 259750397Sobrienstatic void add_type_attribute PROTO((dw_die_ref, tree, int, int, 259850397Sobrien dw_die_ref)); 259950397Sobrienstatic char *type_tag PROTO((tree)); 260050397Sobrienstatic tree member_declared_type PROTO((tree)); 260150397Sobrien#if 0 260250397Sobrienstatic char *decl_start_label PROTO((tree)); 260350397Sobrien#endif 260450397Sobrienstatic void gen_array_type_die PROTO((tree, dw_die_ref)); 260550397Sobrienstatic void gen_set_type_die PROTO((tree, dw_die_ref)); 260650397Sobrien#if 0 260750397Sobrienstatic void gen_entry_point_die PROTO((tree, dw_die_ref)); 260850397Sobrien#endif 260950397Sobrienstatic void pend_type PROTO((tree)); 261050397Sobrienstatic void output_pending_types_for_scope PROTO((dw_die_ref)); 261150397Sobrienstatic void gen_inlined_enumeration_type_die PROTO((tree, dw_die_ref)); 261250397Sobrienstatic void gen_inlined_structure_type_die PROTO((tree, dw_die_ref)); 261350397Sobrienstatic void gen_inlined_union_type_die PROTO((tree, dw_die_ref)); 261450397Sobrienstatic void gen_enumeration_type_die PROTO((tree, dw_die_ref)); 261550397Sobrienstatic dw_die_ref gen_formal_parameter_die PROTO((tree, dw_die_ref)); 261650397Sobrienstatic void gen_unspecified_parameters_die PROTO((tree, dw_die_ref)); 261750397Sobrienstatic void gen_formal_types_die PROTO((tree, dw_die_ref)); 261850397Sobrienstatic void gen_subprogram_die PROTO((tree, dw_die_ref)); 261950397Sobrienstatic void gen_variable_die PROTO((tree, dw_die_ref)); 262050397Sobrienstatic void gen_label_die PROTO((tree, dw_die_ref)); 262150397Sobrienstatic void gen_lexical_block_die PROTO((tree, dw_die_ref, int)); 262250397Sobrienstatic void gen_inlined_subroutine_die PROTO((tree, dw_die_ref, int)); 262350397Sobrienstatic void gen_field_die PROTO((tree, dw_die_ref)); 262450397Sobrienstatic void gen_ptr_to_mbr_type_die PROTO((tree, dw_die_ref)); 262550397Sobrienstatic void gen_compile_unit_die PROTO((char *)); 262650397Sobrienstatic void gen_string_type_die PROTO((tree, dw_die_ref)); 262750397Sobrienstatic void gen_inheritance_die PROTO((tree, dw_die_ref)); 262850397Sobrienstatic void gen_member_die PROTO((tree, dw_die_ref)); 262950397Sobrienstatic void gen_struct_or_union_type_die PROTO((tree, dw_die_ref)); 263050397Sobrienstatic void gen_subroutine_type_die PROTO((tree, dw_die_ref)); 263150397Sobrienstatic void gen_typedef_die PROTO((tree, dw_die_ref)); 263250397Sobrienstatic void gen_type_die PROTO((tree, dw_die_ref)); 263350397Sobrienstatic void gen_tagged_type_instantiation_die PROTO((tree, dw_die_ref)); 263450397Sobrienstatic void gen_block_die PROTO((tree, dw_die_ref, int)); 263550397Sobrienstatic void decls_for_scope PROTO((tree, dw_die_ref, int)); 263650397Sobrienstatic int is_redundant_typedef PROTO((tree)); 263750397Sobrienstatic void gen_decl_die PROTO((tree, dw_die_ref)); 263850397Sobrienstatic unsigned lookup_filename PROTO((char *)); 263950397Sobrien 264050397Sobrien/* Section names used to hold DWARF debugging information. */ 264150397Sobrien#ifndef DEBUG_INFO_SECTION 264250397Sobrien#define DEBUG_INFO_SECTION ".debug_info" 264350397Sobrien#endif 264450397Sobrien#ifndef ABBREV_SECTION 264550397Sobrien#define ABBREV_SECTION ".debug_abbrev" 264650397Sobrien#endif 264750397Sobrien#ifndef ARANGES_SECTION 264850397Sobrien#define ARANGES_SECTION ".debug_aranges" 264950397Sobrien#endif 265050397Sobrien#ifndef DW_MACINFO_SECTION 265150397Sobrien#define DW_MACINFO_SECTION ".debug_macinfo" 265250397Sobrien#endif 265350397Sobrien#ifndef DEBUG_LINE_SECTION 265450397Sobrien#define DEBUG_LINE_SECTION ".debug_line" 265550397Sobrien#endif 265650397Sobrien#ifndef LOC_SECTION 265750397Sobrien#define LOC_SECTION ".debug_loc" 265850397Sobrien#endif 265950397Sobrien#ifndef PUBNAMES_SECTION 266050397Sobrien#define PUBNAMES_SECTION ".debug_pubnames" 266150397Sobrien#endif 266250397Sobrien#ifndef STR_SECTION 266350397Sobrien#define STR_SECTION ".debug_str" 266450397Sobrien#endif 266550397Sobrien 266650397Sobrien/* Standard ELF section names for compiled code and data. */ 266750397Sobrien#ifndef TEXT_SECTION 266850397Sobrien#define TEXT_SECTION ".text" 266950397Sobrien#endif 267050397Sobrien#ifndef DATA_SECTION 267150397Sobrien#define DATA_SECTION ".data" 267250397Sobrien#endif 267350397Sobrien#ifndef BSS_SECTION 267450397Sobrien#define BSS_SECTION ".bss" 267550397Sobrien#endif 267650397Sobrien 267752284Sobrien/* Labels we insert at beginning sections we can reference instead of 267852284Sobrien the section names themselves. */ 267950397Sobrien 268052284Sobrien#ifndef TEXT_SECTION_LABEL 268152284Sobrien#define TEXT_SECTION_LABEL "Ltext" 268252284Sobrien#endif 268352284Sobrien#ifndef DEBUG_LINE_SECTION_LABEL 268452284Sobrien#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" 268552284Sobrien#endif 268652284Sobrien#ifndef DEBUG_INFO_SECTION_LABEL 268752284Sobrien#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" 268852284Sobrien#endif 268952284Sobrien#ifndef ABBREV_SECTION_LABEL 269052284Sobrien#define ABBREV_SECTION_LABEL "Ldebug_abbrev" 269152284Sobrien#endif 269252284Sobrien 269352284Sobrien 269450397Sobrien/* Definitions of defaults for formats and names of various special 269550397Sobrien (artificial) labels which may be generated within this file (when the -g 269650397Sobrien options is used and DWARF_DEBUGGING_INFO is in effect. 269750397Sobrien If necessary, these may be overridden from within the tm.h file, but 269850397Sobrien typically, overriding these defaults is unnecessary. */ 269950397Sobrien 270050397Sobrienstatic char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 270152284Sobrienstatic char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 270252284Sobrienstatic char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 270352284Sobrienstatic char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 270452284Sobrienstatic char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; 270550397Sobrien 270650397Sobrien#ifndef TEXT_END_LABEL 270750397Sobrien#define TEXT_END_LABEL "Letext" 270850397Sobrien#endif 270950397Sobrien#ifndef DATA_END_LABEL 271050397Sobrien#define DATA_END_LABEL "Ledata" 271150397Sobrien#endif 271250397Sobrien#ifndef BSS_END_LABEL 271350397Sobrien#define BSS_END_LABEL "Lebss" 271450397Sobrien#endif 271550397Sobrien#ifndef INSN_LABEL_FMT 271650397Sobrien#define INSN_LABEL_FMT "LI%u_" 271750397Sobrien#endif 271850397Sobrien#ifndef BLOCK_BEGIN_LABEL 271950397Sobrien#define BLOCK_BEGIN_LABEL "LBB" 272050397Sobrien#endif 272150397Sobrien#ifndef BLOCK_END_LABEL 272250397Sobrien#define BLOCK_END_LABEL "LBE" 272350397Sobrien#endif 272450397Sobrien#ifndef BODY_BEGIN_LABEL 272550397Sobrien#define BODY_BEGIN_LABEL "Lbb" 272650397Sobrien#endif 272750397Sobrien#ifndef BODY_END_LABEL 272850397Sobrien#define BODY_END_LABEL "Lbe" 272950397Sobrien#endif 273050397Sobrien#ifndef LINE_CODE_LABEL 273150397Sobrien#define LINE_CODE_LABEL "LM" 273250397Sobrien#endif 273350397Sobrien#ifndef SEPARATE_LINE_CODE_LABEL 273450397Sobrien#define SEPARATE_LINE_CODE_LABEL "LSM" 273550397Sobrien#endif 273650397Sobrien 273750397Sobrien/* Convert a reference to the assembler name of a C-level name. This 273850397Sobrien macro has the same effect as ASM_OUTPUT_LABELREF, but copies to 273950397Sobrien a string rather than writing to a file. */ 274050397Sobrien#ifndef ASM_NAME_TO_STRING 274152284Sobrien#define ASM_NAME_TO_STRING(STR, NAME) \ 274252284Sobrien do { \ 274352284Sobrien if ((NAME)[0] == '*') \ 274452284Sobrien dyn_string_append (STR, NAME + 1); \ 274552284Sobrien else \ 274652284Sobrien { \ 274752284Sobrien char *newstr; \ 274852284Sobrien STRIP_NAME_ENCODING (newstr, NAME); \ 274952284Sobrien dyn_string_append (STR, user_label_prefix); \ 275052284Sobrien dyn_string_append (STR, newstr); \ 275152284Sobrien } \ 275252284Sobrien } \ 275350397Sobrien while (0) 275450397Sobrien#endif 275550397Sobrien 275650397Sobrien/* Convert an integer constant expression into assembler syntax. Addition 275750397Sobrien and subtraction are the only arithmetic that may appear in these 275850397Sobrien expressions. This is an adaptation of output_addr_const in final.c. 275950397Sobrien Here, the target of the conversion is a string buffer. We can't use 276050397Sobrien output_addr_const directly, because it writes to a file. */ 276150397Sobrien 276250397Sobrienstatic void 276350397Sobrienaddr_const_to_string (str, x) 276450397Sobrien dyn_string_t str; 276550397Sobrien rtx x; 276650397Sobrien{ 276750397Sobrien char buf1[256]; 276850397Sobrien 276950397Sobrienrestart: 277050397Sobrien switch (GET_CODE (x)) 277150397Sobrien { 277250397Sobrien case PC: 277350397Sobrien if (flag_pic) 277450397Sobrien dyn_string_append (str, ","); 277550397Sobrien else 277650397Sobrien abort (); 277750397Sobrien break; 277850397Sobrien 277950397Sobrien case SYMBOL_REF: 278050397Sobrien ASM_NAME_TO_STRING (str, XSTR (x, 0)); 278150397Sobrien break; 278250397Sobrien 278350397Sobrien case LABEL_REF: 278450397Sobrien ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 278550397Sobrien ASM_NAME_TO_STRING (str, buf1); 278650397Sobrien break; 278750397Sobrien 278850397Sobrien case CODE_LABEL: 278950397Sobrien ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x)); 279050397Sobrien ASM_NAME_TO_STRING (str, buf1); 279150397Sobrien break; 279250397Sobrien 279350397Sobrien case CONST_INT: 279450397Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 279550397Sobrien dyn_string_append (str, buf1); 279650397Sobrien break; 279750397Sobrien 279850397Sobrien case CONST: 279950397Sobrien /* This used to output parentheses around the expression, but that does 280050397Sobrien not work on the 386 (either ATT or BSD assembler). */ 280150397Sobrien addr_const_to_string (str, XEXP (x, 0)); 280250397Sobrien break; 280350397Sobrien 280450397Sobrien case CONST_DOUBLE: 280550397Sobrien if (GET_MODE (x) == VOIDmode) 280650397Sobrien { 280750397Sobrien /* We can use %d if the number is one word and positive. */ 280850397Sobrien if (CONST_DOUBLE_HIGH (x)) 280950397Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX, 281050397Sobrien CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 281150397Sobrien else if (CONST_DOUBLE_LOW (x) < 0) 281250397Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x)); 281350397Sobrien else 281450397Sobrien sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, 281550397Sobrien CONST_DOUBLE_LOW (x)); 281650397Sobrien dyn_string_append (str, buf1); 281750397Sobrien } 281850397Sobrien else 281950397Sobrien /* We can't handle floating point constants; PRINT_OPERAND must 282050397Sobrien handle them. */ 282150397Sobrien output_operand_lossage ("floating constant misused"); 282250397Sobrien break; 282350397Sobrien 282450397Sobrien case PLUS: 282550397Sobrien /* Some assemblers need integer constants to appear last (eg masm). */ 282650397Sobrien if (GET_CODE (XEXP (x, 0)) == CONST_INT) 282750397Sobrien { 282850397Sobrien addr_const_to_string (str, XEXP (x, 1)); 282950397Sobrien if (INTVAL (XEXP (x, 0)) >= 0) 283050397Sobrien dyn_string_append (str, "+"); 283150397Sobrien 283250397Sobrien addr_const_to_string (str, XEXP (x, 0)); 283350397Sobrien } 283450397Sobrien else 283550397Sobrien { 283650397Sobrien addr_const_to_string (str, XEXP (x, 0)); 283750397Sobrien if (INTVAL (XEXP (x, 1)) >= 0) 283850397Sobrien dyn_string_append (str, "+"); 283950397Sobrien 284050397Sobrien addr_const_to_string (str, XEXP (x, 1)); 284150397Sobrien } 284250397Sobrien break; 284350397Sobrien 284450397Sobrien case MINUS: 284550397Sobrien /* Avoid outputting things like x-x or x+5-x, since some assemblers 284650397Sobrien can't handle that. */ 284750397Sobrien x = simplify_subtraction (x); 284850397Sobrien if (GET_CODE (x) != MINUS) 284950397Sobrien goto restart; 285050397Sobrien 285150397Sobrien addr_const_to_string (str, XEXP (x, 0)); 285250397Sobrien dyn_string_append (str, "-"); 285350397Sobrien if (GET_CODE (XEXP (x, 1)) == CONST_INT 285450397Sobrien && INTVAL (XEXP (x, 1)) < 0) 285550397Sobrien { 285650397Sobrien dyn_string_append (str, ASM_OPEN_PAREN); 285750397Sobrien addr_const_to_string (str, XEXP (x, 1)); 285850397Sobrien dyn_string_append (str, ASM_CLOSE_PAREN); 285950397Sobrien } 286050397Sobrien else 286150397Sobrien addr_const_to_string (str, XEXP (x, 1)); 286250397Sobrien break; 286350397Sobrien 286450397Sobrien case ZERO_EXTEND: 286550397Sobrien case SIGN_EXTEND: 286650397Sobrien addr_const_to_string (str, XEXP (x, 0)); 286750397Sobrien break; 286850397Sobrien 286950397Sobrien default: 287050397Sobrien output_operand_lossage ("invalid expression as operand"); 287150397Sobrien } 287250397Sobrien} 287350397Sobrien 287450397Sobrien/* Convert an address constant to a string, and return a pointer to 287550397Sobrien a copy of the result, located on the heap. */ 287650397Sobrien 287750397Sobrienstatic char * 287850397Sobrienaddr_to_string (x) 287950397Sobrien rtx x; 288050397Sobrien{ 288150397Sobrien dyn_string_t ds = dyn_string_new (256); 288250397Sobrien char *s; 288350397Sobrien 288450397Sobrien addr_const_to_string (ds, x); 288550397Sobrien 288650397Sobrien /* Return the dynamically allocated string, but free the 288750397Sobrien dyn_string_t itself. */ 288850397Sobrien s = ds->s; 288950397Sobrien free (ds); 289050397Sobrien return s; 289150397Sobrien} 289250397Sobrien 289350397Sobrien/* Test if rtl node points to a pseudo register. */ 289450397Sobrien 289550397Sobrienstatic inline int 289650397Sobrienis_pseudo_reg (rtl) 289750397Sobrien register rtx rtl; 289850397Sobrien{ 289950397Sobrien return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER)) 290050397Sobrien || ((GET_CODE (rtl) == SUBREG) 290150397Sobrien && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER))); 290250397Sobrien} 290350397Sobrien 290450397Sobrien/* Return a reference to a type, with its const and volatile qualifiers 290550397Sobrien removed. */ 290650397Sobrien 290750397Sobrienstatic inline tree 290850397Sobrientype_main_variant (type) 290950397Sobrien register tree type; 291050397Sobrien{ 291150397Sobrien type = TYPE_MAIN_VARIANT (type); 291250397Sobrien 291350397Sobrien /* There really should be only one main variant among any group of variants 291450397Sobrien of a given type (and all of the MAIN_VARIANT values for all members of 291550397Sobrien the group should point to that one type) but sometimes the C front-end 291650397Sobrien messes this up for array types, so we work around that bug here. */ 291750397Sobrien 291850397Sobrien if (TREE_CODE (type) == ARRAY_TYPE) 291950397Sobrien while (type != TYPE_MAIN_VARIANT (type)) 292050397Sobrien type = TYPE_MAIN_VARIANT (type); 292150397Sobrien 292250397Sobrien return type; 292350397Sobrien} 292450397Sobrien 292550397Sobrien/* Return non-zero if the given type node represents a tagged type. */ 292650397Sobrien 292750397Sobrienstatic inline int 292850397Sobrienis_tagged_type (type) 292950397Sobrien register tree type; 293050397Sobrien{ 293150397Sobrien register enum tree_code code = TREE_CODE (type); 293250397Sobrien 293350397Sobrien return (code == RECORD_TYPE || code == UNION_TYPE 293450397Sobrien || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE); 293550397Sobrien} 293650397Sobrien 293750397Sobrien/* Convert a DIE tag into its string name. */ 293850397Sobrien 293950397Sobrienstatic char * 294050397Sobriendwarf_tag_name (tag) 294150397Sobrien register unsigned tag; 294250397Sobrien{ 294350397Sobrien switch (tag) 294450397Sobrien { 294550397Sobrien case DW_TAG_padding: 294650397Sobrien return "DW_TAG_padding"; 294750397Sobrien case DW_TAG_array_type: 294850397Sobrien return "DW_TAG_array_type"; 294950397Sobrien case DW_TAG_class_type: 295050397Sobrien return "DW_TAG_class_type"; 295150397Sobrien case DW_TAG_entry_point: 295250397Sobrien return "DW_TAG_entry_point"; 295350397Sobrien case DW_TAG_enumeration_type: 295450397Sobrien return "DW_TAG_enumeration_type"; 295550397Sobrien case DW_TAG_formal_parameter: 295650397Sobrien return "DW_TAG_formal_parameter"; 295750397Sobrien case DW_TAG_imported_declaration: 295850397Sobrien return "DW_TAG_imported_declaration"; 295950397Sobrien case DW_TAG_label: 296050397Sobrien return "DW_TAG_label"; 296150397Sobrien case DW_TAG_lexical_block: 296250397Sobrien return "DW_TAG_lexical_block"; 296350397Sobrien case DW_TAG_member: 296450397Sobrien return "DW_TAG_member"; 296550397Sobrien case DW_TAG_pointer_type: 296650397Sobrien return "DW_TAG_pointer_type"; 296750397Sobrien case DW_TAG_reference_type: 296850397Sobrien return "DW_TAG_reference_type"; 296950397Sobrien case DW_TAG_compile_unit: 297050397Sobrien return "DW_TAG_compile_unit"; 297150397Sobrien case DW_TAG_string_type: 297250397Sobrien return "DW_TAG_string_type"; 297350397Sobrien case DW_TAG_structure_type: 297450397Sobrien return "DW_TAG_structure_type"; 297550397Sobrien case DW_TAG_subroutine_type: 297650397Sobrien return "DW_TAG_subroutine_type"; 297750397Sobrien case DW_TAG_typedef: 297850397Sobrien return "DW_TAG_typedef"; 297950397Sobrien case DW_TAG_union_type: 298050397Sobrien return "DW_TAG_union_type"; 298150397Sobrien case DW_TAG_unspecified_parameters: 298250397Sobrien return "DW_TAG_unspecified_parameters"; 298350397Sobrien case DW_TAG_variant: 298450397Sobrien return "DW_TAG_variant"; 298550397Sobrien case DW_TAG_common_block: 298650397Sobrien return "DW_TAG_common_block"; 298750397Sobrien case DW_TAG_common_inclusion: 298850397Sobrien return "DW_TAG_common_inclusion"; 298950397Sobrien case DW_TAG_inheritance: 299050397Sobrien return "DW_TAG_inheritance"; 299150397Sobrien case DW_TAG_inlined_subroutine: 299250397Sobrien return "DW_TAG_inlined_subroutine"; 299350397Sobrien case DW_TAG_module: 299450397Sobrien return "DW_TAG_module"; 299550397Sobrien case DW_TAG_ptr_to_member_type: 299650397Sobrien return "DW_TAG_ptr_to_member_type"; 299750397Sobrien case DW_TAG_set_type: 299850397Sobrien return "DW_TAG_set_type"; 299950397Sobrien case DW_TAG_subrange_type: 300050397Sobrien return "DW_TAG_subrange_type"; 300150397Sobrien case DW_TAG_with_stmt: 300250397Sobrien return "DW_TAG_with_stmt"; 300350397Sobrien case DW_TAG_access_declaration: 300450397Sobrien return "DW_TAG_access_declaration"; 300550397Sobrien case DW_TAG_base_type: 300650397Sobrien return "DW_TAG_base_type"; 300750397Sobrien case DW_TAG_catch_block: 300850397Sobrien return "DW_TAG_catch_block"; 300950397Sobrien case DW_TAG_const_type: 301050397Sobrien return "DW_TAG_const_type"; 301150397Sobrien case DW_TAG_constant: 301250397Sobrien return "DW_TAG_constant"; 301350397Sobrien case DW_TAG_enumerator: 301450397Sobrien return "DW_TAG_enumerator"; 301550397Sobrien case DW_TAG_file_type: 301650397Sobrien return "DW_TAG_file_type"; 301750397Sobrien case DW_TAG_friend: 301850397Sobrien return "DW_TAG_friend"; 301950397Sobrien case DW_TAG_namelist: 302050397Sobrien return "DW_TAG_namelist"; 302150397Sobrien case DW_TAG_namelist_item: 302250397Sobrien return "DW_TAG_namelist_item"; 302350397Sobrien case DW_TAG_packed_type: 302450397Sobrien return "DW_TAG_packed_type"; 302550397Sobrien case DW_TAG_subprogram: 302650397Sobrien return "DW_TAG_subprogram"; 302750397Sobrien case DW_TAG_template_type_param: 302850397Sobrien return "DW_TAG_template_type_param"; 302950397Sobrien case DW_TAG_template_value_param: 303050397Sobrien return "DW_TAG_template_value_param"; 303150397Sobrien case DW_TAG_thrown_type: 303250397Sobrien return "DW_TAG_thrown_type"; 303350397Sobrien case DW_TAG_try_block: 303450397Sobrien return "DW_TAG_try_block"; 303550397Sobrien case DW_TAG_variant_part: 303650397Sobrien return "DW_TAG_variant_part"; 303750397Sobrien case DW_TAG_variable: 303850397Sobrien return "DW_TAG_variable"; 303950397Sobrien case DW_TAG_volatile_type: 304050397Sobrien return "DW_TAG_volatile_type"; 304150397Sobrien case DW_TAG_MIPS_loop: 304250397Sobrien return "DW_TAG_MIPS_loop"; 304350397Sobrien case DW_TAG_format_label: 304450397Sobrien return "DW_TAG_format_label"; 304550397Sobrien case DW_TAG_function_template: 304650397Sobrien return "DW_TAG_function_template"; 304750397Sobrien case DW_TAG_class_template: 304850397Sobrien return "DW_TAG_class_template"; 304950397Sobrien default: 305050397Sobrien return "DW_TAG_<unknown>"; 305150397Sobrien } 305250397Sobrien} 305350397Sobrien 305450397Sobrien/* Convert a DWARF attribute code into its string name. */ 305550397Sobrien 305650397Sobrienstatic char * 305750397Sobriendwarf_attr_name (attr) 305850397Sobrien register unsigned attr; 305950397Sobrien{ 306050397Sobrien switch (attr) 306150397Sobrien { 306250397Sobrien case DW_AT_sibling: 306350397Sobrien return "DW_AT_sibling"; 306450397Sobrien case DW_AT_location: 306550397Sobrien return "DW_AT_location"; 306650397Sobrien case DW_AT_name: 306750397Sobrien return "DW_AT_name"; 306850397Sobrien case DW_AT_ordering: 306950397Sobrien return "DW_AT_ordering"; 307050397Sobrien case DW_AT_subscr_data: 307150397Sobrien return "DW_AT_subscr_data"; 307250397Sobrien case DW_AT_byte_size: 307350397Sobrien return "DW_AT_byte_size"; 307450397Sobrien case DW_AT_bit_offset: 307550397Sobrien return "DW_AT_bit_offset"; 307650397Sobrien case DW_AT_bit_size: 307750397Sobrien return "DW_AT_bit_size"; 307850397Sobrien case DW_AT_element_list: 307950397Sobrien return "DW_AT_element_list"; 308050397Sobrien case DW_AT_stmt_list: 308150397Sobrien return "DW_AT_stmt_list"; 308250397Sobrien case DW_AT_low_pc: 308350397Sobrien return "DW_AT_low_pc"; 308450397Sobrien case DW_AT_high_pc: 308550397Sobrien return "DW_AT_high_pc"; 308650397Sobrien case DW_AT_language: 308750397Sobrien return "DW_AT_language"; 308850397Sobrien case DW_AT_member: 308950397Sobrien return "DW_AT_member"; 309050397Sobrien case DW_AT_discr: 309150397Sobrien return "DW_AT_discr"; 309250397Sobrien case DW_AT_discr_value: 309350397Sobrien return "DW_AT_discr_value"; 309450397Sobrien case DW_AT_visibility: 309550397Sobrien return "DW_AT_visibility"; 309650397Sobrien case DW_AT_import: 309750397Sobrien return "DW_AT_import"; 309850397Sobrien case DW_AT_string_length: 309950397Sobrien return "DW_AT_string_length"; 310050397Sobrien case DW_AT_common_reference: 310150397Sobrien return "DW_AT_common_reference"; 310250397Sobrien case DW_AT_comp_dir: 310350397Sobrien return "DW_AT_comp_dir"; 310450397Sobrien case DW_AT_const_value: 310550397Sobrien return "DW_AT_const_value"; 310650397Sobrien case DW_AT_containing_type: 310750397Sobrien return "DW_AT_containing_type"; 310850397Sobrien case DW_AT_default_value: 310950397Sobrien return "DW_AT_default_value"; 311050397Sobrien case DW_AT_inline: 311150397Sobrien return "DW_AT_inline"; 311250397Sobrien case DW_AT_is_optional: 311350397Sobrien return "DW_AT_is_optional"; 311450397Sobrien case DW_AT_lower_bound: 311550397Sobrien return "DW_AT_lower_bound"; 311650397Sobrien case DW_AT_producer: 311750397Sobrien return "DW_AT_producer"; 311850397Sobrien case DW_AT_prototyped: 311950397Sobrien return "DW_AT_prototyped"; 312050397Sobrien case DW_AT_return_addr: 312150397Sobrien return "DW_AT_return_addr"; 312250397Sobrien case DW_AT_start_scope: 312350397Sobrien return "DW_AT_start_scope"; 312450397Sobrien case DW_AT_stride_size: 312550397Sobrien return "DW_AT_stride_size"; 312650397Sobrien case DW_AT_upper_bound: 312750397Sobrien return "DW_AT_upper_bound"; 312850397Sobrien case DW_AT_abstract_origin: 312950397Sobrien return "DW_AT_abstract_origin"; 313050397Sobrien case DW_AT_accessibility: 313150397Sobrien return "DW_AT_accessibility"; 313250397Sobrien case DW_AT_address_class: 313350397Sobrien return "DW_AT_address_class"; 313450397Sobrien case DW_AT_artificial: 313550397Sobrien return "DW_AT_artificial"; 313650397Sobrien case DW_AT_base_types: 313750397Sobrien return "DW_AT_base_types"; 313850397Sobrien case DW_AT_calling_convention: 313950397Sobrien return "DW_AT_calling_convention"; 314050397Sobrien case DW_AT_count: 314150397Sobrien return "DW_AT_count"; 314250397Sobrien case DW_AT_data_member_location: 314350397Sobrien return "DW_AT_data_member_location"; 314450397Sobrien case DW_AT_decl_column: 314550397Sobrien return "DW_AT_decl_column"; 314650397Sobrien case DW_AT_decl_file: 314750397Sobrien return "DW_AT_decl_file"; 314850397Sobrien case DW_AT_decl_line: 314950397Sobrien return "DW_AT_decl_line"; 315050397Sobrien case DW_AT_declaration: 315150397Sobrien return "DW_AT_declaration"; 315250397Sobrien case DW_AT_discr_list: 315350397Sobrien return "DW_AT_discr_list"; 315450397Sobrien case DW_AT_encoding: 315550397Sobrien return "DW_AT_encoding"; 315650397Sobrien case DW_AT_external: 315750397Sobrien return "DW_AT_external"; 315850397Sobrien case DW_AT_frame_base: 315950397Sobrien return "DW_AT_frame_base"; 316050397Sobrien case DW_AT_friend: 316150397Sobrien return "DW_AT_friend"; 316250397Sobrien case DW_AT_identifier_case: 316350397Sobrien return "DW_AT_identifier_case"; 316450397Sobrien case DW_AT_macro_info: 316550397Sobrien return "DW_AT_macro_info"; 316650397Sobrien case DW_AT_namelist_items: 316750397Sobrien return "DW_AT_namelist_items"; 316850397Sobrien case DW_AT_priority: 316950397Sobrien return "DW_AT_priority"; 317050397Sobrien case DW_AT_segment: 317150397Sobrien return "DW_AT_segment"; 317250397Sobrien case DW_AT_specification: 317350397Sobrien return "DW_AT_specification"; 317450397Sobrien case DW_AT_static_link: 317550397Sobrien return "DW_AT_static_link"; 317650397Sobrien case DW_AT_type: 317750397Sobrien return "DW_AT_type"; 317850397Sobrien case DW_AT_use_location: 317950397Sobrien return "DW_AT_use_location"; 318050397Sobrien case DW_AT_variable_parameter: 318150397Sobrien return "DW_AT_variable_parameter"; 318250397Sobrien case DW_AT_virtuality: 318350397Sobrien return "DW_AT_virtuality"; 318450397Sobrien case DW_AT_vtable_elem_location: 318550397Sobrien return "DW_AT_vtable_elem_location"; 318650397Sobrien 318750397Sobrien case DW_AT_MIPS_fde: 318850397Sobrien return "DW_AT_MIPS_fde"; 318950397Sobrien case DW_AT_MIPS_loop_begin: 319050397Sobrien return "DW_AT_MIPS_loop_begin"; 319150397Sobrien case DW_AT_MIPS_tail_loop_begin: 319250397Sobrien return "DW_AT_MIPS_tail_loop_begin"; 319350397Sobrien case DW_AT_MIPS_epilog_begin: 319450397Sobrien return "DW_AT_MIPS_epilog_begin"; 319550397Sobrien case DW_AT_MIPS_loop_unroll_factor: 319650397Sobrien return "DW_AT_MIPS_loop_unroll_factor"; 319750397Sobrien case DW_AT_MIPS_software_pipeline_depth: 319850397Sobrien return "DW_AT_MIPS_software_pipeline_depth"; 319950397Sobrien case DW_AT_MIPS_linkage_name: 320050397Sobrien return "DW_AT_MIPS_linkage_name"; 320150397Sobrien case DW_AT_MIPS_stride: 320250397Sobrien return "DW_AT_MIPS_stride"; 320350397Sobrien case DW_AT_MIPS_abstract_name: 320450397Sobrien return "DW_AT_MIPS_abstract_name"; 320550397Sobrien case DW_AT_MIPS_clone_origin: 320650397Sobrien return "DW_AT_MIPS_clone_origin"; 320750397Sobrien case DW_AT_MIPS_has_inlines: 320850397Sobrien return "DW_AT_MIPS_has_inlines"; 320950397Sobrien 321050397Sobrien case DW_AT_sf_names: 321150397Sobrien return "DW_AT_sf_names"; 321250397Sobrien case DW_AT_src_info: 321350397Sobrien return "DW_AT_src_info"; 321450397Sobrien case DW_AT_mac_info: 321550397Sobrien return "DW_AT_mac_info"; 321650397Sobrien case DW_AT_src_coords: 321750397Sobrien return "DW_AT_src_coords"; 321850397Sobrien case DW_AT_body_begin: 321950397Sobrien return "DW_AT_body_begin"; 322050397Sobrien case DW_AT_body_end: 322150397Sobrien return "DW_AT_body_end"; 322250397Sobrien default: 322350397Sobrien return "DW_AT_<unknown>"; 322450397Sobrien } 322550397Sobrien} 322650397Sobrien 322750397Sobrien/* Convert a DWARF value form code into its string name. */ 322850397Sobrien 322950397Sobrienstatic char * 323050397Sobriendwarf_form_name (form) 323150397Sobrien register unsigned form; 323250397Sobrien{ 323350397Sobrien switch (form) 323450397Sobrien { 323550397Sobrien case DW_FORM_addr: 323650397Sobrien return "DW_FORM_addr"; 323750397Sobrien case DW_FORM_block2: 323850397Sobrien return "DW_FORM_block2"; 323950397Sobrien case DW_FORM_block4: 324050397Sobrien return "DW_FORM_block4"; 324150397Sobrien case DW_FORM_data2: 324250397Sobrien return "DW_FORM_data2"; 324350397Sobrien case DW_FORM_data4: 324450397Sobrien return "DW_FORM_data4"; 324550397Sobrien case DW_FORM_data8: 324650397Sobrien return "DW_FORM_data8"; 324750397Sobrien case DW_FORM_string: 324850397Sobrien return "DW_FORM_string"; 324950397Sobrien case DW_FORM_block: 325050397Sobrien return "DW_FORM_block"; 325150397Sobrien case DW_FORM_block1: 325250397Sobrien return "DW_FORM_block1"; 325350397Sobrien case DW_FORM_data1: 325450397Sobrien return "DW_FORM_data1"; 325550397Sobrien case DW_FORM_flag: 325650397Sobrien return "DW_FORM_flag"; 325750397Sobrien case DW_FORM_sdata: 325850397Sobrien return "DW_FORM_sdata"; 325950397Sobrien case DW_FORM_strp: 326050397Sobrien return "DW_FORM_strp"; 326150397Sobrien case DW_FORM_udata: 326250397Sobrien return "DW_FORM_udata"; 326350397Sobrien case DW_FORM_ref_addr: 326450397Sobrien return "DW_FORM_ref_addr"; 326550397Sobrien case DW_FORM_ref1: 326650397Sobrien return "DW_FORM_ref1"; 326750397Sobrien case DW_FORM_ref2: 326850397Sobrien return "DW_FORM_ref2"; 326950397Sobrien case DW_FORM_ref4: 327050397Sobrien return "DW_FORM_ref4"; 327150397Sobrien case DW_FORM_ref8: 327250397Sobrien return "DW_FORM_ref8"; 327350397Sobrien case DW_FORM_ref_udata: 327450397Sobrien return "DW_FORM_ref_udata"; 327550397Sobrien case DW_FORM_indirect: 327650397Sobrien return "DW_FORM_indirect"; 327750397Sobrien default: 327850397Sobrien return "DW_FORM_<unknown>"; 327950397Sobrien } 328050397Sobrien} 328150397Sobrien 328250397Sobrien/* Convert a DWARF stack opcode into its string name. */ 328350397Sobrien 328450397Sobrienstatic char * 328550397Sobriendwarf_stack_op_name (op) 328650397Sobrien register unsigned op; 328750397Sobrien{ 328850397Sobrien switch (op) 328950397Sobrien { 329050397Sobrien case DW_OP_addr: 329150397Sobrien return "DW_OP_addr"; 329250397Sobrien case DW_OP_deref: 329350397Sobrien return "DW_OP_deref"; 329450397Sobrien case DW_OP_const1u: 329550397Sobrien return "DW_OP_const1u"; 329650397Sobrien case DW_OP_const1s: 329750397Sobrien return "DW_OP_const1s"; 329850397Sobrien case DW_OP_const2u: 329950397Sobrien return "DW_OP_const2u"; 330050397Sobrien case DW_OP_const2s: 330150397Sobrien return "DW_OP_const2s"; 330250397Sobrien case DW_OP_const4u: 330350397Sobrien return "DW_OP_const4u"; 330450397Sobrien case DW_OP_const4s: 330550397Sobrien return "DW_OP_const4s"; 330650397Sobrien case DW_OP_const8u: 330750397Sobrien return "DW_OP_const8u"; 330850397Sobrien case DW_OP_const8s: 330950397Sobrien return "DW_OP_const8s"; 331050397Sobrien case DW_OP_constu: 331150397Sobrien return "DW_OP_constu"; 331250397Sobrien case DW_OP_consts: 331350397Sobrien return "DW_OP_consts"; 331450397Sobrien case DW_OP_dup: 331550397Sobrien return "DW_OP_dup"; 331650397Sobrien case DW_OP_drop: 331750397Sobrien return "DW_OP_drop"; 331850397Sobrien case DW_OP_over: 331950397Sobrien return "DW_OP_over"; 332050397Sobrien case DW_OP_pick: 332150397Sobrien return "DW_OP_pick"; 332250397Sobrien case DW_OP_swap: 332350397Sobrien return "DW_OP_swap"; 332450397Sobrien case DW_OP_rot: 332550397Sobrien return "DW_OP_rot"; 332650397Sobrien case DW_OP_xderef: 332750397Sobrien return "DW_OP_xderef"; 332850397Sobrien case DW_OP_abs: 332950397Sobrien return "DW_OP_abs"; 333050397Sobrien case DW_OP_and: 333150397Sobrien return "DW_OP_and"; 333250397Sobrien case DW_OP_div: 333350397Sobrien return "DW_OP_div"; 333450397Sobrien case DW_OP_minus: 333550397Sobrien return "DW_OP_minus"; 333650397Sobrien case DW_OP_mod: 333750397Sobrien return "DW_OP_mod"; 333850397Sobrien case DW_OP_mul: 333950397Sobrien return "DW_OP_mul"; 334050397Sobrien case DW_OP_neg: 334150397Sobrien return "DW_OP_neg"; 334250397Sobrien case DW_OP_not: 334350397Sobrien return "DW_OP_not"; 334450397Sobrien case DW_OP_or: 334550397Sobrien return "DW_OP_or"; 334650397Sobrien case DW_OP_plus: 334750397Sobrien return "DW_OP_plus"; 334850397Sobrien case DW_OP_plus_uconst: 334950397Sobrien return "DW_OP_plus_uconst"; 335050397Sobrien case DW_OP_shl: 335150397Sobrien return "DW_OP_shl"; 335250397Sobrien case DW_OP_shr: 335350397Sobrien return "DW_OP_shr"; 335450397Sobrien case DW_OP_shra: 335550397Sobrien return "DW_OP_shra"; 335650397Sobrien case DW_OP_xor: 335750397Sobrien return "DW_OP_xor"; 335850397Sobrien case DW_OP_bra: 335950397Sobrien return "DW_OP_bra"; 336050397Sobrien case DW_OP_eq: 336150397Sobrien return "DW_OP_eq"; 336250397Sobrien case DW_OP_ge: 336350397Sobrien return "DW_OP_ge"; 336450397Sobrien case DW_OP_gt: 336550397Sobrien return "DW_OP_gt"; 336650397Sobrien case DW_OP_le: 336750397Sobrien return "DW_OP_le"; 336850397Sobrien case DW_OP_lt: 336950397Sobrien return "DW_OP_lt"; 337050397Sobrien case DW_OP_ne: 337150397Sobrien return "DW_OP_ne"; 337250397Sobrien case DW_OP_skip: 337350397Sobrien return "DW_OP_skip"; 337450397Sobrien case DW_OP_lit0: 337550397Sobrien return "DW_OP_lit0"; 337650397Sobrien case DW_OP_lit1: 337750397Sobrien return "DW_OP_lit1"; 337850397Sobrien case DW_OP_lit2: 337950397Sobrien return "DW_OP_lit2"; 338050397Sobrien case DW_OP_lit3: 338150397Sobrien return "DW_OP_lit3"; 338250397Sobrien case DW_OP_lit4: 338350397Sobrien return "DW_OP_lit4"; 338450397Sobrien case DW_OP_lit5: 338550397Sobrien return "DW_OP_lit5"; 338650397Sobrien case DW_OP_lit6: 338750397Sobrien return "DW_OP_lit6"; 338850397Sobrien case DW_OP_lit7: 338950397Sobrien return "DW_OP_lit7"; 339050397Sobrien case DW_OP_lit8: 339150397Sobrien return "DW_OP_lit8"; 339250397Sobrien case DW_OP_lit9: 339350397Sobrien return "DW_OP_lit9"; 339450397Sobrien case DW_OP_lit10: 339550397Sobrien return "DW_OP_lit10"; 339650397Sobrien case DW_OP_lit11: 339750397Sobrien return "DW_OP_lit11"; 339850397Sobrien case DW_OP_lit12: 339950397Sobrien return "DW_OP_lit12"; 340050397Sobrien case DW_OP_lit13: 340150397Sobrien return "DW_OP_lit13"; 340250397Sobrien case DW_OP_lit14: 340350397Sobrien return "DW_OP_lit14"; 340450397Sobrien case DW_OP_lit15: 340550397Sobrien return "DW_OP_lit15"; 340650397Sobrien case DW_OP_lit16: 340750397Sobrien return "DW_OP_lit16"; 340850397Sobrien case DW_OP_lit17: 340950397Sobrien return "DW_OP_lit17"; 341050397Sobrien case DW_OP_lit18: 341150397Sobrien return "DW_OP_lit18"; 341250397Sobrien case DW_OP_lit19: 341350397Sobrien return "DW_OP_lit19"; 341450397Sobrien case DW_OP_lit20: 341550397Sobrien return "DW_OP_lit20"; 341650397Sobrien case DW_OP_lit21: 341750397Sobrien return "DW_OP_lit21"; 341850397Sobrien case DW_OP_lit22: 341950397Sobrien return "DW_OP_lit22"; 342050397Sobrien case DW_OP_lit23: 342150397Sobrien return "DW_OP_lit23"; 342250397Sobrien case DW_OP_lit24: 342350397Sobrien return "DW_OP_lit24"; 342450397Sobrien case DW_OP_lit25: 342550397Sobrien return "DW_OP_lit25"; 342650397Sobrien case DW_OP_lit26: 342750397Sobrien return "DW_OP_lit26"; 342850397Sobrien case DW_OP_lit27: 342950397Sobrien return "DW_OP_lit27"; 343050397Sobrien case DW_OP_lit28: 343150397Sobrien return "DW_OP_lit28"; 343250397Sobrien case DW_OP_lit29: 343350397Sobrien return "DW_OP_lit29"; 343450397Sobrien case DW_OP_lit30: 343550397Sobrien return "DW_OP_lit30"; 343650397Sobrien case DW_OP_lit31: 343750397Sobrien return "DW_OP_lit31"; 343850397Sobrien case DW_OP_reg0: 343950397Sobrien return "DW_OP_reg0"; 344050397Sobrien case DW_OP_reg1: 344150397Sobrien return "DW_OP_reg1"; 344250397Sobrien case DW_OP_reg2: 344350397Sobrien return "DW_OP_reg2"; 344450397Sobrien case DW_OP_reg3: 344550397Sobrien return "DW_OP_reg3"; 344650397Sobrien case DW_OP_reg4: 344750397Sobrien return "DW_OP_reg4"; 344850397Sobrien case DW_OP_reg5: 344950397Sobrien return "DW_OP_reg5"; 345050397Sobrien case DW_OP_reg6: 345150397Sobrien return "DW_OP_reg6"; 345250397Sobrien case DW_OP_reg7: 345350397Sobrien return "DW_OP_reg7"; 345450397Sobrien case DW_OP_reg8: 345550397Sobrien return "DW_OP_reg8"; 345650397Sobrien case DW_OP_reg9: 345750397Sobrien return "DW_OP_reg9"; 345850397Sobrien case DW_OP_reg10: 345950397Sobrien return "DW_OP_reg10"; 346050397Sobrien case DW_OP_reg11: 346150397Sobrien return "DW_OP_reg11"; 346250397Sobrien case DW_OP_reg12: 346350397Sobrien return "DW_OP_reg12"; 346450397Sobrien case DW_OP_reg13: 346550397Sobrien return "DW_OP_reg13"; 346650397Sobrien case DW_OP_reg14: 346750397Sobrien return "DW_OP_reg14"; 346850397Sobrien case DW_OP_reg15: 346950397Sobrien return "DW_OP_reg15"; 347050397Sobrien case DW_OP_reg16: 347150397Sobrien return "DW_OP_reg16"; 347250397Sobrien case DW_OP_reg17: 347350397Sobrien return "DW_OP_reg17"; 347450397Sobrien case DW_OP_reg18: 347550397Sobrien return "DW_OP_reg18"; 347650397Sobrien case DW_OP_reg19: 347750397Sobrien return "DW_OP_reg19"; 347850397Sobrien case DW_OP_reg20: 347950397Sobrien return "DW_OP_reg20"; 348050397Sobrien case DW_OP_reg21: 348150397Sobrien return "DW_OP_reg21"; 348250397Sobrien case DW_OP_reg22: 348350397Sobrien return "DW_OP_reg22"; 348450397Sobrien case DW_OP_reg23: 348550397Sobrien return "DW_OP_reg23"; 348650397Sobrien case DW_OP_reg24: 348750397Sobrien return "DW_OP_reg24"; 348850397Sobrien case DW_OP_reg25: 348950397Sobrien return "DW_OP_reg25"; 349050397Sobrien case DW_OP_reg26: 349150397Sobrien return "DW_OP_reg26"; 349250397Sobrien case DW_OP_reg27: 349350397Sobrien return "DW_OP_reg27"; 349450397Sobrien case DW_OP_reg28: 349550397Sobrien return "DW_OP_reg28"; 349650397Sobrien case DW_OP_reg29: 349750397Sobrien return "DW_OP_reg29"; 349850397Sobrien case DW_OP_reg30: 349950397Sobrien return "DW_OP_reg30"; 350050397Sobrien case DW_OP_reg31: 350150397Sobrien return "DW_OP_reg31"; 350250397Sobrien case DW_OP_breg0: 350350397Sobrien return "DW_OP_breg0"; 350450397Sobrien case DW_OP_breg1: 350550397Sobrien return "DW_OP_breg1"; 350650397Sobrien case DW_OP_breg2: 350750397Sobrien return "DW_OP_breg2"; 350850397Sobrien case DW_OP_breg3: 350950397Sobrien return "DW_OP_breg3"; 351050397Sobrien case DW_OP_breg4: 351150397Sobrien return "DW_OP_breg4"; 351250397Sobrien case DW_OP_breg5: 351350397Sobrien return "DW_OP_breg5"; 351450397Sobrien case DW_OP_breg6: 351550397Sobrien return "DW_OP_breg6"; 351650397Sobrien case DW_OP_breg7: 351750397Sobrien return "DW_OP_breg7"; 351850397Sobrien case DW_OP_breg8: 351950397Sobrien return "DW_OP_breg8"; 352050397Sobrien case DW_OP_breg9: 352150397Sobrien return "DW_OP_breg9"; 352250397Sobrien case DW_OP_breg10: 352350397Sobrien return "DW_OP_breg10"; 352450397Sobrien case DW_OP_breg11: 352550397Sobrien return "DW_OP_breg11"; 352650397Sobrien case DW_OP_breg12: 352750397Sobrien return "DW_OP_breg12"; 352850397Sobrien case DW_OP_breg13: 352950397Sobrien return "DW_OP_breg13"; 353050397Sobrien case DW_OP_breg14: 353150397Sobrien return "DW_OP_breg14"; 353250397Sobrien case DW_OP_breg15: 353350397Sobrien return "DW_OP_breg15"; 353450397Sobrien case DW_OP_breg16: 353550397Sobrien return "DW_OP_breg16"; 353650397Sobrien case DW_OP_breg17: 353750397Sobrien return "DW_OP_breg17"; 353850397Sobrien case DW_OP_breg18: 353950397Sobrien return "DW_OP_breg18"; 354050397Sobrien case DW_OP_breg19: 354150397Sobrien return "DW_OP_breg19"; 354250397Sobrien case DW_OP_breg20: 354350397Sobrien return "DW_OP_breg20"; 354450397Sobrien case DW_OP_breg21: 354550397Sobrien return "DW_OP_breg21"; 354650397Sobrien case DW_OP_breg22: 354750397Sobrien return "DW_OP_breg22"; 354850397Sobrien case DW_OP_breg23: 354950397Sobrien return "DW_OP_breg23"; 355050397Sobrien case DW_OP_breg24: 355150397Sobrien return "DW_OP_breg24"; 355250397Sobrien case DW_OP_breg25: 355350397Sobrien return "DW_OP_breg25"; 355450397Sobrien case DW_OP_breg26: 355550397Sobrien return "DW_OP_breg26"; 355650397Sobrien case DW_OP_breg27: 355750397Sobrien return "DW_OP_breg27"; 355850397Sobrien case DW_OP_breg28: 355950397Sobrien return "DW_OP_breg28"; 356050397Sobrien case DW_OP_breg29: 356150397Sobrien return "DW_OP_breg29"; 356250397Sobrien case DW_OP_breg30: 356350397Sobrien return "DW_OP_breg30"; 356450397Sobrien case DW_OP_breg31: 356550397Sobrien return "DW_OP_breg31"; 356650397Sobrien case DW_OP_regx: 356750397Sobrien return "DW_OP_regx"; 356850397Sobrien case DW_OP_fbreg: 356950397Sobrien return "DW_OP_fbreg"; 357050397Sobrien case DW_OP_bregx: 357150397Sobrien return "DW_OP_bregx"; 357250397Sobrien case DW_OP_piece: 357350397Sobrien return "DW_OP_piece"; 357450397Sobrien case DW_OP_deref_size: 357550397Sobrien return "DW_OP_deref_size"; 357650397Sobrien case DW_OP_xderef_size: 357750397Sobrien return "DW_OP_xderef_size"; 357850397Sobrien case DW_OP_nop: 357950397Sobrien return "DW_OP_nop"; 358050397Sobrien default: 358150397Sobrien return "OP_<unknown>"; 358250397Sobrien } 358350397Sobrien} 358450397Sobrien 358550397Sobrien/* Convert a DWARF type code into its string name. */ 358650397Sobrien 358750397Sobrien#if 0 358850397Sobrienstatic char * 358950397Sobriendwarf_type_encoding_name (enc) 359050397Sobrien register unsigned enc; 359150397Sobrien{ 359250397Sobrien switch (enc) 359350397Sobrien { 359450397Sobrien case DW_ATE_address: 359550397Sobrien return "DW_ATE_address"; 359650397Sobrien case DW_ATE_boolean: 359750397Sobrien return "DW_ATE_boolean"; 359850397Sobrien case DW_ATE_complex_float: 359950397Sobrien return "DW_ATE_complex_float"; 360050397Sobrien case DW_ATE_float: 360150397Sobrien return "DW_ATE_float"; 360250397Sobrien case DW_ATE_signed: 360350397Sobrien return "DW_ATE_signed"; 360450397Sobrien case DW_ATE_signed_char: 360550397Sobrien return "DW_ATE_signed_char"; 360650397Sobrien case DW_ATE_unsigned: 360750397Sobrien return "DW_ATE_unsigned"; 360850397Sobrien case DW_ATE_unsigned_char: 360950397Sobrien return "DW_ATE_unsigned_char"; 361050397Sobrien default: 361150397Sobrien return "DW_ATE_<unknown>"; 361250397Sobrien } 361350397Sobrien} 361450397Sobrien#endif 361550397Sobrien 361650397Sobrien/* Determine the "ultimate origin" of a decl. The decl may be an inlined 361750397Sobrien instance of an inlined instance of a decl which is local to an inline 361850397Sobrien function, so we have to trace all of the way back through the origin chain 361950397Sobrien to find out what sort of node actually served as the original seed for the 362050397Sobrien given block. */ 362150397Sobrien 362250397Sobrienstatic tree 362350397Sobriendecl_ultimate_origin (decl) 362450397Sobrien register tree decl; 362550397Sobrien{ 362652284Sobrien#ifdef ENABLE_CHECKING 362752284Sobrien if (DECL_FROM_INLINE (DECL_ORIGIN (decl))) 362852284Sobrien /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the 362952284Sobrien most distant ancestor, this should never happen. */ 363052284Sobrien abort (); 363152284Sobrien#endif 363250397Sobrien 363352284Sobrien return DECL_ABSTRACT_ORIGIN (decl); 363450397Sobrien} 363550397Sobrien 363650397Sobrien/* Determine the "ultimate origin" of a block. The block may be an inlined 363750397Sobrien instance of an inlined instance of a block which is local to an inline 363850397Sobrien function, so we have to trace all of the way back through the origin chain 363950397Sobrien to find out what sort of node actually served as the original seed for the 364050397Sobrien given block. */ 364150397Sobrien 364250397Sobrienstatic tree 364350397Sobrienblock_ultimate_origin (block) 364450397Sobrien register tree block; 364550397Sobrien{ 364650397Sobrien register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); 364750397Sobrien 364850397Sobrien if (immediate_origin == NULL_TREE) 364950397Sobrien return NULL_TREE; 365050397Sobrien else 365150397Sobrien { 365250397Sobrien register tree ret_val; 365350397Sobrien register tree lookahead = immediate_origin; 365450397Sobrien 365550397Sobrien do 365650397Sobrien { 365750397Sobrien ret_val = lookahead; 365850397Sobrien lookahead = (TREE_CODE (ret_val) == BLOCK) 365950397Sobrien ? BLOCK_ABSTRACT_ORIGIN (ret_val) 366050397Sobrien : NULL; 366150397Sobrien } 366250397Sobrien while (lookahead != NULL && lookahead != ret_val); 366350397Sobrien 366450397Sobrien return ret_val; 366550397Sobrien } 366650397Sobrien} 366750397Sobrien 366850397Sobrien/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT 366950397Sobrien of a virtual function may refer to a base class, so we check the 'this' 367050397Sobrien parameter. */ 367150397Sobrien 367250397Sobrienstatic tree 367350397Sobriendecl_class_context (decl) 367450397Sobrien tree decl; 367550397Sobrien{ 367650397Sobrien tree context = NULL_TREE; 367750397Sobrien 367850397Sobrien if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl)) 367950397Sobrien context = DECL_CONTEXT (decl); 368050397Sobrien else 368150397Sobrien context = TYPE_MAIN_VARIANT 368250397Sobrien (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))))); 368350397Sobrien 368450397Sobrien if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't') 368550397Sobrien context = NULL_TREE; 368650397Sobrien 368750397Sobrien return context; 368850397Sobrien} 368950397Sobrien 369050397Sobrien/* Add an attribute/value pair to a DIE */ 369150397Sobrien 369250397Sobrienstatic inline void 369350397Sobrienadd_dwarf_attr (die, attr) 369450397Sobrien register dw_die_ref die; 369550397Sobrien register dw_attr_ref attr; 369650397Sobrien{ 369750397Sobrien if (die != NULL && attr != NULL) 369850397Sobrien { 369950397Sobrien if (die->die_attr == NULL) 370050397Sobrien { 370150397Sobrien die->die_attr = attr; 370250397Sobrien die->die_attr_last = attr; 370350397Sobrien } 370450397Sobrien else 370550397Sobrien { 370650397Sobrien die->die_attr_last->dw_attr_next = attr; 370750397Sobrien die->die_attr_last = attr; 370850397Sobrien } 370950397Sobrien } 371050397Sobrien} 371150397Sobrien 371250397Sobrien/* Add a flag value attribute to a DIE. */ 371350397Sobrien 371450397Sobrienstatic inline void 371550397Sobrienadd_AT_flag (die, attr_kind, flag) 371650397Sobrien register dw_die_ref die; 371750397Sobrien register enum dwarf_attribute attr_kind; 371850397Sobrien register unsigned flag; 371950397Sobrien{ 372050397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 372150397Sobrien 372250397Sobrien attr->dw_attr_next = NULL; 372350397Sobrien attr->dw_attr = attr_kind; 372450397Sobrien attr->dw_attr_val.val_class = dw_val_class_flag; 372550397Sobrien attr->dw_attr_val.v.val_flag = flag; 372650397Sobrien add_dwarf_attr (die, attr); 372750397Sobrien} 372850397Sobrien 372950397Sobrien/* Add a signed integer attribute value to a DIE. */ 373050397Sobrien 373150397Sobrienstatic inline void 373250397Sobrienadd_AT_int (die, attr_kind, int_val) 373350397Sobrien register dw_die_ref die; 373450397Sobrien register enum dwarf_attribute attr_kind; 373550397Sobrien register long int int_val; 373650397Sobrien{ 373750397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 373850397Sobrien 373950397Sobrien attr->dw_attr_next = NULL; 374050397Sobrien attr->dw_attr = attr_kind; 374150397Sobrien attr->dw_attr_val.val_class = dw_val_class_const; 374250397Sobrien attr->dw_attr_val.v.val_int = int_val; 374350397Sobrien add_dwarf_attr (die, attr); 374450397Sobrien} 374550397Sobrien 374650397Sobrien/* Add an unsigned integer attribute value to a DIE. */ 374750397Sobrien 374850397Sobrienstatic inline void 374950397Sobrienadd_AT_unsigned (die, attr_kind, unsigned_val) 375050397Sobrien register dw_die_ref die; 375150397Sobrien register enum dwarf_attribute attr_kind; 375250397Sobrien register unsigned long unsigned_val; 375350397Sobrien{ 375450397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 375550397Sobrien 375650397Sobrien attr->dw_attr_next = NULL; 375750397Sobrien attr->dw_attr = attr_kind; 375850397Sobrien attr->dw_attr_val.val_class = dw_val_class_unsigned_const; 375950397Sobrien attr->dw_attr_val.v.val_unsigned = unsigned_val; 376050397Sobrien add_dwarf_attr (die, attr); 376150397Sobrien} 376250397Sobrien 376350397Sobrien/* Add an unsigned double integer attribute value to a DIE. */ 376450397Sobrien 376550397Sobrienstatic inline void 376650397Sobrienadd_AT_long_long (die, attr_kind, val_hi, val_low) 376750397Sobrien register dw_die_ref die; 376850397Sobrien register enum dwarf_attribute attr_kind; 376950397Sobrien register unsigned long val_hi; 377050397Sobrien register unsigned long val_low; 377150397Sobrien{ 377250397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 377350397Sobrien 377450397Sobrien attr->dw_attr_next = NULL; 377550397Sobrien attr->dw_attr = attr_kind; 377650397Sobrien attr->dw_attr_val.val_class = dw_val_class_long_long; 377750397Sobrien attr->dw_attr_val.v.val_long_long.hi = val_hi; 377850397Sobrien attr->dw_attr_val.v.val_long_long.low = val_low; 377950397Sobrien add_dwarf_attr (die, attr); 378050397Sobrien} 378150397Sobrien 378250397Sobrien/* Add a floating point attribute value to a DIE and return it. */ 378350397Sobrien 378450397Sobrienstatic inline void 378550397Sobrienadd_AT_float (die, attr_kind, length, array) 378650397Sobrien register dw_die_ref die; 378750397Sobrien register enum dwarf_attribute attr_kind; 378850397Sobrien register unsigned length; 378950397Sobrien register long *array; 379050397Sobrien{ 379150397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 379250397Sobrien 379350397Sobrien attr->dw_attr_next = NULL; 379450397Sobrien attr->dw_attr = attr_kind; 379550397Sobrien attr->dw_attr_val.val_class = dw_val_class_float; 379650397Sobrien attr->dw_attr_val.v.val_float.length = length; 379750397Sobrien attr->dw_attr_val.v.val_float.array = array; 379850397Sobrien add_dwarf_attr (die, attr); 379950397Sobrien} 380050397Sobrien 380150397Sobrien/* Add a string attribute value to a DIE. */ 380250397Sobrien 380350397Sobrienstatic inline void 380450397Sobrienadd_AT_string (die, attr_kind, str) 380550397Sobrien register dw_die_ref die; 380650397Sobrien register enum dwarf_attribute attr_kind; 380750397Sobrien register char *str; 380850397Sobrien{ 380950397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 381050397Sobrien 381150397Sobrien attr->dw_attr_next = NULL; 381250397Sobrien attr->dw_attr = attr_kind; 381350397Sobrien attr->dw_attr_val.val_class = dw_val_class_str; 381450397Sobrien attr->dw_attr_val.v.val_str = xstrdup (str); 381550397Sobrien add_dwarf_attr (die, attr); 381650397Sobrien} 381750397Sobrien 381850397Sobrien/* Add a DIE reference attribute value to a DIE. */ 381950397Sobrien 382050397Sobrienstatic inline void 382150397Sobrienadd_AT_die_ref (die, attr_kind, targ_die) 382250397Sobrien register dw_die_ref die; 382350397Sobrien register enum dwarf_attribute attr_kind; 382450397Sobrien register dw_die_ref targ_die; 382550397Sobrien{ 382650397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 382750397Sobrien 382850397Sobrien attr->dw_attr_next = NULL; 382950397Sobrien attr->dw_attr = attr_kind; 383050397Sobrien attr->dw_attr_val.val_class = dw_val_class_die_ref; 383150397Sobrien attr->dw_attr_val.v.val_die_ref = targ_die; 383250397Sobrien add_dwarf_attr (die, attr); 383350397Sobrien} 383450397Sobrien 383550397Sobrien/* Add an FDE reference attribute value to a DIE. */ 383650397Sobrien 383750397Sobrienstatic inline void 383850397Sobrienadd_AT_fde_ref (die, attr_kind, targ_fde) 383950397Sobrien register dw_die_ref die; 384050397Sobrien register enum dwarf_attribute attr_kind; 384150397Sobrien register unsigned targ_fde; 384250397Sobrien{ 384350397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 384450397Sobrien 384550397Sobrien attr->dw_attr_next = NULL; 384650397Sobrien attr->dw_attr = attr_kind; 384750397Sobrien attr->dw_attr_val.val_class = dw_val_class_fde_ref; 384850397Sobrien attr->dw_attr_val.v.val_fde_index = targ_fde; 384950397Sobrien add_dwarf_attr (die, attr); 385050397Sobrien} 385150397Sobrien 385250397Sobrien/* Add a location description attribute value to a DIE. */ 385350397Sobrien 385450397Sobrienstatic inline void 385550397Sobrienadd_AT_loc (die, attr_kind, loc) 385650397Sobrien register dw_die_ref die; 385750397Sobrien register enum dwarf_attribute attr_kind; 385850397Sobrien register dw_loc_descr_ref loc; 385950397Sobrien{ 386050397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 386150397Sobrien 386250397Sobrien attr->dw_attr_next = NULL; 386350397Sobrien attr->dw_attr = attr_kind; 386450397Sobrien attr->dw_attr_val.val_class = dw_val_class_loc; 386550397Sobrien attr->dw_attr_val.v.val_loc = loc; 386650397Sobrien add_dwarf_attr (die, attr); 386750397Sobrien} 386850397Sobrien 386950397Sobrien/* Add an address constant attribute value to a DIE. */ 387050397Sobrien 387150397Sobrienstatic inline void 387250397Sobrienadd_AT_addr (die, attr_kind, addr) 387350397Sobrien register dw_die_ref die; 387450397Sobrien register enum dwarf_attribute attr_kind; 387550397Sobrien char *addr; 387650397Sobrien{ 387750397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 387850397Sobrien 387950397Sobrien attr->dw_attr_next = NULL; 388050397Sobrien attr->dw_attr = attr_kind; 388150397Sobrien attr->dw_attr_val.val_class = dw_val_class_addr; 388250397Sobrien attr->dw_attr_val.v.val_addr = addr; 388350397Sobrien add_dwarf_attr (die, attr); 388450397Sobrien} 388550397Sobrien 388650397Sobrien/* Add a label identifier attribute value to a DIE. */ 388750397Sobrien 388850397Sobrienstatic inline void 388950397Sobrienadd_AT_lbl_id (die, attr_kind, lbl_id) 389050397Sobrien register dw_die_ref die; 389150397Sobrien register enum dwarf_attribute attr_kind; 389250397Sobrien register char *lbl_id; 389350397Sobrien{ 389450397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 389550397Sobrien 389650397Sobrien attr->dw_attr_next = NULL; 389750397Sobrien attr->dw_attr = attr_kind; 389850397Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_id; 389950397Sobrien attr->dw_attr_val.v.val_lbl_id = xstrdup (lbl_id); 390050397Sobrien add_dwarf_attr (die, attr); 390150397Sobrien} 390250397Sobrien 390350397Sobrien/* Add a section offset attribute value to a DIE. */ 390450397Sobrien 390550397Sobrienstatic inline void 390652284Sobrienadd_AT_lbl_offset (die, attr_kind, label) 390750397Sobrien register dw_die_ref die; 390850397Sobrien register enum dwarf_attribute attr_kind; 390952284Sobrien register char *label; 391050397Sobrien{ 391150397Sobrien register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 391250397Sobrien 391350397Sobrien attr->dw_attr_next = NULL; 391450397Sobrien attr->dw_attr = attr_kind; 391552284Sobrien attr->dw_attr_val.val_class = dw_val_class_lbl_offset; 391652284Sobrien attr->dw_attr_val.v.val_lbl_id = label; 391750397Sobrien add_dwarf_attr (die, attr); 391850397Sobrien 391950397Sobrien} 392050397Sobrien 392150397Sobrien/* Test if die refers to an external subroutine. */ 392250397Sobrien 392350397Sobrienstatic inline int 392450397Sobrienis_extern_subr_die (die) 392550397Sobrien register dw_die_ref die; 392650397Sobrien{ 392750397Sobrien register dw_attr_ref a; 392850397Sobrien register int is_subr = FALSE; 392950397Sobrien register int is_extern = FALSE; 393050397Sobrien 393150397Sobrien if (die != NULL && die->die_tag == DW_TAG_subprogram) 393250397Sobrien { 393350397Sobrien is_subr = TRUE; 393450397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 393550397Sobrien { 393650397Sobrien if (a->dw_attr == DW_AT_external 393750397Sobrien && a->dw_attr_val.val_class == dw_val_class_flag 393850397Sobrien && a->dw_attr_val.v.val_flag != 0) 393950397Sobrien { 394050397Sobrien is_extern = TRUE; 394150397Sobrien break; 394250397Sobrien } 394350397Sobrien } 394450397Sobrien } 394550397Sobrien 394650397Sobrien return is_subr && is_extern; 394750397Sobrien} 394850397Sobrien 394950397Sobrien/* Get the attribute of type attr_kind. */ 395050397Sobrien 395150397Sobrienstatic inline dw_attr_ref 395250397Sobrienget_AT (die, attr_kind) 395350397Sobrien register dw_die_ref die; 395450397Sobrien register enum dwarf_attribute attr_kind; 395550397Sobrien{ 395650397Sobrien register dw_attr_ref a; 395750397Sobrien register dw_die_ref spec = NULL; 395850397Sobrien 395950397Sobrien if (die != NULL) 396050397Sobrien { 396150397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 396250397Sobrien { 396350397Sobrien if (a->dw_attr == attr_kind) 396450397Sobrien return a; 396550397Sobrien 396650397Sobrien if (a->dw_attr == DW_AT_specification 396750397Sobrien || a->dw_attr == DW_AT_abstract_origin) 396850397Sobrien spec = a->dw_attr_val.v.val_die_ref; 396950397Sobrien } 397050397Sobrien 397150397Sobrien if (spec) 397250397Sobrien return get_AT (spec, attr_kind); 397350397Sobrien } 397450397Sobrien 397550397Sobrien return NULL; 397650397Sobrien} 397750397Sobrien 397850397Sobrien/* Return the "low pc" attribute value, typically associated with 397950397Sobrien a subprogram DIE. Return null if the "low pc" attribute is 398050397Sobrien either not prsent, or if it cannot be represented as an 398150397Sobrien assembler label identifier. */ 398250397Sobrien 398350397Sobrienstatic inline char * 398450397Sobrienget_AT_low_pc (die) 398550397Sobrien register dw_die_ref die; 398650397Sobrien{ 398750397Sobrien register dw_attr_ref a = get_AT (die, DW_AT_low_pc); 398850397Sobrien 398950397Sobrien if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id) 399050397Sobrien return a->dw_attr_val.v.val_lbl_id; 399150397Sobrien 399250397Sobrien return NULL; 399350397Sobrien} 399450397Sobrien 399550397Sobrien/* Return the "high pc" attribute value, typically associated with 399650397Sobrien a subprogram DIE. Return null if the "high pc" attribute is 399750397Sobrien either not prsent, or if it cannot be represented as an 399850397Sobrien assembler label identifier. */ 399950397Sobrien 400050397Sobrienstatic inline char * 400150397Sobrienget_AT_hi_pc (die) 400250397Sobrien register dw_die_ref die; 400350397Sobrien{ 400450397Sobrien register dw_attr_ref a = get_AT (die, DW_AT_high_pc); 400550397Sobrien 400650397Sobrien if (a && a->dw_attr_val.val_class == dw_val_class_lbl_id) 400750397Sobrien return a->dw_attr_val.v.val_lbl_id; 400850397Sobrien 400950397Sobrien return NULL; 401050397Sobrien} 401150397Sobrien 401250397Sobrien/* Return the value of the string attribute designated by ATTR_KIND, or 401350397Sobrien NULL if it is not present. */ 401450397Sobrien 401550397Sobrienstatic inline char * 401650397Sobrienget_AT_string (die, attr_kind) 401750397Sobrien register dw_die_ref die; 401850397Sobrien register enum dwarf_attribute attr_kind; 401950397Sobrien{ 402050397Sobrien register dw_attr_ref a = get_AT (die, attr_kind); 402150397Sobrien 402250397Sobrien if (a && a->dw_attr_val.val_class == dw_val_class_str) 402350397Sobrien return a->dw_attr_val.v.val_str; 402450397Sobrien 402550397Sobrien return NULL; 402650397Sobrien} 402750397Sobrien 402850397Sobrien/* Return the value of the flag attribute designated by ATTR_KIND, or -1 402950397Sobrien if it is not present. */ 403050397Sobrien 403150397Sobrienstatic inline int 403250397Sobrienget_AT_flag (die, attr_kind) 403350397Sobrien register dw_die_ref die; 403450397Sobrien register enum dwarf_attribute attr_kind; 403550397Sobrien{ 403650397Sobrien register dw_attr_ref a = get_AT (die, attr_kind); 403750397Sobrien 403850397Sobrien if (a && a->dw_attr_val.val_class == dw_val_class_flag) 403950397Sobrien return a->dw_attr_val.v.val_flag; 404050397Sobrien 404150397Sobrien return -1; 404250397Sobrien} 404350397Sobrien 404450397Sobrien/* Return the value of the unsigned attribute designated by ATTR_KIND, or 0 404550397Sobrien if it is not present. */ 404650397Sobrien 404750397Sobrienstatic inline unsigned 404850397Sobrienget_AT_unsigned (die, attr_kind) 404950397Sobrien register dw_die_ref die; 405050397Sobrien register enum dwarf_attribute attr_kind; 405150397Sobrien{ 405250397Sobrien register dw_attr_ref a = get_AT (die, attr_kind); 405350397Sobrien 405450397Sobrien if (a && a->dw_attr_val.val_class == dw_val_class_unsigned_const) 405550397Sobrien return a->dw_attr_val.v.val_unsigned; 405650397Sobrien 405750397Sobrien return 0; 405850397Sobrien} 405950397Sobrien 406050397Sobrienstatic inline int 406150397Sobrienis_c_family () 406250397Sobrien{ 406350397Sobrien register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 406450397Sobrien 406550397Sobrien return (lang == DW_LANG_C || lang == DW_LANG_C89 406650397Sobrien || lang == DW_LANG_C_plus_plus); 406750397Sobrien} 406850397Sobrien 406950397Sobrienstatic inline int 407050397Sobrienis_fortran () 407150397Sobrien{ 407250397Sobrien register unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); 407350397Sobrien 407450397Sobrien return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90); 407550397Sobrien} 407650397Sobrien 407750397Sobrien/* Remove the specified attribute if present. */ 407850397Sobrien 407950397Sobrienstatic inline void 408050397Sobrienremove_AT (die, attr_kind) 408150397Sobrien register dw_die_ref die; 408250397Sobrien register enum dwarf_attribute attr_kind; 408350397Sobrien{ 408450397Sobrien register dw_attr_ref a; 408550397Sobrien register dw_attr_ref removed = NULL;; 408650397Sobrien 408750397Sobrien if (die != NULL) 408850397Sobrien { 408950397Sobrien if (die->die_attr->dw_attr == attr_kind) 409050397Sobrien { 409150397Sobrien removed = die->die_attr; 409250397Sobrien if (die->die_attr_last == die->die_attr) 409350397Sobrien die->die_attr_last = NULL; 409450397Sobrien 409550397Sobrien die->die_attr = die->die_attr->dw_attr_next; 409650397Sobrien } 409750397Sobrien 409850397Sobrien else 409950397Sobrien for (a = die->die_attr; a->dw_attr_next != NULL; 410050397Sobrien a = a->dw_attr_next) 410150397Sobrien if (a->dw_attr_next->dw_attr == attr_kind) 410250397Sobrien { 410350397Sobrien removed = a->dw_attr_next; 410450397Sobrien if (die->die_attr_last == a->dw_attr_next) 410550397Sobrien die->die_attr_last = a; 410650397Sobrien 410750397Sobrien a->dw_attr_next = a->dw_attr_next->dw_attr_next; 410850397Sobrien break; 410950397Sobrien } 411050397Sobrien 411150397Sobrien if (removed != 0) 411250397Sobrien free (removed); 411350397Sobrien } 411450397Sobrien} 411550397Sobrien 411650397Sobrien/* Discard the children of this DIE. */ 411750397Sobrien 411850397Sobrienstatic inline void 411950397Sobrienremove_children (die) 412050397Sobrien register dw_die_ref die; 412150397Sobrien{ 412250397Sobrien register dw_die_ref child_die = die->die_child; 412350397Sobrien 412450397Sobrien die->die_child = NULL; 412550397Sobrien die->die_child_last = NULL; 412650397Sobrien 412750397Sobrien while (child_die != NULL) 412850397Sobrien { 412950397Sobrien register dw_die_ref tmp_die = child_die; 413050397Sobrien register dw_attr_ref a; 413150397Sobrien 413250397Sobrien child_die = child_die->die_sib; 413350397Sobrien 413450397Sobrien for (a = tmp_die->die_attr; a != NULL; ) 413550397Sobrien { 413650397Sobrien register dw_attr_ref tmp_a = a; 413750397Sobrien 413850397Sobrien a = a->dw_attr_next; 413950397Sobrien free (tmp_a); 414050397Sobrien } 414150397Sobrien 414250397Sobrien free (tmp_die); 414350397Sobrien } 414450397Sobrien} 414550397Sobrien 414650397Sobrien/* Add a child DIE below its parent. */ 414750397Sobrien 414850397Sobrienstatic inline void 414950397Sobrienadd_child_die (die, child_die) 415050397Sobrien register dw_die_ref die; 415150397Sobrien register dw_die_ref child_die; 415250397Sobrien{ 415350397Sobrien if (die != NULL && child_die != NULL) 415450397Sobrien { 415550397Sobrien if (die == child_die) 415650397Sobrien abort (); 415750397Sobrien child_die->die_parent = die; 415850397Sobrien child_die->die_sib = NULL; 415950397Sobrien 416050397Sobrien if (die->die_child == NULL) 416150397Sobrien { 416250397Sobrien die->die_child = child_die; 416350397Sobrien die->die_child_last = child_die; 416450397Sobrien } 416550397Sobrien else 416650397Sobrien { 416750397Sobrien die->die_child_last->die_sib = child_die; 416850397Sobrien die->die_child_last = child_die; 416950397Sobrien } 417050397Sobrien } 417150397Sobrien} 417250397Sobrien 417350397Sobrien/* Return a pointer to a newly created DIE node. */ 417450397Sobrien 417550397Sobrienstatic inline dw_die_ref 417650397Sobriennew_die (tag_value, parent_die) 417750397Sobrien register enum dwarf_tag tag_value; 417850397Sobrien register dw_die_ref parent_die; 417950397Sobrien{ 418050397Sobrien register dw_die_ref die = (dw_die_ref) xmalloc (sizeof (die_node)); 418150397Sobrien 418250397Sobrien die->die_tag = tag_value; 418350397Sobrien die->die_abbrev = 0; 418450397Sobrien die->die_offset = 0; 418550397Sobrien die->die_child = NULL; 418650397Sobrien die->die_parent = NULL; 418750397Sobrien die->die_sib = NULL; 418850397Sobrien die->die_child_last = NULL; 418950397Sobrien die->die_attr = NULL; 419050397Sobrien die->die_attr_last = NULL; 419150397Sobrien 419250397Sobrien if (parent_die != NULL) 419350397Sobrien add_child_die (parent_die, die); 419450397Sobrien else 419550397Sobrien { 419650397Sobrien limbo_die_node *limbo_node; 419750397Sobrien 419850397Sobrien limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node)); 419950397Sobrien limbo_node->die = die; 420050397Sobrien limbo_node->next = limbo_die_list; 420150397Sobrien limbo_die_list = limbo_node; 420250397Sobrien } 420350397Sobrien 420450397Sobrien return die; 420550397Sobrien} 420650397Sobrien 420750397Sobrien/* Return the DIE associated with the given type specifier. */ 420850397Sobrien 420950397Sobrienstatic inline dw_die_ref 421050397Sobrienlookup_type_die (type) 421150397Sobrien register tree type; 421250397Sobrien{ 421350397Sobrien return (dw_die_ref) TYPE_SYMTAB_POINTER (type); 421450397Sobrien} 421550397Sobrien 421650397Sobrien/* Equate a DIE to a given type specifier. */ 421750397Sobrien 421850397Sobrienstatic void 421950397Sobrienequate_type_number_to_die (type, type_die) 422050397Sobrien register tree type; 422150397Sobrien register dw_die_ref type_die; 422250397Sobrien{ 422350397Sobrien TYPE_SYMTAB_POINTER (type) = (char *) type_die; 422450397Sobrien} 422550397Sobrien 422650397Sobrien/* Return the DIE associated with a given declaration. */ 422750397Sobrien 422850397Sobrienstatic inline dw_die_ref 422950397Sobrienlookup_decl_die (decl) 423050397Sobrien register tree decl; 423150397Sobrien{ 423250397Sobrien register unsigned decl_id = DECL_UID (decl); 423350397Sobrien 423450397Sobrien return (decl_id < decl_die_table_in_use 423550397Sobrien ? decl_die_table[decl_id] : NULL); 423650397Sobrien} 423750397Sobrien 423850397Sobrien/* Equate a DIE to a particular declaration. */ 423950397Sobrien 424050397Sobrienstatic void 424150397Sobrienequate_decl_number_to_die (decl, decl_die) 424250397Sobrien register tree decl; 424350397Sobrien register dw_die_ref decl_die; 424450397Sobrien{ 424550397Sobrien register unsigned decl_id = DECL_UID (decl); 424650397Sobrien register unsigned num_allocated; 424750397Sobrien 424850397Sobrien if (decl_id >= decl_die_table_allocated) 424950397Sobrien { 425050397Sobrien num_allocated 425150397Sobrien = ((decl_id + 1 + DECL_DIE_TABLE_INCREMENT - 1) 425250397Sobrien / DECL_DIE_TABLE_INCREMENT) 425350397Sobrien * DECL_DIE_TABLE_INCREMENT; 425450397Sobrien 425550397Sobrien decl_die_table 425650397Sobrien = (dw_die_ref *) xrealloc (decl_die_table, 425750397Sobrien sizeof (dw_die_ref) * num_allocated); 425850397Sobrien 425950397Sobrien bzero ((char *) &decl_die_table[decl_die_table_allocated], 426050397Sobrien (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref)); 426150397Sobrien decl_die_table_allocated = num_allocated; 426250397Sobrien } 426350397Sobrien 426450397Sobrien if (decl_id >= decl_die_table_in_use) 426550397Sobrien decl_die_table_in_use = (decl_id + 1); 426650397Sobrien 426750397Sobrien decl_die_table[decl_id] = decl_die; 426850397Sobrien} 426950397Sobrien 427050397Sobrien/* Return a pointer to a newly allocated location description. Location 427150397Sobrien descriptions are simple expression terms that can be strung 427250397Sobrien together to form more complicated location (address) descriptions. */ 427350397Sobrien 427450397Sobrienstatic inline dw_loc_descr_ref 427550397Sobriennew_loc_descr (op, oprnd1, oprnd2) 427650397Sobrien register enum dwarf_location_atom op; 427750397Sobrien register unsigned long oprnd1; 427850397Sobrien register unsigned long oprnd2; 427950397Sobrien{ 428050397Sobrien register dw_loc_descr_ref descr 428150397Sobrien = (dw_loc_descr_ref) xmalloc (sizeof (dw_loc_descr_node)); 428250397Sobrien 428350397Sobrien descr->dw_loc_next = NULL; 428450397Sobrien descr->dw_loc_opc = op; 428550397Sobrien descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const; 428650397Sobrien descr->dw_loc_oprnd1.v.val_unsigned = oprnd1; 428750397Sobrien descr->dw_loc_oprnd2.val_class = dw_val_class_unsigned_const; 428850397Sobrien descr->dw_loc_oprnd2.v.val_unsigned = oprnd2; 428950397Sobrien 429050397Sobrien return descr; 429150397Sobrien} 429250397Sobrien 429350397Sobrien/* Add a location description term to a location description expression. */ 429450397Sobrien 429550397Sobrienstatic inline void 429650397Sobrienadd_loc_descr (list_head, descr) 429750397Sobrien register dw_loc_descr_ref *list_head; 429850397Sobrien register dw_loc_descr_ref descr; 429950397Sobrien{ 430050397Sobrien register dw_loc_descr_ref *d; 430150397Sobrien 430250397Sobrien /* Find the end of the chain. */ 430350397Sobrien for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) 430450397Sobrien ; 430550397Sobrien 430650397Sobrien *d = descr; 430750397Sobrien} 430850397Sobrien 430950397Sobrien/* Keep track of the number of spaces used to indent the 431050397Sobrien output of the debugging routines that print the structure of 431150397Sobrien the DIE internal representation. */ 431250397Sobrienstatic int print_indent; 431350397Sobrien 431450397Sobrien/* Indent the line the number of spaces given by print_indent. */ 431550397Sobrien 431650397Sobrienstatic inline void 431750397Sobrienprint_spaces (outfile) 431850397Sobrien FILE *outfile; 431950397Sobrien{ 432050397Sobrien fprintf (outfile, "%*s", print_indent, ""); 432150397Sobrien} 432250397Sobrien 432350397Sobrien/* Print the information associated with a given DIE, and its children. 432450397Sobrien This routine is a debugging aid only. */ 432550397Sobrien 432650397Sobrienstatic void 432750397Sobrienprint_die (die, outfile) 432850397Sobrien dw_die_ref die; 432950397Sobrien FILE *outfile; 433050397Sobrien{ 433150397Sobrien register dw_attr_ref a; 433250397Sobrien register dw_die_ref c; 433350397Sobrien 433450397Sobrien print_spaces (outfile); 433550397Sobrien fprintf (outfile, "DIE %4lu: %s\n", 433650397Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 433750397Sobrien print_spaces (outfile); 433850397Sobrien fprintf (outfile, " abbrev id: %lu", die->die_abbrev); 433950397Sobrien fprintf (outfile, " offset: %lu\n", die->die_offset); 434050397Sobrien 434150397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 434250397Sobrien { 434350397Sobrien print_spaces (outfile); 434450397Sobrien fprintf (outfile, " %s: ", dwarf_attr_name (a->dw_attr)); 434550397Sobrien 434650397Sobrien switch (a->dw_attr_val.val_class) 434750397Sobrien { 434850397Sobrien case dw_val_class_addr: 434950397Sobrien fprintf (outfile, "address"); 435050397Sobrien break; 435150397Sobrien case dw_val_class_loc: 435250397Sobrien fprintf (outfile, "location descriptor"); 435350397Sobrien break; 435450397Sobrien case dw_val_class_const: 435550397Sobrien fprintf (outfile, "%ld", a->dw_attr_val.v.val_int); 435650397Sobrien break; 435750397Sobrien case dw_val_class_unsigned_const: 435850397Sobrien fprintf (outfile, "%lu", a->dw_attr_val.v.val_unsigned); 435950397Sobrien break; 436050397Sobrien case dw_val_class_long_long: 436150397Sobrien fprintf (outfile, "constant (%lu,%lu)", 436250397Sobrien a->dw_attr_val.v.val_long_long.hi, 436350397Sobrien a->dw_attr_val.v.val_long_long.low); 436450397Sobrien break; 436550397Sobrien case dw_val_class_float: 436650397Sobrien fprintf (outfile, "floating-point constant"); 436750397Sobrien break; 436850397Sobrien case dw_val_class_flag: 436950397Sobrien fprintf (outfile, "%u", a->dw_attr_val.v.val_flag); 437050397Sobrien break; 437150397Sobrien case dw_val_class_die_ref: 437250397Sobrien if (a->dw_attr_val.v.val_die_ref != NULL) 437350397Sobrien fprintf (outfile, "die -> %lu", 437450397Sobrien a->dw_attr_val.v.val_die_ref->die_offset); 437550397Sobrien else 437650397Sobrien fprintf (outfile, "die -> <null>"); 437750397Sobrien break; 437850397Sobrien case dw_val_class_lbl_id: 437952284Sobrien case dw_val_class_lbl_offset: 438050397Sobrien fprintf (outfile, "label: %s", a->dw_attr_val.v.val_lbl_id); 438150397Sobrien break; 438250397Sobrien case dw_val_class_str: 438350397Sobrien if (a->dw_attr_val.v.val_str != NULL) 438450397Sobrien fprintf (outfile, "\"%s\"", a->dw_attr_val.v.val_str); 438550397Sobrien else 438650397Sobrien fprintf (outfile, "<null>"); 438750397Sobrien break; 438850397Sobrien default: 438950397Sobrien break; 439050397Sobrien } 439150397Sobrien 439250397Sobrien fprintf (outfile, "\n"); 439350397Sobrien } 439450397Sobrien 439550397Sobrien if (die->die_child != NULL) 439650397Sobrien { 439750397Sobrien print_indent += 4; 439850397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 439950397Sobrien print_die (c, outfile); 440050397Sobrien 440150397Sobrien print_indent -= 4; 440250397Sobrien } 440350397Sobrien} 440450397Sobrien 440550397Sobrien/* Print the contents of the source code line number correspondence table. 440650397Sobrien This routine is a debugging aid only. */ 440750397Sobrien 440850397Sobrienstatic void 440950397Sobrienprint_dwarf_line_table (outfile) 441050397Sobrien FILE *outfile; 441150397Sobrien{ 441250397Sobrien register unsigned i; 441350397Sobrien register dw_line_info_ref line_info; 441450397Sobrien 441550397Sobrien fprintf (outfile, "\n\nDWARF source line information\n"); 441650397Sobrien for (i = 1; i < line_info_table_in_use; ++i) 441750397Sobrien { 441850397Sobrien line_info = &line_info_table[i]; 441950397Sobrien fprintf (outfile, "%5d: ", i); 442050397Sobrien fprintf (outfile, "%-20s", file_table[line_info->dw_file_num]); 442150397Sobrien fprintf (outfile, "%6ld", line_info->dw_line_num); 442250397Sobrien fprintf (outfile, "\n"); 442350397Sobrien } 442450397Sobrien 442550397Sobrien fprintf (outfile, "\n\n"); 442650397Sobrien} 442750397Sobrien 442850397Sobrien/* Print the information collected for a given DIE. */ 442950397Sobrien 443050397Sobrienvoid 443150397Sobriendebug_dwarf_die (die) 443250397Sobrien dw_die_ref die; 443350397Sobrien{ 443450397Sobrien print_die (die, stderr); 443550397Sobrien} 443650397Sobrien 443750397Sobrien/* Print all DWARF information collected for the compilation unit. 443850397Sobrien This routine is a debugging aid only. */ 443950397Sobrien 444050397Sobrienvoid 444150397Sobriendebug_dwarf () 444250397Sobrien{ 444350397Sobrien print_indent = 0; 444450397Sobrien print_die (comp_unit_die, stderr); 444550397Sobrien print_dwarf_line_table (stderr); 444650397Sobrien} 444750397Sobrien 444850397Sobrien/* Traverse the DIE, and add a sibling attribute if it may have the 444950397Sobrien effect of speeding up access to siblings. To save some space, 445050397Sobrien avoid generating sibling attributes for DIE's without children. */ 445150397Sobrien 445250397Sobrienstatic void 445350397Sobrienadd_sibling_attributes(die) 445450397Sobrien register dw_die_ref die; 445550397Sobrien{ 445650397Sobrien register dw_die_ref c; 445750397Sobrien register dw_attr_ref attr; 445850397Sobrien if (die != comp_unit_die && die->die_child != NULL) 445950397Sobrien { 446050397Sobrien attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); 446150397Sobrien attr->dw_attr_next = NULL; 446250397Sobrien attr->dw_attr = DW_AT_sibling; 446350397Sobrien attr->dw_attr_val.val_class = dw_val_class_die_ref; 446450397Sobrien attr->dw_attr_val.v.val_die_ref = die->die_sib; 446550397Sobrien 446650397Sobrien /* Add the sibling link to the front of the attribute list. */ 446750397Sobrien attr->dw_attr_next = die->die_attr; 446850397Sobrien if (die->die_attr == NULL) 446950397Sobrien die->die_attr_last = attr; 447050397Sobrien 447150397Sobrien die->die_attr = attr; 447250397Sobrien } 447350397Sobrien 447450397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 447550397Sobrien add_sibling_attributes (c); 447650397Sobrien} 447750397Sobrien 447850397Sobrien/* The format of each DIE (and its attribute value pairs) 447950397Sobrien is encoded in an abbreviation table. This routine builds the 448050397Sobrien abbreviation table and assigns a unique abbreviation id for 448150397Sobrien each abbreviation entry. The children of each die are visited 448250397Sobrien recursively. */ 448350397Sobrien 448450397Sobrienstatic void 448550397Sobrienbuild_abbrev_table (die) 448650397Sobrien register dw_die_ref die; 448750397Sobrien{ 448850397Sobrien register unsigned long abbrev_id; 448950397Sobrien register unsigned long n_alloc; 449050397Sobrien register dw_die_ref c; 449150397Sobrien register dw_attr_ref d_attr, a_attr; 449250397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 449350397Sobrien { 449450397Sobrien register dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 449550397Sobrien 449650397Sobrien if (abbrev->die_tag == die->die_tag) 449750397Sobrien { 449850397Sobrien if ((abbrev->die_child != NULL) == (die->die_child != NULL)) 449950397Sobrien { 450050397Sobrien a_attr = abbrev->die_attr; 450150397Sobrien d_attr = die->die_attr; 450250397Sobrien 450350397Sobrien while (a_attr != NULL && d_attr != NULL) 450450397Sobrien { 450550397Sobrien if ((a_attr->dw_attr != d_attr->dw_attr) 450650397Sobrien || (value_format (&a_attr->dw_attr_val) 450750397Sobrien != value_format (&d_attr->dw_attr_val))) 450850397Sobrien break; 450950397Sobrien 451050397Sobrien a_attr = a_attr->dw_attr_next; 451150397Sobrien d_attr = d_attr->dw_attr_next; 451250397Sobrien } 451350397Sobrien 451450397Sobrien if (a_attr == NULL && d_attr == NULL) 451550397Sobrien break; 451650397Sobrien } 451750397Sobrien } 451850397Sobrien } 451950397Sobrien 452050397Sobrien if (abbrev_id >= abbrev_die_table_in_use) 452150397Sobrien { 452250397Sobrien if (abbrev_die_table_in_use >= abbrev_die_table_allocated) 452350397Sobrien { 452450397Sobrien n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; 452550397Sobrien abbrev_die_table 452650397Sobrien = (dw_die_ref *) xrealloc (abbrev_die_table, 452750397Sobrien sizeof (dw_die_ref) * n_alloc); 452850397Sobrien 452950397Sobrien bzero ((char *) &abbrev_die_table[abbrev_die_table_allocated], 453050397Sobrien (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); 453150397Sobrien abbrev_die_table_allocated = n_alloc; 453250397Sobrien } 453350397Sobrien 453450397Sobrien ++abbrev_die_table_in_use; 453550397Sobrien abbrev_die_table[abbrev_id] = die; 453650397Sobrien } 453750397Sobrien 453850397Sobrien die->die_abbrev = abbrev_id; 453950397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 454050397Sobrien build_abbrev_table (c); 454150397Sobrien} 454250397Sobrien 454350397Sobrien/* Return the size of a string, including the null byte. 454450397Sobrien 454550397Sobrien This used to treat backslashes as escapes, and hence they were not included 454650397Sobrien in the count. However, that conflicts with what ASM_OUTPUT_ASCII does, 454750397Sobrien which treats a backslash as a backslash, escaping it if necessary, and hence 454850397Sobrien we must include them in the count. */ 454950397Sobrien 455050397Sobrienstatic unsigned long 455150397Sobriensize_of_string (str) 455250397Sobrien register char *str; 455350397Sobrien{ 455450397Sobrien return strlen (str) + 1; 455550397Sobrien} 455650397Sobrien 455750397Sobrien/* Return the size of a location descriptor. */ 455850397Sobrien 455950397Sobrienstatic unsigned long 456050397Sobriensize_of_loc_descr (loc) 456150397Sobrien register dw_loc_descr_ref loc; 456250397Sobrien{ 456350397Sobrien register unsigned long size = 1; 456450397Sobrien 456550397Sobrien switch (loc->dw_loc_opc) 456650397Sobrien { 456750397Sobrien case DW_OP_addr: 456850397Sobrien size += PTR_SIZE; 456950397Sobrien break; 457050397Sobrien case DW_OP_const1u: 457150397Sobrien case DW_OP_const1s: 457250397Sobrien size += 1; 457350397Sobrien break; 457450397Sobrien case DW_OP_const2u: 457550397Sobrien case DW_OP_const2s: 457650397Sobrien size += 2; 457750397Sobrien break; 457850397Sobrien case DW_OP_const4u: 457950397Sobrien case DW_OP_const4s: 458050397Sobrien size += 4; 458150397Sobrien break; 458250397Sobrien case DW_OP_const8u: 458350397Sobrien case DW_OP_const8s: 458450397Sobrien size += 8; 458550397Sobrien break; 458650397Sobrien case DW_OP_constu: 458750397Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 458850397Sobrien break; 458950397Sobrien case DW_OP_consts: 459050397Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 459150397Sobrien break; 459250397Sobrien case DW_OP_pick: 459350397Sobrien size += 1; 459450397Sobrien break; 459550397Sobrien case DW_OP_plus_uconst: 459650397Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 459750397Sobrien break; 459850397Sobrien case DW_OP_skip: 459950397Sobrien case DW_OP_bra: 460050397Sobrien size += 2; 460150397Sobrien break; 460250397Sobrien case DW_OP_breg0: 460350397Sobrien case DW_OP_breg1: 460450397Sobrien case DW_OP_breg2: 460550397Sobrien case DW_OP_breg3: 460650397Sobrien case DW_OP_breg4: 460750397Sobrien case DW_OP_breg5: 460850397Sobrien case DW_OP_breg6: 460950397Sobrien case DW_OP_breg7: 461050397Sobrien case DW_OP_breg8: 461150397Sobrien case DW_OP_breg9: 461250397Sobrien case DW_OP_breg10: 461350397Sobrien case DW_OP_breg11: 461450397Sobrien case DW_OP_breg12: 461550397Sobrien case DW_OP_breg13: 461650397Sobrien case DW_OP_breg14: 461750397Sobrien case DW_OP_breg15: 461850397Sobrien case DW_OP_breg16: 461950397Sobrien case DW_OP_breg17: 462050397Sobrien case DW_OP_breg18: 462150397Sobrien case DW_OP_breg19: 462250397Sobrien case DW_OP_breg20: 462350397Sobrien case DW_OP_breg21: 462450397Sobrien case DW_OP_breg22: 462550397Sobrien case DW_OP_breg23: 462650397Sobrien case DW_OP_breg24: 462750397Sobrien case DW_OP_breg25: 462850397Sobrien case DW_OP_breg26: 462950397Sobrien case DW_OP_breg27: 463050397Sobrien case DW_OP_breg28: 463150397Sobrien case DW_OP_breg29: 463250397Sobrien case DW_OP_breg30: 463350397Sobrien case DW_OP_breg31: 463450397Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 463550397Sobrien break; 463650397Sobrien case DW_OP_regx: 463750397Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 463850397Sobrien break; 463950397Sobrien case DW_OP_fbreg: 464050397Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd1.v.val_int); 464150397Sobrien break; 464250397Sobrien case DW_OP_bregx: 464350397Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 464450397Sobrien size += size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int); 464550397Sobrien break; 464650397Sobrien case DW_OP_piece: 464750397Sobrien size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned); 464850397Sobrien break; 464950397Sobrien case DW_OP_deref_size: 465050397Sobrien case DW_OP_xderef_size: 465150397Sobrien size += 1; 465250397Sobrien break; 465350397Sobrien default: 465450397Sobrien break; 465550397Sobrien } 465650397Sobrien 465750397Sobrien return size; 465850397Sobrien} 465950397Sobrien 466050397Sobrien/* Return the size of a series of location descriptors. */ 466150397Sobrien 466250397Sobrienstatic unsigned long 466350397Sobriensize_of_locs (loc) 466450397Sobrien register dw_loc_descr_ref loc; 466550397Sobrien{ 466650397Sobrien register unsigned long size = 0; 466750397Sobrien 466850397Sobrien for (; loc != NULL; loc = loc->dw_loc_next) 466950397Sobrien size += size_of_loc_descr (loc); 467050397Sobrien 467150397Sobrien return size; 467250397Sobrien} 467350397Sobrien 467450397Sobrien/* Return the power-of-two number of bytes necessary to represent VALUE. */ 467550397Sobrien 467650397Sobrienstatic int 467750397Sobrienconstant_size (value) 467850397Sobrien long unsigned value; 467950397Sobrien{ 468050397Sobrien int log; 468150397Sobrien 468250397Sobrien if (value == 0) 468350397Sobrien log = 0; 468450397Sobrien else 468550397Sobrien log = floor_log2 (value); 468650397Sobrien 468750397Sobrien log = log / 8; 468850397Sobrien log = 1 << (floor_log2 (log) + 1); 468950397Sobrien 469050397Sobrien return log; 469150397Sobrien} 469250397Sobrien 469350397Sobrien/* Return the size of a DIE, as it is represented in the 469450397Sobrien .debug_info section. */ 469550397Sobrien 469650397Sobrienstatic unsigned long 469750397Sobriensize_of_die (die) 469850397Sobrien register dw_die_ref die; 469950397Sobrien{ 470050397Sobrien register unsigned long size = 0; 470150397Sobrien register dw_attr_ref a; 470250397Sobrien 470350397Sobrien size += size_of_uleb128 (die->die_abbrev); 470450397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 470550397Sobrien { 470650397Sobrien switch (a->dw_attr_val.val_class) 470750397Sobrien { 470850397Sobrien case dw_val_class_addr: 470950397Sobrien size += PTR_SIZE; 471050397Sobrien break; 471150397Sobrien case dw_val_class_loc: 471250397Sobrien { 471350397Sobrien register unsigned long lsize 471450397Sobrien = size_of_locs (a->dw_attr_val.v.val_loc); 471550397Sobrien 471650397Sobrien /* Block length. */ 471750397Sobrien size += constant_size (lsize); 471850397Sobrien size += lsize; 471950397Sobrien } 472050397Sobrien break; 472150397Sobrien case dw_val_class_const: 472250397Sobrien size += 4; 472350397Sobrien break; 472450397Sobrien case dw_val_class_unsigned_const: 472550397Sobrien size += constant_size (a->dw_attr_val.v.val_unsigned); 472650397Sobrien break; 472750397Sobrien case dw_val_class_long_long: 472850397Sobrien size += 1 + 8; /* block */ 472950397Sobrien break; 473050397Sobrien case dw_val_class_float: 473150397Sobrien size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ 473250397Sobrien break; 473350397Sobrien case dw_val_class_flag: 473450397Sobrien size += 1; 473550397Sobrien break; 473650397Sobrien case dw_val_class_die_ref: 473750397Sobrien size += DWARF_OFFSET_SIZE; 473850397Sobrien break; 473950397Sobrien case dw_val_class_fde_ref: 474050397Sobrien size += DWARF_OFFSET_SIZE; 474150397Sobrien break; 474250397Sobrien case dw_val_class_lbl_id: 474350397Sobrien size += PTR_SIZE; 474450397Sobrien break; 474552284Sobrien case dw_val_class_lbl_offset: 474650397Sobrien size += DWARF_OFFSET_SIZE; 474750397Sobrien break; 474850397Sobrien case dw_val_class_str: 474950397Sobrien size += size_of_string (a->dw_attr_val.v.val_str); 475050397Sobrien break; 475150397Sobrien default: 475250397Sobrien abort (); 475350397Sobrien } 475450397Sobrien } 475550397Sobrien 475650397Sobrien return size; 475750397Sobrien} 475850397Sobrien 475950397Sobrien/* Size the debugging information associated with a given DIE. 476050397Sobrien Visits the DIE's children recursively. Updates the global 476150397Sobrien variable next_die_offset, on each time through. Uses the 476250397Sobrien current value of next_die_offset to update the die_offset 476350397Sobrien field in each DIE. */ 476450397Sobrien 476550397Sobrienstatic void 476650397Sobriencalc_die_sizes (die) 476750397Sobrien dw_die_ref die; 476850397Sobrien{ 476950397Sobrien register dw_die_ref c; 477050397Sobrien die->die_offset = next_die_offset; 477150397Sobrien next_die_offset += size_of_die (die); 477250397Sobrien 477350397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 477450397Sobrien calc_die_sizes (c); 477550397Sobrien 477650397Sobrien if (die->die_child != NULL) 477750397Sobrien /* Count the null byte used to terminate sibling lists. */ 477850397Sobrien next_die_offset += 1; 477950397Sobrien} 478050397Sobrien 478150397Sobrien/* Return the size of the line information prolog generated for the 478250397Sobrien compilation unit. */ 478350397Sobrien 478450397Sobrienstatic unsigned long 478550397Sobriensize_of_line_prolog () 478650397Sobrien{ 478750397Sobrien register unsigned long size; 478850397Sobrien register unsigned long ft_index; 478950397Sobrien 479050397Sobrien size = DWARF_LINE_PROLOG_HEADER_SIZE; 479150397Sobrien 479250397Sobrien /* Count the size of the table giving number of args for each 479350397Sobrien standard opcode. */ 479450397Sobrien size += DWARF_LINE_OPCODE_BASE - 1; 479550397Sobrien 479650397Sobrien /* Include directory table is empty (at present). Count only the 479750397Sobrien null byte used to terminate the table. */ 479850397Sobrien size += 1; 479950397Sobrien 480050397Sobrien for (ft_index = 1; ft_index < file_table_in_use; ++ft_index) 480150397Sobrien { 480250397Sobrien /* File name entry. */ 480350397Sobrien size += size_of_string (file_table[ft_index]); 480450397Sobrien 480550397Sobrien /* Include directory index. */ 480650397Sobrien size += size_of_uleb128 (0); 480750397Sobrien 480850397Sobrien /* Modification time. */ 480950397Sobrien size += size_of_uleb128 (0); 481050397Sobrien 481150397Sobrien /* File length in bytes. */ 481250397Sobrien size += size_of_uleb128 (0); 481350397Sobrien } 481450397Sobrien 481550397Sobrien /* Count the file table terminator. */ 481650397Sobrien size += 1; 481750397Sobrien return size; 481850397Sobrien} 481950397Sobrien 482050397Sobrien/* Return the size of the line information generated for this 482150397Sobrien compilation unit. */ 482250397Sobrien 482350397Sobrienstatic unsigned long 482450397Sobriensize_of_line_info () 482550397Sobrien{ 482650397Sobrien register unsigned long size; 482750397Sobrien register unsigned long lt_index; 482850397Sobrien register unsigned long current_line; 482950397Sobrien register long line_offset; 483050397Sobrien register long line_delta; 483150397Sobrien register unsigned long current_file; 483250397Sobrien register unsigned long function; 483350397Sobrien unsigned long size_of_set_address; 483450397Sobrien 483550397Sobrien /* Size of a DW_LNE_set_address instruction. */ 483650397Sobrien size_of_set_address = 1 + size_of_uleb128 (1 + PTR_SIZE) + 1 + PTR_SIZE; 483750397Sobrien 483850397Sobrien /* Version number. */ 483950397Sobrien size = 2; 484050397Sobrien 484150397Sobrien /* Prolog length specifier. */ 484250397Sobrien size += DWARF_OFFSET_SIZE; 484350397Sobrien 484450397Sobrien /* Prolog. */ 484550397Sobrien size += size_of_line_prolog (); 484650397Sobrien 484750397Sobrien current_file = 1; 484850397Sobrien current_line = 1; 484950397Sobrien for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) 485050397Sobrien { 485152284Sobrien register dw_line_info_ref line_info = &line_info_table[lt_index]; 485250397Sobrien 485352284Sobrien if (line_info->dw_line_num == current_line 485452284Sobrien && line_info->dw_file_num == current_file) 485552284Sobrien continue; 485652284Sobrien 485750397Sobrien /* Advance pc instruction. */ 485850397Sobrien /* ??? See the DW_LNS_advance_pc comment in output_line_info. */ 485950397Sobrien if (0) 486050397Sobrien size += 1 + 2; 486150397Sobrien else 486250397Sobrien size += size_of_set_address; 486350397Sobrien 486450397Sobrien if (line_info->dw_file_num != current_file) 486550397Sobrien { 486650397Sobrien /* Set file number instruction. */ 486750397Sobrien size += 1; 486850397Sobrien current_file = line_info->dw_file_num; 486950397Sobrien size += size_of_uleb128 (current_file); 487050397Sobrien } 487150397Sobrien 487250397Sobrien if (line_info->dw_line_num != current_line) 487350397Sobrien { 487450397Sobrien line_offset = line_info->dw_line_num - current_line; 487550397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 487650397Sobrien current_line = line_info->dw_line_num; 487750397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 487850397Sobrien /* 1-byte special line number instruction. */ 487950397Sobrien size += 1; 488050397Sobrien else 488150397Sobrien { 488250397Sobrien /* Advance line instruction. */ 488350397Sobrien size += 1; 488450397Sobrien size += size_of_sleb128 (line_offset); 488550397Sobrien /* Generate line entry instruction. */ 488650397Sobrien size += 1; 488750397Sobrien } 488850397Sobrien } 488950397Sobrien } 489050397Sobrien 489150397Sobrien /* Advance pc instruction. */ 489250397Sobrien if (0) 489350397Sobrien size += 1 + 2; 489450397Sobrien else 489550397Sobrien size += size_of_set_address; 489650397Sobrien 489750397Sobrien /* End of line number info. marker. */ 489850397Sobrien size += 1 + size_of_uleb128 (1) + 1; 489950397Sobrien 490050397Sobrien function = 0; 490150397Sobrien current_file = 1; 490250397Sobrien current_line = 1; 490350397Sobrien for (lt_index = 0; lt_index < separate_line_info_table_in_use; ) 490450397Sobrien { 490550397Sobrien register dw_separate_line_info_ref line_info 490650397Sobrien = &separate_line_info_table[lt_index]; 490752284Sobrien 490852284Sobrien if (line_info->dw_line_num == current_line 490952284Sobrien && line_info->dw_file_num == current_file 491052284Sobrien && line_info->function == function) 491152284Sobrien goto cont; 491252284Sobrien 491350397Sobrien if (function != line_info->function) 491450397Sobrien { 491550397Sobrien function = line_info->function; 491650397Sobrien /* Set address register instruction. */ 491750397Sobrien size += size_of_set_address; 491850397Sobrien } 491950397Sobrien else 492050397Sobrien { 492150397Sobrien /* Advance pc instruction. */ 492250397Sobrien if (0) 492350397Sobrien size += 1 + 2; 492450397Sobrien else 492550397Sobrien size += size_of_set_address; 492650397Sobrien } 492750397Sobrien 492850397Sobrien if (line_info->dw_file_num != current_file) 492950397Sobrien { 493050397Sobrien /* Set file number instruction. */ 493150397Sobrien size += 1; 493250397Sobrien current_file = line_info->dw_file_num; 493350397Sobrien size += size_of_uleb128 (current_file); 493450397Sobrien } 493550397Sobrien 493650397Sobrien if (line_info->dw_line_num != current_line) 493750397Sobrien { 493850397Sobrien line_offset = line_info->dw_line_num - current_line; 493950397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 494050397Sobrien current_line = line_info->dw_line_num; 494150397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 494250397Sobrien /* 1-byte special line number instruction. */ 494350397Sobrien size += 1; 494450397Sobrien else 494550397Sobrien { 494650397Sobrien /* Advance line instruction. */ 494750397Sobrien size += 1; 494850397Sobrien size += size_of_sleb128 (line_offset); 494950397Sobrien 495050397Sobrien /* Generate line entry instruction. */ 495150397Sobrien size += 1; 495250397Sobrien } 495350397Sobrien } 495450397Sobrien 495552284Sobrien cont: 495650397Sobrien ++lt_index; 495750397Sobrien 495850397Sobrien /* If we're done with a function, end its sequence. */ 495950397Sobrien if (lt_index == separate_line_info_table_in_use 496050397Sobrien || separate_line_info_table[lt_index].function != function) 496150397Sobrien { 496250397Sobrien current_file = 1; 496350397Sobrien current_line = 1; 496450397Sobrien 496550397Sobrien /* Advance pc instruction. */ 496650397Sobrien if (0) 496750397Sobrien size += 1 + 2; 496850397Sobrien else 496950397Sobrien size += size_of_set_address; 497050397Sobrien 497150397Sobrien /* End of line number info. marker. */ 497250397Sobrien size += 1 + size_of_uleb128 (1) + 1; 497350397Sobrien } 497450397Sobrien } 497550397Sobrien 497650397Sobrien return size; 497750397Sobrien} 497850397Sobrien 497950397Sobrien/* Return the size of the .debug_pubnames table generated for the 498050397Sobrien compilation unit. */ 498150397Sobrien 498250397Sobrienstatic unsigned long 498350397Sobriensize_of_pubnames () 498450397Sobrien{ 498550397Sobrien register unsigned long size; 498650397Sobrien register unsigned i; 498750397Sobrien 498850397Sobrien size = DWARF_PUBNAMES_HEADER_SIZE; 498950397Sobrien for (i = 0; i < pubname_table_in_use; ++i) 499050397Sobrien { 499150397Sobrien register pubname_ref p = &pubname_table[i]; 499250397Sobrien size += DWARF_OFFSET_SIZE + size_of_string (p->name); 499350397Sobrien } 499450397Sobrien 499550397Sobrien size += DWARF_OFFSET_SIZE; 499650397Sobrien return size; 499750397Sobrien} 499850397Sobrien 499950397Sobrien/* Return the size of the information in the .debug_aranges section. */ 500050397Sobrien 500150397Sobrienstatic unsigned long 500250397Sobriensize_of_aranges () 500350397Sobrien{ 500450397Sobrien register unsigned long size; 500550397Sobrien 500650397Sobrien size = DWARF_ARANGES_HEADER_SIZE; 500750397Sobrien 500850397Sobrien /* Count the address/length pair for this compilation unit. */ 500950397Sobrien size += 2 * PTR_SIZE; 501050397Sobrien size += 2 * PTR_SIZE * arange_table_in_use; 501150397Sobrien 501250397Sobrien /* Count the two zero words used to terminated the address range table. */ 501350397Sobrien size += 2 * PTR_SIZE; 501450397Sobrien return size; 501550397Sobrien} 501650397Sobrien 501750397Sobrien/* Select the encoding of an attribute value. */ 501850397Sobrien 501950397Sobrienstatic enum dwarf_form 502050397Sobrienvalue_format (v) 502150397Sobrien dw_val_ref v; 502250397Sobrien{ 502350397Sobrien switch (v->val_class) 502450397Sobrien { 502550397Sobrien case dw_val_class_addr: 502650397Sobrien return DW_FORM_addr; 502750397Sobrien case dw_val_class_loc: 502850397Sobrien switch (constant_size (size_of_locs (v->v.val_loc))) 502950397Sobrien { 503050397Sobrien case 1: 503150397Sobrien return DW_FORM_block1; 503250397Sobrien case 2: 503350397Sobrien return DW_FORM_block2; 503450397Sobrien default: 503550397Sobrien abort (); 503650397Sobrien } 503750397Sobrien case dw_val_class_const: 503850397Sobrien return DW_FORM_data4; 503950397Sobrien case dw_val_class_unsigned_const: 504050397Sobrien switch (constant_size (v->v.val_unsigned)) 504150397Sobrien { 504250397Sobrien case 1: 504350397Sobrien return DW_FORM_data1; 504450397Sobrien case 2: 504550397Sobrien return DW_FORM_data2; 504650397Sobrien case 4: 504750397Sobrien return DW_FORM_data4; 504850397Sobrien case 8: 504950397Sobrien return DW_FORM_data8; 505050397Sobrien default: 505150397Sobrien abort (); 505250397Sobrien } 505350397Sobrien case dw_val_class_long_long: 505450397Sobrien return DW_FORM_block1; 505550397Sobrien case dw_val_class_float: 505650397Sobrien return DW_FORM_block1; 505750397Sobrien case dw_val_class_flag: 505850397Sobrien return DW_FORM_flag; 505950397Sobrien case dw_val_class_die_ref: 506050397Sobrien return DW_FORM_ref; 506150397Sobrien case dw_val_class_fde_ref: 506250397Sobrien return DW_FORM_data; 506350397Sobrien case dw_val_class_lbl_id: 506450397Sobrien return DW_FORM_addr; 506552284Sobrien case dw_val_class_lbl_offset: 506650397Sobrien return DW_FORM_data; 506750397Sobrien case dw_val_class_str: 506850397Sobrien return DW_FORM_string; 506950397Sobrien default: 507050397Sobrien abort (); 507150397Sobrien } 507250397Sobrien} 507350397Sobrien 507450397Sobrien/* Output the encoding of an attribute value. */ 507550397Sobrien 507650397Sobrienstatic void 507750397Sobrienoutput_value_format (v) 507850397Sobrien dw_val_ref v; 507950397Sobrien{ 508050397Sobrien enum dwarf_form form = value_format (v); 508150397Sobrien 508250397Sobrien output_uleb128 (form); 508350397Sobrien if (flag_debug_asm) 508450397Sobrien fprintf (asm_out_file, " (%s)", dwarf_form_name (form)); 508550397Sobrien 508650397Sobrien fputc ('\n', asm_out_file); 508750397Sobrien} 508850397Sobrien 508950397Sobrien/* Output the .debug_abbrev section which defines the DIE abbreviation 509050397Sobrien table. */ 509150397Sobrien 509250397Sobrienstatic void 509350397Sobrienoutput_abbrev_section () 509450397Sobrien{ 509550397Sobrien unsigned long abbrev_id; 509650397Sobrien 509750397Sobrien dw_attr_ref a_attr; 509850397Sobrien for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id) 509950397Sobrien { 510050397Sobrien register dw_die_ref abbrev = abbrev_die_table[abbrev_id]; 510150397Sobrien 510250397Sobrien output_uleb128 (abbrev_id); 510350397Sobrien if (flag_debug_asm) 510450397Sobrien fprintf (asm_out_file, " (abbrev code)"); 510550397Sobrien 510650397Sobrien fputc ('\n', asm_out_file); 510750397Sobrien output_uleb128 (abbrev->die_tag); 510850397Sobrien if (flag_debug_asm) 510950397Sobrien fprintf (asm_out_file, " (TAG: %s)", 511050397Sobrien dwarf_tag_name (abbrev->die_tag)); 511150397Sobrien 511250397Sobrien fputc ('\n', asm_out_file); 511350397Sobrien fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, 511450397Sobrien abbrev->die_child != NULL ? DW_children_yes : DW_children_no); 511550397Sobrien 511650397Sobrien if (flag_debug_asm) 511750397Sobrien fprintf (asm_out_file, "\t%s %s", 511850397Sobrien ASM_COMMENT_START, 511950397Sobrien (abbrev->die_child != NULL 512050397Sobrien ? "DW_children_yes" : "DW_children_no")); 512150397Sobrien 512250397Sobrien fputc ('\n', asm_out_file); 512350397Sobrien 512450397Sobrien for (a_attr = abbrev->die_attr; a_attr != NULL; 512550397Sobrien a_attr = a_attr->dw_attr_next) 512650397Sobrien { 512750397Sobrien output_uleb128 (a_attr->dw_attr); 512850397Sobrien if (flag_debug_asm) 512950397Sobrien fprintf (asm_out_file, " (%s)", 513050397Sobrien dwarf_attr_name (a_attr->dw_attr)); 513150397Sobrien 513250397Sobrien fputc ('\n', asm_out_file); 513350397Sobrien output_value_format (&a_attr->dw_attr_val); 513450397Sobrien } 513550397Sobrien 513650397Sobrien fprintf (asm_out_file, "\t%s\t0,0\n", ASM_BYTE_OP); 513750397Sobrien } 513852284Sobrien 513952284Sobrien /* We need to properly terminate the abbrev table for this 514052284Sobrien compilation unit, as per the standard, and not rely on 514152284Sobrien workarounds in e.g. gdb. */ 514252284Sobrien fprintf (asm_out_file, "\t%s\t0\n", ASM_BYTE_OP); 514350397Sobrien} 514450397Sobrien 514550397Sobrien/* Output location description stack opcode's operands (if any). */ 514650397Sobrien 514750397Sobrienstatic void 514850397Sobrienoutput_loc_operands (loc) 514950397Sobrien register dw_loc_descr_ref loc; 515050397Sobrien{ 515150397Sobrien register dw_val_ref val1 = &loc->dw_loc_oprnd1; 515250397Sobrien register dw_val_ref val2 = &loc->dw_loc_oprnd2; 515350397Sobrien 515450397Sobrien switch (loc->dw_loc_opc) 515550397Sobrien { 515650397Sobrien case DW_OP_addr: 515750397Sobrien ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, val1->v.val_addr); 515850397Sobrien fputc ('\n', asm_out_file); 515950397Sobrien break; 516050397Sobrien case DW_OP_const1u: 516150397Sobrien case DW_OP_const1s: 516250397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag); 516350397Sobrien fputc ('\n', asm_out_file); 516450397Sobrien break; 516550397Sobrien case DW_OP_const2u: 516650397Sobrien case DW_OP_const2s: 516750397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int); 516850397Sobrien fputc ('\n', asm_out_file); 516950397Sobrien break; 517050397Sobrien case DW_OP_const4u: 517150397Sobrien case DW_OP_const4s: 517250397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, val1->v.val_int); 517350397Sobrien fputc ('\n', asm_out_file); 517450397Sobrien break; 517550397Sobrien case DW_OP_const8u: 517650397Sobrien case DW_OP_const8s: 517750397Sobrien abort (); 517850397Sobrien fputc ('\n', asm_out_file); 517950397Sobrien break; 518050397Sobrien case DW_OP_constu: 518150397Sobrien output_uleb128 (val1->v.val_unsigned); 518250397Sobrien fputc ('\n', asm_out_file); 518350397Sobrien break; 518450397Sobrien case DW_OP_consts: 518550397Sobrien output_sleb128 (val1->v.val_int); 518650397Sobrien fputc ('\n', asm_out_file); 518750397Sobrien break; 518850397Sobrien case DW_OP_pick: 518950397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_int); 519050397Sobrien fputc ('\n', asm_out_file); 519150397Sobrien break; 519250397Sobrien case DW_OP_plus_uconst: 519350397Sobrien output_uleb128 (val1->v.val_unsigned); 519450397Sobrien fputc ('\n', asm_out_file); 519550397Sobrien break; 519650397Sobrien case DW_OP_skip: 519750397Sobrien case DW_OP_bra: 519850397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, val1->v.val_int); 519950397Sobrien fputc ('\n', asm_out_file); 520050397Sobrien break; 520150397Sobrien case DW_OP_breg0: 520250397Sobrien case DW_OP_breg1: 520350397Sobrien case DW_OP_breg2: 520450397Sobrien case DW_OP_breg3: 520550397Sobrien case DW_OP_breg4: 520650397Sobrien case DW_OP_breg5: 520750397Sobrien case DW_OP_breg6: 520850397Sobrien case DW_OP_breg7: 520950397Sobrien case DW_OP_breg8: 521050397Sobrien case DW_OP_breg9: 521150397Sobrien case DW_OP_breg10: 521250397Sobrien case DW_OP_breg11: 521350397Sobrien case DW_OP_breg12: 521450397Sobrien case DW_OP_breg13: 521550397Sobrien case DW_OP_breg14: 521650397Sobrien case DW_OP_breg15: 521750397Sobrien case DW_OP_breg16: 521850397Sobrien case DW_OP_breg17: 521950397Sobrien case DW_OP_breg18: 522050397Sobrien case DW_OP_breg19: 522150397Sobrien case DW_OP_breg20: 522250397Sobrien case DW_OP_breg21: 522350397Sobrien case DW_OP_breg22: 522450397Sobrien case DW_OP_breg23: 522550397Sobrien case DW_OP_breg24: 522650397Sobrien case DW_OP_breg25: 522750397Sobrien case DW_OP_breg26: 522850397Sobrien case DW_OP_breg27: 522950397Sobrien case DW_OP_breg28: 523050397Sobrien case DW_OP_breg29: 523150397Sobrien case DW_OP_breg30: 523250397Sobrien case DW_OP_breg31: 523350397Sobrien output_sleb128 (val1->v.val_int); 523450397Sobrien fputc ('\n', asm_out_file); 523550397Sobrien break; 523650397Sobrien case DW_OP_regx: 523750397Sobrien output_uleb128 (val1->v.val_unsigned); 523850397Sobrien fputc ('\n', asm_out_file); 523950397Sobrien break; 524050397Sobrien case DW_OP_fbreg: 524150397Sobrien output_sleb128 (val1->v.val_int); 524250397Sobrien fputc ('\n', asm_out_file); 524350397Sobrien break; 524450397Sobrien case DW_OP_bregx: 524550397Sobrien output_uleb128 (val1->v.val_unsigned); 524650397Sobrien fputc ('\n', asm_out_file); 524750397Sobrien output_sleb128 (val2->v.val_int); 524850397Sobrien fputc ('\n', asm_out_file); 524950397Sobrien break; 525050397Sobrien case DW_OP_piece: 525150397Sobrien output_uleb128 (val1->v.val_unsigned); 525250397Sobrien fputc ('\n', asm_out_file); 525350397Sobrien break; 525450397Sobrien case DW_OP_deref_size: 525550397Sobrien case DW_OP_xderef_size: 525650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, val1->v.val_flag); 525750397Sobrien fputc ('\n', asm_out_file); 525850397Sobrien break; 525950397Sobrien default: 526050397Sobrien break; 526150397Sobrien } 526250397Sobrien} 526350397Sobrien 526450397Sobrien/* Compute the offset of a sibling. */ 526550397Sobrien 526650397Sobrienstatic unsigned long 526750397Sobriensibling_offset (die) 526850397Sobrien dw_die_ref die; 526950397Sobrien{ 527050397Sobrien unsigned long offset; 527150397Sobrien 527250397Sobrien if (die->die_child_last == NULL) 527350397Sobrien offset = die->die_offset + size_of_die (die); 527450397Sobrien else 527550397Sobrien offset = sibling_offset (die->die_child_last) + 1; 527650397Sobrien 527750397Sobrien return offset; 527850397Sobrien} 527950397Sobrien 528050397Sobrien/* Output the DIE and its attributes. Called recursively to generate 528150397Sobrien the definitions of each child DIE. */ 528250397Sobrien 528350397Sobrienstatic void 528450397Sobrienoutput_die (die) 528550397Sobrien register dw_die_ref die; 528650397Sobrien{ 528750397Sobrien register dw_attr_ref a; 528850397Sobrien register dw_die_ref c; 528950397Sobrien register unsigned long ref_offset; 529050397Sobrien register unsigned long size; 529150397Sobrien register dw_loc_descr_ref loc; 529250397Sobrien 529350397Sobrien output_uleb128 (die->die_abbrev); 529450397Sobrien if (flag_debug_asm) 529550397Sobrien fprintf (asm_out_file, " (DIE (0x%lx) %s)", 529650397Sobrien die->die_offset, dwarf_tag_name (die->die_tag)); 529750397Sobrien 529850397Sobrien fputc ('\n', asm_out_file); 529950397Sobrien 530050397Sobrien for (a = die->die_attr; a != NULL; a = a->dw_attr_next) 530150397Sobrien { 530250397Sobrien switch (a->dw_attr_val.val_class) 530350397Sobrien { 530450397Sobrien case dw_val_class_addr: 530550397Sobrien ASM_OUTPUT_DWARF_ADDR_CONST (asm_out_file, 530650397Sobrien a->dw_attr_val.v.val_addr); 530750397Sobrien break; 530850397Sobrien 530950397Sobrien case dw_val_class_loc: 531050397Sobrien size = size_of_locs (a->dw_attr_val.v.val_loc); 531150397Sobrien 531250397Sobrien /* Output the block length for this list of location operations. */ 531350397Sobrien switch (constant_size (size)) 531450397Sobrien { 531550397Sobrien case 1: 531650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, size); 531750397Sobrien break; 531850397Sobrien case 2: 531950397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, size); 532050397Sobrien break; 532150397Sobrien default: 532250397Sobrien abort (); 532350397Sobrien } 532450397Sobrien 532550397Sobrien if (flag_debug_asm) 532650397Sobrien fprintf (asm_out_file, "\t%s %s", 532750397Sobrien ASM_COMMENT_START, dwarf_attr_name (a->dw_attr)); 532850397Sobrien 532950397Sobrien fputc ('\n', asm_out_file); 533050397Sobrien for (loc = a->dw_attr_val.v.val_loc; loc != NULL; 533150397Sobrien loc = loc->dw_loc_next) 533250397Sobrien { 533350397Sobrien /* Output the opcode. */ 533450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, loc->dw_loc_opc); 533550397Sobrien if (flag_debug_asm) 533650397Sobrien fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, 533750397Sobrien dwarf_stack_op_name (loc->dw_loc_opc)); 533850397Sobrien 533950397Sobrien fputc ('\n', asm_out_file); 534050397Sobrien 534150397Sobrien /* Output the operand(s) (if any). */ 534250397Sobrien output_loc_operands (loc); 534350397Sobrien } 534450397Sobrien break; 534550397Sobrien 534650397Sobrien case dw_val_class_const: 534750397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, a->dw_attr_val.v.val_int); 534850397Sobrien break; 534950397Sobrien 535050397Sobrien case dw_val_class_unsigned_const: 535150397Sobrien switch (constant_size (a->dw_attr_val.v.val_unsigned)) 535250397Sobrien { 535350397Sobrien case 1: 535450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 535550397Sobrien a->dw_attr_val.v.val_unsigned); 535650397Sobrien break; 535750397Sobrien case 2: 535850397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, 535950397Sobrien a->dw_attr_val.v.val_unsigned); 536050397Sobrien break; 536150397Sobrien case 4: 536250397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 536350397Sobrien a->dw_attr_val.v.val_unsigned); 536450397Sobrien break; 536550397Sobrien case 8: 536650397Sobrien ASM_OUTPUT_DWARF_DATA8 (asm_out_file, 536750397Sobrien a->dw_attr_val.v.val_long_long.hi, 536850397Sobrien a->dw_attr_val.v.val_long_long.low); 536950397Sobrien break; 537050397Sobrien default: 537150397Sobrien abort (); 537250397Sobrien } 537350397Sobrien break; 537450397Sobrien 537550397Sobrien case dw_val_class_long_long: 537650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 8); 537750397Sobrien if (flag_debug_asm) 537850397Sobrien fprintf (asm_out_file, "\t%s %s", 537950397Sobrien ASM_COMMENT_START, dwarf_attr_name (a->dw_attr)); 538050397Sobrien 538150397Sobrien fputc ('\n', asm_out_file); 538250397Sobrien ASM_OUTPUT_DWARF_DATA8 (asm_out_file, 538350397Sobrien a->dw_attr_val.v.val_long_long.hi, 538450397Sobrien a->dw_attr_val.v.val_long_long.low); 538550397Sobrien 538650397Sobrien if (flag_debug_asm) 538750397Sobrien fprintf (asm_out_file, 538850397Sobrien "\t%s long long constant", ASM_COMMENT_START); 538950397Sobrien 539050397Sobrien fputc ('\n', asm_out_file); 539150397Sobrien break; 539250397Sobrien 539350397Sobrien case dw_val_class_float: 539452284Sobrien { 539552284Sobrien register unsigned int i; 539652284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 539752284Sobrien a->dw_attr_val.v.val_float.length * 4); 539852284Sobrien if (flag_debug_asm) 539952284Sobrien fprintf (asm_out_file, "\t%s %s", 540052284Sobrien ASM_COMMENT_START, dwarf_attr_name (a->dw_attr)); 540150397Sobrien 540252284Sobrien fputc ('\n', asm_out_file); 540352284Sobrien for (i = 0; i < a->dw_attr_val.v.val_float.length; ++i) 540452284Sobrien { 540552284Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 540652284Sobrien a->dw_attr_val.v.val_float.array[i]); 540752284Sobrien if (flag_debug_asm) 540852284Sobrien fprintf (asm_out_file, "\t%s fp constant word %u", 540952284Sobrien ASM_COMMENT_START, i); 541050397Sobrien 541152284Sobrien fputc ('\n', asm_out_file); 541252284Sobrien } 541350397Sobrien break; 541452284Sobrien } 541550397Sobrien 541650397Sobrien case dw_val_class_flag: 541750397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, a->dw_attr_val.v.val_flag); 541850397Sobrien break; 541950397Sobrien 542050397Sobrien case dw_val_class_die_ref: 542150397Sobrien if (a->dw_attr_val.v.val_die_ref != NULL) 542250397Sobrien ref_offset = a->dw_attr_val.v.val_die_ref->die_offset; 542350397Sobrien else if (a->dw_attr == DW_AT_sibling) 542450397Sobrien ref_offset = sibling_offset(die); 542550397Sobrien else 542650397Sobrien abort (); 542750397Sobrien 542850397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, ref_offset); 542950397Sobrien break; 543050397Sobrien 543150397Sobrien case dw_val_class_fde_ref: 543250397Sobrien { 543350397Sobrien char l1[20]; 543450397Sobrien ASM_GENERATE_INTERNAL_LABEL 543550397Sobrien (l1, FDE_AFTER_SIZE_LABEL, a->dw_attr_val.v.val_fde_index * 2); 543650397Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, l1); 543750397Sobrien fprintf (asm_out_file, " - %d", DWARF_OFFSET_SIZE); 543850397Sobrien } 543950397Sobrien break; 544050397Sobrien 544150397Sobrien case dw_val_class_lbl_id: 544250397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, a->dw_attr_val.v.val_lbl_id); 544350397Sobrien break; 544450397Sobrien 544552284Sobrien case dw_val_class_lbl_offset: 544652284Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, a->dw_attr_val.v.val_lbl_id); 544750397Sobrien break; 544850397Sobrien 544950397Sobrien case dw_val_class_str: 545050397Sobrien if (flag_debug_asm) 545150397Sobrien ASM_OUTPUT_DWARF_STRING (asm_out_file, a->dw_attr_val.v.val_str); 545250397Sobrien else 545350397Sobrien ASM_OUTPUT_ASCII (asm_out_file, 545450397Sobrien a->dw_attr_val.v.val_str, 545552284Sobrien (int) strlen (a->dw_attr_val.v.val_str) + 1); 545650397Sobrien break; 545750397Sobrien 545850397Sobrien default: 545950397Sobrien abort (); 546050397Sobrien } 546150397Sobrien 546250397Sobrien if (a->dw_attr_val.val_class != dw_val_class_loc 546350397Sobrien && a->dw_attr_val.val_class != dw_val_class_long_long 546450397Sobrien && a->dw_attr_val.val_class != dw_val_class_float) 546550397Sobrien { 546650397Sobrien if (flag_debug_asm) 546750397Sobrien fprintf (asm_out_file, "\t%s %s", 546850397Sobrien ASM_COMMENT_START, dwarf_attr_name (a->dw_attr)); 546950397Sobrien 547050397Sobrien fputc ('\n', asm_out_file); 547150397Sobrien } 547250397Sobrien } 547350397Sobrien 547450397Sobrien for (c = die->die_child; c != NULL; c = c->die_sib) 547550397Sobrien output_die (c); 547650397Sobrien 547750397Sobrien if (die->die_child != NULL) 547850397Sobrien { 547950397Sobrien /* Add null byte to terminate sibling list. */ 548050397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 548150397Sobrien if (flag_debug_asm) 548250397Sobrien fprintf (asm_out_file, "\t%s end of children of DIE 0x%lx", 548350397Sobrien ASM_COMMENT_START, die->die_offset); 548450397Sobrien 548550397Sobrien fputc ('\n', asm_out_file); 548650397Sobrien } 548750397Sobrien} 548850397Sobrien 548950397Sobrien/* Output the compilation unit that appears at the beginning of the 549050397Sobrien .debug_info section, and precedes the DIE descriptions. */ 549150397Sobrien 549250397Sobrienstatic void 549350397Sobrienoutput_compilation_unit_header () 549450397Sobrien{ 549550397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset - DWARF_OFFSET_SIZE); 549650397Sobrien if (flag_debug_asm) 549750397Sobrien fprintf (asm_out_file, "\t%s Length of Compilation Unit Info.", 549850397Sobrien ASM_COMMENT_START); 549950397Sobrien 550050397Sobrien fputc ('\n', asm_out_file); 550150397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION); 550250397Sobrien if (flag_debug_asm) 550350397Sobrien fprintf (asm_out_file, "\t%s DWARF version number", ASM_COMMENT_START); 550450397Sobrien 550550397Sobrien fputc ('\n', asm_out_file); 550652284Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, abbrev_section_label); 550750397Sobrien if (flag_debug_asm) 550850397Sobrien fprintf (asm_out_file, "\t%s Offset Into Abbrev. Section", 550950397Sobrien ASM_COMMENT_START); 551050397Sobrien 551150397Sobrien fputc ('\n', asm_out_file); 551250397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE); 551350397Sobrien if (flag_debug_asm) 551450397Sobrien fprintf (asm_out_file, "\t%s Pointer Size (in bytes)", ASM_COMMENT_START); 551550397Sobrien 551650397Sobrien fputc ('\n', asm_out_file); 551750397Sobrien} 551850397Sobrien 551950397Sobrien/* The DWARF2 pubname for a nested thingy looks like "A::f". The output 552050397Sobrien of decl_printable_name for C++ looks like "A::f(int)". Let's drop the 552150397Sobrien argument list, and maybe the scope. */ 552250397Sobrien 552350397Sobrienstatic char * 552450397Sobriendwarf2_name (decl, scope) 552550397Sobrien tree decl; 552650397Sobrien int scope; 552750397Sobrien{ 552850397Sobrien return (*decl_printable_name) (decl, scope ? 1 : 0); 552950397Sobrien} 553050397Sobrien 553150397Sobrien/* Add a new entry to .debug_pubnames if appropriate. */ 553250397Sobrien 553350397Sobrienstatic void 553450397Sobrienadd_pubname (decl, die) 553550397Sobrien tree decl; 553650397Sobrien dw_die_ref die; 553750397Sobrien{ 553850397Sobrien pubname_ref p; 553950397Sobrien 554050397Sobrien if (! TREE_PUBLIC (decl)) 554150397Sobrien return; 554250397Sobrien 554350397Sobrien if (pubname_table_in_use == pubname_table_allocated) 554450397Sobrien { 554550397Sobrien pubname_table_allocated += PUBNAME_TABLE_INCREMENT; 554650397Sobrien pubname_table = (pubname_ref) xrealloc 554750397Sobrien (pubname_table, pubname_table_allocated * sizeof (pubname_entry)); 554850397Sobrien } 554950397Sobrien 555050397Sobrien p = &pubname_table[pubname_table_in_use++]; 555150397Sobrien p->die = die; 555250397Sobrien 555350397Sobrien p->name = xstrdup (dwarf2_name (decl, 1)); 555450397Sobrien} 555550397Sobrien 555650397Sobrien/* Output the public names table used to speed up access to externally 555750397Sobrien visible names. For now, only generate entries for externally 555850397Sobrien visible procedures. */ 555950397Sobrien 556050397Sobrienstatic void 556150397Sobrienoutput_pubnames () 556250397Sobrien{ 556350397Sobrien register unsigned i; 556450397Sobrien register unsigned long pubnames_length = size_of_pubnames (); 556550397Sobrien 556650397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, pubnames_length); 556750397Sobrien 556850397Sobrien if (flag_debug_asm) 556950397Sobrien fprintf (asm_out_file, "\t%s Length of Public Names Info.", 557050397Sobrien ASM_COMMENT_START); 557150397Sobrien 557250397Sobrien fputc ('\n', asm_out_file); 557350397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION); 557450397Sobrien 557550397Sobrien if (flag_debug_asm) 557650397Sobrien fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START); 557750397Sobrien 557850397Sobrien fputc ('\n', asm_out_file); 557952284Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label); 558050397Sobrien if (flag_debug_asm) 558150397Sobrien fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.", 558250397Sobrien ASM_COMMENT_START); 558350397Sobrien 558450397Sobrien fputc ('\n', asm_out_file); 558550397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, next_die_offset); 558650397Sobrien if (flag_debug_asm) 558750397Sobrien fprintf (asm_out_file, "\t%s Compilation Unit Length", ASM_COMMENT_START); 558850397Sobrien 558950397Sobrien fputc ('\n', asm_out_file); 559050397Sobrien for (i = 0; i < pubname_table_in_use; ++i) 559150397Sobrien { 559250397Sobrien register pubname_ref pub = &pubname_table[i]; 559350397Sobrien 559450397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, pub->die->die_offset); 559550397Sobrien if (flag_debug_asm) 559650397Sobrien fprintf (asm_out_file, "\t%s DIE offset", ASM_COMMENT_START); 559750397Sobrien 559850397Sobrien fputc ('\n', asm_out_file); 559950397Sobrien 560050397Sobrien if (flag_debug_asm) 560150397Sobrien { 560250397Sobrien ASM_OUTPUT_DWARF_STRING (asm_out_file, pub->name); 560350397Sobrien fprintf (asm_out_file, "%s external name", ASM_COMMENT_START); 560450397Sobrien } 560550397Sobrien else 560650397Sobrien { 560752284Sobrien ASM_OUTPUT_ASCII (asm_out_file, pub->name, 560852284Sobrien (int) strlen (pub->name) + 1); 560950397Sobrien } 561050397Sobrien 561150397Sobrien fputc ('\n', asm_out_file); 561250397Sobrien } 561350397Sobrien 561450397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, 0); 561550397Sobrien fputc ('\n', asm_out_file); 561650397Sobrien} 561750397Sobrien 561850397Sobrien/* Add a new entry to .debug_aranges if appropriate. */ 561950397Sobrien 562050397Sobrienstatic void 562150397Sobrienadd_arange (decl, die) 562250397Sobrien tree decl; 562350397Sobrien dw_die_ref die; 562450397Sobrien{ 562550397Sobrien if (! DECL_SECTION_NAME (decl)) 562650397Sobrien return; 562750397Sobrien 562850397Sobrien if (arange_table_in_use == arange_table_allocated) 562950397Sobrien { 563050397Sobrien arange_table_allocated += ARANGE_TABLE_INCREMENT; 563150397Sobrien arange_table 563250397Sobrien = (arange_ref) xrealloc (arange_table, 563350397Sobrien arange_table_allocated * sizeof (dw_die_ref)); 563450397Sobrien } 563550397Sobrien 563650397Sobrien arange_table[arange_table_in_use++] = die; 563750397Sobrien} 563850397Sobrien 563950397Sobrien/* Output the information that goes into the .debug_aranges table. 564050397Sobrien Namely, define the beginning and ending address range of the 564150397Sobrien text section generated for this compilation unit. */ 564250397Sobrien 564350397Sobrienstatic void 564450397Sobrienoutput_aranges () 564550397Sobrien{ 564650397Sobrien register unsigned i; 564750397Sobrien register unsigned long aranges_length = size_of_aranges (); 564850397Sobrien 564950397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, aranges_length); 565050397Sobrien if (flag_debug_asm) 565150397Sobrien fprintf (asm_out_file, "\t%s Length of Address Ranges Info.", 565250397Sobrien ASM_COMMENT_START); 565350397Sobrien 565450397Sobrien fputc ('\n', asm_out_file); 565550397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION); 565650397Sobrien if (flag_debug_asm) 565750397Sobrien fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START); 565850397Sobrien 565950397Sobrien fputc ('\n', asm_out_file); 566052284Sobrien ASM_OUTPUT_DWARF_OFFSET (asm_out_file, debug_info_section_label); 566150397Sobrien if (flag_debug_asm) 566250397Sobrien fprintf (asm_out_file, "\t%s Offset of Compilation Unit Info.", 566350397Sobrien ASM_COMMENT_START); 566450397Sobrien 566550397Sobrien fputc ('\n', asm_out_file); 566650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, PTR_SIZE); 566750397Sobrien if (flag_debug_asm) 566850397Sobrien fprintf (asm_out_file, "\t%s Size of Address", ASM_COMMENT_START); 566950397Sobrien 567050397Sobrien fputc ('\n', asm_out_file); 567150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 567250397Sobrien if (flag_debug_asm) 567350397Sobrien fprintf (asm_out_file, "\t%s Size of Segment Descriptor", 567450397Sobrien ASM_COMMENT_START); 567550397Sobrien 567650397Sobrien fputc ('\n', asm_out_file); 567750397Sobrien ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 4); 567850397Sobrien if (PTR_SIZE == 8) 567950397Sobrien fprintf (asm_out_file, ",0,0"); 568050397Sobrien 568150397Sobrien if (flag_debug_asm) 568250397Sobrien fprintf (asm_out_file, "\t%s Pad to %d byte boundary", 568350397Sobrien ASM_COMMENT_START, 2 * PTR_SIZE); 568450397Sobrien 568550397Sobrien fputc ('\n', asm_out_file); 568652284Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_section_label); 568750397Sobrien if (flag_debug_asm) 568850397Sobrien fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START); 568950397Sobrien 569050397Sobrien fputc ('\n', asm_out_file); 569152284Sobrien ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, text_end_label, 569252284Sobrien text_section_label); 569350397Sobrien if (flag_debug_asm) 569450397Sobrien fprintf (asm_out_file, "%s Length", ASM_COMMENT_START); 569550397Sobrien 569650397Sobrien fputc ('\n', asm_out_file); 569750397Sobrien for (i = 0; i < arange_table_in_use; ++i) 569850397Sobrien { 569950397Sobrien dw_die_ref a = arange_table[i]; 570050397Sobrien 570150397Sobrien if (a->die_tag == DW_TAG_subprogram) 570250397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, get_AT_low_pc (a)); 570350397Sobrien else 570450397Sobrien { 570550397Sobrien char *name = get_AT_string (a, DW_AT_MIPS_linkage_name); 570650397Sobrien if (! name) 570750397Sobrien name = get_AT_string (a, DW_AT_name); 570850397Sobrien 570950397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, name); 571050397Sobrien } 571150397Sobrien 571250397Sobrien if (flag_debug_asm) 571350397Sobrien fprintf (asm_out_file, "\t%s Address", ASM_COMMENT_START); 571450397Sobrien 571550397Sobrien fputc ('\n', asm_out_file); 571650397Sobrien if (a->die_tag == DW_TAG_subprogram) 571750397Sobrien ASM_OUTPUT_DWARF_ADDR_DELTA (asm_out_file, get_AT_hi_pc (a), 571850397Sobrien get_AT_low_pc (a)); 571950397Sobrien else 572050397Sobrien ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 572150397Sobrien get_AT_unsigned (a, DW_AT_byte_size)); 572250397Sobrien 572350397Sobrien if (flag_debug_asm) 572450397Sobrien fprintf (asm_out_file, "%s Length", ASM_COMMENT_START); 572550397Sobrien 572650397Sobrien fputc ('\n', asm_out_file); 572750397Sobrien } 572850397Sobrien 572950397Sobrien /* Output the terminator words. */ 573050397Sobrien ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 0); 573150397Sobrien fputc ('\n', asm_out_file); 573250397Sobrien ASM_OUTPUT_DWARF_ADDR_DATA (asm_out_file, 0); 573350397Sobrien fputc ('\n', asm_out_file); 573450397Sobrien} 573550397Sobrien 573650397Sobrien/* Output the source line number correspondence information. This 573750397Sobrien information goes into the .debug_line section. 573850397Sobrien 573950397Sobrien If the format of this data changes, then the function size_of_line_info 574050397Sobrien must also be adjusted the same way. */ 574150397Sobrien 574250397Sobrienstatic void 574350397Sobrienoutput_line_info () 574450397Sobrien{ 574550397Sobrien char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 574650397Sobrien char prev_line_label[MAX_ARTIFICIAL_LABEL_BYTES]; 574750397Sobrien register unsigned opc; 574850397Sobrien register unsigned n_op_args; 574950397Sobrien register unsigned long ft_index; 575050397Sobrien register unsigned long lt_index; 575150397Sobrien register unsigned long current_line; 575250397Sobrien register long line_offset; 575350397Sobrien register long line_delta; 575450397Sobrien register unsigned long current_file; 575550397Sobrien register unsigned long function; 575650397Sobrien 575750397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, size_of_line_info ()); 575850397Sobrien if (flag_debug_asm) 575950397Sobrien fprintf (asm_out_file, "\t%s Length of Source Line Info.", 576050397Sobrien ASM_COMMENT_START); 576150397Sobrien 576250397Sobrien fputc ('\n', asm_out_file); 576350397Sobrien ASM_OUTPUT_DWARF_DATA2 (asm_out_file, DWARF_VERSION); 576450397Sobrien if (flag_debug_asm) 576550397Sobrien fprintf (asm_out_file, "\t%s DWARF Version", ASM_COMMENT_START); 576650397Sobrien 576750397Sobrien fputc ('\n', asm_out_file); 576850397Sobrien ASM_OUTPUT_DWARF_DATA (asm_out_file, size_of_line_prolog ()); 576950397Sobrien if (flag_debug_asm) 577050397Sobrien fprintf (asm_out_file, "\t%s Prolog Length", ASM_COMMENT_START); 577150397Sobrien 577250397Sobrien fputc ('\n', asm_out_file); 577350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_LINE_MIN_INSTR_LENGTH); 577450397Sobrien if (flag_debug_asm) 577550397Sobrien fprintf (asm_out_file, "\t%s Minimum Instruction Length", 577650397Sobrien ASM_COMMENT_START); 577750397Sobrien 577850397Sobrien fputc ('\n', asm_out_file); 577950397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DWARF_LINE_DEFAULT_IS_STMT_START); 578050397Sobrien if (flag_debug_asm) 578150397Sobrien fprintf (asm_out_file, "\t%s Default is_stmt_start flag", 578250397Sobrien ASM_COMMENT_START); 578350397Sobrien 578450397Sobrien fputc ('\n', asm_out_file); 578550397Sobrien fprintf (asm_out_file, "\t%s\t%d", ASM_BYTE_OP, DWARF_LINE_BASE); 578650397Sobrien if (flag_debug_asm) 578750397Sobrien fprintf (asm_out_file, "\t%s Line Base Value (Special Opcodes)", 578850397Sobrien ASM_COMMENT_START); 578950397Sobrien 579050397Sobrien fputc ('\n', asm_out_file); 579150397Sobrien fprintf (asm_out_file, "\t%s\t%u", ASM_BYTE_OP, DWARF_LINE_RANGE); 579250397Sobrien if (flag_debug_asm) 579350397Sobrien fprintf (asm_out_file, "\t%s Line Range Value (Special Opcodes)", 579450397Sobrien ASM_COMMENT_START); 579550397Sobrien 579650397Sobrien fputc ('\n', asm_out_file); 579750397Sobrien fprintf (asm_out_file, "\t%s\t%u", ASM_BYTE_OP, DWARF_LINE_OPCODE_BASE); 579850397Sobrien if (flag_debug_asm) 579950397Sobrien fprintf (asm_out_file, "\t%s Special Opcode Base", ASM_COMMENT_START); 580050397Sobrien 580150397Sobrien fputc ('\n', asm_out_file); 580250397Sobrien for (opc = 1; opc < DWARF_LINE_OPCODE_BASE; ++opc) 580350397Sobrien { 580450397Sobrien switch (opc) 580550397Sobrien { 580650397Sobrien case DW_LNS_advance_pc: 580750397Sobrien case DW_LNS_advance_line: 580850397Sobrien case DW_LNS_set_file: 580950397Sobrien case DW_LNS_set_column: 581050397Sobrien case DW_LNS_fixed_advance_pc: 581150397Sobrien n_op_args = 1; 581250397Sobrien break; 581350397Sobrien default: 581450397Sobrien n_op_args = 0; 581550397Sobrien break; 581650397Sobrien } 581750397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, n_op_args); 581850397Sobrien if (flag_debug_asm) 581950397Sobrien fprintf (asm_out_file, "\t%s opcode: 0x%x has %d args", 582050397Sobrien ASM_COMMENT_START, opc, n_op_args); 582150397Sobrien fputc ('\n', asm_out_file); 582250397Sobrien } 582350397Sobrien 582450397Sobrien if (flag_debug_asm) 582550397Sobrien fprintf (asm_out_file, "%s Include Directory Table\n", ASM_COMMENT_START); 582650397Sobrien 582750397Sobrien /* Include directory table is empty, at present */ 582850397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 582950397Sobrien fputc ('\n', asm_out_file); 583050397Sobrien if (flag_debug_asm) 583150397Sobrien fprintf (asm_out_file, "%s File Name Table\n", ASM_COMMENT_START); 583250397Sobrien 583350397Sobrien for (ft_index = 1; ft_index < file_table_in_use; ++ft_index) 583450397Sobrien { 583550397Sobrien if (flag_debug_asm) 583650397Sobrien { 583750397Sobrien ASM_OUTPUT_DWARF_STRING (asm_out_file, file_table[ft_index]); 583850397Sobrien fprintf (asm_out_file, "%s File Entry: 0x%lx", 583950397Sobrien ASM_COMMENT_START, ft_index); 584050397Sobrien } 584150397Sobrien else 584250397Sobrien { 584350397Sobrien ASM_OUTPUT_ASCII (asm_out_file, 584450397Sobrien file_table[ft_index], 584552284Sobrien (int) strlen (file_table[ft_index]) + 1); 584650397Sobrien } 584750397Sobrien 584850397Sobrien fputc ('\n', asm_out_file); 584950397Sobrien 585050397Sobrien /* Include directory index */ 585150397Sobrien output_uleb128 (0); 585250397Sobrien fputc ('\n', asm_out_file); 585350397Sobrien 585450397Sobrien /* Modification time */ 585550397Sobrien output_uleb128 (0); 585650397Sobrien fputc ('\n', asm_out_file); 585750397Sobrien 585850397Sobrien /* File length in bytes */ 585950397Sobrien output_uleb128 (0); 586050397Sobrien fputc ('\n', asm_out_file); 586150397Sobrien } 586250397Sobrien 586350397Sobrien /* Terminate the file name table */ 586450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 586550397Sobrien fputc ('\n', asm_out_file); 586650397Sobrien 586752284Sobrien /* We used to set the address register to the first location in the text 586852284Sobrien section here, but that didn't accomplish anything since we already 586952284Sobrien have a line note for the opening brace of the first function. */ 587050397Sobrien 587150397Sobrien /* Generate the line number to PC correspondence table, encoded as 587250397Sobrien a series of state machine operations. */ 587350397Sobrien current_file = 1; 587450397Sobrien current_line = 1; 587552284Sobrien strcpy (prev_line_label, text_section_label); 587650397Sobrien for (lt_index = 1; lt_index < line_info_table_in_use; ++lt_index) 587750397Sobrien { 587852284Sobrien register dw_line_info_ref line_info = &line_info_table[lt_index]; 587950397Sobrien 588052284Sobrien /* Don't emit anything for redundant notes. Just updating the 588152284Sobrien address doesn't accomplish anything, because we already assume 588252284Sobrien that anything after the last address is this line. */ 588352284Sobrien if (line_info->dw_line_num == current_line 588452284Sobrien && line_info->dw_file_num == current_file) 588552284Sobrien continue; 588652284Sobrien 588750397Sobrien /* Emit debug info for the address of the current line, choosing 588850397Sobrien the encoding that uses the least amount of space. */ 588950397Sobrien /* ??? Unfortunately, we have little choice here currently, and must 589050397Sobrien always use the most general form. Gcc does not know the address 589150397Sobrien delta itself, so we can't use DW_LNS_advance_pc. There are no known 589250397Sobrien dwarf2 aware assemblers at this time, so we can't use any special 589350397Sobrien pseudo ops that would allow the assembler to optimally encode this for 589450397Sobrien us. Many ports do have length attributes which will give an upper 589550397Sobrien bound on the address range. We could perhaps use length attributes 589650397Sobrien to determine when it is safe to use DW_LNS_fixed_advance_pc. */ 589750397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, LINE_CODE_LABEL, lt_index); 589850397Sobrien if (0) 589950397Sobrien { 590050397Sobrien /* This can handle deltas up to 0xffff. This takes 3 bytes. */ 590150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc); 590250397Sobrien if (flag_debug_asm) 590350397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc", 590450397Sobrien ASM_COMMENT_START); 590550397Sobrien 590650397Sobrien fputc ('\n', asm_out_file); 590750397Sobrien ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, line_label, prev_line_label); 590850397Sobrien fputc ('\n', asm_out_file); 590950397Sobrien } 591050397Sobrien else 591150397Sobrien { 591250397Sobrien /* This can handle any delta. This takes 4+PTR_SIZE bytes. */ 591350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 591450397Sobrien if (flag_debug_asm) 591550397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_set_address", 591650397Sobrien ASM_COMMENT_START); 591750397Sobrien fputc ('\n', asm_out_file); 591850397Sobrien output_uleb128 (1 + PTR_SIZE); 591950397Sobrien fputc ('\n', asm_out_file); 592050397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address); 592150397Sobrien fputc ('\n', asm_out_file); 592250397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, line_label); 592350397Sobrien fputc ('\n', asm_out_file); 592450397Sobrien } 592550397Sobrien strcpy (prev_line_label, line_label); 592650397Sobrien 592750397Sobrien /* Emit debug info for the source file of the current line, if 592850397Sobrien different from the previous line. */ 592950397Sobrien if (line_info->dw_file_num != current_file) 593050397Sobrien { 593150397Sobrien current_file = line_info->dw_file_num; 593250397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_set_file); 593350397Sobrien if (flag_debug_asm) 593450397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_set_file", ASM_COMMENT_START); 593550397Sobrien 593650397Sobrien fputc ('\n', asm_out_file); 593750397Sobrien output_uleb128 (current_file); 593850397Sobrien if (flag_debug_asm) 593950397Sobrien fprintf (asm_out_file, " (\"%s\")", file_table[current_file]); 594050397Sobrien 594150397Sobrien fputc ('\n', asm_out_file); 594250397Sobrien } 594350397Sobrien 594450397Sobrien /* Emit debug info for the current line number, choosing the encoding 594550397Sobrien that uses the least amount of space. */ 594652284Sobrien if (line_info->dw_line_num != current_line) 594750397Sobrien { 594852284Sobrien line_offset = line_info->dw_line_num - current_line; 594952284Sobrien line_delta = line_offset - DWARF_LINE_BASE; 595052284Sobrien current_line = line_info->dw_line_num; 595152284Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 595252284Sobrien { 595352284Sobrien /* This can handle deltas from -10 to 234, using the current 595452284Sobrien definitions of DWARF_LINE_BASE and DWARF_LINE_RANGE. This 595552284Sobrien takes 1 byte. */ 595652284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 595752284Sobrien DWARF_LINE_OPCODE_BASE + line_delta); 595852284Sobrien if (flag_debug_asm) 595952284Sobrien fprintf (asm_out_file, 596052284Sobrien "\t%s line %ld", ASM_COMMENT_START, current_line); 596150397Sobrien 596252284Sobrien fputc ('\n', asm_out_file); 596352284Sobrien } 596452284Sobrien else 596552284Sobrien { 596652284Sobrien /* This can handle any delta. This takes at least 4 bytes, 596752284Sobrien depending on the value being encoded. */ 596852284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line); 596952284Sobrien if (flag_debug_asm) 597052284Sobrien fprintf (asm_out_file, "\t%s advance to line %ld", 597152284Sobrien ASM_COMMENT_START, current_line); 597252284Sobrien 597352284Sobrien fputc ('\n', asm_out_file); 597452284Sobrien output_sleb128 (line_offset); 597552284Sobrien fputc ('\n', asm_out_file); 597652284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy); 597752284Sobrien if (flag_debug_asm) 597852284Sobrien fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START); 597952284Sobrien fputc ('\n', asm_out_file); 598052284Sobrien } 598150397Sobrien } 598250397Sobrien else 598350397Sobrien { 598452284Sobrien /* We still need to start a new row, so output a copy insn. */ 598552284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy); 598650397Sobrien if (flag_debug_asm) 598752284Sobrien fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START); 598850397Sobrien fputc ('\n', asm_out_file); 598950397Sobrien } 599050397Sobrien } 599150397Sobrien 599250397Sobrien /* Emit debug info for the address of the end of the function. */ 599350397Sobrien if (0) 599450397Sobrien { 599550397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc); 599650397Sobrien if (flag_debug_asm) 599750397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc", 599850397Sobrien ASM_COMMENT_START); 599950397Sobrien 600050397Sobrien fputc ('\n', asm_out_file); 600150397Sobrien ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, text_end_label, prev_line_label); 600250397Sobrien fputc ('\n', asm_out_file); 600350397Sobrien } 600450397Sobrien else 600550397Sobrien { 600650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 600750397Sobrien if (flag_debug_asm) 600850397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_set_address", ASM_COMMENT_START); 600950397Sobrien fputc ('\n', asm_out_file); 601050397Sobrien output_uleb128 (1 + PTR_SIZE); 601150397Sobrien fputc ('\n', asm_out_file); 601250397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address); 601350397Sobrien fputc ('\n', asm_out_file); 601450397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, text_end_label); 601550397Sobrien fputc ('\n', asm_out_file); 601650397Sobrien } 601750397Sobrien 601850397Sobrien /* Output the marker for the end of the line number info. */ 601950397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 602050397Sobrien if (flag_debug_asm) 602150397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_end_sequence", ASM_COMMENT_START); 602250397Sobrien 602350397Sobrien fputc ('\n', asm_out_file); 602450397Sobrien output_uleb128 (1); 602550397Sobrien fputc ('\n', asm_out_file); 602650397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_end_sequence); 602750397Sobrien fputc ('\n', asm_out_file); 602850397Sobrien 602950397Sobrien function = 0; 603050397Sobrien current_file = 1; 603150397Sobrien current_line = 1; 603250397Sobrien for (lt_index = 0; lt_index < separate_line_info_table_in_use; ) 603350397Sobrien { 603450397Sobrien register dw_separate_line_info_ref line_info 603550397Sobrien = &separate_line_info_table[lt_index]; 603650397Sobrien 603752284Sobrien /* Don't emit anything for redundant notes. */ 603852284Sobrien if (line_info->dw_line_num == current_line 603952284Sobrien && line_info->dw_file_num == current_file 604052284Sobrien && line_info->function == function) 604152284Sobrien goto cont; 604252284Sobrien 604350397Sobrien /* Emit debug info for the address of the current line. If this is 604450397Sobrien a new function, or the first line of a function, then we need 604550397Sobrien to handle it differently. */ 604650397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, SEPARATE_LINE_CODE_LABEL, 604750397Sobrien lt_index); 604850397Sobrien if (function != line_info->function) 604950397Sobrien { 605050397Sobrien function = line_info->function; 605150397Sobrien 605250397Sobrien /* Set the address register to the first line in the function */ 605350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 605450397Sobrien if (flag_debug_asm) 605550397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_set_address", 605650397Sobrien ASM_COMMENT_START); 605750397Sobrien 605850397Sobrien fputc ('\n', asm_out_file); 605950397Sobrien output_uleb128 (1 + PTR_SIZE); 606050397Sobrien fputc ('\n', asm_out_file); 606150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address); 606250397Sobrien fputc ('\n', asm_out_file); 606350397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, line_label); 606450397Sobrien fputc ('\n', asm_out_file); 606550397Sobrien } 606650397Sobrien else 606750397Sobrien { 606850397Sobrien /* ??? See the DW_LNS_advance_pc comment above. */ 606950397Sobrien if (0) 607050397Sobrien { 607150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc); 607250397Sobrien if (flag_debug_asm) 607350397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc", 607450397Sobrien ASM_COMMENT_START); 607550397Sobrien 607650397Sobrien fputc ('\n', asm_out_file); 607750397Sobrien ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, line_label, 607850397Sobrien prev_line_label); 607950397Sobrien fputc ('\n', asm_out_file); 608050397Sobrien } 608150397Sobrien else 608250397Sobrien { 608350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 608450397Sobrien if (flag_debug_asm) 608550397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_set_address", 608650397Sobrien ASM_COMMENT_START); 608750397Sobrien fputc ('\n', asm_out_file); 608850397Sobrien output_uleb128 (1 + PTR_SIZE); 608950397Sobrien fputc ('\n', asm_out_file); 609050397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address); 609150397Sobrien fputc ('\n', asm_out_file); 609250397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, line_label); 609350397Sobrien fputc ('\n', asm_out_file); 609450397Sobrien } 609550397Sobrien } 609650397Sobrien strcpy (prev_line_label, line_label); 609750397Sobrien 609850397Sobrien /* Emit debug info for the source file of the current line, if 609950397Sobrien different from the previous line. */ 610050397Sobrien if (line_info->dw_file_num != current_file) 610150397Sobrien { 610250397Sobrien current_file = line_info->dw_file_num; 610350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_set_file); 610450397Sobrien if (flag_debug_asm) 610550397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_set_file", ASM_COMMENT_START); 610650397Sobrien 610750397Sobrien fputc ('\n', asm_out_file); 610850397Sobrien output_uleb128 (current_file); 610950397Sobrien if (flag_debug_asm) 611050397Sobrien fprintf (asm_out_file, " (\"%s\")", file_table[current_file]); 611150397Sobrien 611250397Sobrien fputc ('\n', asm_out_file); 611350397Sobrien } 611450397Sobrien 611550397Sobrien /* Emit debug info for the current line number, choosing the encoding 611650397Sobrien that uses the least amount of space. */ 611750397Sobrien if (line_info->dw_line_num != current_line) 611850397Sobrien { 611950397Sobrien line_offset = line_info->dw_line_num - current_line; 612050397Sobrien line_delta = line_offset - DWARF_LINE_BASE; 612150397Sobrien current_line = line_info->dw_line_num; 612250397Sobrien if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1)) 612350397Sobrien { 612450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 612550397Sobrien DWARF_LINE_OPCODE_BASE + line_delta); 612650397Sobrien if (flag_debug_asm) 612750397Sobrien fprintf (asm_out_file, 612850397Sobrien "\t%s line %ld", ASM_COMMENT_START, current_line); 612950397Sobrien 613050397Sobrien fputc ('\n', asm_out_file); 613150397Sobrien } 613250397Sobrien else 613350397Sobrien { 613450397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line); 613550397Sobrien if (flag_debug_asm) 613650397Sobrien fprintf (asm_out_file, "\t%s advance to line %ld", 613750397Sobrien ASM_COMMENT_START, current_line); 613850397Sobrien 613950397Sobrien fputc ('\n', asm_out_file); 614050397Sobrien output_sleb128 (line_offset); 614150397Sobrien fputc ('\n', asm_out_file); 614250397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy); 614352284Sobrien if (flag_debug_asm) 614452284Sobrien fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START); 614550397Sobrien fputc ('\n', asm_out_file); 614650397Sobrien } 614750397Sobrien } 614852284Sobrien else 614952284Sobrien { 615052284Sobrien /* We still need to start a new row, so output a copy insn. */ 615152284Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy); 615252284Sobrien if (flag_debug_asm) 615352284Sobrien fprintf (asm_out_file, "\t%s DW_LNS_copy", ASM_COMMENT_START); 615452284Sobrien fputc ('\n', asm_out_file); 615552284Sobrien } 615650397Sobrien 615752284Sobrien cont: 615850397Sobrien ++lt_index; 615950397Sobrien 616050397Sobrien /* If we're done with a function, end its sequence. */ 616150397Sobrien if (lt_index == separate_line_info_table_in_use 616250397Sobrien || separate_line_info_table[lt_index].function != function) 616350397Sobrien { 616450397Sobrien current_file = 1; 616550397Sobrien current_line = 1; 616650397Sobrien 616750397Sobrien /* Emit debug info for the address of the end of the function. */ 616850397Sobrien ASM_GENERATE_INTERNAL_LABEL (line_label, FUNC_END_LABEL, function); 616950397Sobrien if (0) 617050397Sobrien { 617150397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_fixed_advance_pc); 617250397Sobrien if (flag_debug_asm) 617350397Sobrien fprintf (asm_out_file, "\t%s DW_LNS_fixed_advance_pc", 617450397Sobrien ASM_COMMENT_START); 617550397Sobrien 617650397Sobrien fputc ('\n', asm_out_file); 617750397Sobrien ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, line_label, 617850397Sobrien prev_line_label); 617950397Sobrien fputc ('\n', asm_out_file); 618050397Sobrien } 618150397Sobrien else 618250397Sobrien { 618350397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 618450397Sobrien if (flag_debug_asm) 618550397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_set_address", 618650397Sobrien ASM_COMMENT_START); 618750397Sobrien fputc ('\n', asm_out_file); 618850397Sobrien output_uleb128 (1 + PTR_SIZE); 618950397Sobrien fputc ('\n', asm_out_file); 619050397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_set_address); 619150397Sobrien fputc ('\n', asm_out_file); 619250397Sobrien ASM_OUTPUT_DWARF_ADDR (asm_out_file, line_label); 619350397Sobrien fputc ('\n', asm_out_file); 619450397Sobrien } 619550397Sobrien 619650397Sobrien /* Output the marker for the end of this sequence. */ 619750397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, 0); 619850397Sobrien if (flag_debug_asm) 619950397Sobrien fprintf (asm_out_file, "\t%s DW_LNE_end_sequence", 620050397Sobrien ASM_COMMENT_START); 620150397Sobrien 620250397Sobrien fputc ('\n', asm_out_file); 620350397Sobrien output_uleb128 (1); 620450397Sobrien fputc ('\n', asm_out_file); 620550397Sobrien ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNE_end_sequence); 620650397Sobrien fputc ('\n', asm_out_file); 620750397Sobrien } 620850397Sobrien } 620950397Sobrien} 621050397Sobrien 621150397Sobrien/* Given a pointer to a BLOCK node return non-zero if (and only if) the node 621250397Sobrien in question represents the outermost pair of curly braces (i.e. the "body 621350397Sobrien block") of a function or method. 621450397Sobrien 621550397Sobrien For any BLOCK node representing a "body block" of a function or method, the 621650397Sobrien BLOCK_SUPERCONTEXT of the node will point to another BLOCK node which 621750397Sobrien represents the outermost (function) scope for the function or method (i.e. 621850397Sobrien the one which includes the formal parameters). The BLOCK_SUPERCONTEXT of 621950397Sobrien *that* node in turn will point to the relevant FUNCTION_DECL node. */ 622050397Sobrien 622150397Sobrienstatic inline int 622250397Sobrienis_body_block (stmt) 622350397Sobrien register tree stmt; 622450397Sobrien{ 622550397Sobrien if (TREE_CODE (stmt) == BLOCK) 622650397Sobrien { 622750397Sobrien register tree parent = BLOCK_SUPERCONTEXT (stmt); 622850397Sobrien 622950397Sobrien if (TREE_CODE (parent) == BLOCK) 623050397Sobrien { 623150397Sobrien register tree grandparent = BLOCK_SUPERCONTEXT (parent); 623250397Sobrien 623350397Sobrien if (TREE_CODE (grandparent) == FUNCTION_DECL) 623450397Sobrien return 1; 623550397Sobrien } 623650397Sobrien } 623750397Sobrien 623850397Sobrien return 0; 623950397Sobrien} 624050397Sobrien 624150397Sobrien/* Given a pointer to a tree node for some base type, return a pointer to 624250397Sobrien a DIE that describes the given type. 624350397Sobrien 624450397Sobrien This routine must only be called for GCC type nodes that correspond to 624550397Sobrien Dwarf base (fundamental) types. */ 624650397Sobrien 624750397Sobrienstatic dw_die_ref 624850397Sobrienbase_type_die (type) 624950397Sobrien register tree type; 625050397Sobrien{ 625150397Sobrien register dw_die_ref base_type_result; 625250397Sobrien register char *type_name; 625350397Sobrien register enum dwarf_type encoding; 625450397Sobrien register tree name = TYPE_NAME (type); 625550397Sobrien 625650397Sobrien if (TREE_CODE (type) == ERROR_MARK 625750397Sobrien || TREE_CODE (type) == VOID_TYPE) 625850397Sobrien return 0; 625950397Sobrien 626050397Sobrien if (TREE_CODE (name) == TYPE_DECL) 626150397Sobrien name = DECL_NAME (name); 626250397Sobrien type_name = IDENTIFIER_POINTER (name); 626350397Sobrien 626450397Sobrien switch (TREE_CODE (type)) 626550397Sobrien { 626650397Sobrien case INTEGER_TYPE: 626750397Sobrien /* Carefully distinguish the C character types, without messing 626850397Sobrien up if the language is not C. Note that we check only for the names 626950397Sobrien that contain spaces; other names might occur by coincidence in other 627050397Sobrien languages. */ 627150397Sobrien if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE 627250397Sobrien && (type == char_type_node 627350397Sobrien || ! strcmp (type_name, "signed char") 627450397Sobrien || ! strcmp (type_name, "unsigned char")))) 627550397Sobrien { 627650397Sobrien if (TREE_UNSIGNED (type)) 627750397Sobrien encoding = DW_ATE_unsigned; 627850397Sobrien else 627950397Sobrien encoding = DW_ATE_signed; 628050397Sobrien break; 628150397Sobrien } 628250397Sobrien /* else fall through */ 628350397Sobrien 628450397Sobrien case CHAR_TYPE: 628550397Sobrien /* GNU Pascal/Ada CHAR type. Not used in C. */ 628650397Sobrien if (TREE_UNSIGNED (type)) 628750397Sobrien encoding = DW_ATE_unsigned_char; 628850397Sobrien else 628950397Sobrien encoding = DW_ATE_signed_char; 629050397Sobrien break; 629150397Sobrien 629250397Sobrien case REAL_TYPE: 629350397Sobrien encoding = DW_ATE_float; 629450397Sobrien break; 629550397Sobrien 629650397Sobrien case COMPLEX_TYPE: 629750397Sobrien encoding = DW_ATE_complex_float; 629850397Sobrien break; 629950397Sobrien 630050397Sobrien case BOOLEAN_TYPE: 630150397Sobrien /* GNU FORTRAN/Ada/C++ BOOLEAN type. */ 630250397Sobrien encoding = DW_ATE_boolean; 630350397Sobrien break; 630450397Sobrien 630550397Sobrien default: 630650397Sobrien abort (); /* No other TREE_CODEs are Dwarf fundamental types. */ 630750397Sobrien } 630850397Sobrien 630950397Sobrien base_type_result = new_die (DW_TAG_base_type, comp_unit_die); 631050397Sobrien add_AT_string (base_type_result, DW_AT_name, type_name); 631150397Sobrien add_AT_unsigned (base_type_result, DW_AT_byte_size, 631250397Sobrien int_size_in_bytes (type)); 631350397Sobrien add_AT_unsigned (base_type_result, DW_AT_encoding, encoding); 631450397Sobrien 631550397Sobrien return base_type_result; 631650397Sobrien} 631750397Sobrien 631850397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a pointer to 631950397Sobrien the Dwarf "root" type for the given input type. The Dwarf "root" type of 632050397Sobrien a given type is generally the same as the given type, except that if the 632150397Sobrien given type is a pointer or reference type, then the root type of the given 632250397Sobrien type is the root type of the "basis" type for the pointer or reference 632350397Sobrien type. (This definition of the "root" type is recursive.) Also, the root 632450397Sobrien type of a `const' qualified type or a `volatile' qualified type is the 632550397Sobrien root type of the given type without the qualifiers. */ 632650397Sobrien 632750397Sobrienstatic tree 632850397Sobrienroot_type (type) 632950397Sobrien register tree type; 633050397Sobrien{ 633150397Sobrien if (TREE_CODE (type) == ERROR_MARK) 633250397Sobrien return error_mark_node; 633350397Sobrien 633450397Sobrien switch (TREE_CODE (type)) 633550397Sobrien { 633650397Sobrien case ERROR_MARK: 633750397Sobrien return error_mark_node; 633850397Sobrien 633950397Sobrien case POINTER_TYPE: 634050397Sobrien case REFERENCE_TYPE: 634150397Sobrien return type_main_variant (root_type (TREE_TYPE (type))); 634250397Sobrien 634350397Sobrien default: 634450397Sobrien return type_main_variant (type); 634550397Sobrien } 634650397Sobrien} 634750397Sobrien 634850397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the 634950397Sobrien given input type is a Dwarf "fundamental" type. Otherwise return null. */ 635050397Sobrien 635150397Sobrienstatic inline int 635250397Sobrienis_base_type (type) 635350397Sobrien register tree type; 635450397Sobrien{ 635550397Sobrien switch (TREE_CODE (type)) 635650397Sobrien { 635750397Sobrien case ERROR_MARK: 635850397Sobrien case VOID_TYPE: 635950397Sobrien case INTEGER_TYPE: 636050397Sobrien case REAL_TYPE: 636150397Sobrien case COMPLEX_TYPE: 636250397Sobrien case BOOLEAN_TYPE: 636350397Sobrien case CHAR_TYPE: 636450397Sobrien return 1; 636550397Sobrien 636650397Sobrien case SET_TYPE: 636750397Sobrien case ARRAY_TYPE: 636850397Sobrien case RECORD_TYPE: 636950397Sobrien case UNION_TYPE: 637050397Sobrien case QUAL_UNION_TYPE: 637150397Sobrien case ENUMERAL_TYPE: 637250397Sobrien case FUNCTION_TYPE: 637350397Sobrien case METHOD_TYPE: 637450397Sobrien case POINTER_TYPE: 637550397Sobrien case REFERENCE_TYPE: 637650397Sobrien case FILE_TYPE: 637750397Sobrien case OFFSET_TYPE: 637850397Sobrien case LANG_TYPE: 637950397Sobrien return 0; 638050397Sobrien 638150397Sobrien default: 638250397Sobrien abort (); 638350397Sobrien } 638450397Sobrien 638550397Sobrien return 0; 638650397Sobrien} 638750397Sobrien 638850397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging 638950397Sobrien entry that chains various modifiers in front of the given type. */ 639050397Sobrien 639150397Sobrienstatic dw_die_ref 639250397Sobrienmodified_type_die (type, is_const_type, is_volatile_type, context_die) 639350397Sobrien register tree type; 639450397Sobrien register int is_const_type; 639550397Sobrien register int is_volatile_type; 639650397Sobrien register dw_die_ref context_die; 639750397Sobrien{ 639850397Sobrien register enum tree_code code = TREE_CODE (type); 639950397Sobrien register dw_die_ref mod_type_die = NULL; 640050397Sobrien register dw_die_ref sub_die = NULL; 640150397Sobrien register tree item_type = NULL; 640250397Sobrien 640350397Sobrien if (code != ERROR_MARK) 640450397Sobrien { 640550397Sobrien type = build_type_variant (type, is_const_type, is_volatile_type); 640650397Sobrien 640750397Sobrien mod_type_die = lookup_type_die (type); 640850397Sobrien if (mod_type_die) 640950397Sobrien return mod_type_die; 641050397Sobrien 641150397Sobrien /* Handle C typedef types. */ 641250397Sobrien if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 641350397Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 641450397Sobrien { 641550397Sobrien tree dtype = TREE_TYPE (TYPE_NAME (type)); 641650397Sobrien if (type == dtype) 641750397Sobrien { 641850397Sobrien /* For a named type, use the typedef. */ 641950397Sobrien gen_type_die (type, context_die); 642050397Sobrien mod_type_die = lookup_type_die (type); 642150397Sobrien } 642250397Sobrien 642350397Sobrien else if (is_const_type < TYPE_READONLY (dtype) 642450397Sobrien || is_volatile_type < TYPE_VOLATILE (dtype)) 642550397Sobrien /* cv-unqualified version of named type. Just use the unnamed 642650397Sobrien type to which it refers. */ 642750397Sobrien mod_type_die 642850397Sobrien = modified_type_die (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 642950397Sobrien is_const_type, is_volatile_type, 643050397Sobrien context_die); 643150397Sobrien /* Else cv-qualified version of named type; fall through. */ 643250397Sobrien } 643350397Sobrien 643450397Sobrien if (mod_type_die) 643550397Sobrien /* OK */; 643650397Sobrien else if (is_const_type) 643750397Sobrien { 643850397Sobrien mod_type_die = new_die (DW_TAG_const_type, comp_unit_die); 643950397Sobrien sub_die = modified_type_die (type, 0, is_volatile_type, context_die); 644050397Sobrien } 644150397Sobrien else if (is_volatile_type) 644250397Sobrien { 644350397Sobrien mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die); 644450397Sobrien sub_die = modified_type_die (type, 0, 0, context_die); 644550397Sobrien } 644650397Sobrien else if (code == POINTER_TYPE) 644750397Sobrien { 644850397Sobrien mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die); 644950397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 645050397Sobrien#if 0 645150397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 645250397Sobrien#endif 645350397Sobrien item_type = TREE_TYPE (type); 645450397Sobrien } 645550397Sobrien else if (code == REFERENCE_TYPE) 645650397Sobrien { 645750397Sobrien mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die); 645850397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 645950397Sobrien#if 0 646050397Sobrien add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); 646150397Sobrien#endif 646250397Sobrien item_type = TREE_TYPE (type); 646350397Sobrien } 646450397Sobrien else if (is_base_type (type)) 646550397Sobrien mod_type_die = base_type_die (type); 646650397Sobrien else 646750397Sobrien { 646850397Sobrien gen_type_die (type, context_die); 646950397Sobrien 647050397Sobrien /* We have to get the type_main_variant here (and pass that to the 647150397Sobrien `lookup_type_die' routine) because the ..._TYPE node we have 647250397Sobrien might simply be a *copy* of some original type node (where the 647350397Sobrien copy was created to help us keep track of typedef names) and 647450397Sobrien that copy might have a different TYPE_UID from the original 647550397Sobrien ..._TYPE node. */ 647650397Sobrien mod_type_die = lookup_type_die (type_main_variant (type)); 647750397Sobrien if (mod_type_die == NULL) 647850397Sobrien abort (); 647950397Sobrien } 648050397Sobrien } 648150397Sobrien 648250397Sobrien equate_type_number_to_die (type, mod_type_die); 648350397Sobrien if (item_type) 648450397Sobrien /* We must do this after the equate_type_number_to_die call, in case 648550397Sobrien this is a recursive type. This ensures that the modified_type_die 648650397Sobrien recursion will terminate even if the type is recursive. Recursive 648750397Sobrien types are possible in Ada. */ 648850397Sobrien sub_die = modified_type_die (item_type, 648950397Sobrien TYPE_READONLY (item_type), 649050397Sobrien TYPE_VOLATILE (item_type), 649150397Sobrien context_die); 649250397Sobrien 649350397Sobrien if (sub_die != NULL) 649450397Sobrien add_AT_die_ref (mod_type_die, DW_AT_type, sub_die); 649550397Sobrien 649650397Sobrien return mod_type_die; 649750397Sobrien} 649850397Sobrien 649950397Sobrien/* Given a pointer to an arbitrary ..._TYPE tree node, return true if it is 650050397Sobrien an enumerated type. */ 650150397Sobrien 650250397Sobrienstatic inline int 650350397Sobrientype_is_enum (type) 650450397Sobrien register tree type; 650550397Sobrien{ 650650397Sobrien return TREE_CODE (type) == ENUMERAL_TYPE; 650750397Sobrien} 650850397Sobrien 650950397Sobrien/* Return a location descriptor that designates a machine register. */ 651050397Sobrien 651150397Sobrienstatic dw_loc_descr_ref 651250397Sobrienreg_loc_descriptor (rtl) 651350397Sobrien register rtx rtl; 651450397Sobrien{ 651550397Sobrien register dw_loc_descr_ref loc_result = NULL; 651650397Sobrien register unsigned reg = reg_number (rtl); 651750397Sobrien 651850397Sobrien if (reg <= 31) 651950397Sobrien loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0); 652050397Sobrien else 652150397Sobrien loc_result = new_loc_descr (DW_OP_regx, reg, 0); 652250397Sobrien 652350397Sobrien return loc_result; 652450397Sobrien} 652550397Sobrien 652650397Sobrien/* Return a location descriptor that designates a base+offset location. */ 652750397Sobrien 652850397Sobrienstatic dw_loc_descr_ref 652950397Sobrienbased_loc_descr (reg, offset) 653050397Sobrien unsigned reg; 653150397Sobrien long int offset; 653250397Sobrien{ 653350397Sobrien register dw_loc_descr_ref loc_result; 653450397Sobrien /* For the "frame base", we use the frame pointer or stack pointer 653550397Sobrien registers, since the RTL for local variables is relative to one of 653650397Sobrien them. */ 653750397Sobrien register unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed 653850397Sobrien ? HARD_FRAME_POINTER_REGNUM 653950397Sobrien : STACK_POINTER_REGNUM); 654050397Sobrien 654150397Sobrien if (reg == fp_reg) 654250397Sobrien loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); 654350397Sobrien else if (reg <= 31) 654450397Sobrien loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); 654550397Sobrien else 654650397Sobrien loc_result = new_loc_descr (DW_OP_bregx, reg, offset); 654750397Sobrien 654850397Sobrien return loc_result; 654950397Sobrien} 655050397Sobrien 655150397Sobrien/* Return true if this RTL expression describes a base+offset calculation. */ 655250397Sobrien 655350397Sobrienstatic inline int 655450397Sobrienis_based_loc (rtl) 655550397Sobrien register rtx rtl; 655650397Sobrien{ 655750397Sobrien return (GET_CODE (rtl) == PLUS 655850397Sobrien && ((GET_CODE (XEXP (rtl, 0)) == REG 655950397Sobrien && GET_CODE (XEXP (rtl, 1)) == CONST_INT))); 656050397Sobrien} 656150397Sobrien 656250397Sobrien/* The following routine converts the RTL for a variable or parameter 656350397Sobrien (resident in memory) into an equivalent Dwarf representation of a 656450397Sobrien mechanism for getting the address of that same variable onto the top of a 656550397Sobrien hypothetical "address evaluation" stack. 656650397Sobrien 656750397Sobrien When creating memory location descriptors, we are effectively transforming 656850397Sobrien the RTL for a memory-resident object into its Dwarf postfix expression 656950397Sobrien equivalent. This routine recursively descends an RTL tree, turning 657050397Sobrien it into Dwarf postfix code as it goes. */ 657150397Sobrien 657250397Sobrienstatic dw_loc_descr_ref 657350397Sobrienmem_loc_descriptor (rtl) 657450397Sobrien register rtx rtl; 657550397Sobrien{ 657650397Sobrien dw_loc_descr_ref mem_loc_result = NULL; 657750397Sobrien /* Note that for a dynamically sized array, the location we will generate a 657850397Sobrien description of here will be the lowest numbered location which is 657950397Sobrien actually within the array. That's *not* necessarily the same as the 658050397Sobrien zeroth element of the array. */ 658150397Sobrien 658250397Sobrien switch (GET_CODE (rtl)) 658350397Sobrien { 658450397Sobrien case SUBREG: 658550397Sobrien /* The case of a subreg may arise when we have a local (register) 658650397Sobrien variable or a formal (register) parameter which doesn't quite fill 658750397Sobrien up an entire register. For now, just assume that it is 658850397Sobrien legitimate to make the Dwarf info refer to the whole register which 658950397Sobrien contains the given subreg. */ 659050397Sobrien rtl = XEXP (rtl, 0); 659150397Sobrien 659250397Sobrien /* ... fall through ... */ 659350397Sobrien 659450397Sobrien case REG: 659550397Sobrien /* Whenever a register number forms a part of the description of the 659650397Sobrien method for calculating the (dynamic) address of a memory resident 659750397Sobrien object, DWARF rules require the register number be referred to as 659850397Sobrien a "base register". This distinction is not based in any way upon 659950397Sobrien what category of register the hardware believes the given register 660050397Sobrien belongs to. This is strictly DWARF terminology we're dealing with 660150397Sobrien here. Note that in cases where the location of a memory-resident 660250397Sobrien data object could be expressed as: OP_ADD (OP_BASEREG (basereg), 660350397Sobrien OP_CONST (0)) the actual DWARF location descriptor that we generate 660450397Sobrien may just be OP_BASEREG (basereg). This may look deceptively like 660550397Sobrien the object in question was allocated to a register (rather than in 660650397Sobrien memory) so DWARF consumers need to be aware of the subtle 660750397Sobrien distinction between OP_REG and OP_BASEREG. */ 660850397Sobrien mem_loc_result = based_loc_descr (reg_number (rtl), 0); 660950397Sobrien break; 661050397Sobrien 661150397Sobrien case MEM: 661250397Sobrien mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0)); 661350397Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); 661450397Sobrien break; 661550397Sobrien 661650397Sobrien case CONST: 661750397Sobrien case SYMBOL_REF: 661850397Sobrien mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); 661950397Sobrien mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; 662050397Sobrien mem_loc_result->dw_loc_oprnd1.v.val_addr = addr_to_string (rtl); 662150397Sobrien break; 662250397Sobrien 662350397Sobrien case PLUS: 662450397Sobrien if (is_based_loc (rtl)) 662550397Sobrien mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), 662650397Sobrien INTVAL (XEXP (rtl, 1))); 662750397Sobrien else 662850397Sobrien { 662950397Sobrien add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0))); 663050397Sobrien add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1))); 663150397Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0)); 663250397Sobrien } 663350397Sobrien break; 663450397Sobrien 663550397Sobrien case MULT: 663650397Sobrien /* If a pseudo-reg is optimized away, it is possible for it to 663750397Sobrien be replaced with a MEM containing a multiply. */ 663850397Sobrien add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 0))); 663950397Sobrien add_loc_descr (&mem_loc_result, mem_loc_descriptor (XEXP (rtl, 1))); 664050397Sobrien add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_mul, 0, 0)); 664150397Sobrien break; 664250397Sobrien 664350397Sobrien case CONST_INT: 664450397Sobrien mem_loc_result = new_loc_descr (DW_OP_constu, INTVAL (rtl), 0); 664550397Sobrien break; 664650397Sobrien 664750397Sobrien default: 664850397Sobrien abort (); 664950397Sobrien } 665050397Sobrien 665150397Sobrien return mem_loc_result; 665250397Sobrien} 665350397Sobrien 665450397Sobrien/* Return a descriptor that describes the concatenation of two locations. 665550397Sobrien This is typically a complex variable. */ 665650397Sobrien 665750397Sobrienstatic dw_loc_descr_ref 665850397Sobrienconcat_loc_descriptor (x0, x1) 665950397Sobrien register rtx x0, x1; 666050397Sobrien{ 666150397Sobrien dw_loc_descr_ref cc_loc_result = NULL; 666250397Sobrien 666350397Sobrien if (!is_pseudo_reg (x0) 666450397Sobrien && (GET_CODE (x0) != MEM || !is_pseudo_reg (XEXP (x0, 0)))) 666550397Sobrien add_loc_descr (&cc_loc_result, loc_descriptor (x0)); 666650397Sobrien add_loc_descr (&cc_loc_result, 666750397Sobrien new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x0)), 0)); 666850397Sobrien 666950397Sobrien if (!is_pseudo_reg (x1) 667050397Sobrien && (GET_CODE (x1) != MEM || !is_pseudo_reg (XEXP (x1, 0)))) 667150397Sobrien add_loc_descr (&cc_loc_result, loc_descriptor (x1)); 667250397Sobrien add_loc_descr (&cc_loc_result, 667350397Sobrien new_loc_descr (DW_OP_piece, GET_MODE_SIZE (GET_MODE (x1)), 0)); 667450397Sobrien 667550397Sobrien return cc_loc_result; 667650397Sobrien} 667750397Sobrien 667850397Sobrien/* Output a proper Dwarf location descriptor for a variable or parameter 667950397Sobrien which is either allocated in a register or in a memory location. For a 668050397Sobrien register, we just generate an OP_REG and the register number. For a 668150397Sobrien memory location we provide a Dwarf postfix expression describing how to 668250397Sobrien generate the (dynamic) address of the object onto the address stack. */ 668350397Sobrien 668450397Sobrienstatic dw_loc_descr_ref 668550397Sobrienloc_descriptor (rtl) 668650397Sobrien register rtx rtl; 668750397Sobrien{ 668850397Sobrien dw_loc_descr_ref loc_result = NULL; 668950397Sobrien switch (GET_CODE (rtl)) 669050397Sobrien { 669150397Sobrien case SUBREG: 669250397Sobrien /* The case of a subreg may arise when we have a local (register) 669350397Sobrien variable or a formal (register) parameter which doesn't quite fill 669450397Sobrien up an entire register. For now, just assume that it is 669550397Sobrien legitimate to make the Dwarf info refer to the whole register which 669650397Sobrien contains the given subreg. */ 669750397Sobrien rtl = XEXP (rtl, 0); 669850397Sobrien 669950397Sobrien /* ... fall through ... */ 670050397Sobrien 670150397Sobrien case REG: 670250397Sobrien loc_result = reg_loc_descriptor (rtl); 670350397Sobrien break; 670450397Sobrien 670550397Sobrien case MEM: 670650397Sobrien loc_result = mem_loc_descriptor (XEXP (rtl, 0)); 670750397Sobrien break; 670850397Sobrien 670950397Sobrien case CONCAT: 671050397Sobrien loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); 671150397Sobrien break; 671250397Sobrien 671350397Sobrien default: 671450397Sobrien abort (); 671550397Sobrien } 671650397Sobrien 671750397Sobrien return loc_result; 671850397Sobrien} 671950397Sobrien 672050397Sobrien/* Given an unsigned value, round it up to the lowest multiple of `boundary' 672150397Sobrien which is not less than the value itself. */ 672250397Sobrien 672350397Sobrienstatic inline unsigned 672450397Sobrienceiling (value, boundary) 672550397Sobrien register unsigned value; 672650397Sobrien register unsigned boundary; 672750397Sobrien{ 672850397Sobrien return (((value + boundary - 1) / boundary) * boundary); 672950397Sobrien} 673050397Sobrien 673150397Sobrien/* Given a pointer to what is assumed to be a FIELD_DECL node, return a 673250397Sobrien pointer to the declared type for the relevant field variable, or return 673350397Sobrien `integer_type_node' if the given node turns out to be an 673450397Sobrien ERROR_MARK node. */ 673550397Sobrien 673650397Sobrienstatic inline tree 673750397Sobrienfield_type (decl) 673850397Sobrien register tree decl; 673950397Sobrien{ 674050397Sobrien register tree type; 674150397Sobrien 674250397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 674350397Sobrien return integer_type_node; 674450397Sobrien 674550397Sobrien type = DECL_BIT_FIELD_TYPE (decl); 674650397Sobrien if (type == NULL_TREE) 674750397Sobrien type = TREE_TYPE (decl); 674850397Sobrien 674950397Sobrien return type; 675050397Sobrien} 675150397Sobrien 675250397Sobrien/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE 675350397Sobrien node, return the alignment in bits for the type, or else return 675450397Sobrien BITS_PER_WORD if the node actually turns out to be an 675550397Sobrien ERROR_MARK node. */ 675650397Sobrien 675750397Sobrienstatic inline unsigned 675850397Sobriensimple_type_align_in_bits (type) 675950397Sobrien register tree type; 676050397Sobrien{ 676150397Sobrien return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; 676250397Sobrien} 676350397Sobrien 676450397Sobrien/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE 676550397Sobrien node, return the size in bits for the type if it is a constant, or else 676650397Sobrien return the alignment for the type if the type's size is not constant, or 676750397Sobrien else return BITS_PER_WORD if the type actually turns out to be an 676850397Sobrien ERROR_MARK node. */ 676950397Sobrien 677050397Sobrienstatic inline unsigned 677150397Sobriensimple_type_size_in_bits (type) 677250397Sobrien register tree type; 677350397Sobrien{ 677450397Sobrien if (TREE_CODE (type) == ERROR_MARK) 677550397Sobrien return BITS_PER_WORD; 677650397Sobrien else 677750397Sobrien { 677850397Sobrien register tree type_size_tree = TYPE_SIZE (type); 677950397Sobrien 678050397Sobrien if (TREE_CODE (type_size_tree) != INTEGER_CST) 678150397Sobrien return TYPE_ALIGN (type); 678250397Sobrien 678350397Sobrien return (unsigned) TREE_INT_CST_LOW (type_size_tree); 678450397Sobrien } 678550397Sobrien} 678650397Sobrien 678750397Sobrien/* Given a pointer to what is assumed to be a FIELD_DECL node, compute and 678850397Sobrien return the byte offset of the lowest addressed byte of the "containing 678950397Sobrien object" for the given FIELD_DECL, or return 0 if we are unable to 679050397Sobrien determine what that offset is, either because the argument turns out to 679150397Sobrien be a pointer to an ERROR_MARK node, or because the offset is actually 679250397Sobrien variable. (We can't handle the latter case just yet). */ 679350397Sobrien 679450397Sobrienstatic unsigned 679550397Sobrienfield_byte_offset (decl) 679650397Sobrien register tree decl; 679750397Sobrien{ 679850397Sobrien register unsigned type_align_in_bytes; 679950397Sobrien register unsigned type_align_in_bits; 680050397Sobrien register unsigned type_size_in_bits; 680150397Sobrien register unsigned object_offset_in_align_units; 680250397Sobrien register unsigned object_offset_in_bits; 680350397Sobrien register unsigned object_offset_in_bytes; 680450397Sobrien register tree type; 680550397Sobrien register tree bitpos_tree; 680650397Sobrien register tree field_size_tree; 680750397Sobrien register unsigned bitpos_int; 680850397Sobrien register unsigned deepest_bitpos; 680950397Sobrien register unsigned field_size_in_bits; 681050397Sobrien 681150397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 681250397Sobrien return 0; 681350397Sobrien 681450397Sobrien if (TREE_CODE (decl) != FIELD_DECL) 681550397Sobrien abort (); 681650397Sobrien 681750397Sobrien type = field_type (decl); 681850397Sobrien 681950397Sobrien bitpos_tree = DECL_FIELD_BITPOS (decl); 682050397Sobrien field_size_tree = DECL_SIZE (decl); 682150397Sobrien 682250397Sobrien /* We cannot yet cope with fields whose positions or sizes are variable, so 682350397Sobrien for now, when we see such things, we simply return 0. Someday, we may 682450397Sobrien be able to handle such cases, but it will be damn difficult. */ 682550397Sobrien if (TREE_CODE (bitpos_tree) != INTEGER_CST) 682650397Sobrien return 0; 682750397Sobrien bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); 682850397Sobrien 682950397Sobrien if (TREE_CODE (field_size_tree) != INTEGER_CST) 683050397Sobrien return 0; 683150397Sobrien 683250397Sobrien field_size_in_bits = (unsigned) TREE_INT_CST_LOW (field_size_tree); 683350397Sobrien type_size_in_bits = simple_type_size_in_bits (type); 683450397Sobrien type_align_in_bits = simple_type_align_in_bits (type); 683550397Sobrien type_align_in_bytes = type_align_in_bits / BITS_PER_UNIT; 683650397Sobrien 683750397Sobrien /* Note that the GCC front-end doesn't make any attempt to keep track of 683850397Sobrien the starting bit offset (relative to the start of the containing 683950397Sobrien structure type) of the hypothetical "containing object" for a bit- 684050397Sobrien field. Thus, when computing the byte offset value for the start of the 684150397Sobrien "containing object" of a bit-field, we must deduce this information on 684250397Sobrien our own. This can be rather tricky to do in some cases. For example, 684350397Sobrien handling the following structure type definition when compiling for an 684450397Sobrien i386/i486 target (which only aligns long long's to 32-bit boundaries) 684550397Sobrien can be very tricky: 684650397Sobrien 684750397Sobrien struct S { int field1; long long field2:31; }; 684850397Sobrien 684950397Sobrien Fortunately, there is a simple rule-of-thumb which can be 685050397Sobrien used in such cases. When compiling for an i386/i486, GCC will allocate 685150397Sobrien 8 bytes for the structure shown above. It decides to do this based upon 685250397Sobrien one simple rule for bit-field allocation. Quite simply, GCC allocates 685350397Sobrien each "containing object" for each bit-field at the first (i.e. lowest 685450397Sobrien addressed) legitimate alignment boundary (based upon the required 685550397Sobrien minimum alignment for the declared type of the field) which it can 685650397Sobrien possibly use, subject to the condition that there is still enough 685750397Sobrien available space remaining in the containing object (when allocated at 685850397Sobrien the selected point) to fully accommodate all of the bits of the 685950397Sobrien bit-field itself. This simple rule makes it obvious why GCC allocates 686050397Sobrien 8 bytes for each object of the structure type shown above. When looking 686150397Sobrien for a place to allocate the "containing object" for `field2', the 686250397Sobrien compiler simply tries to allocate a 64-bit "containing object" at each 686350397Sobrien successive 32-bit boundary (starting at zero) until it finds a place to 686450397Sobrien allocate that 64- bit field such that at least 31 contiguous (and 686550397Sobrien previously unallocated) bits remain within that selected 64 bit field. 686650397Sobrien (As it turns out, for the example above, the compiler finds that it is 686750397Sobrien OK to allocate the "containing object" 64-bit field at bit-offset zero 686850397Sobrien within the structure type.) Here we attempt to work backwards from the 686950397Sobrien limited set of facts we're given, and we try to deduce from those facts, 687050397Sobrien where GCC must have believed that the containing object started (within 687150397Sobrien the structure type). The value we deduce is then used (by the callers of 687250397Sobrien this routine) to generate DW_AT_location and DW_AT_bit_offset attributes 687350397Sobrien for fields (both bit-fields and, in the case of DW_AT_location, regular 687450397Sobrien fields as well). */ 687550397Sobrien 687650397Sobrien /* Figure out the bit-distance from the start of the structure to the 687750397Sobrien "deepest" bit of the bit-field. */ 687850397Sobrien deepest_bitpos = bitpos_int + field_size_in_bits; 687950397Sobrien 688050397Sobrien /* This is the tricky part. Use some fancy footwork to deduce where the 688150397Sobrien lowest addressed bit of the containing object must be. */ 688250397Sobrien object_offset_in_bits 688350397Sobrien = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits; 688450397Sobrien 688550397Sobrien /* Compute the offset of the containing object in "alignment units". */ 688650397Sobrien object_offset_in_align_units = object_offset_in_bits / type_align_in_bits; 688750397Sobrien 688850397Sobrien /* Compute the offset of the containing object in bytes. */ 688950397Sobrien object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes; 689050397Sobrien 689150397Sobrien return object_offset_in_bytes; 689250397Sobrien} 689350397Sobrien 689450397Sobrien/* The following routines define various Dwarf attributes and any data 689550397Sobrien associated with them. */ 689650397Sobrien 689750397Sobrien/* Add a location description attribute value to a DIE. 689850397Sobrien 689950397Sobrien This emits location attributes suitable for whole variables and 690050397Sobrien whole parameters. Note that the location attributes for struct fields are 690150397Sobrien generated by the routine `data_member_location_attribute' below. */ 690250397Sobrien 690350397Sobrienstatic void 690450397Sobrienadd_AT_location_description (die, attr_kind, rtl) 690550397Sobrien dw_die_ref die; 690650397Sobrien enum dwarf_attribute attr_kind; 690750397Sobrien register rtx rtl; 690850397Sobrien{ 690950397Sobrien /* Handle a special case. If we are about to output a location descriptor 691050397Sobrien for a variable or parameter which has been optimized out of existence, 691150397Sobrien don't do that. A variable which has been optimized out 691250397Sobrien of existence will have a DECL_RTL value which denotes a pseudo-reg. 691350397Sobrien Currently, in some rare cases, variables can have DECL_RTL values which 691450397Sobrien look like (MEM (REG pseudo-reg#)). These cases are due to bugs 691550397Sobrien elsewhere in the compiler. We treat such cases as if the variable(s) in 691650397Sobrien question had been optimized out of existence. */ 691750397Sobrien 691850397Sobrien if (is_pseudo_reg (rtl) 691950397Sobrien || (GET_CODE (rtl) == MEM 692050397Sobrien && is_pseudo_reg (XEXP (rtl, 0))) 692150397Sobrien || (GET_CODE (rtl) == CONCAT 692250397Sobrien && is_pseudo_reg (XEXP (rtl, 0)) 692350397Sobrien && is_pseudo_reg (XEXP (rtl, 1)))) 692450397Sobrien return; 692550397Sobrien 692650397Sobrien add_AT_loc (die, attr_kind, loc_descriptor (rtl)); 692750397Sobrien} 692850397Sobrien 692950397Sobrien/* Attach the specialized form of location attribute used for data 693050397Sobrien members of struct and union types. In the special case of a 693150397Sobrien FIELD_DECL node which represents a bit-field, the "offset" part 693250397Sobrien of this special location descriptor must indicate the distance 693350397Sobrien in bytes from the lowest-addressed byte of the containing struct 693450397Sobrien or union type to the lowest-addressed byte of the "containing 693550397Sobrien object" for the bit-field. (See the `field_byte_offset' function 693650397Sobrien above).. For any given bit-field, the "containing object" is a 693750397Sobrien hypothetical object (of some integral or enum type) within which 693850397Sobrien the given bit-field lives. The type of this hypothetical 693950397Sobrien "containing object" is always the same as the declared type of 694050397Sobrien the individual bit-field itself (for GCC anyway... the DWARF 694150397Sobrien spec doesn't actually mandate this). Note that it is the size 694250397Sobrien (in bytes) of the hypothetical "containing object" which will 694350397Sobrien be given in the DW_AT_byte_size attribute for this bit-field. 694450397Sobrien (See the `byte_size_attribute' function below.) It is also used 694550397Sobrien when calculating the value of the DW_AT_bit_offset attribute. 694650397Sobrien (See the `bit_offset_attribute' function below). */ 694750397Sobrien 694850397Sobrienstatic void 694950397Sobrienadd_data_member_location_attribute (die, decl) 695050397Sobrien register dw_die_ref die; 695150397Sobrien register tree decl; 695250397Sobrien{ 695350397Sobrien register unsigned long offset; 695450397Sobrien register dw_loc_descr_ref loc_descr; 695550397Sobrien register enum dwarf_location_atom op; 695650397Sobrien 695750397Sobrien if (TREE_CODE (decl) == TREE_VEC) 695850397Sobrien offset = TREE_INT_CST_LOW (BINFO_OFFSET (decl)); 695950397Sobrien else 696050397Sobrien offset = field_byte_offset (decl); 696150397Sobrien 696250397Sobrien /* The DWARF2 standard says that we should assume that the structure address 696350397Sobrien is already on the stack, so we can specify a structure field address 696450397Sobrien by using DW_OP_plus_uconst. */ 696550397Sobrien 696650397Sobrien#ifdef MIPS_DEBUGGING_INFO 696750397Sobrien /* ??? The SGI dwarf reader does not handle the DW_OP_plus_uconst operator 696850397Sobrien correctly. It works only if we leave the offset on the stack. */ 696950397Sobrien op = DW_OP_constu; 697050397Sobrien#else 697150397Sobrien op = DW_OP_plus_uconst; 697250397Sobrien#endif 697350397Sobrien 697450397Sobrien loc_descr = new_loc_descr (op, offset, 0); 697550397Sobrien add_AT_loc (die, DW_AT_data_member_location, loc_descr); 697650397Sobrien} 697750397Sobrien 697850397Sobrien/* Attach an DW_AT_const_value attribute for a variable or a parameter which 697950397Sobrien does not have a "location" either in memory or in a register. These 698050397Sobrien things can arise in GNU C when a constant is passed as an actual parameter 698150397Sobrien to an inlined function. They can also arise in C++ where declared 698250397Sobrien constants do not necessarily get memory "homes". */ 698350397Sobrien 698450397Sobrienstatic void 698550397Sobrienadd_const_value_attribute (die, rtl) 698650397Sobrien register dw_die_ref die; 698750397Sobrien register rtx rtl; 698850397Sobrien{ 698950397Sobrien switch (GET_CODE (rtl)) 699050397Sobrien { 699150397Sobrien case CONST_INT: 699250397Sobrien /* Note that a CONST_INT rtx could represent either an integer or a 699350397Sobrien floating-point constant. A CONST_INT is used whenever the constant 699450397Sobrien will fit into a single word. In all such cases, the original mode 699550397Sobrien of the constant value is wiped out, and the CONST_INT rtx is 699650397Sobrien assigned VOIDmode. */ 699750397Sobrien add_AT_unsigned (die, DW_AT_const_value, (unsigned) INTVAL (rtl)); 699850397Sobrien break; 699950397Sobrien 700050397Sobrien case CONST_DOUBLE: 700150397Sobrien /* Note that a CONST_DOUBLE rtx could represent either an integer or a 700250397Sobrien floating-point constant. A CONST_DOUBLE is used whenever the 700350397Sobrien constant requires more than one word in order to be adequately 700450397Sobrien represented. We output CONST_DOUBLEs as blocks. */ 700550397Sobrien { 700650397Sobrien register enum machine_mode mode = GET_MODE (rtl); 700750397Sobrien 700850397Sobrien if (GET_MODE_CLASS (mode) == MODE_FLOAT) 700950397Sobrien { 701050397Sobrien register unsigned length = GET_MODE_SIZE (mode) / sizeof (long); 701150397Sobrien long array[4]; 701250397Sobrien REAL_VALUE_TYPE rv; 701350397Sobrien 701450397Sobrien REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); 701550397Sobrien switch (mode) 701650397Sobrien { 701750397Sobrien case SFmode: 701850397Sobrien REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); 701950397Sobrien break; 702050397Sobrien 702150397Sobrien case DFmode: 702250397Sobrien REAL_VALUE_TO_TARGET_DOUBLE (rv, array); 702350397Sobrien break; 702450397Sobrien 702550397Sobrien case XFmode: 702650397Sobrien case TFmode: 702750397Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); 702850397Sobrien break; 702950397Sobrien 703050397Sobrien default: 703150397Sobrien abort (); 703250397Sobrien } 703350397Sobrien 703450397Sobrien add_AT_float (die, DW_AT_const_value, length, array); 703550397Sobrien } 703650397Sobrien else 703750397Sobrien add_AT_long_long (die, DW_AT_const_value, 703850397Sobrien CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl)); 703950397Sobrien } 704050397Sobrien break; 704150397Sobrien 704250397Sobrien case CONST_STRING: 704350397Sobrien add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); 704450397Sobrien break; 704550397Sobrien 704650397Sobrien case SYMBOL_REF: 704750397Sobrien case LABEL_REF: 704850397Sobrien case CONST: 704950397Sobrien add_AT_addr (die, DW_AT_const_value, addr_to_string (rtl)); 705050397Sobrien break; 705150397Sobrien 705250397Sobrien case PLUS: 705350397Sobrien /* In cases where an inlined instance of an inline function is passed 705450397Sobrien the address of an `auto' variable (which is local to the caller) we 705550397Sobrien can get a situation where the DECL_RTL of the artificial local 705650397Sobrien variable (for the inlining) which acts as a stand-in for the 705750397Sobrien corresponding formal parameter (of the inline function) will look 705850397Sobrien like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not 705950397Sobrien exactly a compile-time constant expression, but it isn't the address 706050397Sobrien of the (artificial) local variable either. Rather, it represents the 706150397Sobrien *value* which the artificial local variable always has during its 706250397Sobrien lifetime. We currently have no way to represent such quasi-constant 706350397Sobrien values in Dwarf, so for now we just punt and generate nothing. */ 706450397Sobrien break; 706550397Sobrien 706650397Sobrien default: 706750397Sobrien /* No other kinds of rtx should be possible here. */ 706850397Sobrien abort (); 706950397Sobrien } 707050397Sobrien 707150397Sobrien} 707250397Sobrien 707350397Sobrien/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value 707450397Sobrien data attribute for a variable or a parameter. We generate the 707550397Sobrien DW_AT_const_value attribute only in those cases where the given variable 707650397Sobrien or parameter does not have a true "location" either in memory or in a 707750397Sobrien register. This can happen (for example) when a constant is passed as an 707850397Sobrien actual argument in a call to an inline function. (It's possible that 707950397Sobrien these things can crop up in other ways also.) Note that one type of 708050397Sobrien constant value which can be passed into an inlined function is a constant 708150397Sobrien pointer. This can happen for example if an actual argument in an inlined 708250397Sobrien function call evaluates to a compile-time constant address. */ 708350397Sobrien 708450397Sobrienstatic void 708550397Sobrienadd_location_or_const_value_attribute (die, decl) 708650397Sobrien register dw_die_ref die; 708750397Sobrien register tree decl; 708850397Sobrien{ 708950397Sobrien register rtx rtl; 709050397Sobrien register tree declared_type; 709150397Sobrien register tree passed_type; 709250397Sobrien 709350397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 709450397Sobrien return; 709550397Sobrien 709650397Sobrien if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != PARM_DECL) 709750397Sobrien abort (); 709850397Sobrien 709950397Sobrien /* Here we have to decide where we are going to say the parameter "lives" 710050397Sobrien (as far as the debugger is concerned). We only have a couple of 710150397Sobrien choices. GCC provides us with DECL_RTL and with DECL_INCOMING_RTL. 710250397Sobrien 710350397Sobrien DECL_RTL normally indicates where the parameter lives during most of the 710450397Sobrien activation of the function. If optimization is enabled however, this 710550397Sobrien could be either NULL or else a pseudo-reg. Both of those cases indicate 710650397Sobrien that the parameter doesn't really live anywhere (as far as the code 710750397Sobrien generation parts of GCC are concerned) during most of the function's 710850397Sobrien activation. That will happen (for example) if the parameter is never 710950397Sobrien referenced within the function. 711050397Sobrien 711150397Sobrien We could just generate a location descriptor here for all non-NULL 711250397Sobrien non-pseudo values of DECL_RTL and ignore all of the rest, but we can be 711350397Sobrien a little nicer than that if we also consider DECL_INCOMING_RTL in cases 711450397Sobrien where DECL_RTL is NULL or is a pseudo-reg. 711550397Sobrien 711650397Sobrien Note however that we can only get away with using DECL_INCOMING_RTL as 711750397Sobrien a backup substitute for DECL_RTL in certain limited cases. In cases 711850397Sobrien where DECL_ARG_TYPE (decl) indicates the same type as TREE_TYPE (decl), 711950397Sobrien we can be sure that the parameter was passed using the same type as it is 712050397Sobrien declared to have within the function, and that its DECL_INCOMING_RTL 712150397Sobrien points us to a place where a value of that type is passed. 712250397Sobrien 712350397Sobrien In cases where DECL_ARG_TYPE (decl) and TREE_TYPE (decl) are different, 712450397Sobrien we cannot (in general) use DECL_INCOMING_RTL as a substitute for DECL_RTL 712550397Sobrien because in these cases DECL_INCOMING_RTL points us to a value of some 712650397Sobrien type which is *different* from the type of the parameter itself. Thus, 712750397Sobrien if we tried to use DECL_INCOMING_RTL to generate a location attribute in 712850397Sobrien such cases, the debugger would end up (for example) trying to fetch a 712950397Sobrien `float' from a place which actually contains the first part of a 713050397Sobrien `double'. That would lead to really incorrect and confusing 713150397Sobrien output at debug-time. 713250397Sobrien 713350397Sobrien So, in general, we *do not* use DECL_INCOMING_RTL as a backup for DECL_RTL 713450397Sobrien in cases where DECL_ARG_TYPE (decl) != TREE_TYPE (decl). There 713550397Sobrien are a couple of exceptions however. On little-endian machines we can 713650397Sobrien get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE (decl) is 713750397Sobrien not the same as TREE_TYPE (decl), but only when DECL_ARG_TYPE (decl) is 713850397Sobrien an integral type that is smaller than TREE_TYPE (decl). These cases arise 713950397Sobrien when (on a little-endian machine) a non-prototyped function has a 714050397Sobrien parameter declared to be of type `short' or `char'. In such cases, 714150397Sobrien TREE_TYPE (decl) will be `short' or `char', DECL_ARG_TYPE (decl) will 714250397Sobrien be `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the 714350397Sobrien passed `int' value. If the debugger then uses that address to fetch 714450397Sobrien a `short' or a `char' (on a little-endian machine) the result will be 714550397Sobrien the correct data, so we allow for such exceptional cases below. 714650397Sobrien 714750397Sobrien Note that our goal here is to describe the place where the given formal 714850397Sobrien parameter lives during most of the function's activation (i.e. between 714950397Sobrien the end of the prologue and the start of the epilogue). We'll do that 715050397Sobrien as best as we can. Note however that if the given formal parameter is 715150397Sobrien modified sometime during the execution of the function, then a stack 715250397Sobrien backtrace (at debug-time) will show the function as having been 715350397Sobrien called with the *new* value rather than the value which was 715450397Sobrien originally passed in. This happens rarely enough that it is not 715550397Sobrien a major problem, but it *is* a problem, and I'd like to fix it. 715650397Sobrien 715750397Sobrien A future version of dwarf2out.c may generate two additional 715850397Sobrien attributes for any given DW_TAG_formal_parameter DIE which will 715950397Sobrien describe the "passed type" and the "passed location" for the 716050397Sobrien given formal parameter in addition to the attributes we now 716150397Sobrien generate to indicate the "declared type" and the "active 716250397Sobrien location" for each parameter. This additional set of attributes 716350397Sobrien could be used by debuggers for stack backtraces. Separately, note 716450397Sobrien that sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL can be 716550397Sobrien NULL also. This happens (for example) for inlined-instances of 716650397Sobrien inline function formal parameters which are never referenced. 716750397Sobrien This really shouldn't be happening. All PARM_DECL nodes should 716850397Sobrien get valid non-NULL DECL_INCOMING_RTL values, but integrate.c 716950397Sobrien doesn't currently generate these values for inlined instances of 717050397Sobrien inline function parameters, so when we see such cases, we are 717150397Sobrien just out-of-luck for the time being (until integrate.c 717250397Sobrien gets fixed). */ 717350397Sobrien 717450397Sobrien /* Use DECL_RTL as the "location" unless we find something better. */ 717550397Sobrien rtl = DECL_RTL (decl); 717650397Sobrien 717750397Sobrien if (TREE_CODE (decl) == PARM_DECL) 717850397Sobrien { 717950397Sobrien if (rtl == NULL_RTX || is_pseudo_reg (rtl)) 718050397Sobrien { 718150397Sobrien declared_type = type_main_variant (TREE_TYPE (decl)); 718250397Sobrien passed_type = type_main_variant (DECL_ARG_TYPE (decl)); 718350397Sobrien 718450397Sobrien /* This decl represents a formal parameter which was optimized out. 718550397Sobrien Note that DECL_INCOMING_RTL may be NULL in here, but we handle 718650397Sobrien all* cases where (rtl == NULL_RTX) just below. */ 718750397Sobrien if (declared_type == passed_type) 718850397Sobrien rtl = DECL_INCOMING_RTL (decl); 718950397Sobrien else if (! BYTES_BIG_ENDIAN 719050397Sobrien && TREE_CODE (declared_type) == INTEGER_TYPE 719152284Sobrien && (GET_MODE_SIZE (TYPE_MODE (declared_type)) 719252284Sobrien <= GET_MODE_SIZE (TYPE_MODE (passed_type)))) 719350397Sobrien rtl = DECL_INCOMING_RTL (decl); 719450397Sobrien } 719552284Sobrien 719652284Sobrien /* If the parm was passed in registers, but lives on the stack, then 719752284Sobrien make a big endian correction if the mode of the type of the 719852284Sobrien parameter is not the same as the mode of the rtl. */ 719952284Sobrien /* ??? This is the same series of checks that are made in dbxout.c before 720052284Sobrien we reach the big endian correction code there. It isn't clear if all 720152284Sobrien of these checks are necessary here, but keeping them all is the safe 720252284Sobrien thing to do. */ 720352284Sobrien else if (GET_CODE (rtl) == MEM 720452284Sobrien && XEXP (rtl, 0) != const0_rtx 720552284Sobrien && ! CONSTANT_P (XEXP (rtl, 0)) 720652284Sobrien /* Not passed in memory. */ 720752284Sobrien && GET_CODE (DECL_INCOMING_RTL (decl)) != MEM 720852284Sobrien /* Not passed by invisible reference. */ 720952284Sobrien && (GET_CODE (XEXP (rtl, 0)) != REG 721052284Sobrien || REGNO (XEXP (rtl, 0)) == HARD_FRAME_POINTER_REGNUM 721152284Sobrien || REGNO (XEXP (rtl, 0)) == STACK_POINTER_REGNUM 721252284Sobrien#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM 721352284Sobrien || REGNO (XEXP (rtl, 0)) == ARG_POINTER_REGNUM 721452284Sobrien#endif 721552284Sobrien ) 721652284Sobrien /* Big endian correction check. */ 721752284Sobrien && BYTES_BIG_ENDIAN 721852284Sobrien && TYPE_MODE (TREE_TYPE (decl)) != GET_MODE (rtl) 721952284Sobrien && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))) 722052284Sobrien < UNITS_PER_WORD)) 722152284Sobrien { 722252284Sobrien int offset = (UNITS_PER_WORD 722352284Sobrien - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))); 722452284Sobrien rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)), 722552284Sobrien plus_constant (XEXP (rtl, 0), offset)); 722652284Sobrien } 722750397Sobrien } 722850397Sobrien 722950397Sobrien if (rtl == NULL_RTX) 723050397Sobrien return; 723150397Sobrien 723250397Sobrien rtl = eliminate_regs (rtl, 0, NULL_RTX); 723350397Sobrien#ifdef LEAF_REG_REMAP 723452284Sobrien if (current_function_uses_only_leaf_regs) 723550397Sobrien leaf_renumber_regs_insn (rtl); 723650397Sobrien#endif 723750397Sobrien 723850397Sobrien switch (GET_CODE (rtl)) 723950397Sobrien { 724050397Sobrien case ADDRESSOF: 724150397Sobrien /* The address of a variable that was optimized away; don't emit 724250397Sobrien anything. */ 724350397Sobrien break; 724450397Sobrien 724550397Sobrien case CONST_INT: 724650397Sobrien case CONST_DOUBLE: 724750397Sobrien case CONST_STRING: 724850397Sobrien case SYMBOL_REF: 724950397Sobrien case LABEL_REF: 725050397Sobrien case CONST: 725150397Sobrien case PLUS: 725250397Sobrien /* DECL_RTL could be (plus (reg ...) (const_int ...)) */ 725350397Sobrien add_const_value_attribute (die, rtl); 725450397Sobrien break; 725550397Sobrien 725650397Sobrien case MEM: 725750397Sobrien case REG: 725850397Sobrien case SUBREG: 725950397Sobrien case CONCAT: 726050397Sobrien add_AT_location_description (die, DW_AT_location, rtl); 726150397Sobrien break; 726250397Sobrien 726350397Sobrien default: 726450397Sobrien abort (); 726550397Sobrien } 726650397Sobrien} 726750397Sobrien 726850397Sobrien/* Generate an DW_AT_name attribute given some string value to be included as 726950397Sobrien the value of the attribute. */ 727050397Sobrien 727150397Sobrienstatic inline void 727250397Sobrienadd_name_attribute (die, name_string) 727350397Sobrien register dw_die_ref die; 727450397Sobrien register char *name_string; 727550397Sobrien{ 727650397Sobrien if (name_string != NULL && *name_string != 0) 727750397Sobrien add_AT_string (die, DW_AT_name, name_string); 727850397Sobrien} 727950397Sobrien 728050397Sobrien/* Given a tree node describing an array bound (either lower or upper) output 728150397Sobrien a representation for that bound. */ 728250397Sobrien 728350397Sobrienstatic void 728450397Sobrienadd_bound_info (subrange_die, bound_attr, bound) 728550397Sobrien register dw_die_ref subrange_die; 728650397Sobrien register enum dwarf_attribute bound_attr; 728750397Sobrien register tree bound; 728850397Sobrien{ 728950397Sobrien register unsigned bound_value = 0; 729050397Sobrien 729150397Sobrien /* If this is an Ada unconstrained array type, then don't emit any debug 729250397Sobrien info because the array bounds are unknown. They are parameterized when 729350397Sobrien the type is instantiated. */ 729450397Sobrien if (contains_placeholder_p (bound)) 729550397Sobrien return; 729650397Sobrien 729750397Sobrien switch (TREE_CODE (bound)) 729850397Sobrien { 729950397Sobrien case ERROR_MARK: 730050397Sobrien return; 730150397Sobrien 730250397Sobrien /* All fixed-bounds are represented by INTEGER_CST nodes. */ 730350397Sobrien case INTEGER_CST: 730450397Sobrien bound_value = TREE_INT_CST_LOW (bound); 730550397Sobrien if (bound_attr == DW_AT_lower_bound 730650397Sobrien && ((is_c_family () && bound_value == 0) 730750397Sobrien || (is_fortran () && bound_value == 1))) 730850397Sobrien /* use the default */; 730950397Sobrien else 731050397Sobrien add_AT_unsigned (subrange_die, bound_attr, bound_value); 731150397Sobrien break; 731250397Sobrien 731350397Sobrien case CONVERT_EXPR: 731450397Sobrien case NOP_EXPR: 731550397Sobrien case NON_LVALUE_EXPR: 731650397Sobrien add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0)); 731750397Sobrien break; 731850397Sobrien 731950397Sobrien case SAVE_EXPR: 732050397Sobrien /* If optimization is turned on, the SAVE_EXPRs that describe how to 732150397Sobrien access the upper bound values may be bogus. If they refer to a 732250397Sobrien register, they may only describe how to get at these values at the 732350397Sobrien points in the generated code right after they have just been 732450397Sobrien computed. Worse yet, in the typical case, the upper bound values 732550397Sobrien will not even *be* computed in the optimized code (though the 732650397Sobrien number of elements will), so these SAVE_EXPRs are entirely 732750397Sobrien bogus. In order to compensate for this fact, we check here to see 732850397Sobrien if optimization is enabled, and if so, we don't add an attribute 732950397Sobrien for the (unknown and unknowable) upper bound. This should not 733050397Sobrien cause too much trouble for existing (stupid?) debuggers because 733150397Sobrien they have to deal with empty upper bounds location descriptions 733250397Sobrien anyway in order to be able to deal with incomplete array types. 733350397Sobrien Of course an intelligent debugger (GDB?) should be able to 733450397Sobrien comprehend that a missing upper bound specification in a array 733550397Sobrien type used for a storage class `auto' local array variable 733650397Sobrien indicates that the upper bound is both unknown (at compile- time) 733750397Sobrien and unknowable (at run-time) due to optimization. 733850397Sobrien 733950397Sobrien We assume that a MEM rtx is safe because gcc wouldn't put the 734050397Sobrien value there unless it was going to be used repeatedly in the 734150397Sobrien function, i.e. for cleanups. */ 734250397Sobrien if (! optimize || GET_CODE (SAVE_EXPR_RTL (bound)) == MEM) 734350397Sobrien { 734450397Sobrien register dw_die_ref ctx = lookup_decl_die (current_function_decl); 734550397Sobrien register dw_die_ref decl_die = new_die (DW_TAG_variable, ctx); 734650397Sobrien register rtx loc = SAVE_EXPR_RTL (bound); 734750397Sobrien 734850397Sobrien /* If the RTL for the SAVE_EXPR is memory, handle the case where 734950397Sobrien it references an outer function's frame. */ 735050397Sobrien 735150397Sobrien if (GET_CODE (loc) == MEM) 735250397Sobrien { 735350397Sobrien rtx new_addr = fix_lexical_addr (XEXP (loc, 0), bound); 735450397Sobrien 735550397Sobrien if (XEXP (loc, 0) != new_addr) 735650397Sobrien loc = gen_rtx (MEM, GET_MODE (loc), new_addr); 735750397Sobrien } 735850397Sobrien 735950397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 736050397Sobrien add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); 736150397Sobrien add_AT_location_description (decl_die, DW_AT_location, loc); 736250397Sobrien add_AT_die_ref (subrange_die, bound_attr, decl_die); 736350397Sobrien } 736450397Sobrien 736550397Sobrien /* Else leave out the attribute. */ 736650397Sobrien break; 736750397Sobrien 736850397Sobrien case MAX_EXPR: 736950397Sobrien case VAR_DECL: 737050397Sobrien case COMPONENT_REF: 737150397Sobrien /* ??? These types of bounds can be created by the Ada front end, 737250397Sobrien and it isn't clear how to emit debug info for them. */ 737350397Sobrien break; 737450397Sobrien 737550397Sobrien default: 737650397Sobrien abort (); 737750397Sobrien } 737850397Sobrien} 737950397Sobrien 738050397Sobrien/* Note that the block of subscript information for an array type also 738150397Sobrien includes information about the element type of type given array type. */ 738250397Sobrien 738350397Sobrienstatic void 738450397Sobrienadd_subscript_info (type_die, type) 738550397Sobrien register dw_die_ref type_die; 738650397Sobrien register tree type; 738750397Sobrien{ 738850397Sobrien#ifndef MIPS_DEBUGGING_INFO 738950397Sobrien register unsigned dimension_number; 739050397Sobrien#endif 739150397Sobrien register tree lower, upper; 739250397Sobrien register dw_die_ref subrange_die; 739350397Sobrien 739450397Sobrien /* The GNU compilers represent multidimensional array types as sequences of 739550397Sobrien one dimensional array types whose element types are themselves array 739650397Sobrien types. Here we squish that down, so that each multidimensional array 739750397Sobrien type gets only one array_type DIE in the Dwarf debugging info. The draft 739850397Sobrien Dwarf specification say that we are allowed to do this kind of 739950397Sobrien compression in C (because there is no difference between an array or 740050397Sobrien arrays and a multidimensional array in C) but for other source languages 740150397Sobrien (e.g. Ada) we probably shouldn't do this. */ 740250397Sobrien 740350397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 740450397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 740550397Sobrien We work around this by disabling this feature. See also 740650397Sobrien gen_array_type_die. */ 740750397Sobrien#ifndef MIPS_DEBUGGING_INFO 740850397Sobrien for (dimension_number = 0; 740950397Sobrien TREE_CODE (type) == ARRAY_TYPE; 741050397Sobrien type = TREE_TYPE (type), dimension_number++) 741150397Sobrien { 741250397Sobrien#endif 741350397Sobrien register tree domain = TYPE_DOMAIN (type); 741450397Sobrien 741550397Sobrien /* Arrays come in three flavors: Unspecified bounds, fixed bounds, 741650397Sobrien and (in GNU C only) variable bounds. Handle all three forms 741750397Sobrien here. */ 741850397Sobrien subrange_die = new_die (DW_TAG_subrange_type, type_die); 741950397Sobrien if (domain) 742050397Sobrien { 742150397Sobrien /* We have an array type with specified bounds. */ 742250397Sobrien lower = TYPE_MIN_VALUE (domain); 742350397Sobrien upper = TYPE_MAX_VALUE (domain); 742450397Sobrien 742550397Sobrien /* define the index type. */ 742650397Sobrien if (TREE_TYPE (domain)) 742750397Sobrien { 742850397Sobrien /* ??? This is probably an Ada unnamed subrange type. Ignore the 742950397Sobrien TREE_TYPE field. We can't emit debug info for this 743050397Sobrien because it is an unnamed integral type. */ 743150397Sobrien if (TREE_CODE (domain) == INTEGER_TYPE 743250397Sobrien && TYPE_NAME (domain) == NULL_TREE 743350397Sobrien && TREE_CODE (TREE_TYPE (domain)) == INTEGER_TYPE 743450397Sobrien && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE) 743550397Sobrien ; 743650397Sobrien else 743750397Sobrien add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0, 743850397Sobrien type_die); 743950397Sobrien } 744050397Sobrien 744150397Sobrien /* ??? If upper is NULL, the array has unspecified length, 744250397Sobrien but it does have a lower bound. This happens with Fortran 744350397Sobrien dimension arr(N:*) 744450397Sobrien Since the debugger is definitely going to need to know N 744550397Sobrien to produce useful results, go ahead and output the lower 744650397Sobrien bound solo, and hope the debugger can cope. */ 744750397Sobrien 744850397Sobrien add_bound_info (subrange_die, DW_AT_lower_bound, lower); 744950397Sobrien if (upper) 745050397Sobrien add_bound_info (subrange_die, DW_AT_upper_bound, upper); 745150397Sobrien } 745250397Sobrien else 745350397Sobrien /* We have an array type with an unspecified length. The DWARF-2 745450397Sobrien spec does not say how to handle this; let's just leave out the 745550397Sobrien bounds. */ 745650397Sobrien {;} 745750397Sobrien 745850397Sobrien 745950397Sobrien#ifndef MIPS_DEBUGGING_INFO 746050397Sobrien } 746150397Sobrien#endif 746250397Sobrien} 746350397Sobrien 746450397Sobrienstatic void 746550397Sobrienadd_byte_size_attribute (die, tree_node) 746650397Sobrien dw_die_ref die; 746750397Sobrien register tree tree_node; 746850397Sobrien{ 746950397Sobrien register unsigned size; 747050397Sobrien 747150397Sobrien switch (TREE_CODE (tree_node)) 747250397Sobrien { 747350397Sobrien case ERROR_MARK: 747450397Sobrien size = 0; 747550397Sobrien break; 747650397Sobrien case ENUMERAL_TYPE: 747750397Sobrien case RECORD_TYPE: 747850397Sobrien case UNION_TYPE: 747950397Sobrien case QUAL_UNION_TYPE: 748050397Sobrien size = int_size_in_bytes (tree_node); 748150397Sobrien break; 748250397Sobrien case FIELD_DECL: 748350397Sobrien /* For a data member of a struct or union, the DW_AT_byte_size is 748450397Sobrien generally given as the number of bytes normally allocated for an 748550397Sobrien object of the *declared* type of the member itself. This is true 748650397Sobrien even for bit-fields. */ 748750397Sobrien size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT; 748850397Sobrien break; 748950397Sobrien default: 749050397Sobrien abort (); 749150397Sobrien } 749250397Sobrien 749350397Sobrien /* Note that `size' might be -1 when we get to this point. If it is, that 749450397Sobrien indicates that the byte size of the entity in question is variable. We 749550397Sobrien have no good way of expressing this fact in Dwarf at the present time, 749650397Sobrien so just let the -1 pass on through. */ 749750397Sobrien 749850397Sobrien add_AT_unsigned (die, DW_AT_byte_size, size); 749950397Sobrien} 750050397Sobrien 750150397Sobrien/* For a FIELD_DECL node which represents a bit-field, output an attribute 750250397Sobrien which specifies the distance in bits from the highest order bit of the 750350397Sobrien "containing object" for the bit-field to the highest order bit of the 750450397Sobrien bit-field itself. 750550397Sobrien 750650397Sobrien For any given bit-field, the "containing object" is a hypothetical 750750397Sobrien object (of some integral or enum type) within which the given bit-field 750850397Sobrien lives. The type of this hypothetical "containing object" is always the 750950397Sobrien same as the declared type of the individual bit-field itself. The 751050397Sobrien determination of the exact location of the "containing object" for a 751150397Sobrien bit-field is rather complicated. It's handled by the 751250397Sobrien `field_byte_offset' function (above). 751350397Sobrien 751450397Sobrien Note that it is the size (in bytes) of the hypothetical "containing object" 751550397Sobrien which will be given in the DW_AT_byte_size attribute for this bit-field. 751650397Sobrien (See `byte_size_attribute' above). */ 751750397Sobrien 751850397Sobrienstatic inline void 751950397Sobrienadd_bit_offset_attribute (die, decl) 752050397Sobrien register dw_die_ref die; 752150397Sobrien register tree decl; 752250397Sobrien{ 752350397Sobrien register unsigned object_offset_in_bytes = field_byte_offset (decl); 752450397Sobrien register tree type = DECL_BIT_FIELD_TYPE (decl); 752550397Sobrien register tree bitpos_tree = DECL_FIELD_BITPOS (decl); 752650397Sobrien register unsigned bitpos_int; 752750397Sobrien register unsigned highest_order_object_bit_offset; 752850397Sobrien register unsigned highest_order_field_bit_offset; 752950397Sobrien register unsigned bit_offset; 753050397Sobrien 753150397Sobrien /* Must be a field and a bit field. */ 753250397Sobrien if (!type 753350397Sobrien || TREE_CODE (decl) != FIELD_DECL) 753450397Sobrien abort (); 753550397Sobrien 753650397Sobrien /* We can't yet handle bit-fields whose offsets are variable, so if we 753750397Sobrien encounter such things, just return without generating any attribute 753850397Sobrien whatsoever. */ 753950397Sobrien if (TREE_CODE (bitpos_tree) != INTEGER_CST) 754050397Sobrien return; 754150397Sobrien 754250397Sobrien bitpos_int = (unsigned) TREE_INT_CST_LOW (bitpos_tree); 754350397Sobrien 754450397Sobrien /* Note that the bit offset is always the distance (in bits) from the 754550397Sobrien highest-order bit of the "containing object" to the highest-order bit of 754650397Sobrien the bit-field itself. Since the "high-order end" of any object or field 754750397Sobrien is different on big-endian and little-endian machines, the computation 754850397Sobrien below must take account of these differences. */ 754950397Sobrien highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT; 755050397Sobrien highest_order_field_bit_offset = bitpos_int; 755150397Sobrien 755250397Sobrien if (! BYTES_BIG_ENDIAN) 755350397Sobrien { 755450397Sobrien highest_order_field_bit_offset 755550397Sobrien += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl)); 755650397Sobrien 755750397Sobrien highest_order_object_bit_offset += simple_type_size_in_bits (type); 755850397Sobrien } 755950397Sobrien 756050397Sobrien bit_offset 756150397Sobrien = (! BYTES_BIG_ENDIAN 756250397Sobrien ? highest_order_object_bit_offset - highest_order_field_bit_offset 756350397Sobrien : highest_order_field_bit_offset - highest_order_object_bit_offset); 756450397Sobrien 756550397Sobrien add_AT_unsigned (die, DW_AT_bit_offset, bit_offset); 756650397Sobrien} 756750397Sobrien 756850397Sobrien/* For a FIELD_DECL node which represents a bit field, output an attribute 756950397Sobrien which specifies the length in bits of the given field. */ 757050397Sobrien 757150397Sobrienstatic inline void 757250397Sobrienadd_bit_size_attribute (die, decl) 757350397Sobrien register dw_die_ref die; 757450397Sobrien register tree decl; 757550397Sobrien{ 757650397Sobrien /* Must be a field and a bit field. */ 757750397Sobrien if (TREE_CODE (decl) != FIELD_DECL 757850397Sobrien || ! DECL_BIT_FIELD_TYPE (decl)) 757950397Sobrien abort (); 758050397Sobrien add_AT_unsigned (die, DW_AT_bit_size, 758150397Sobrien (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl))); 758250397Sobrien} 758350397Sobrien 758450397Sobrien/* If the compiled language is ANSI C, then add a 'prototyped' 758550397Sobrien attribute, if arg types are given for the parameters of a function. */ 758650397Sobrien 758750397Sobrienstatic inline void 758850397Sobrienadd_prototyped_attribute (die, func_type) 758950397Sobrien register dw_die_ref die; 759050397Sobrien register tree func_type; 759150397Sobrien{ 759250397Sobrien if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 759350397Sobrien && TYPE_ARG_TYPES (func_type) != NULL) 759450397Sobrien add_AT_flag (die, DW_AT_prototyped, 1); 759550397Sobrien} 759650397Sobrien 759750397Sobrien 759850397Sobrien/* Add an 'abstract_origin' attribute below a given DIE. The DIE is found 759950397Sobrien by looking in either the type declaration or object declaration 760050397Sobrien equate table. */ 760150397Sobrien 760250397Sobrienstatic inline void 760350397Sobrienadd_abstract_origin_attribute (die, origin) 760450397Sobrien register dw_die_ref die; 760550397Sobrien register tree origin; 760650397Sobrien{ 760750397Sobrien dw_die_ref origin_die = NULL; 760850397Sobrien if (TREE_CODE_CLASS (TREE_CODE (origin)) == 'd') 760950397Sobrien origin_die = lookup_decl_die (origin); 761050397Sobrien else if (TREE_CODE_CLASS (TREE_CODE (origin)) == 't') 761150397Sobrien origin_die = lookup_type_die (origin); 761250397Sobrien 761350397Sobrien add_AT_die_ref (die, DW_AT_abstract_origin, origin_die); 761450397Sobrien} 761550397Sobrien 761650397Sobrien/* We do not currently support the pure_virtual attribute. */ 761750397Sobrien 761850397Sobrienstatic inline void 761950397Sobrienadd_pure_or_virtual_attribute (die, func_decl) 762050397Sobrien register dw_die_ref die; 762150397Sobrien register tree func_decl; 762250397Sobrien{ 762350397Sobrien if (DECL_VINDEX (func_decl)) 762450397Sobrien { 762550397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 762650397Sobrien add_AT_loc (die, DW_AT_vtable_elem_location, 762750397Sobrien new_loc_descr (DW_OP_constu, 762850397Sobrien TREE_INT_CST_LOW (DECL_VINDEX (func_decl)), 762950397Sobrien 0)); 763050397Sobrien 763150397Sobrien /* GNU extension: Record what type this method came from originally. */ 763250397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 763350397Sobrien add_AT_die_ref (die, DW_AT_containing_type, 763450397Sobrien lookup_type_die (DECL_CONTEXT (func_decl))); 763550397Sobrien } 763650397Sobrien} 763750397Sobrien 763850397Sobrien/* Add source coordinate attributes for the given decl. */ 763950397Sobrien 764050397Sobrienstatic void 764150397Sobrienadd_src_coords_attributes (die, decl) 764250397Sobrien register dw_die_ref die; 764350397Sobrien register tree decl; 764450397Sobrien{ 764550397Sobrien register unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); 764650397Sobrien 764750397Sobrien add_AT_unsigned (die, DW_AT_decl_file, file_index); 764850397Sobrien add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 764950397Sobrien} 765050397Sobrien 765150397Sobrien/* Add an DW_AT_name attribute and source coordinate attribute for the 765250397Sobrien given decl, but only if it actually has a name. */ 765350397Sobrien 765450397Sobrienstatic void 765550397Sobrienadd_name_and_src_coords_attributes (die, decl) 765650397Sobrien register dw_die_ref die; 765750397Sobrien register tree decl; 765850397Sobrien{ 765950397Sobrien register tree decl_name; 766050397Sobrien 766150397Sobrien decl_name = DECL_NAME (decl); 766250397Sobrien if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) 766350397Sobrien { 766450397Sobrien add_name_attribute (die, dwarf2_name (decl, 0)); 766550397Sobrien add_src_coords_attributes (die, decl); 766650397Sobrien if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) 766750397Sobrien && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)) 766850397Sobrien add_AT_string (die, DW_AT_MIPS_linkage_name, 766950397Sobrien IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 767050397Sobrien } 767150397Sobrien} 767250397Sobrien 767350397Sobrien/* Push a new declaration scope. */ 767450397Sobrien 767550397Sobrienstatic void 767650397Sobrienpush_decl_scope (scope) 767750397Sobrien tree scope; 767850397Sobrien{ 767950397Sobrien tree containing_scope; 768050397Sobrien int i; 768150397Sobrien 768250397Sobrien /* Make room in the decl_scope_table, if necessary. */ 768350397Sobrien if (decl_scope_table_allocated == decl_scope_depth) 768450397Sobrien { 768550397Sobrien decl_scope_table_allocated += DECL_SCOPE_TABLE_INCREMENT; 768650397Sobrien decl_scope_table 768750397Sobrien = (decl_scope_node *) xrealloc (decl_scope_table, 768850397Sobrien (decl_scope_table_allocated 768950397Sobrien * sizeof (decl_scope_node))); 769050397Sobrien } 769150397Sobrien 769250397Sobrien decl_scope_table[decl_scope_depth].scope = scope; 769350397Sobrien 769450397Sobrien /* Sometimes, while recursively emitting subtypes within a class type, 769550397Sobrien we end up recuring on a subtype at a higher level then the current 769650397Sobrien subtype. In such a case, we need to search the decl_scope_table to 769750397Sobrien find the parent of this subtype. */ 769850397Sobrien 769952284Sobrien if (AGGREGATE_TYPE_P (scope)) 770050397Sobrien containing_scope = TYPE_CONTEXT (scope); 770150397Sobrien else 770250397Sobrien containing_scope = NULL_TREE; 770350397Sobrien 770450397Sobrien /* The normal case. */ 770550397Sobrien if (decl_scope_depth == 0 770650397Sobrien || containing_scope == NULL_TREE 770750397Sobrien /* Ignore namespaces for the moment. */ 770850397Sobrien || TREE_CODE (containing_scope) == NAMESPACE_DECL 770950397Sobrien || containing_scope == decl_scope_table[decl_scope_depth - 1].scope) 771050397Sobrien decl_scope_table[decl_scope_depth].previous = decl_scope_depth - 1; 771150397Sobrien else 771250397Sobrien { 771350397Sobrien /* We need to search for the containing_scope. */ 771450397Sobrien for (i = 0; i < decl_scope_depth; i++) 771550397Sobrien if (decl_scope_table[i].scope == containing_scope) 771650397Sobrien break; 771750397Sobrien 771850397Sobrien if (i == decl_scope_depth) 771950397Sobrien abort (); 772050397Sobrien else 772150397Sobrien decl_scope_table[decl_scope_depth].previous = i; 772250397Sobrien } 772350397Sobrien 772450397Sobrien decl_scope_depth++; 772550397Sobrien} 772650397Sobrien 772750397Sobrien/* Return the DIE for the scope that immediately contains this declaration. */ 772850397Sobrien 772950397Sobrienstatic dw_die_ref 773050397Sobrienscope_die_for (t, context_die) 773150397Sobrien register tree t; 773250397Sobrien register dw_die_ref context_die; 773350397Sobrien{ 773450397Sobrien register dw_die_ref scope_die = NULL; 773550397Sobrien register tree containing_scope; 773650397Sobrien register int i; 773750397Sobrien 773850397Sobrien /* Walk back up the declaration tree looking for a place to define 773950397Sobrien this type. */ 774050397Sobrien if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') 774150397Sobrien containing_scope = TYPE_CONTEXT (t); 774250397Sobrien else if (TREE_CODE (t) == FUNCTION_DECL && DECL_VINDEX (t)) 774350397Sobrien containing_scope = decl_class_context (t); 774450397Sobrien else 774550397Sobrien containing_scope = DECL_CONTEXT (t); 774650397Sobrien 774750397Sobrien /* Ignore namespaces for the moment. */ 774850397Sobrien if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL) 774950397Sobrien containing_scope = NULL_TREE; 775050397Sobrien 775152284Sobrien /* Ignore function type "scopes" from the C frontend. They mean that 775252284Sobrien a tagged type is local to a parmlist of a function declarator, but 775352284Sobrien that isn't useful to DWARF. */ 775452284Sobrien if (containing_scope && TREE_CODE (containing_scope) == FUNCTION_TYPE) 775552284Sobrien containing_scope = NULL_TREE; 775652284Sobrien 775750397Sobrien /* Function-local tags and functions get stuck in limbo until they are 775850397Sobrien fixed up by decls_for_scope. */ 775950397Sobrien if (context_die == NULL && containing_scope != NULL_TREE 776050397Sobrien && (TREE_CODE (t) == FUNCTION_DECL || is_tagged_type (t))) 776150397Sobrien return NULL; 776250397Sobrien 776350397Sobrien if (containing_scope == NULL_TREE) 776450397Sobrien scope_die = comp_unit_die; 776550397Sobrien else 776650397Sobrien { 776750397Sobrien for (i = decl_scope_depth - 1, scope_die = context_die; 776850397Sobrien i >= 0 && decl_scope_table[i].scope != containing_scope; 776950397Sobrien (scope_die = scope_die->die_parent, 777050397Sobrien i = decl_scope_table[i].previous)) 777150397Sobrien ; 777250397Sobrien 777350397Sobrien /* ??? Integrate_decl_tree does not handle BLOCK_TYPE_TAGS, nor 777450397Sobrien does it try to handle types defined by TYPE_DECLs. Such types 777550397Sobrien thus have an incorrect TYPE_CONTEXT, which points to the block 777650397Sobrien they were originally defined in, instead of the current block 777750397Sobrien created by function inlining. We try to detect that here and 777850397Sobrien work around it. */ 777950397Sobrien 778050397Sobrien if (i < 0 && scope_die == comp_unit_die 778150397Sobrien && TREE_CODE (containing_scope) == BLOCK 778250397Sobrien && is_tagged_type (t) 778350397Sobrien && (block_ultimate_origin (decl_scope_table[decl_scope_depth - 1].scope) 778450397Sobrien == containing_scope)) 778550397Sobrien { 778650397Sobrien scope_die = context_die; 778750397Sobrien /* Since the checks below are no longer applicable. */ 778850397Sobrien i = 0; 778950397Sobrien } 779050397Sobrien 779150397Sobrien if (i < 0) 779250397Sobrien { 779352284Sobrien if (TREE_CODE_CLASS (TREE_CODE (containing_scope)) != 't') 779450397Sobrien abort (); 779550397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE 779650397Sobrien && !TREE_ASM_WRITTEN (containing_scope)) 779750397Sobrien abort (); 779852284Sobrien 779952284Sobrien /* If none of the current dies are suitable, we get file scope. */ 780052284Sobrien scope_die = comp_unit_die; 780150397Sobrien } 780250397Sobrien } 780350397Sobrien 780450397Sobrien return scope_die; 780550397Sobrien} 780650397Sobrien 780750397Sobrien/* Pop a declaration scope. */ 780850397Sobrienstatic inline void 780950397Sobrienpop_decl_scope () 781050397Sobrien{ 781150397Sobrien if (decl_scope_depth <= 0) 781250397Sobrien abort (); 781350397Sobrien --decl_scope_depth; 781450397Sobrien} 781550397Sobrien 781650397Sobrien/* Many forms of DIEs require a "type description" attribute. This 781750397Sobrien routine locates the proper "type descriptor" die for the type given 781850397Sobrien by 'type', and adds an DW_AT_type attribute below the given die. */ 781950397Sobrien 782050397Sobrienstatic void 782150397Sobrienadd_type_attribute (object_die, type, decl_const, decl_volatile, context_die) 782250397Sobrien register dw_die_ref object_die; 782350397Sobrien register tree type; 782450397Sobrien register int decl_const; 782550397Sobrien register int decl_volatile; 782650397Sobrien register dw_die_ref context_die; 782750397Sobrien{ 782850397Sobrien register enum tree_code code = TREE_CODE (type); 782950397Sobrien register dw_die_ref type_die = NULL; 783050397Sobrien 783150397Sobrien /* ??? If this type is an unnamed subrange type of an integral or 783250397Sobrien floating-point type, use the inner type. This is because we have no 783350397Sobrien support for unnamed types in base_type_die. This can happen if this is 783450397Sobrien an Ada subrange type. Correct solution is emit a subrange type die. */ 783550397Sobrien if ((code == INTEGER_TYPE || code == REAL_TYPE) 783650397Sobrien && TREE_TYPE (type) != 0 && TYPE_NAME (type) == 0) 783750397Sobrien type = TREE_TYPE (type), code = TREE_CODE (type); 783850397Sobrien 783950397Sobrien if (code == ERROR_MARK) 784050397Sobrien return; 784150397Sobrien 784250397Sobrien /* Handle a special case. For functions whose return type is void, we 784350397Sobrien generate *no* type attribute. (Note that no object may have type 784450397Sobrien `void', so this only applies to function return types). */ 784550397Sobrien if (code == VOID_TYPE) 784650397Sobrien return; 784750397Sobrien 784850397Sobrien type_die = modified_type_die (type, 784950397Sobrien decl_const || TYPE_READONLY (type), 785050397Sobrien decl_volatile || TYPE_VOLATILE (type), 785150397Sobrien context_die); 785250397Sobrien if (type_die != NULL) 785350397Sobrien add_AT_die_ref (object_die, DW_AT_type, type_die); 785450397Sobrien} 785550397Sobrien 785650397Sobrien/* Given a tree pointer to a struct, class, union, or enum type node, return 785750397Sobrien a pointer to the (string) tag name for the given type, or zero if the type 785850397Sobrien was declared without a tag. */ 785950397Sobrien 786050397Sobrienstatic char * 786150397Sobrientype_tag (type) 786250397Sobrien register tree type; 786350397Sobrien{ 786450397Sobrien register char *name = 0; 786550397Sobrien 786650397Sobrien if (TYPE_NAME (type) != 0) 786750397Sobrien { 786850397Sobrien register tree t = 0; 786950397Sobrien 787050397Sobrien /* Find the IDENTIFIER_NODE for the type name. */ 787150397Sobrien if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 787250397Sobrien t = TYPE_NAME (type); 787350397Sobrien 787450397Sobrien /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 787550397Sobrien a TYPE_DECL node, regardless of whether or not a `typedef' was 787650397Sobrien involved. */ 787750397Sobrien else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 787850397Sobrien && ! DECL_IGNORED_P (TYPE_NAME (type))) 787950397Sobrien t = DECL_NAME (TYPE_NAME (type)); 788050397Sobrien 788150397Sobrien /* Now get the name as a string, or invent one. */ 788250397Sobrien if (t != 0) 788350397Sobrien name = IDENTIFIER_POINTER (t); 788450397Sobrien } 788550397Sobrien 788650397Sobrien return (name == 0 || *name == '\0') ? 0 : name; 788750397Sobrien} 788850397Sobrien 788950397Sobrien/* Return the type associated with a data member, make a special check 789050397Sobrien for bit field types. */ 789150397Sobrien 789250397Sobrienstatic inline tree 789350397Sobrienmember_declared_type (member) 789450397Sobrien register tree member; 789550397Sobrien{ 789650397Sobrien return (DECL_BIT_FIELD_TYPE (member) 789750397Sobrien ? DECL_BIT_FIELD_TYPE (member) 789850397Sobrien : TREE_TYPE (member)); 789950397Sobrien} 790050397Sobrien 790150397Sobrien/* Get the decl's label, as described by its RTL. This may be different 790250397Sobrien from the DECL_NAME name used in the source file. */ 790350397Sobrien 790450397Sobrien#if 0 790550397Sobrienstatic char * 790650397Sobriendecl_start_label (decl) 790750397Sobrien register tree decl; 790850397Sobrien{ 790950397Sobrien rtx x; 791050397Sobrien char *fnname; 791150397Sobrien x = DECL_RTL (decl); 791250397Sobrien if (GET_CODE (x) != MEM) 791350397Sobrien abort (); 791450397Sobrien 791550397Sobrien x = XEXP (x, 0); 791650397Sobrien if (GET_CODE (x) != SYMBOL_REF) 791750397Sobrien abort (); 791850397Sobrien 791950397Sobrien fnname = XSTR (x, 0); 792050397Sobrien return fnname; 792150397Sobrien} 792250397Sobrien#endif 792350397Sobrien 792450397Sobrien/* These routines generate the internal representation of the DIE's for 792550397Sobrien the compilation unit. Debugging information is collected by walking 792650397Sobrien the declaration trees passed in from dwarf2out_decl(). */ 792750397Sobrien 792850397Sobrienstatic void 792950397Sobriengen_array_type_die (type, context_die) 793050397Sobrien register tree type; 793150397Sobrien register dw_die_ref context_die; 793250397Sobrien{ 793350397Sobrien register dw_die_ref scope_die = scope_die_for (type, context_die); 793450397Sobrien register dw_die_ref array_die; 793550397Sobrien register tree element_type; 793650397Sobrien 793750397Sobrien /* ??? The SGI dwarf reader fails for array of array of enum types unless 793850397Sobrien the inner array type comes before the outer array type. Thus we must 793950397Sobrien call gen_type_die before we call new_die. See below also. */ 794050397Sobrien#ifdef MIPS_DEBUGGING_INFO 794150397Sobrien gen_type_die (TREE_TYPE (type), context_die); 794250397Sobrien#endif 794350397Sobrien 794450397Sobrien array_die = new_die (DW_TAG_array_type, scope_die); 794550397Sobrien 794650397Sobrien#if 0 794750397Sobrien /* We default the array ordering. SDB will probably do 794850397Sobrien the right things even if DW_AT_ordering is not present. It's not even 794950397Sobrien an issue until we start to get into multidimensional arrays anyway. If 795050397Sobrien SDB is ever caught doing the Wrong Thing for multi-dimensional arrays, 795150397Sobrien then we'll have to put the DW_AT_ordering attribute back in. (But if 795250397Sobrien and when we find out that we need to put these in, we will only do so 795350397Sobrien for multidimensional arrays. */ 795450397Sobrien add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major); 795550397Sobrien#endif 795650397Sobrien 795750397Sobrien#ifdef MIPS_DEBUGGING_INFO 795850397Sobrien /* The SGI compilers handle arrays of unknown bound by setting 795950397Sobrien AT_declaration and not emitting any subrange DIEs. */ 796050397Sobrien if (! TYPE_DOMAIN (type)) 796150397Sobrien add_AT_unsigned (array_die, DW_AT_declaration, 1); 796250397Sobrien else 796350397Sobrien#endif 796450397Sobrien add_subscript_info (array_die, type); 796550397Sobrien 796650397Sobrien equate_type_number_to_die (type, array_die); 796750397Sobrien 796850397Sobrien /* Add representation of the type of the elements of this array type. */ 796950397Sobrien element_type = TREE_TYPE (type); 797050397Sobrien 797150397Sobrien /* ??? The SGI dwarf reader fails for multidimensional arrays with a 797250397Sobrien const enum type. E.g. const enum machine_mode insn_operand_mode[2][10]. 797350397Sobrien We work around this by disabling this feature. See also 797450397Sobrien add_subscript_info. */ 797550397Sobrien#ifndef MIPS_DEBUGGING_INFO 797650397Sobrien while (TREE_CODE (element_type) == ARRAY_TYPE) 797750397Sobrien element_type = TREE_TYPE (element_type); 797850397Sobrien 797950397Sobrien gen_type_die (element_type, context_die); 798050397Sobrien#endif 798150397Sobrien 798250397Sobrien add_type_attribute (array_die, element_type, 0, 0, context_die); 798350397Sobrien} 798450397Sobrien 798550397Sobrienstatic void 798650397Sobriengen_set_type_die (type, context_die) 798750397Sobrien register tree type; 798850397Sobrien register dw_die_ref context_die; 798950397Sobrien{ 799050397Sobrien register dw_die_ref type_die 799150397Sobrien = new_die (DW_TAG_set_type, scope_die_for (type, context_die)); 799250397Sobrien 799350397Sobrien equate_type_number_to_die (type, type_die); 799450397Sobrien add_type_attribute (type_die, TREE_TYPE (type), 0, 0, context_die); 799550397Sobrien} 799650397Sobrien 799750397Sobrien#if 0 799850397Sobrienstatic void 799950397Sobriengen_entry_point_die (decl, context_die) 800050397Sobrien register tree decl; 800150397Sobrien register dw_die_ref context_die; 800250397Sobrien{ 800350397Sobrien register tree origin = decl_ultimate_origin (decl); 800450397Sobrien register dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die); 800550397Sobrien if (origin != NULL) 800650397Sobrien add_abstract_origin_attribute (decl_die, origin); 800750397Sobrien else 800850397Sobrien { 800950397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 801050397Sobrien add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)), 801150397Sobrien 0, 0, context_die); 801250397Sobrien } 801350397Sobrien 801450397Sobrien if (DECL_ABSTRACT (decl)) 801550397Sobrien equate_decl_number_to_die (decl, decl_die); 801650397Sobrien else 801750397Sobrien add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl)); 801850397Sobrien} 801950397Sobrien#endif 802050397Sobrien 802150397Sobrien/* Remember a type in the pending_types_list. */ 802250397Sobrien 802350397Sobrienstatic void 802450397Sobrienpend_type (type) 802550397Sobrien register tree type; 802650397Sobrien{ 802750397Sobrien if (pending_types == pending_types_allocated) 802850397Sobrien { 802950397Sobrien pending_types_allocated += PENDING_TYPES_INCREMENT; 803050397Sobrien pending_types_list 803150397Sobrien = (tree *) xrealloc (pending_types_list, 803250397Sobrien sizeof (tree) * pending_types_allocated); 803350397Sobrien } 803450397Sobrien 803550397Sobrien pending_types_list[pending_types++] = type; 803650397Sobrien} 803750397Sobrien 803850397Sobrien/* Output any pending types (from the pending_types list) which we can output 803950397Sobrien now (taking into account the scope that we are working on now). 804050397Sobrien 804150397Sobrien For each type output, remove the given type from the pending_types_list 804250397Sobrien *before* we try to output it. */ 804350397Sobrien 804450397Sobrienstatic void 804550397Sobrienoutput_pending_types_for_scope (context_die) 804650397Sobrien register dw_die_ref context_die; 804750397Sobrien{ 804850397Sobrien register tree type; 804950397Sobrien 805050397Sobrien while (pending_types) 805150397Sobrien { 805250397Sobrien --pending_types; 805350397Sobrien type = pending_types_list[pending_types]; 805450397Sobrien gen_type_die (type, context_die); 805550397Sobrien if (!TREE_ASM_WRITTEN (type)) 805650397Sobrien abort (); 805750397Sobrien } 805850397Sobrien} 805950397Sobrien 806052284Sobrien/* Remember a type in the incomplete_types_list. */ 806152284Sobrien 806252284Sobrienstatic void 806352284Sobrienadd_incomplete_type (type) 806452284Sobrien tree type; 806552284Sobrien{ 806652284Sobrien if (incomplete_types == incomplete_types_allocated) 806752284Sobrien { 806852284Sobrien incomplete_types_allocated += INCOMPLETE_TYPES_INCREMENT; 806952284Sobrien incomplete_types_list 807052284Sobrien = (tree *) xrealloc (incomplete_types_list, 807152284Sobrien sizeof (tree) * incomplete_types_allocated); 807252284Sobrien } 807352284Sobrien 807452284Sobrien incomplete_types_list[incomplete_types++] = type; 807552284Sobrien} 807652284Sobrien 807752284Sobrien/* Walk through the list of incomplete types again, trying once more to 807852284Sobrien emit full debugging info for them. */ 807952284Sobrien 808052284Sobrienstatic void 808152284Sobrienretry_incomplete_types () 808252284Sobrien{ 808352284Sobrien register tree type; 808452284Sobrien 808552284Sobrien while (incomplete_types) 808652284Sobrien { 808752284Sobrien --incomplete_types; 808852284Sobrien type = incomplete_types_list[incomplete_types]; 808952284Sobrien gen_type_die (type, comp_unit_die); 809052284Sobrien } 809152284Sobrien} 809252284Sobrien 809350397Sobrien/* Generate a DIE to represent an inlined instance of an enumeration type. */ 809450397Sobrien 809550397Sobrienstatic void 809650397Sobriengen_inlined_enumeration_type_die (type, context_die) 809750397Sobrien register tree type; 809850397Sobrien register dw_die_ref context_die; 809950397Sobrien{ 810050397Sobrien register dw_die_ref type_die = new_die (DW_TAG_enumeration_type, 810150397Sobrien scope_die_for (type, context_die)); 810250397Sobrien 810350397Sobrien if (!TREE_ASM_WRITTEN (type)) 810450397Sobrien abort (); 810550397Sobrien add_abstract_origin_attribute (type_die, type); 810650397Sobrien} 810750397Sobrien 810850397Sobrien/* Generate a DIE to represent an inlined instance of a structure type. */ 810950397Sobrien 811050397Sobrienstatic void 811150397Sobriengen_inlined_structure_type_die (type, context_die) 811250397Sobrien register tree type; 811350397Sobrien register dw_die_ref context_die; 811450397Sobrien{ 811550397Sobrien register dw_die_ref type_die = new_die (DW_TAG_structure_type, 811650397Sobrien scope_die_for (type, context_die)); 811750397Sobrien 811850397Sobrien if (!TREE_ASM_WRITTEN (type)) 811950397Sobrien abort (); 812050397Sobrien add_abstract_origin_attribute (type_die, type); 812150397Sobrien} 812250397Sobrien 812350397Sobrien/* Generate a DIE to represent an inlined instance of a union type. */ 812450397Sobrien 812550397Sobrienstatic void 812650397Sobriengen_inlined_union_type_die (type, context_die) 812750397Sobrien register tree type; 812850397Sobrien register dw_die_ref context_die; 812950397Sobrien{ 813050397Sobrien register dw_die_ref type_die = new_die (DW_TAG_union_type, 813150397Sobrien scope_die_for (type, context_die)); 813250397Sobrien 813350397Sobrien if (!TREE_ASM_WRITTEN (type)) 813450397Sobrien abort (); 813550397Sobrien add_abstract_origin_attribute (type_die, type); 813650397Sobrien} 813750397Sobrien 813850397Sobrien/* Generate a DIE to represent an enumeration type. Note that these DIEs 813950397Sobrien include all of the information about the enumeration values also. Each 814050397Sobrien enumerated type name/value is listed as a child of the enumerated type 814150397Sobrien DIE. */ 814250397Sobrien 814350397Sobrienstatic void 814450397Sobriengen_enumeration_type_die (type, context_die) 814550397Sobrien register tree type; 814650397Sobrien register dw_die_ref context_die; 814750397Sobrien{ 814850397Sobrien register dw_die_ref type_die = lookup_type_die (type); 814950397Sobrien 815050397Sobrien if (type_die == NULL) 815150397Sobrien { 815250397Sobrien type_die = new_die (DW_TAG_enumeration_type, 815350397Sobrien scope_die_for (type, context_die)); 815450397Sobrien equate_type_number_to_die (type, type_die); 815550397Sobrien add_name_attribute (type_die, type_tag (type)); 815650397Sobrien } 815750397Sobrien else if (! TYPE_SIZE (type)) 815850397Sobrien return; 815950397Sobrien else 816050397Sobrien remove_AT (type_die, DW_AT_declaration); 816150397Sobrien 816250397Sobrien /* Handle a GNU C/C++ extension, i.e. incomplete enum types. If the 816350397Sobrien given enum type is incomplete, do not generate the DW_AT_byte_size 816450397Sobrien attribute or the DW_AT_element_list attribute. */ 816550397Sobrien if (TYPE_SIZE (type)) 816650397Sobrien { 816750397Sobrien register tree link; 816850397Sobrien 816950397Sobrien TREE_ASM_WRITTEN (type) = 1; 817050397Sobrien add_byte_size_attribute (type_die, type); 817150397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 817250397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 817350397Sobrien 817450397Sobrien /* If the first reference to this type was as the return type of an 817550397Sobrien inline function, then it may not have a parent. Fix this now. */ 817650397Sobrien if (type_die->die_parent == NULL) 817750397Sobrien add_child_die (scope_die_for (type, context_die), type_die); 817850397Sobrien 817950397Sobrien for (link = TYPE_FIELDS (type); 818050397Sobrien link != NULL; link = TREE_CHAIN (link)) 818150397Sobrien { 818250397Sobrien register dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die); 818350397Sobrien 818450397Sobrien add_name_attribute (enum_die, 818550397Sobrien IDENTIFIER_POINTER (TREE_PURPOSE (link))); 818650397Sobrien add_AT_unsigned (enum_die, DW_AT_const_value, 818750397Sobrien (unsigned) TREE_INT_CST_LOW (TREE_VALUE (link))); 818850397Sobrien } 818950397Sobrien } 819050397Sobrien else 819150397Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 819250397Sobrien} 819350397Sobrien 819450397Sobrien 819550397Sobrien/* Generate a DIE to represent either a real live formal parameter decl or to 819650397Sobrien represent just the type of some formal parameter position in some function 819750397Sobrien type. 819850397Sobrien 819950397Sobrien Note that this routine is a bit unusual because its argument may be a 820050397Sobrien ..._DECL node (i.e. either a PARM_DECL or perhaps a VAR_DECL which 820150397Sobrien represents an inlining of some PARM_DECL) or else some sort of a ..._TYPE 820250397Sobrien node. If it's the former then this function is being called to output a 820350397Sobrien DIE to represent a formal parameter object (or some inlining thereof). If 820450397Sobrien it's the latter, then this function is only being called to output a 820550397Sobrien DW_TAG_formal_parameter DIE to stand as a placeholder for some formal 820650397Sobrien argument type of some subprogram type. */ 820750397Sobrien 820850397Sobrienstatic dw_die_ref 820950397Sobriengen_formal_parameter_die (node, context_die) 821050397Sobrien register tree node; 821150397Sobrien register dw_die_ref context_die; 821250397Sobrien{ 821350397Sobrien register dw_die_ref parm_die 821450397Sobrien = new_die (DW_TAG_formal_parameter, context_die); 821550397Sobrien register tree origin; 821650397Sobrien 821750397Sobrien switch (TREE_CODE_CLASS (TREE_CODE (node))) 821850397Sobrien { 821950397Sobrien case 'd': 822050397Sobrien origin = decl_ultimate_origin (node); 822150397Sobrien if (origin != NULL) 822250397Sobrien add_abstract_origin_attribute (parm_die, origin); 822350397Sobrien else 822450397Sobrien { 822550397Sobrien add_name_and_src_coords_attributes (parm_die, node); 822650397Sobrien add_type_attribute (parm_die, TREE_TYPE (node), 822750397Sobrien TREE_READONLY (node), 822850397Sobrien TREE_THIS_VOLATILE (node), 822950397Sobrien context_die); 823050397Sobrien if (DECL_ARTIFICIAL (node)) 823150397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 823250397Sobrien } 823350397Sobrien 823450397Sobrien equate_decl_number_to_die (node, parm_die); 823550397Sobrien if (! DECL_ABSTRACT (node)) 823650397Sobrien add_location_or_const_value_attribute (parm_die, node); 823750397Sobrien 823850397Sobrien break; 823950397Sobrien 824050397Sobrien case 't': 824150397Sobrien /* We were called with some kind of a ..._TYPE node. */ 824250397Sobrien add_type_attribute (parm_die, node, 0, 0, context_die); 824350397Sobrien break; 824450397Sobrien 824550397Sobrien default: 824650397Sobrien abort (); 824750397Sobrien } 824850397Sobrien 824950397Sobrien return parm_die; 825050397Sobrien} 825150397Sobrien 825250397Sobrien/* Generate a special type of DIE used as a stand-in for a trailing ellipsis 825350397Sobrien at the end of an (ANSI prototyped) formal parameters list. */ 825450397Sobrien 825550397Sobrienstatic void 825650397Sobriengen_unspecified_parameters_die (decl_or_type, context_die) 825750397Sobrien register tree decl_or_type; 825850397Sobrien register dw_die_ref context_die; 825950397Sobrien{ 826050397Sobrien new_die (DW_TAG_unspecified_parameters, context_die); 826150397Sobrien} 826250397Sobrien 826350397Sobrien/* Generate a list of nameless DW_TAG_formal_parameter DIEs (and perhaps a 826450397Sobrien DW_TAG_unspecified_parameters DIE) to represent the types of the formal 826550397Sobrien parameters as specified in some function type specification (except for 826650397Sobrien those which appear as part of a function *definition*). 826750397Sobrien 826850397Sobrien Note we must be careful here to output all of the parameter DIEs before* 826950397Sobrien we output any DIEs needed to represent the types of the formal parameters. 827050397Sobrien This keeps svr4 SDB happy because it (incorrectly) thinks that the first 827150397Sobrien non-parameter DIE it sees ends the formal parameter list. */ 827250397Sobrien 827350397Sobrienstatic void 827450397Sobriengen_formal_types_die (function_or_method_type, context_die) 827550397Sobrien register tree function_or_method_type; 827650397Sobrien register dw_die_ref context_die; 827750397Sobrien{ 827850397Sobrien register tree link; 827950397Sobrien register tree formal_type = NULL; 828050397Sobrien register tree first_parm_type = TYPE_ARG_TYPES (function_or_method_type); 828150397Sobrien 828250397Sobrien#if 0 828350397Sobrien /* In the case where we are generating a formal types list for a C++ 828450397Sobrien non-static member function type, skip over the first thing on the 828550397Sobrien TYPE_ARG_TYPES list because it only represents the type of the hidden 828650397Sobrien `this pointer'. The debugger should be able to figure out (without 828750397Sobrien being explicitly told) that this non-static member function type takes a 828850397Sobrien `this pointer' and should be able to figure what the type of that hidden 828950397Sobrien parameter is from the DW_AT_member attribute of the parent 829050397Sobrien DW_TAG_subroutine_type DIE. */ 829150397Sobrien if (TREE_CODE (function_or_method_type) == METHOD_TYPE) 829250397Sobrien first_parm_type = TREE_CHAIN (first_parm_type); 829350397Sobrien#endif 829450397Sobrien 829550397Sobrien /* Make our first pass over the list of formal parameter types and output a 829650397Sobrien DW_TAG_formal_parameter DIE for each one. */ 829750397Sobrien for (link = first_parm_type; link; link = TREE_CHAIN (link)) 829850397Sobrien { 829950397Sobrien register dw_die_ref parm_die; 830050397Sobrien 830150397Sobrien formal_type = TREE_VALUE (link); 830250397Sobrien if (formal_type == void_type_node) 830350397Sobrien break; 830450397Sobrien 830550397Sobrien /* Output a (nameless) DIE to represent the formal parameter itself. */ 830650397Sobrien parm_die = gen_formal_parameter_die (formal_type, context_die); 830750397Sobrien if (TREE_CODE (function_or_method_type) == METHOD_TYPE 830850397Sobrien && link == first_parm_type) 830950397Sobrien add_AT_flag (parm_die, DW_AT_artificial, 1); 831050397Sobrien } 831150397Sobrien 831250397Sobrien /* If this function type has an ellipsis, add a 831350397Sobrien DW_TAG_unspecified_parameters DIE to the end of the parameter list. */ 831450397Sobrien if (formal_type != void_type_node) 831550397Sobrien gen_unspecified_parameters_die (function_or_method_type, context_die); 831650397Sobrien 831750397Sobrien /* Make our second (and final) pass over the list of formal parameter types 831850397Sobrien and output DIEs to represent those types (as necessary). */ 831950397Sobrien for (link = TYPE_ARG_TYPES (function_or_method_type); 832050397Sobrien link; 832150397Sobrien link = TREE_CHAIN (link)) 832250397Sobrien { 832350397Sobrien formal_type = TREE_VALUE (link); 832450397Sobrien if (formal_type == void_type_node) 832550397Sobrien break; 832650397Sobrien 832750397Sobrien gen_type_die (formal_type, context_die); 832850397Sobrien } 832950397Sobrien} 833050397Sobrien 833150397Sobrien/* Generate a DIE to represent a declared function (either file-scope or 833250397Sobrien block-local). */ 833350397Sobrien 833450397Sobrienstatic void 833550397Sobriengen_subprogram_die (decl, context_die) 833650397Sobrien register tree decl; 833750397Sobrien register dw_die_ref context_die; 833850397Sobrien{ 833950397Sobrien char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; 834050397Sobrien register tree origin = decl_ultimate_origin (decl); 834150397Sobrien register dw_die_ref subr_die; 834250397Sobrien register rtx fp_reg; 834350397Sobrien register tree fn_arg_types; 834450397Sobrien register tree outer_scope; 834550397Sobrien register dw_die_ref old_die = lookup_decl_die (decl); 834650397Sobrien register int declaration 834750397Sobrien = (current_function_decl != decl 834850397Sobrien || (context_die 834950397Sobrien && (context_die->die_tag == DW_TAG_structure_type 835050397Sobrien || context_die->die_tag == DW_TAG_union_type))); 835150397Sobrien 835250397Sobrien if (origin != NULL) 835350397Sobrien { 835450397Sobrien subr_die = new_die (DW_TAG_subprogram, context_die); 835550397Sobrien add_abstract_origin_attribute (subr_die, origin); 835650397Sobrien } 835750397Sobrien else if (old_die && DECL_ABSTRACT (decl) 835850397Sobrien && get_AT_unsigned (old_die, DW_AT_inline)) 835950397Sobrien { 836050397Sobrien /* This must be a redefinition of an extern inline function. 836150397Sobrien We can just reuse the old die here. */ 836250397Sobrien subr_die = old_die; 836350397Sobrien 836450397Sobrien /* Clear out the inlined attribute and parm types. */ 836550397Sobrien remove_AT (subr_die, DW_AT_inline); 836650397Sobrien remove_children (subr_die); 836750397Sobrien } 836850397Sobrien else if (old_die) 836950397Sobrien { 837050397Sobrien register unsigned file_index 837150397Sobrien = lookup_filename (DECL_SOURCE_FILE (decl)); 837250397Sobrien 837350397Sobrien if (get_AT_flag (old_die, DW_AT_declaration) != 1) 837452284Sobrien { 837552284Sobrien /* ??? This can happen if there is a bug in the program, for 837652284Sobrien instance, if it has duplicate function definitions. Ideally, 837752284Sobrien we should detect this case and ignore it. For now, if we have 837852284Sobrien already reported an error, any error at all, then assume that 837952284Sobrien we got here because of a input error, not a dwarf2 bug. */ 838052284Sobrien extern int errorcount; 838152284Sobrien if (errorcount) 838252284Sobrien return; 838352284Sobrien abort (); 838452284Sobrien } 838550397Sobrien 838650397Sobrien /* If the definition comes from the same place as the declaration, 838750397Sobrien maybe use the old DIE. We always want the DIE for this function 838850397Sobrien that has the *_pc attributes to be under comp_unit_die so the 838950397Sobrien debugger can find it. For inlines, that is the concrete instance, 839050397Sobrien so we can use the old DIE here. For non-inline methods, we want a 839150397Sobrien specification DIE at toplevel, so we need a new DIE. For local 839250397Sobrien class methods, this does not apply. */ 839350397Sobrien if ((DECL_ABSTRACT (decl) || old_die->die_parent == comp_unit_die 839450397Sobrien || context_die == NULL) 839550397Sobrien && get_AT_unsigned (old_die, DW_AT_decl_file) == file_index 839650397Sobrien && (get_AT_unsigned (old_die, DW_AT_decl_line) 839750397Sobrien == DECL_SOURCE_LINE (decl))) 839850397Sobrien { 839950397Sobrien subr_die = old_die; 840050397Sobrien 840150397Sobrien /* Clear out the declaration attribute and the parm types. */ 840250397Sobrien remove_AT (subr_die, DW_AT_declaration); 840350397Sobrien remove_children (subr_die); 840450397Sobrien } 840550397Sobrien else 840650397Sobrien { 840750397Sobrien subr_die = new_die (DW_TAG_subprogram, context_die); 840850397Sobrien add_AT_die_ref (subr_die, DW_AT_specification, old_die); 840950397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 841050397Sobrien add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); 841150397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 841250397Sobrien != DECL_SOURCE_LINE (decl)) 841350397Sobrien add_AT_unsigned 841450397Sobrien (subr_die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); 841550397Sobrien } 841650397Sobrien } 841750397Sobrien else 841850397Sobrien { 841950397Sobrien register dw_die_ref scope_die; 842050397Sobrien 842150397Sobrien if (DECL_CONTEXT (decl)) 842250397Sobrien scope_die = scope_die_for (decl, context_die); 842350397Sobrien else 842450397Sobrien /* Don't put block extern declarations under comp_unit_die. */ 842550397Sobrien scope_die = context_die; 842650397Sobrien 842750397Sobrien subr_die = new_die (DW_TAG_subprogram, scope_die); 842850397Sobrien 842950397Sobrien if (TREE_PUBLIC (decl)) 843050397Sobrien add_AT_flag (subr_die, DW_AT_external, 1); 843150397Sobrien 843250397Sobrien add_name_and_src_coords_attributes (subr_die, decl); 843350397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 843450397Sobrien { 843550397Sobrien register tree type = TREE_TYPE (decl); 843650397Sobrien 843750397Sobrien add_prototyped_attribute (subr_die, type); 843850397Sobrien add_type_attribute (subr_die, TREE_TYPE (type), 0, 0, context_die); 843950397Sobrien } 844050397Sobrien 844150397Sobrien add_pure_or_virtual_attribute (subr_die, decl); 844250397Sobrien if (DECL_ARTIFICIAL (decl)) 844350397Sobrien add_AT_flag (subr_die, DW_AT_artificial, 1); 844450397Sobrien if (TREE_PROTECTED (decl)) 844550397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected); 844650397Sobrien else if (TREE_PRIVATE (decl)) 844750397Sobrien add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private); 844850397Sobrien } 844950397Sobrien 845050397Sobrien if (declaration) 845150397Sobrien { 845250397Sobrien add_AT_flag (subr_die, DW_AT_declaration, 1); 845350397Sobrien 845450397Sobrien /* The first time we see a member function, it is in the context of 845550397Sobrien the class to which it belongs. We make sure of this by emitting 845650397Sobrien the class first. The next time is the definition, which is 845750397Sobrien handled above. The two may come from the same source text. */ 845850397Sobrien if (DECL_CONTEXT (decl)) 845950397Sobrien equate_decl_number_to_die (decl, subr_die); 846050397Sobrien } 846150397Sobrien else if (DECL_ABSTRACT (decl)) 846250397Sobrien { 846350397Sobrien /* ??? Checking DECL_DEFER_OUTPUT is correct for static inline functions, 846450397Sobrien but not for extern inline functions. We can't get this completely 846550397Sobrien correct because information about whether the function was declared 846650397Sobrien inline is not saved anywhere. */ 846750397Sobrien if (DECL_DEFER_OUTPUT (decl)) 846850397Sobrien { 846950397Sobrien if (DECL_INLINE (decl)) 847050397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined); 847150397Sobrien else 847250397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, 847350397Sobrien DW_INL_declared_not_inlined); 847450397Sobrien } 847550397Sobrien else if (DECL_INLINE (decl)) 847650397Sobrien add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); 847750397Sobrien else 847850397Sobrien abort (); 847950397Sobrien 848050397Sobrien equate_decl_number_to_die (decl, subr_die); 848150397Sobrien } 848250397Sobrien else if (!DECL_EXTERNAL (decl)) 848350397Sobrien { 848450397Sobrien if (origin == NULL_TREE) 848550397Sobrien equate_decl_number_to_die (decl, subr_die); 848650397Sobrien 848750397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, 848850397Sobrien current_funcdef_number); 848950397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label_id); 849050397Sobrien ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_END_LABEL, 849150397Sobrien current_funcdef_number); 849250397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label_id); 849350397Sobrien 849450397Sobrien add_pubname (decl, subr_die); 849550397Sobrien add_arange (decl, subr_die); 849650397Sobrien 849750397Sobrien#ifdef MIPS_DEBUGGING_INFO 849850397Sobrien /* Add a reference to the FDE for this routine. */ 849950397Sobrien add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); 850050397Sobrien#endif 850150397Sobrien 850250397Sobrien /* Define the "frame base" location for this routine. We use the 850350397Sobrien frame pointer or stack pointer registers, since the RTL for local 850450397Sobrien variables is relative to one of them. */ 850550397Sobrien fp_reg 850650397Sobrien = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; 850750397Sobrien add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); 850850397Sobrien 850950397Sobrien#if 0 851050397Sobrien /* ??? This fails for nested inline functions, because context_display 851150397Sobrien is not part of the state saved/restored for inline functions. */ 851250397Sobrien if (current_function_needs_context) 851350397Sobrien add_AT_location_description (subr_die, DW_AT_static_link, 851450397Sobrien lookup_static_chain (decl)); 851550397Sobrien#endif 851650397Sobrien } 851750397Sobrien 851850397Sobrien /* Now output descriptions of the arguments for this function. This gets 851950397Sobrien (unnecessarily?) complex because of the fact that the DECL_ARGUMENT list 852050397Sobrien for a FUNCTION_DECL doesn't indicate cases where there was a trailing 852150397Sobrien `...' at the end of the formal parameter list. In order to find out if 852250397Sobrien there was a trailing ellipsis or not, we must instead look at the type 852350397Sobrien associated with the FUNCTION_DECL. This will be a node of type 852450397Sobrien FUNCTION_TYPE. If the chain of type nodes hanging off of this 852550397Sobrien FUNCTION_TYPE node ends with a void_type_node then there should *not* be 852650397Sobrien an ellipsis at the end. */ 852750397Sobrien push_decl_scope (decl); 852850397Sobrien 852950397Sobrien /* In the case where we are describing a mere function declaration, all we 853050397Sobrien need to do here (and all we *can* do here) is to describe the *types* of 853150397Sobrien its formal parameters. */ 853250397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 853350397Sobrien ; 853450397Sobrien else if (declaration) 853550397Sobrien gen_formal_types_die (TREE_TYPE (decl), subr_die); 853650397Sobrien else 853750397Sobrien { 853850397Sobrien /* Generate DIEs to represent all known formal parameters */ 853950397Sobrien register tree arg_decls = DECL_ARGUMENTS (decl); 854050397Sobrien register tree parm; 854150397Sobrien 854250397Sobrien /* When generating DIEs, generate the unspecified_parameters DIE 854350397Sobrien instead if we come across the arg "__builtin_va_alist" */ 854450397Sobrien for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) 854550397Sobrien if (TREE_CODE (parm) == PARM_DECL) 854650397Sobrien { 854750397Sobrien if (DECL_NAME (parm) 854850397Sobrien && !strcmp (IDENTIFIER_POINTER (DECL_NAME (parm)), 854950397Sobrien "__builtin_va_alist")) 855050397Sobrien gen_unspecified_parameters_die (parm, subr_die); 855150397Sobrien else 855250397Sobrien gen_decl_die (parm, subr_die); 855350397Sobrien } 855450397Sobrien 855550397Sobrien /* Decide whether we need a unspecified_parameters DIE at the end. 855650397Sobrien There are 2 more cases to do this for: 1) the ansi ... declaration - 855750397Sobrien this is detectable when the end of the arg list is not a 855850397Sobrien void_type_node 2) an unprototyped function declaration (not a 855950397Sobrien definition). This just means that we have no info about the 856050397Sobrien parameters at all. */ 856150397Sobrien fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); 856250397Sobrien if (fn_arg_types != NULL) 856350397Sobrien { 856450397Sobrien /* this is the prototyped case, check for ... */ 856550397Sobrien if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) 856650397Sobrien gen_unspecified_parameters_die (decl, subr_die); 856750397Sobrien } 856850397Sobrien else if (DECL_INITIAL (decl) == NULL_TREE) 856950397Sobrien gen_unspecified_parameters_die (decl, subr_die); 857050397Sobrien } 857150397Sobrien 857250397Sobrien /* Output Dwarf info for all of the stuff within the body of the function 857350397Sobrien (if it has one - it may be just a declaration). */ 857450397Sobrien outer_scope = DECL_INITIAL (decl); 857550397Sobrien 857650397Sobrien /* Note that here, `outer_scope' is a pointer to the outermost BLOCK 857750397Sobrien node created to represent a function. This outermost BLOCK actually 857850397Sobrien represents the outermost binding contour for the function, i.e. the 857950397Sobrien contour in which the function's formal parameters and labels get 858050397Sobrien declared. Curiously, it appears that the front end doesn't actually 858150397Sobrien put the PARM_DECL nodes for the current function onto the BLOCK_VARS 858250397Sobrien list for this outer scope. (They are strung off of the DECL_ARGUMENTS 858350397Sobrien list for the function instead.) The BLOCK_VARS list for the 858450397Sobrien `outer_scope' does provide us with a list of the LABEL_DECL nodes for 858550397Sobrien the function however, and we output DWARF info for those in 858650397Sobrien decls_for_scope. Just within the `outer_scope' there will be a BLOCK 858750397Sobrien node representing the function's outermost pair of curly braces, and 858850397Sobrien any blocks used for the base and member initializers of a C++ 858950397Sobrien constructor function. */ 859050397Sobrien if (! declaration && TREE_CODE (outer_scope) != ERROR_MARK) 859150397Sobrien { 859250397Sobrien current_function_has_inlines = 0; 859350397Sobrien decls_for_scope (outer_scope, subr_die, 0); 859450397Sobrien 859550397Sobrien#if 0 && defined (MIPS_DEBUGGING_INFO) 859650397Sobrien if (current_function_has_inlines) 859750397Sobrien { 859850397Sobrien add_AT_flag (subr_die, DW_AT_MIPS_has_inlines, 1); 859950397Sobrien if (! comp_unit_has_inlines) 860050397Sobrien { 860150397Sobrien add_AT_flag (comp_unit_die, DW_AT_MIPS_has_inlines, 1); 860250397Sobrien comp_unit_has_inlines = 1; 860350397Sobrien } 860450397Sobrien } 860550397Sobrien#endif 860650397Sobrien } 860750397Sobrien 860850397Sobrien pop_decl_scope (); 860950397Sobrien} 861050397Sobrien 861150397Sobrien/* Generate a DIE to represent a declared data object. */ 861250397Sobrien 861350397Sobrienstatic void 861450397Sobriengen_variable_die (decl, context_die) 861550397Sobrien register tree decl; 861650397Sobrien register dw_die_ref context_die; 861750397Sobrien{ 861850397Sobrien register tree origin = decl_ultimate_origin (decl); 861950397Sobrien register dw_die_ref var_die = new_die (DW_TAG_variable, context_die); 862050397Sobrien 862150397Sobrien dw_die_ref old_die = lookup_decl_die (decl); 862250397Sobrien int declaration 862350397Sobrien = (DECL_EXTERNAL (decl) 862450397Sobrien || current_function_decl != decl_function_context (decl) 862550397Sobrien || context_die->die_tag == DW_TAG_structure_type 862650397Sobrien || context_die->die_tag == DW_TAG_union_type); 862750397Sobrien 862850397Sobrien if (origin != NULL) 862950397Sobrien add_abstract_origin_attribute (var_die, origin); 863050397Sobrien /* Loop unrolling can create multiple blocks that refer to the same 863150397Sobrien static variable, so we must test for the DW_AT_declaration flag. */ 863250397Sobrien /* ??? Loop unrolling/reorder_blocks should perhaps be rewritten to 863350397Sobrien copy decls and set the DECL_ABSTRACT flag on them instead of 863450397Sobrien sharing them. */ 863550397Sobrien else if (old_die && TREE_STATIC (decl) 863650397Sobrien && get_AT_flag (old_die, DW_AT_declaration) == 1) 863750397Sobrien { 863850397Sobrien /* ??? This is an instantiation of a C++ class level static. */ 863950397Sobrien add_AT_die_ref (var_die, DW_AT_specification, old_die); 864050397Sobrien if (DECL_NAME (decl)) 864150397Sobrien { 864250397Sobrien register unsigned file_index 864350397Sobrien = lookup_filename (DECL_SOURCE_FILE (decl)); 864450397Sobrien 864550397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) 864650397Sobrien add_AT_unsigned (var_die, DW_AT_decl_file, file_index); 864750397Sobrien 864850397Sobrien if (get_AT_unsigned (old_die, DW_AT_decl_line) 864950397Sobrien != DECL_SOURCE_LINE (decl)) 865050397Sobrien 865150397Sobrien add_AT_unsigned (var_die, DW_AT_decl_line, 865250397Sobrien DECL_SOURCE_LINE (decl)); 865350397Sobrien } 865450397Sobrien } 865550397Sobrien else 865650397Sobrien { 865750397Sobrien add_name_and_src_coords_attributes (var_die, decl); 865850397Sobrien add_type_attribute (var_die, TREE_TYPE (decl), 865950397Sobrien TREE_READONLY (decl), 866050397Sobrien TREE_THIS_VOLATILE (decl), context_die); 866150397Sobrien 866250397Sobrien if (TREE_PUBLIC (decl)) 866350397Sobrien add_AT_flag (var_die, DW_AT_external, 1); 866450397Sobrien 866550397Sobrien if (DECL_ARTIFICIAL (decl)) 866650397Sobrien add_AT_flag (var_die, DW_AT_artificial, 1); 866750397Sobrien 866850397Sobrien if (TREE_PROTECTED (decl)) 866950397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); 867050397Sobrien 867150397Sobrien else if (TREE_PRIVATE (decl)) 867250397Sobrien add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); 867350397Sobrien } 867450397Sobrien 867550397Sobrien if (declaration) 867650397Sobrien add_AT_flag (var_die, DW_AT_declaration, 1); 867750397Sobrien 867850397Sobrien if ((declaration && decl_class_context (decl)) || DECL_ABSTRACT (decl)) 867950397Sobrien equate_decl_number_to_die (decl, var_die); 868050397Sobrien 868150397Sobrien if (! declaration && ! DECL_ABSTRACT (decl)) 868250397Sobrien { 868350397Sobrien equate_decl_number_to_die (decl, var_die); 868450397Sobrien add_location_or_const_value_attribute (var_die, decl); 868550397Sobrien add_pubname (decl, var_die); 868650397Sobrien } 868750397Sobrien} 868850397Sobrien 868950397Sobrien/* Generate a DIE to represent a label identifier. */ 869050397Sobrien 869150397Sobrienstatic void 869250397Sobriengen_label_die (decl, context_die) 869350397Sobrien register tree decl; 869450397Sobrien register dw_die_ref context_die; 869550397Sobrien{ 869650397Sobrien register tree origin = decl_ultimate_origin (decl); 869750397Sobrien register dw_die_ref lbl_die = new_die (DW_TAG_label, context_die); 869850397Sobrien register rtx insn; 869950397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 870050397Sobrien char label2[MAX_ARTIFICIAL_LABEL_BYTES]; 870150397Sobrien 870250397Sobrien if (origin != NULL) 870350397Sobrien add_abstract_origin_attribute (lbl_die, origin); 870450397Sobrien else 870550397Sobrien add_name_and_src_coords_attributes (lbl_die, decl); 870650397Sobrien 870750397Sobrien if (DECL_ABSTRACT (decl)) 870850397Sobrien equate_decl_number_to_die (decl, lbl_die); 870950397Sobrien else 871050397Sobrien { 871150397Sobrien insn = DECL_RTL (decl); 871252284Sobrien 871352284Sobrien /* Deleted labels are programmer specified labels which have been 871452284Sobrien eliminated because of various optimisations. We still emit them 871552284Sobrien here so that it is possible to put breakpoints on them. */ 871652284Sobrien if (GET_CODE (insn) == CODE_LABEL 871752284Sobrien || ((GET_CODE (insn) == NOTE 871852284Sobrien && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))) 871950397Sobrien { 872050397Sobrien /* When optimization is enabled (via -O) some parts of the compiler 872150397Sobrien (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which 872250397Sobrien represent source-level labels which were explicitly declared by 872350397Sobrien the user. This really shouldn't be happening though, so catch 872450397Sobrien it if it ever does happen. */ 872550397Sobrien if (INSN_DELETED_P (insn)) 872650397Sobrien abort (); 872750397Sobrien 872850397Sobrien sprintf (label2, INSN_LABEL_FMT, current_funcdef_number); 872950397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, label2, 873050397Sobrien (unsigned) INSN_UID (insn)); 873150397Sobrien add_AT_lbl_id (lbl_die, DW_AT_low_pc, label); 873250397Sobrien } 873350397Sobrien } 873450397Sobrien} 873550397Sobrien 873650397Sobrien/* Generate a DIE for a lexical block. */ 873750397Sobrien 873850397Sobrienstatic void 873950397Sobriengen_lexical_block_die (stmt, context_die, depth) 874050397Sobrien register tree stmt; 874150397Sobrien register dw_die_ref context_die; 874250397Sobrien int depth; 874350397Sobrien{ 874450397Sobrien register dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die); 874550397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 874650397Sobrien 874750397Sobrien if (! BLOCK_ABSTRACT (stmt)) 874850397Sobrien { 874950397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 875050397Sobrien next_block_number); 875150397Sobrien add_AT_lbl_id (stmt_die, DW_AT_low_pc, label); 875250397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, next_block_number); 875350397Sobrien add_AT_lbl_id (stmt_die, DW_AT_high_pc, label); 875450397Sobrien } 875550397Sobrien 875650397Sobrien push_decl_scope (stmt); 875750397Sobrien decls_for_scope (stmt, stmt_die, depth); 875850397Sobrien pop_decl_scope (); 875950397Sobrien} 876050397Sobrien 876150397Sobrien/* Generate a DIE for an inlined subprogram. */ 876250397Sobrien 876350397Sobrienstatic void 876450397Sobriengen_inlined_subroutine_die (stmt, context_die, depth) 876550397Sobrien register tree stmt; 876650397Sobrien register dw_die_ref context_die; 876750397Sobrien int depth; 876850397Sobrien{ 876950397Sobrien if (! BLOCK_ABSTRACT (stmt)) 877050397Sobrien { 877150397Sobrien register dw_die_ref subr_die 877250397Sobrien = new_die (DW_TAG_inlined_subroutine, context_die); 877350397Sobrien register tree decl = block_ultimate_origin (stmt); 877450397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 877550397Sobrien 877650397Sobrien add_abstract_origin_attribute (subr_die, decl); 877750397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, 877850397Sobrien next_block_number); 877950397Sobrien add_AT_lbl_id (subr_die, DW_AT_low_pc, label); 878050397Sobrien ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, next_block_number); 878150397Sobrien add_AT_lbl_id (subr_die, DW_AT_high_pc, label); 878250397Sobrien push_decl_scope (decl); 878350397Sobrien decls_for_scope (stmt, subr_die, depth); 878450397Sobrien pop_decl_scope (); 878550397Sobrien current_function_has_inlines = 1; 878650397Sobrien } 878750397Sobrien} 878850397Sobrien 878950397Sobrien/* Generate a DIE for a field in a record, or structure. */ 879050397Sobrien 879150397Sobrienstatic void 879250397Sobriengen_field_die (decl, context_die) 879350397Sobrien register tree decl; 879450397Sobrien register dw_die_ref context_die; 879550397Sobrien{ 879650397Sobrien register dw_die_ref decl_die = new_die (DW_TAG_member, context_die); 879750397Sobrien 879850397Sobrien add_name_and_src_coords_attributes (decl_die, decl); 879950397Sobrien add_type_attribute (decl_die, member_declared_type (decl), 880050397Sobrien TREE_READONLY (decl), TREE_THIS_VOLATILE (decl), 880150397Sobrien context_die); 880250397Sobrien 880350397Sobrien /* If this is a bit field... */ 880450397Sobrien if (DECL_BIT_FIELD_TYPE (decl)) 880550397Sobrien { 880650397Sobrien add_byte_size_attribute (decl_die, decl); 880750397Sobrien add_bit_size_attribute (decl_die, decl); 880850397Sobrien add_bit_offset_attribute (decl_die, decl); 880950397Sobrien } 881050397Sobrien 881150397Sobrien if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE) 881250397Sobrien add_data_member_location_attribute (decl_die, decl); 881350397Sobrien 881450397Sobrien if (DECL_ARTIFICIAL (decl)) 881550397Sobrien add_AT_flag (decl_die, DW_AT_artificial, 1); 881650397Sobrien 881750397Sobrien if (TREE_PROTECTED (decl)) 881850397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected); 881950397Sobrien 882050397Sobrien else if (TREE_PRIVATE (decl)) 882150397Sobrien add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private); 882250397Sobrien} 882350397Sobrien 882450397Sobrien#if 0 882550397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 882650397Sobrien Use modified_type_die instead. 882750397Sobrien We keep this code here just in case these types of DIEs may be needed to 882850397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 882950397Sobrienstatic void 883050397Sobriengen_pointer_type_die (type, context_die) 883150397Sobrien register tree type; 883250397Sobrien register dw_die_ref context_die; 883350397Sobrien{ 883450397Sobrien register dw_die_ref ptr_die 883550397Sobrien = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die)); 883650397Sobrien 883750397Sobrien equate_type_number_to_die (type, ptr_die); 883850397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 883950397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 884050397Sobrien} 884150397Sobrien 884250397Sobrien/* Don't generate either pointer_type DIEs or reference_type DIEs here. 884350397Sobrien Use modified_type_die instead. 884450397Sobrien We keep this code here just in case these types of DIEs may be needed to 884550397Sobrien represent certain things in other languages (e.g. Pascal) someday. */ 884650397Sobrienstatic void 884750397Sobriengen_reference_type_die (type, context_die) 884850397Sobrien register tree type; 884950397Sobrien register dw_die_ref context_die; 885050397Sobrien{ 885150397Sobrien register dw_die_ref ref_die 885250397Sobrien = new_die (DW_TAG_reference_type, scope_die_for (type, context_die)); 885350397Sobrien 885450397Sobrien equate_type_number_to_die (type, ref_die); 885550397Sobrien add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die); 885650397Sobrien add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); 885750397Sobrien} 885850397Sobrien#endif 885950397Sobrien 886050397Sobrien/* Generate a DIE for a pointer to a member type. */ 886150397Sobrienstatic void 886250397Sobriengen_ptr_to_mbr_type_die (type, context_die) 886350397Sobrien register tree type; 886450397Sobrien register dw_die_ref context_die; 886550397Sobrien{ 886650397Sobrien register dw_die_ref ptr_die 886750397Sobrien = new_die (DW_TAG_ptr_to_member_type, scope_die_for (type, context_die)); 886850397Sobrien 886950397Sobrien equate_type_number_to_die (type, ptr_die); 887050397Sobrien add_AT_die_ref (ptr_die, DW_AT_containing_type, 887150397Sobrien lookup_type_die (TYPE_OFFSET_BASETYPE (type))); 887250397Sobrien add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); 887350397Sobrien} 887450397Sobrien 887550397Sobrien/* Generate the DIE for the compilation unit. */ 887650397Sobrien 887750397Sobrienstatic void 887850397Sobriengen_compile_unit_die (main_input_filename) 887950397Sobrien register char *main_input_filename; 888050397Sobrien{ 888150397Sobrien char producer[250]; 888250397Sobrien char *wd = getpwd (); 888350397Sobrien 888450397Sobrien comp_unit_die = new_die (DW_TAG_compile_unit, NULL); 888550397Sobrien add_name_attribute (comp_unit_die, main_input_filename); 888650397Sobrien 888750397Sobrien if (wd != NULL) 888850397Sobrien add_AT_string (comp_unit_die, DW_AT_comp_dir, wd); 888950397Sobrien 889050397Sobrien sprintf (producer, "%s %s", language_string, version_string); 889150397Sobrien 889250397Sobrien#ifdef MIPS_DEBUGGING_INFO 889350397Sobrien /* The MIPS/SGI compilers place the 'cc' command line options in the producer 889450397Sobrien string. The SGI debugger looks for -g, -g1, -g2, or -g3; if they do 889550397Sobrien not appear in the producer string, the debugger reaches the conclusion 889650397Sobrien that the object file is stripped and has no debugging information. 889750397Sobrien To get the MIPS/SGI debugger to believe that there is debugging 889850397Sobrien information in the object file, we add a -g to the producer string. */ 889950397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 890050397Sobrien strcat (producer, " -g"); 890150397Sobrien#endif 890250397Sobrien 890350397Sobrien add_AT_string (comp_unit_die, DW_AT_producer, producer); 890450397Sobrien 890550397Sobrien if (strcmp (language_string, "GNU C++") == 0) 890650397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_C_plus_plus); 890750397Sobrien 890850397Sobrien else if (strcmp (language_string, "GNU Ada") == 0) 890950397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_Ada83); 891050397Sobrien 891150397Sobrien else if (strcmp (language_string, "GNU F77") == 0) 891250397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_Fortran77); 891350397Sobrien 891450397Sobrien else if (strcmp (language_string, "GNU Pascal") == 0) 891550397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_Pascal83); 891650397Sobrien 891750397Sobrien else if (flag_traditional) 891850397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_C); 891950397Sobrien 892050397Sobrien else 892150397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_language, DW_LANG_C89); 892250397Sobrien 892350397Sobrien#if 0 /* unimplemented */ 892450397Sobrien if (debug_info_level >= DINFO_LEVEL_VERBOSE) 892550397Sobrien add_AT_unsigned (comp_unit_die, DW_AT_macro_info, 0); 892650397Sobrien#endif 892750397Sobrien} 892850397Sobrien 892950397Sobrien/* Generate a DIE for a string type. */ 893050397Sobrien 893150397Sobrienstatic void 893250397Sobriengen_string_type_die (type, context_die) 893350397Sobrien register tree type; 893450397Sobrien register dw_die_ref context_die; 893550397Sobrien{ 893650397Sobrien register dw_die_ref type_die 893750397Sobrien = new_die (DW_TAG_string_type, scope_die_for (type, context_die)); 893850397Sobrien 893950397Sobrien equate_type_number_to_die (type, type_die); 894050397Sobrien 894150397Sobrien /* Fudge the string length attribute for now. */ 894250397Sobrien 894350397Sobrien /* TODO: add string length info. 894450397Sobrien string_length_attribute (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 894550397Sobrien bound_representation (upper_bound, 0, 'u'); */ 894650397Sobrien} 894750397Sobrien 894850397Sobrien/* Generate the DIE for a base class. */ 894950397Sobrien 895050397Sobrienstatic void 895150397Sobriengen_inheritance_die (binfo, context_die) 895250397Sobrien register tree binfo; 895350397Sobrien register dw_die_ref context_die; 895450397Sobrien{ 895550397Sobrien dw_die_ref die = new_die (DW_TAG_inheritance, context_die); 895650397Sobrien 895750397Sobrien add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die); 895850397Sobrien add_data_member_location_attribute (die, binfo); 895950397Sobrien 896050397Sobrien if (TREE_VIA_VIRTUAL (binfo)) 896150397Sobrien add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); 896250397Sobrien if (TREE_VIA_PUBLIC (binfo)) 896350397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); 896450397Sobrien else if (TREE_VIA_PROTECTED (binfo)) 896550397Sobrien add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); 896650397Sobrien} 896750397Sobrien 896850397Sobrien/* Generate a DIE for a class member. */ 896950397Sobrien 897050397Sobrienstatic void 897150397Sobriengen_member_die (type, context_die) 897250397Sobrien register tree type; 897350397Sobrien register dw_die_ref context_die; 897450397Sobrien{ 897550397Sobrien register tree member; 897650397Sobrien 897750397Sobrien /* If this is not an incomplete type, output descriptions of each of its 897850397Sobrien members. Note that as we output the DIEs necessary to represent the 897950397Sobrien members of this record or union type, we will also be trying to output 898050397Sobrien DIEs to represent the *types* of those members. However the `type' 898150397Sobrien function (above) will specifically avoid generating type DIEs for member 898250397Sobrien types *within* the list of member DIEs for this (containing) type execpt 898350397Sobrien for those types (of members) which are explicitly marked as also being 898450397Sobrien members of this (containing) type themselves. The g++ front- end can 898550397Sobrien force any given type to be treated as a member of some other 898650397Sobrien (containing) type by setting the TYPE_CONTEXT of the given (member) type 898750397Sobrien to point to the TREE node representing the appropriate (containing) 898850397Sobrien type. */ 898950397Sobrien 899050397Sobrien /* First output info about the base classes. */ 899150397Sobrien if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) 899250397Sobrien { 899350397Sobrien register tree bases = TYPE_BINFO_BASETYPES (type); 899450397Sobrien register int n_bases = TREE_VEC_LENGTH (bases); 899550397Sobrien register int i; 899650397Sobrien 899750397Sobrien for (i = 0; i < n_bases; i++) 899850397Sobrien gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die); 899950397Sobrien } 900050397Sobrien 900150397Sobrien /* Now output info about the data members and type members. */ 900250397Sobrien for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member)) 900350397Sobrien gen_decl_die (member, context_die); 900450397Sobrien 900550397Sobrien /* Now output info about the function members (if any). */ 900650397Sobrien for (member = TYPE_METHODS (type); member; member = TREE_CHAIN (member)) 900750397Sobrien gen_decl_die (member, context_die); 900850397Sobrien} 900950397Sobrien 901050397Sobrien/* Generate a DIE for a structure or union type. */ 901150397Sobrien 901250397Sobrienstatic void 901350397Sobriengen_struct_or_union_type_die (type, context_die) 901450397Sobrien register tree type; 901550397Sobrien register dw_die_ref context_die; 901650397Sobrien{ 901750397Sobrien register dw_die_ref type_die = lookup_type_die (type); 901850397Sobrien register dw_die_ref scope_die = 0; 901950397Sobrien register int nested = 0; 902050397Sobrien 902150397Sobrien if (type_die && ! TYPE_SIZE (type)) 902250397Sobrien return; 902350397Sobrien 902450397Sobrien if (TYPE_CONTEXT (type) != NULL_TREE 902552284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))) 902650397Sobrien nested = 1; 902750397Sobrien 902850397Sobrien scope_die = scope_die_for (type, context_die); 902950397Sobrien 903050397Sobrien if (! type_die || (nested && scope_die == comp_unit_die)) 903150397Sobrien /* First occurrence of type or toplevel definition of nested class. */ 903250397Sobrien { 903350397Sobrien register dw_die_ref old_die = type_die; 903450397Sobrien 903550397Sobrien type_die = new_die (TREE_CODE (type) == RECORD_TYPE 903650397Sobrien ? DW_TAG_structure_type : DW_TAG_union_type, 903750397Sobrien scope_die); 903850397Sobrien equate_type_number_to_die (type, type_die); 903950397Sobrien add_name_attribute (type_die, type_tag (type)); 904050397Sobrien if (old_die) 904150397Sobrien add_AT_die_ref (type_die, DW_AT_specification, old_die); 904250397Sobrien } 904350397Sobrien else 904450397Sobrien remove_AT (type_die, DW_AT_declaration); 904550397Sobrien 904650397Sobrien /* If we're not in the right context to be defining this type, defer to 904750397Sobrien avoid tricky recursion. */ 904850397Sobrien if (TYPE_SIZE (type) && decl_scope_depth > 0 && scope_die == comp_unit_die) 904950397Sobrien { 905050397Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 905150397Sobrien pend_type (type); 905250397Sobrien } 905350397Sobrien /* If this type has been completed, then give it a byte_size attribute and 905450397Sobrien then give a list of members. */ 905550397Sobrien else if (TYPE_SIZE (type)) 905650397Sobrien { 905750397Sobrien /* Prevent infinite recursion in cases where the type of some member of 905850397Sobrien this type is expressed in terms of this type itself. */ 905950397Sobrien TREE_ASM_WRITTEN (type) = 1; 906050397Sobrien add_byte_size_attribute (type_die, type); 906150397Sobrien if (TYPE_STUB_DECL (type) != NULL_TREE) 906250397Sobrien add_src_coords_attributes (type_die, TYPE_STUB_DECL (type)); 906350397Sobrien 906450397Sobrien /* If the first reference to this type was as the return type of an 906550397Sobrien inline function, then it may not have a parent. Fix this now. */ 906650397Sobrien if (type_die->die_parent == NULL) 906750397Sobrien add_child_die (scope_die, type_die); 906850397Sobrien 906950397Sobrien push_decl_scope (type); 907050397Sobrien gen_member_die (type, type_die); 907150397Sobrien pop_decl_scope (); 907250397Sobrien 907350397Sobrien /* GNU extension: Record what type our vtable lives in. */ 907450397Sobrien if (TYPE_VFIELD (type)) 907550397Sobrien { 907650397Sobrien tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type)); 907750397Sobrien 907850397Sobrien gen_type_die (vtype, context_die); 907950397Sobrien add_AT_die_ref (type_die, DW_AT_containing_type, 908050397Sobrien lookup_type_die (vtype)); 908150397Sobrien } 908250397Sobrien } 908350397Sobrien else 908452284Sobrien { 908552284Sobrien add_AT_flag (type_die, DW_AT_declaration, 1); 908652284Sobrien 908752284Sobrien /* We can't do this for function-local types, and we don't need to. */ 908852284Sobrien if (TREE_PERMANENT (type)) 908952284Sobrien add_incomplete_type (type); 909052284Sobrien } 909150397Sobrien} 909250397Sobrien 909350397Sobrien/* Generate a DIE for a subroutine _type_. */ 909450397Sobrien 909550397Sobrienstatic void 909650397Sobriengen_subroutine_type_die (type, context_die) 909750397Sobrien register tree type; 909850397Sobrien register dw_die_ref context_die; 909950397Sobrien{ 910050397Sobrien register tree return_type = TREE_TYPE (type); 910150397Sobrien register dw_die_ref subr_die 910250397Sobrien = new_die (DW_TAG_subroutine_type, scope_die_for (type, context_die)); 910350397Sobrien 910450397Sobrien equate_type_number_to_die (type, subr_die); 910550397Sobrien add_prototyped_attribute (subr_die, type); 910650397Sobrien add_type_attribute (subr_die, return_type, 0, 0, context_die); 910750397Sobrien gen_formal_types_die (type, subr_die); 910850397Sobrien} 910950397Sobrien 911050397Sobrien/* Generate a DIE for a type definition */ 911150397Sobrien 911250397Sobrienstatic void 911350397Sobriengen_typedef_die (decl, context_die) 911450397Sobrien register tree decl; 911550397Sobrien register dw_die_ref context_die; 911650397Sobrien{ 911750397Sobrien register dw_die_ref type_die; 911850397Sobrien register tree origin; 911950397Sobrien 912050397Sobrien if (TREE_ASM_WRITTEN (decl)) 912150397Sobrien return; 912250397Sobrien TREE_ASM_WRITTEN (decl) = 1; 912350397Sobrien 912450397Sobrien type_die = new_die (DW_TAG_typedef, scope_die_for (decl, context_die)); 912550397Sobrien origin = decl_ultimate_origin (decl); 912650397Sobrien if (origin != NULL) 912750397Sobrien add_abstract_origin_attribute (type_die, origin); 912850397Sobrien else 912950397Sobrien { 913050397Sobrien register tree type; 913150397Sobrien add_name_and_src_coords_attributes (type_die, decl); 913250397Sobrien if (DECL_ORIGINAL_TYPE (decl)) 913350397Sobrien { 913450397Sobrien type = DECL_ORIGINAL_TYPE (decl); 913550397Sobrien equate_type_number_to_die (TREE_TYPE (decl), type_die); 913650397Sobrien } 913750397Sobrien else 913850397Sobrien type = TREE_TYPE (decl); 913950397Sobrien add_type_attribute (type_die, type, TREE_READONLY (decl), 914050397Sobrien TREE_THIS_VOLATILE (decl), context_die); 914150397Sobrien } 914250397Sobrien 914350397Sobrien if (DECL_ABSTRACT (decl)) 914450397Sobrien equate_decl_number_to_die (decl, type_die); 914550397Sobrien} 914650397Sobrien 914750397Sobrien/* Generate a type description DIE. */ 914850397Sobrien 914950397Sobrienstatic void 915050397Sobriengen_type_die (type, context_die) 915150397Sobrien register tree type; 915250397Sobrien register dw_die_ref context_die; 915350397Sobrien{ 915450397Sobrien if (type == NULL_TREE || type == error_mark_node) 915550397Sobrien return; 915650397Sobrien 915750397Sobrien /* We are going to output a DIE to represent the unqualified version of 915850397Sobrien this type (i.e. without any const or volatile qualifiers) so get the 915950397Sobrien main variant (i.e. the unqualified version) of this type now. */ 916050397Sobrien type = type_main_variant (type); 916150397Sobrien 916250397Sobrien if (TREE_ASM_WRITTEN (type)) 916350397Sobrien return; 916450397Sobrien 916550397Sobrien if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 916650397Sobrien && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) 916750397Sobrien { 916850397Sobrien TREE_ASM_WRITTEN (type) = 1; 916950397Sobrien gen_decl_die (TYPE_NAME (type), context_die); 917050397Sobrien return; 917150397Sobrien } 917250397Sobrien 917350397Sobrien switch (TREE_CODE (type)) 917450397Sobrien { 917550397Sobrien case ERROR_MARK: 917650397Sobrien break; 917750397Sobrien 917850397Sobrien case POINTER_TYPE: 917950397Sobrien case REFERENCE_TYPE: 918050397Sobrien /* We must set TREE_ASM_WRITTEN in case this is a recursive type. This 918150397Sobrien ensures that the gen_type_die recursion will terminate even if the 918250397Sobrien type is recursive. Recursive types are possible in Ada. */ 918350397Sobrien /* ??? We could perhaps do this for all types before the switch 918450397Sobrien statement. */ 918550397Sobrien TREE_ASM_WRITTEN (type) = 1; 918650397Sobrien 918750397Sobrien /* For these types, all that is required is that we output a DIE (or a 918850397Sobrien set of DIEs) to represent the "basis" type. */ 918950397Sobrien gen_type_die (TREE_TYPE (type), context_die); 919050397Sobrien break; 919150397Sobrien 919250397Sobrien case OFFSET_TYPE: 919350397Sobrien /* This code is used for C++ pointer-to-data-member types. 919450397Sobrien Output a description of the relevant class type. */ 919550397Sobrien gen_type_die (TYPE_OFFSET_BASETYPE (type), context_die); 919650397Sobrien 919750397Sobrien /* Output a description of the type of the object pointed to. */ 919850397Sobrien gen_type_die (TREE_TYPE (type), context_die); 919950397Sobrien 920050397Sobrien /* Now output a DIE to represent this pointer-to-data-member type 920150397Sobrien itself. */ 920250397Sobrien gen_ptr_to_mbr_type_die (type, context_die); 920350397Sobrien break; 920450397Sobrien 920550397Sobrien case SET_TYPE: 920650397Sobrien gen_type_die (TYPE_DOMAIN (type), context_die); 920750397Sobrien gen_set_type_die (type, context_die); 920850397Sobrien break; 920950397Sobrien 921050397Sobrien case FILE_TYPE: 921150397Sobrien gen_type_die (TREE_TYPE (type), context_die); 921250397Sobrien abort (); /* No way to represent these in Dwarf yet! */ 921350397Sobrien break; 921450397Sobrien 921550397Sobrien case FUNCTION_TYPE: 921650397Sobrien /* Force out return type (in case it wasn't forced out already). */ 921750397Sobrien gen_type_die (TREE_TYPE (type), context_die); 921850397Sobrien gen_subroutine_type_die (type, context_die); 921950397Sobrien break; 922050397Sobrien 922150397Sobrien case METHOD_TYPE: 922250397Sobrien /* Force out return type (in case it wasn't forced out already). */ 922350397Sobrien gen_type_die (TREE_TYPE (type), context_die); 922450397Sobrien gen_subroutine_type_die (type, context_die); 922550397Sobrien break; 922650397Sobrien 922750397Sobrien case ARRAY_TYPE: 922850397Sobrien if (TYPE_STRING_FLAG (type) && TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE) 922950397Sobrien { 923050397Sobrien gen_type_die (TREE_TYPE (type), context_die); 923150397Sobrien gen_string_type_die (type, context_die); 923250397Sobrien } 923350397Sobrien else 923450397Sobrien gen_array_type_die (type, context_die); 923550397Sobrien break; 923650397Sobrien 923750397Sobrien case ENUMERAL_TYPE: 923850397Sobrien case RECORD_TYPE: 923950397Sobrien case UNION_TYPE: 924050397Sobrien case QUAL_UNION_TYPE: 924150397Sobrien /* If this is a nested type whose containing class hasn't been 924250397Sobrien written out yet, writing it out will cover this one, too. */ 924350397Sobrien if (TYPE_CONTEXT (type) 924452284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) 924550397Sobrien && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 924650397Sobrien { 924750397Sobrien gen_type_die (TYPE_CONTEXT (type), context_die); 924850397Sobrien 924950397Sobrien if (TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 925050397Sobrien return; 925150397Sobrien 925250397Sobrien /* If that failed, attach ourselves to the stub. */ 925350397Sobrien push_decl_scope (TYPE_CONTEXT (type)); 925450397Sobrien context_die = lookup_type_die (TYPE_CONTEXT (type)); 925550397Sobrien } 925650397Sobrien 925750397Sobrien if (TREE_CODE (type) == ENUMERAL_TYPE) 925850397Sobrien gen_enumeration_type_die (type, context_die); 925950397Sobrien else 926050397Sobrien gen_struct_or_union_type_die (type, context_die); 926150397Sobrien 926250397Sobrien if (TYPE_CONTEXT (type) 926352284Sobrien && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) 926450397Sobrien && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) 926550397Sobrien pop_decl_scope (); 926650397Sobrien 926750397Sobrien /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix 926850397Sobrien it up if it is ever completed. gen_*_type_die will set it for us 926950397Sobrien when appropriate. */ 927050397Sobrien return; 927150397Sobrien 927250397Sobrien case VOID_TYPE: 927350397Sobrien case INTEGER_TYPE: 927450397Sobrien case REAL_TYPE: 927550397Sobrien case COMPLEX_TYPE: 927650397Sobrien case BOOLEAN_TYPE: 927750397Sobrien case CHAR_TYPE: 927850397Sobrien /* No DIEs needed for fundamental types. */ 927950397Sobrien break; 928050397Sobrien 928150397Sobrien case LANG_TYPE: 928250397Sobrien /* No Dwarf representation currently defined. */ 928350397Sobrien break; 928450397Sobrien 928550397Sobrien default: 928650397Sobrien abort (); 928750397Sobrien } 928850397Sobrien 928950397Sobrien TREE_ASM_WRITTEN (type) = 1; 929050397Sobrien} 929150397Sobrien 929250397Sobrien/* Generate a DIE for a tagged type instantiation. */ 929350397Sobrien 929450397Sobrienstatic void 929550397Sobriengen_tagged_type_instantiation_die (type, context_die) 929650397Sobrien register tree type; 929750397Sobrien register dw_die_ref context_die; 929850397Sobrien{ 929950397Sobrien if (type == NULL_TREE || type == error_mark_node) 930050397Sobrien return; 930150397Sobrien 930250397Sobrien /* We are going to output a DIE to represent the unqualified version of 930350397Sobrien this type (i.e. without any const or volatile qualifiers) so make sure 930450397Sobrien that we have the main variant (i.e. the unqualified version) of this 930550397Sobrien type now. */ 930650397Sobrien if (type != type_main_variant (type) 930750397Sobrien || !TREE_ASM_WRITTEN (type)) 930850397Sobrien abort (); 930950397Sobrien 931050397Sobrien switch (TREE_CODE (type)) 931150397Sobrien { 931250397Sobrien case ERROR_MARK: 931350397Sobrien break; 931450397Sobrien 931550397Sobrien case ENUMERAL_TYPE: 931650397Sobrien gen_inlined_enumeration_type_die (type, context_die); 931750397Sobrien break; 931850397Sobrien 931950397Sobrien case RECORD_TYPE: 932050397Sobrien gen_inlined_structure_type_die (type, context_die); 932150397Sobrien break; 932250397Sobrien 932350397Sobrien case UNION_TYPE: 932450397Sobrien case QUAL_UNION_TYPE: 932550397Sobrien gen_inlined_union_type_die (type, context_die); 932650397Sobrien break; 932750397Sobrien 932850397Sobrien default: 932950397Sobrien abort (); 933050397Sobrien } 933150397Sobrien} 933250397Sobrien 933350397Sobrien/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the 933450397Sobrien things which are local to the given block. */ 933550397Sobrien 933650397Sobrienstatic void 933750397Sobriengen_block_die (stmt, context_die, depth) 933850397Sobrien register tree stmt; 933950397Sobrien register dw_die_ref context_die; 934050397Sobrien int depth; 934150397Sobrien{ 934250397Sobrien register int must_output_die = 0; 934350397Sobrien register tree origin; 934450397Sobrien register tree decl; 934550397Sobrien register enum tree_code origin_code; 934650397Sobrien 934750397Sobrien /* Ignore blocks never really used to make RTL. */ 934850397Sobrien 934950397Sobrien if (stmt == NULL_TREE || !TREE_USED (stmt)) 935050397Sobrien return; 935150397Sobrien 935250397Sobrien /* Determine the "ultimate origin" of this block. This block may be an 935350397Sobrien inlined instance of an inlined instance of inline function, so we have 935450397Sobrien to trace all of the way back through the origin chain to find out what 935550397Sobrien sort of node actually served as the original seed for the creation of 935650397Sobrien the current block. */ 935750397Sobrien origin = block_ultimate_origin (stmt); 935850397Sobrien origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK; 935950397Sobrien 936050397Sobrien /* Determine if we need to output any Dwarf DIEs at all to represent this 936150397Sobrien block. */ 936250397Sobrien if (origin_code == FUNCTION_DECL) 936350397Sobrien /* The outer scopes for inlinings *must* always be represented. We 936450397Sobrien generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */ 936550397Sobrien must_output_die = 1; 936650397Sobrien else 936750397Sobrien { 936850397Sobrien /* In the case where the current block represents an inlining of the 936950397Sobrien "body block" of an inline function, we must *NOT* output any DIE for 937050397Sobrien this block because we have already output a DIE to represent the 937150397Sobrien whole inlined function scope and the "body block" of any function 937250397Sobrien doesn't really represent a different scope according to ANSI C 937350397Sobrien rules. So we check here to make sure that this block does not 937450397Sobrien represent a "body block inlining" before trying to set the 937550397Sobrien `must_output_die' flag. */ 937650397Sobrien if (! is_body_block (origin ? origin : stmt)) 937750397Sobrien { 937850397Sobrien /* Determine if this block directly contains any "significant" 937950397Sobrien local declarations which we will need to output DIEs for. */ 938050397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 938150397Sobrien /* We are not in terse mode so *any* local declaration counts 938250397Sobrien as being a "significant" one. */ 938350397Sobrien must_output_die = (BLOCK_VARS (stmt) != NULL); 938450397Sobrien else 938550397Sobrien /* We are in terse mode, so only local (nested) function 938650397Sobrien definitions count as "significant" local declarations. */ 938750397Sobrien for (decl = BLOCK_VARS (stmt); 938850397Sobrien decl != NULL; decl = TREE_CHAIN (decl)) 938950397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 939050397Sobrien && DECL_INITIAL (decl)) 939150397Sobrien { 939250397Sobrien must_output_die = 1; 939350397Sobrien break; 939450397Sobrien } 939550397Sobrien } 939650397Sobrien } 939750397Sobrien 939850397Sobrien /* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block 939950397Sobrien DIE for any block which contains no significant local declarations at 940050397Sobrien all. Rather, in such cases we just call `decls_for_scope' so that any 940150397Sobrien needed Dwarf info for any sub-blocks will get properly generated. Note 940250397Sobrien that in terse mode, our definition of what constitutes a "significant" 940350397Sobrien local declaration gets restricted to include only inlined function 940450397Sobrien instances and local (nested) function definitions. */ 940550397Sobrien if (must_output_die) 940650397Sobrien { 940750397Sobrien if (origin_code == FUNCTION_DECL) 940850397Sobrien gen_inlined_subroutine_die (stmt, context_die, depth); 940950397Sobrien else 941050397Sobrien gen_lexical_block_die (stmt, context_die, depth); 941150397Sobrien } 941250397Sobrien else 941350397Sobrien decls_for_scope (stmt, context_die, depth); 941450397Sobrien} 941550397Sobrien 941650397Sobrien/* Generate all of the decls declared within a given scope and (recursively) 941750397Sobrien all of its sub-blocks. */ 941850397Sobrien 941950397Sobrienstatic void 942050397Sobriendecls_for_scope (stmt, context_die, depth) 942150397Sobrien register tree stmt; 942250397Sobrien register dw_die_ref context_die; 942350397Sobrien int depth; 942450397Sobrien{ 942550397Sobrien register tree decl; 942650397Sobrien register tree subblocks; 942750397Sobrien 942850397Sobrien /* Ignore blocks never really used to make RTL. */ 942950397Sobrien if (stmt == NULL_TREE || ! TREE_USED (stmt)) 943050397Sobrien return; 943150397Sobrien 943250397Sobrien if (!BLOCK_ABSTRACT (stmt) && depth > 0) 943350397Sobrien next_block_number++; 943450397Sobrien 943550397Sobrien /* Output the DIEs to represent all of the data objects and typedefs 943650397Sobrien declared directly within this block but not within any nested 943750397Sobrien sub-blocks. Also, nested function and tag DIEs have been 943850397Sobrien generated with a parent of NULL; fix that up now. */ 943950397Sobrien for (decl = BLOCK_VARS (stmt); 944050397Sobrien decl != NULL; decl = TREE_CHAIN (decl)) 944150397Sobrien { 944250397Sobrien register dw_die_ref die; 944350397Sobrien 944450397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL) 944550397Sobrien die = lookup_decl_die (decl); 944650397Sobrien else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl)) 944750397Sobrien die = lookup_type_die (TREE_TYPE (decl)); 944850397Sobrien else 944950397Sobrien die = NULL; 945050397Sobrien 945150397Sobrien if (die != NULL && die->die_parent == NULL) 945250397Sobrien add_child_die (context_die, die); 945350397Sobrien else 945450397Sobrien gen_decl_die (decl, context_die); 945550397Sobrien } 945650397Sobrien 945750397Sobrien /* Output the DIEs to represent all sub-blocks (and the items declared 945850397Sobrien therein) of this block. */ 945950397Sobrien for (subblocks = BLOCK_SUBBLOCKS (stmt); 946050397Sobrien subblocks != NULL; 946150397Sobrien subblocks = BLOCK_CHAIN (subblocks)) 946250397Sobrien gen_block_die (subblocks, context_die, depth + 1); 946350397Sobrien} 946450397Sobrien 946550397Sobrien/* Is this a typedef we can avoid emitting? */ 946650397Sobrien 946750397Sobrienstatic inline int 946850397Sobrienis_redundant_typedef (decl) 946950397Sobrien register tree decl; 947050397Sobrien{ 947150397Sobrien if (TYPE_DECL_IS_STUB (decl)) 947250397Sobrien return 1; 947350397Sobrien 947450397Sobrien if (DECL_ARTIFICIAL (decl) 947550397Sobrien && DECL_CONTEXT (decl) 947650397Sobrien && is_tagged_type (DECL_CONTEXT (decl)) 947750397Sobrien && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL 947850397Sobrien && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl)))) 947950397Sobrien /* Also ignore the artificial member typedef for the class name. */ 948050397Sobrien return 1; 948150397Sobrien 948250397Sobrien return 0; 948350397Sobrien} 948450397Sobrien 948550397Sobrien/* Generate Dwarf debug information for a decl described by DECL. */ 948650397Sobrien 948750397Sobrienstatic void 948850397Sobriengen_decl_die (decl, context_die) 948950397Sobrien register tree decl; 949050397Sobrien register dw_die_ref context_die; 949150397Sobrien{ 949250397Sobrien register tree origin; 949350397Sobrien 949450397Sobrien /* Make a note of the decl node we are going to be working on. We may need 949550397Sobrien to give the user the source coordinates of where it appeared in case we 949650397Sobrien notice (later on) that something about it looks screwy. */ 949750397Sobrien dwarf_last_decl = decl; 949850397Sobrien 949950397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 950050397Sobrien return; 950150397Sobrien 950250397Sobrien /* If this ..._DECL node is marked to be ignored, then ignore it. But don't 950350397Sobrien ignore a function definition, since that would screw up our count of 950450397Sobrien blocks, and that in turn will completely screw up the labels we will 950550397Sobrien reference in subsequent DW_AT_low_pc and DW_AT_high_pc attributes (for 950650397Sobrien subsequent blocks). */ 950750397Sobrien if (DECL_IGNORED_P (decl) && TREE_CODE (decl) != FUNCTION_DECL) 950850397Sobrien return; 950950397Sobrien 951050397Sobrien switch (TREE_CODE (decl)) 951150397Sobrien { 951250397Sobrien case CONST_DECL: 951350397Sobrien /* The individual enumerators of an enum type get output when we output 951450397Sobrien the Dwarf representation of the relevant enum type itself. */ 951550397Sobrien break; 951650397Sobrien 951750397Sobrien case FUNCTION_DECL: 951850397Sobrien /* Don't output any DIEs to represent mere function declarations, 951950397Sobrien unless they are class members or explicit block externs. */ 952050397Sobrien if (DECL_INITIAL (decl) == NULL_TREE && DECL_CONTEXT (decl) == NULL_TREE 952150397Sobrien && (current_function_decl == NULL_TREE || ! DECL_ARTIFICIAL (decl))) 952250397Sobrien break; 952350397Sobrien 952450397Sobrien if (debug_info_level > DINFO_LEVEL_TERSE) 952550397Sobrien { 952650397Sobrien /* Before we describe the FUNCTION_DECL itself, make sure that we 952750397Sobrien have described its return type. */ 952850397Sobrien gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die); 952950397Sobrien 953050397Sobrien /* And its containing type. */ 953150397Sobrien origin = decl_class_context (decl); 953250397Sobrien if (origin != NULL_TREE) 953350397Sobrien gen_type_die (origin, context_die); 953450397Sobrien 953550397Sobrien /* And its virtual context. */ 953650397Sobrien if (DECL_VINDEX (decl) != NULL_TREE) 953750397Sobrien gen_type_die (DECL_CONTEXT (decl), context_die); 953850397Sobrien } 953950397Sobrien 954050397Sobrien /* Now output a DIE to represent the function itself. */ 954150397Sobrien gen_subprogram_die (decl, context_die); 954250397Sobrien break; 954350397Sobrien 954450397Sobrien case TYPE_DECL: 954550397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 954650397Sobrien actual typedefs. */ 954750397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 954850397Sobrien break; 954950397Sobrien 955050397Sobrien /* In the special case of a TYPE_DECL node representing the 955150397Sobrien declaration of some type tag, if the given TYPE_DECL is marked as 955250397Sobrien having been instantiated from some other (original) TYPE_DECL node 955350397Sobrien (e.g. one which was generated within the original definition of an 955450397Sobrien inline function) we have to generate a special (abbreviated) 955550397Sobrien DW_TAG_structure_type, DW_TAG_union_type, or DW_TAG_enumeration_type 955650397Sobrien DIE here. */ 955750397Sobrien if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE) 955850397Sobrien { 955950397Sobrien gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die); 956050397Sobrien break; 956150397Sobrien } 956250397Sobrien 956350397Sobrien if (is_redundant_typedef (decl)) 956450397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 956550397Sobrien else 956650397Sobrien /* Output a DIE to represent the typedef itself. */ 956750397Sobrien gen_typedef_die (decl, context_die); 956850397Sobrien break; 956950397Sobrien 957050397Sobrien case LABEL_DECL: 957150397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 957250397Sobrien gen_label_die (decl, context_die); 957350397Sobrien break; 957450397Sobrien 957550397Sobrien case VAR_DECL: 957650397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 957750397Sobrien variable declarations or definitions. */ 957850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 957950397Sobrien break; 958050397Sobrien 958150397Sobrien /* Output any DIEs that are needed to specify the type of this data 958250397Sobrien object. */ 958350397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 958450397Sobrien 958550397Sobrien /* And its containing type. */ 958650397Sobrien origin = decl_class_context (decl); 958750397Sobrien if (origin != NULL_TREE) 958850397Sobrien gen_type_die (origin, context_die); 958950397Sobrien 959050397Sobrien /* Now output the DIE to represent the data object itself. This gets 959150397Sobrien complicated because of the possibility that the VAR_DECL really 959250397Sobrien represents an inlined instance of a formal parameter for an inline 959350397Sobrien function. */ 959450397Sobrien origin = decl_ultimate_origin (decl); 959550397Sobrien if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) 959650397Sobrien gen_formal_parameter_die (decl, context_die); 959750397Sobrien else 959850397Sobrien gen_variable_die (decl, context_die); 959950397Sobrien break; 960050397Sobrien 960150397Sobrien case FIELD_DECL: 960250397Sobrien /* Ignore the nameless fields that are used to skip bits, but 960350397Sobrien handle C++ anonymous unions. */ 960450397Sobrien if (DECL_NAME (decl) != NULL_TREE 960550397Sobrien || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE) 960650397Sobrien { 960750397Sobrien gen_type_die (member_declared_type (decl), context_die); 960850397Sobrien gen_field_die (decl, context_die); 960950397Sobrien } 961050397Sobrien break; 961150397Sobrien 961250397Sobrien case PARM_DECL: 961350397Sobrien gen_type_die (TREE_TYPE (decl), context_die); 961450397Sobrien gen_formal_parameter_die (decl, context_die); 961550397Sobrien break; 961650397Sobrien 961750397Sobrien default: 961850397Sobrien abort (); 961950397Sobrien } 962050397Sobrien} 962150397Sobrien 962250397Sobrien/* Write the debugging output for DECL. */ 962350397Sobrien 962450397Sobrienvoid 962550397Sobriendwarf2out_decl (decl) 962650397Sobrien register tree decl; 962750397Sobrien{ 962850397Sobrien register dw_die_ref context_die = comp_unit_die; 962950397Sobrien 963050397Sobrien if (TREE_CODE (decl) == ERROR_MARK) 963150397Sobrien return; 963250397Sobrien 963350397Sobrien /* If this ..._DECL node is marked to be ignored, then ignore it. We gotta 963450397Sobrien hope that the node in question doesn't represent a function definition. 963550397Sobrien If it does, then totally ignoring it is bound to screw up our count of 963650397Sobrien blocks, and that in turn will completely screw up the labels we will 963750397Sobrien reference in subsequent DW_AT_low_pc and DW_AT_high_pc attributes (for 963850397Sobrien subsequent blocks). (It's too bad that BLOCK nodes don't carry their 963950397Sobrien own sequence numbers with them!) */ 964050397Sobrien if (DECL_IGNORED_P (decl)) 964150397Sobrien { 964250397Sobrien if (TREE_CODE (decl) == FUNCTION_DECL 964352284Sobrien && DECL_INITIAL (decl) != NULL) 964450397Sobrien abort (); 964550397Sobrien 964650397Sobrien return; 964750397Sobrien } 964850397Sobrien 964950397Sobrien switch (TREE_CODE (decl)) 965050397Sobrien { 965150397Sobrien case FUNCTION_DECL: 965250397Sobrien /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a 965350397Sobrien builtin function. Explicit programmer-supplied declarations of 965450397Sobrien these same functions should NOT be ignored however. */ 965550397Sobrien if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl)) 965650397Sobrien return; 965750397Sobrien 965850397Sobrien /* What we would really like to do here is to filter out all mere 965950397Sobrien file-scope declarations of file-scope functions which are never 966050397Sobrien referenced later within this translation unit (and keep all of ones 966150397Sobrien that *are* referenced later on) but we aren't clairvoyant, so we have 966250397Sobrien no idea which functions will be referenced in the future (i.e. later 966350397Sobrien on within the current translation unit). So here we just ignore all 966450397Sobrien file-scope function declarations which are not also definitions. If 966550397Sobrien and when the debugger needs to know something about these functions, 966650397Sobrien it wil have to hunt around and find the DWARF information associated 966750397Sobrien with the definition of the function. Note that we can't just check 966850397Sobrien `DECL_EXTERNAL' to find out which FUNCTION_DECL nodes represent 966950397Sobrien definitions and which ones represent mere declarations. We have to 967050397Sobrien check `DECL_INITIAL' instead. That's because the C front-end 967150397Sobrien supports some weird semantics for "extern inline" function 967250397Sobrien definitions. These can get inlined within the current translation 967350397Sobrien unit (an thus, we need to generate DWARF info for their abstract 967450397Sobrien instances so that the DWARF info for the concrete inlined instances 967550397Sobrien can have something to refer to) but the compiler never generates any 967650397Sobrien out-of-lines instances of such things (despite the fact that they 967750397Sobrien *are* definitions). The important point is that the C front-end 967850397Sobrien marks these "extern inline" functions as DECL_EXTERNAL, but we need 967950397Sobrien to generate DWARF for them anyway. Note that the C++ front-end also 968050397Sobrien plays some similar games for inline function definitions appearing 968150397Sobrien within include files which also contain 968250397Sobrien `#pragma interface' pragmas. */ 968350397Sobrien if (DECL_INITIAL (decl) == NULL_TREE) 968450397Sobrien return; 968550397Sobrien 968650397Sobrien /* If we're a nested function, initially use a parent of NULL; if we're 968750397Sobrien a plain function, this will be fixed up in decls_for_scope. If 968850397Sobrien we're a method, it will be ignored, since we already have a DIE. */ 968950397Sobrien if (decl_function_context (decl)) 969050397Sobrien context_die = NULL; 969150397Sobrien 969250397Sobrien break; 969350397Sobrien 969450397Sobrien case VAR_DECL: 969550397Sobrien /* Ignore this VAR_DECL if it refers to a file-scope extern data object 969650397Sobrien declaration and if the declaration was never even referenced from 969750397Sobrien within this entire compilation unit. We suppress these DIEs in 969850397Sobrien order to save space in the .debug section (by eliminating entries 969950397Sobrien which are probably useless). Note that we must not suppress 970050397Sobrien block-local extern declarations (whether used or not) because that 970150397Sobrien would screw-up the debugger's name lookup mechanism and cause it to 970250397Sobrien miss things which really ought to be in scope at a given point. */ 970350397Sobrien if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) 970450397Sobrien return; 970550397Sobrien 970650397Sobrien /* If we are in terse mode, don't generate any DIEs to represent any 970750397Sobrien variable declarations or definitions. */ 970850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 970950397Sobrien return; 971050397Sobrien break; 971150397Sobrien 971250397Sobrien case TYPE_DECL: 971350397Sobrien /* Don't bother trying to generate any DIEs to represent any of the 971450397Sobrien normal built-in types for the language we are compiling. */ 971550397Sobrien if (DECL_SOURCE_LINE (decl) == 0) 971650397Sobrien { 971750397Sobrien /* OK, we need to generate one for `bool' so GDB knows what type 971850397Sobrien comparisons have. */ 971950397Sobrien if ((get_AT_unsigned (comp_unit_die, DW_AT_language) 972050397Sobrien == DW_LANG_C_plus_plus) 972150397Sobrien && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE) 972250397Sobrien modified_type_die (TREE_TYPE (decl), 0, 0, NULL); 972350397Sobrien 972450397Sobrien return; 972550397Sobrien } 972650397Sobrien 972750397Sobrien /* If we are in terse mode, don't generate any DIEs for types. */ 972850397Sobrien if (debug_info_level <= DINFO_LEVEL_TERSE) 972950397Sobrien return; 973050397Sobrien 973150397Sobrien /* If we're a function-scope tag, initially use a parent of NULL; 973250397Sobrien this will be fixed up in decls_for_scope. */ 973350397Sobrien if (decl_function_context (decl)) 973450397Sobrien context_die = NULL; 973550397Sobrien 973650397Sobrien break; 973750397Sobrien 973850397Sobrien default: 973950397Sobrien return; 974050397Sobrien } 974150397Sobrien 974250397Sobrien gen_decl_die (decl, context_die); 974350397Sobrien output_pending_types_for_scope (comp_unit_die); 974450397Sobrien} 974550397Sobrien 974650397Sobrien/* Output a marker (i.e. a label) for the beginning of the generated code for 974750397Sobrien a lexical block. */ 974850397Sobrien 974950397Sobrienvoid 975050397Sobriendwarf2out_begin_block (blocknum) 975150397Sobrien register unsigned blocknum; 975250397Sobrien{ 975350397Sobrien function_section (current_function_decl); 975450397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 975550397Sobrien} 975650397Sobrien 975750397Sobrien/* Output a marker (i.e. a label) for the end of the generated code for a 975850397Sobrien lexical block. */ 975950397Sobrien 976050397Sobrienvoid 976150397Sobriendwarf2out_end_block (blocknum) 976250397Sobrien register unsigned blocknum; 976350397Sobrien{ 976450397Sobrien function_section (current_function_decl); 976550397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); 976650397Sobrien} 976750397Sobrien 976850397Sobrien/* Output a marker (i.e. a label) at a point in the assembly code which 976950397Sobrien corresponds to a given source level label. */ 977050397Sobrien 977150397Sobrienvoid 977250397Sobriendwarf2out_label (insn) 977350397Sobrien register rtx insn; 977450397Sobrien{ 977550397Sobrien char label[MAX_ARTIFICIAL_LABEL_BYTES]; 977650397Sobrien 977750397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 977850397Sobrien { 977950397Sobrien function_section (current_function_decl); 978050397Sobrien sprintf (label, INSN_LABEL_FMT, current_funcdef_number); 978150397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, label, 978250397Sobrien (unsigned) INSN_UID (insn)); 978350397Sobrien } 978450397Sobrien} 978550397Sobrien 978650397Sobrien/* Lookup a filename (in the list of filenames that we know about here in 978750397Sobrien dwarf2out.c) and return its "index". The index of each (known) filename is 978850397Sobrien just a unique number which is associated with only that one filename. 978950397Sobrien We need such numbers for the sake of generating labels 979050397Sobrien (in the .debug_sfnames section) and references to those 979150397Sobrien files numbers (in the .debug_srcinfo and.debug_macinfo sections). 979250397Sobrien If the filename given as an argument is not found in our current list, 979350397Sobrien add it to the list and assign it the next available unique index number. 979450397Sobrien In order to speed up searches, we remember the index of the filename 979550397Sobrien was looked up last. This handles the majority of all searches. */ 979650397Sobrien 979750397Sobrienstatic unsigned 979850397Sobrienlookup_filename (file_name) 979950397Sobrien char *file_name; 980050397Sobrien{ 980150397Sobrien static unsigned last_file_lookup_index = 0; 980250397Sobrien register unsigned i; 980350397Sobrien 980450397Sobrien /* Check to see if the file name that was searched on the previous call 980550397Sobrien matches this file name. If so, return the index. */ 980650397Sobrien if (last_file_lookup_index != 0) 980750397Sobrien if (strcmp (file_name, file_table[last_file_lookup_index]) == 0) 980850397Sobrien return last_file_lookup_index; 980950397Sobrien 981050397Sobrien /* Didn't match the previous lookup, search the table */ 981150397Sobrien for (i = 1; i < file_table_in_use; ++i) 981250397Sobrien if (strcmp (file_name, file_table[i]) == 0) 981350397Sobrien { 981450397Sobrien last_file_lookup_index = i; 981550397Sobrien return i; 981650397Sobrien } 981750397Sobrien 981850397Sobrien /* Prepare to add a new table entry by making sure there is enough space in 981950397Sobrien the table to do so. If not, expand the current table. */ 982050397Sobrien if (file_table_in_use == file_table_allocated) 982150397Sobrien { 982250397Sobrien file_table_allocated += FILE_TABLE_INCREMENT; 982350397Sobrien file_table 982450397Sobrien = (char **) xrealloc (file_table, 982550397Sobrien file_table_allocated * sizeof (char *)); 982650397Sobrien } 982750397Sobrien 982850397Sobrien /* Add the new entry to the end of the filename table. */ 982950397Sobrien file_table[file_table_in_use] = xstrdup (file_name); 983050397Sobrien last_file_lookup_index = file_table_in_use++; 983150397Sobrien 983250397Sobrien return last_file_lookup_index; 983350397Sobrien} 983450397Sobrien 983550397Sobrien/* Output a label to mark the beginning of a source code line entry 983650397Sobrien and record information relating to this source line, in 983750397Sobrien 'line_info_table' for later output of the .debug_line section. */ 983850397Sobrien 983950397Sobrienvoid 984050397Sobriendwarf2out_line (filename, line) 984150397Sobrien register char *filename; 984250397Sobrien register unsigned line; 984350397Sobrien{ 984450397Sobrien if (debug_info_level >= DINFO_LEVEL_NORMAL) 984550397Sobrien { 984650397Sobrien function_section (current_function_decl); 984750397Sobrien 984850397Sobrien if (DECL_SECTION_NAME (current_function_decl)) 984950397Sobrien { 985050397Sobrien register dw_separate_line_info_ref line_info; 985150397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, 985250397Sobrien separate_line_info_table_in_use); 985350397Sobrien fputc ('\n', asm_out_file); 985450397Sobrien 985550397Sobrien /* expand the line info table if necessary */ 985650397Sobrien if (separate_line_info_table_in_use 985750397Sobrien == separate_line_info_table_allocated) 985850397Sobrien { 985950397Sobrien separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 986050397Sobrien separate_line_info_table 986150397Sobrien = (dw_separate_line_info_ref) 986250397Sobrien xrealloc (separate_line_info_table, 986350397Sobrien separate_line_info_table_allocated 986450397Sobrien * sizeof (dw_separate_line_info_entry)); 986550397Sobrien } 986650397Sobrien 986750397Sobrien /* Add the new entry at the end of the line_info_table. */ 986850397Sobrien line_info 986950397Sobrien = &separate_line_info_table[separate_line_info_table_in_use++]; 987050397Sobrien line_info->dw_file_num = lookup_filename (filename); 987150397Sobrien line_info->dw_line_num = line; 987250397Sobrien line_info->function = current_funcdef_number; 987350397Sobrien } 987450397Sobrien else 987550397Sobrien { 987650397Sobrien register dw_line_info_ref line_info; 987750397Sobrien 987850397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, 987950397Sobrien line_info_table_in_use); 988050397Sobrien fputc ('\n', asm_out_file); 988150397Sobrien 988250397Sobrien /* Expand the line info table if necessary. */ 988350397Sobrien if (line_info_table_in_use == line_info_table_allocated) 988450397Sobrien { 988550397Sobrien line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 988650397Sobrien line_info_table 988750397Sobrien = (dw_line_info_ref) 988850397Sobrien xrealloc (line_info_table, 988950397Sobrien (line_info_table_allocated 989050397Sobrien * sizeof (dw_line_info_entry))); 989150397Sobrien } 989250397Sobrien 989350397Sobrien /* Add the new entry at the end of the line_info_table. */ 989450397Sobrien line_info = &line_info_table[line_info_table_in_use++]; 989550397Sobrien line_info->dw_file_num = lookup_filename (filename); 989650397Sobrien line_info->dw_line_num = line; 989750397Sobrien } 989850397Sobrien } 989950397Sobrien} 990050397Sobrien 990150397Sobrien/* Record the beginning of a new source file, for later output 990250397Sobrien of the .debug_macinfo section. At present, unimplemented. */ 990350397Sobrien 990450397Sobrienvoid 990550397Sobriendwarf2out_start_source_file (filename) 990650397Sobrien register char *filename ATTRIBUTE_UNUSED; 990750397Sobrien{ 990850397Sobrien} 990950397Sobrien 991050397Sobrien/* Record the end of a source file, for later output 991150397Sobrien of the .debug_macinfo section. At present, unimplemented. */ 991250397Sobrien 991350397Sobrienvoid 991450397Sobriendwarf2out_end_source_file () 991550397Sobrien{ 991650397Sobrien} 991750397Sobrien 991850397Sobrien/* Called from check_newline in c-parse.y. The `buffer' parameter contains 991950397Sobrien the tail part of the directive line, i.e. the part which is past the 992050397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 992150397Sobrien 992250397Sobrienvoid 992350397Sobriendwarf2out_define (lineno, buffer) 992450397Sobrien register unsigned lineno; 992550397Sobrien register char *buffer; 992650397Sobrien{ 992750397Sobrien static int initialized = 0; 992850397Sobrien if (!initialized) 992950397Sobrien { 993050397Sobrien dwarf2out_start_source_file (primary_filename); 993150397Sobrien initialized = 1; 993250397Sobrien } 993350397Sobrien} 993450397Sobrien 993550397Sobrien/* Called from check_newline in c-parse.y. The `buffer' parameter contains 993650397Sobrien the tail part of the directive line, i.e. the part which is past the 993750397Sobrien initial whitespace, #, whitespace, directive-name, whitespace part. */ 993850397Sobrien 993950397Sobrienvoid 994050397Sobriendwarf2out_undef (lineno, buffer) 994150397Sobrien register unsigned lineno ATTRIBUTE_UNUSED; 994250397Sobrien register char *buffer ATTRIBUTE_UNUSED; 994350397Sobrien{ 994450397Sobrien} 994550397Sobrien 994650397Sobrien/* Set up for Dwarf output at the start of compilation. */ 994750397Sobrien 994850397Sobrienvoid 994950397Sobriendwarf2out_init (asm_out_file, main_input_filename) 995050397Sobrien register FILE *asm_out_file; 995150397Sobrien register char *main_input_filename; 995250397Sobrien{ 995350397Sobrien /* Remember the name of the primary input file. */ 995450397Sobrien primary_filename = main_input_filename; 995550397Sobrien 995650397Sobrien /* Allocate the initial hunk of the file_table. */ 995750397Sobrien file_table = (char **) xmalloc (FILE_TABLE_INCREMENT * sizeof (char *)); 995850397Sobrien bzero ((char *) file_table, FILE_TABLE_INCREMENT * sizeof (char *)); 995950397Sobrien file_table_allocated = FILE_TABLE_INCREMENT; 996050397Sobrien 996150397Sobrien /* Skip the first entry - file numbers begin at 1. */ 996250397Sobrien file_table_in_use = 1; 996350397Sobrien 996450397Sobrien /* Allocate the initial hunk of the decl_die_table. */ 996550397Sobrien decl_die_table 996650397Sobrien = (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref)); 996750397Sobrien bzero ((char *) decl_die_table, 996850397Sobrien DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref)); 996950397Sobrien decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT; 997050397Sobrien decl_die_table_in_use = 0; 997150397Sobrien 997250397Sobrien /* Allocate the initial hunk of the decl_scope_table. */ 997350397Sobrien decl_scope_table 997450397Sobrien = (decl_scope_node *) xmalloc (DECL_SCOPE_TABLE_INCREMENT 997550397Sobrien * sizeof (decl_scope_node)); 997650397Sobrien bzero ((char *) decl_scope_table, 997750397Sobrien DECL_SCOPE_TABLE_INCREMENT * sizeof (decl_scope_node)); 997850397Sobrien decl_scope_table_allocated = DECL_SCOPE_TABLE_INCREMENT; 997950397Sobrien decl_scope_depth = 0; 998050397Sobrien 998150397Sobrien /* Allocate the initial hunk of the abbrev_die_table. */ 998250397Sobrien abbrev_die_table 998350397Sobrien = (dw_die_ref *) xmalloc (ABBREV_DIE_TABLE_INCREMENT 998450397Sobrien * sizeof (dw_die_ref)); 998550397Sobrien bzero ((char *) abbrev_die_table, 998650397Sobrien ABBREV_DIE_TABLE_INCREMENT * sizeof (dw_die_ref)); 998750397Sobrien abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; 998850397Sobrien /* Zero-th entry is allocated, but unused */ 998950397Sobrien abbrev_die_table_in_use = 1; 999050397Sobrien 999150397Sobrien /* Allocate the initial hunk of the line_info_table. */ 999250397Sobrien line_info_table 999350397Sobrien = (dw_line_info_ref) xmalloc (LINE_INFO_TABLE_INCREMENT 999450397Sobrien * sizeof (dw_line_info_entry)); 999550397Sobrien bzero ((char *) line_info_table, 999650397Sobrien LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry)); 999750397Sobrien line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 999850397Sobrien /* Zero-th entry is allocated, but unused */ 999950397Sobrien line_info_table_in_use = 1; 1000050397Sobrien 1000150397Sobrien /* Generate the initial DIE for the .debug section. Note that the (string) 1000250397Sobrien value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE 1000350397Sobrien will (typically) be a relative pathname and that this pathname should be 1000450397Sobrien taken as being relative to the directory from which the compiler was 1000550397Sobrien invoked when the given (base) source file was compiled. */ 1000650397Sobrien gen_compile_unit_die (main_input_filename); 1000750397Sobrien 1000850397Sobrien ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1000952284Sobrien ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0); 1001052284Sobrien ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0); 1001152284Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_info_section_label, 1001252284Sobrien DEBUG_INFO_SECTION_LABEL, 0); 1001352284Sobrien ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, 1001452284Sobrien DEBUG_LINE_SECTION_LABEL, 0); 1001552284Sobrien 1001652284Sobrien ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION); 1001752284Sobrien ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); 1001852284Sobrien ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION); 1001952284Sobrien ASM_OUTPUT_LABEL (asm_out_file, text_section_label); 1002052284Sobrien ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION); 1002152284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label); 1002252284Sobrien ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION); 1002352284Sobrien ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); 1002450397Sobrien} 1002550397Sobrien 1002650397Sobrien/* Output stuff that dwarf requires at the end of every file, 1002750397Sobrien and generate the DWARF-2 debugging info. */ 1002850397Sobrien 1002950397Sobrienvoid 1003050397Sobriendwarf2out_finish () 1003150397Sobrien{ 1003250397Sobrien limbo_die_node *node, *next_node; 1003350397Sobrien dw_die_ref die; 1003450397Sobrien dw_attr_ref a; 1003550397Sobrien 1003650397Sobrien /* Traverse the limbo die list, and add parent/child links. The only 1003750397Sobrien dies without parents that should be here are concrete instances of 1003850397Sobrien inline functions, and the comp_unit_die. We can ignore the comp_unit_die. 1003950397Sobrien For concrete instances, we can get the parent die from the abstract 1004050397Sobrien instance. */ 1004150397Sobrien for (node = limbo_die_list; node; node = next_node) 1004250397Sobrien { 1004350397Sobrien next_node = node->next; 1004450397Sobrien die = node->die; 1004550397Sobrien 1004650397Sobrien if (die->die_parent == NULL) 1004750397Sobrien { 1004850397Sobrien a = get_AT (die, DW_AT_abstract_origin); 1004950397Sobrien if (a) 1005050397Sobrien add_child_die (a->dw_attr_val.v.val_die_ref->die_parent, die); 1005150397Sobrien else if (die == comp_unit_die) 1005250397Sobrien ; 1005350397Sobrien else 1005450397Sobrien abort (); 1005550397Sobrien } 1005650397Sobrien free (node); 1005750397Sobrien } 1005850397Sobrien 1005952284Sobrien /* Walk through the list of incomplete types again, trying once more to 1006052284Sobrien emit full debugging info for them. */ 1006152284Sobrien retry_incomplete_types (); 1006252284Sobrien 1006350397Sobrien /* Traverse the DIE tree and add sibling attributes to those DIE's 1006450397Sobrien that have children. */ 1006550397Sobrien add_sibling_attributes (comp_unit_die); 1006650397Sobrien 1006750397Sobrien /* Output a terminator label for the .text section. */ 1006850397Sobrien fputc ('\n', asm_out_file); 1006950397Sobrien ASM_OUTPUT_SECTION (asm_out_file, TEXT_SECTION); 1007050397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); 1007150397Sobrien 1007250397Sobrien#if 0 1007350397Sobrien /* Output a terminator label for the .data section. */ 1007450397Sobrien fputc ('\n', asm_out_file); 1007550397Sobrien ASM_OUTPUT_SECTION (asm_out_file, DATA_SECTION); 1007650397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, DATA_END_LABEL, 0); 1007750397Sobrien 1007850397Sobrien /* Output a terminator label for the .bss section. */ 1007950397Sobrien fputc ('\n', asm_out_file); 1008050397Sobrien ASM_OUTPUT_SECTION (asm_out_file, BSS_SECTION); 1008150397Sobrien ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0); 1008250397Sobrien#endif 1008350397Sobrien 1008450397Sobrien /* Output the source line correspondence table. */ 1008550397Sobrien if (line_info_table_in_use > 1 || separate_line_info_table_in_use) 1008650397Sobrien { 1008750397Sobrien fputc ('\n', asm_out_file); 1008850397Sobrien ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION); 1008950397Sobrien output_line_info (); 1009050397Sobrien 1009150397Sobrien /* We can only use the low/high_pc attributes if all of the code 1009250397Sobrien was in .text. */ 1009350397Sobrien if (separate_line_info_table_in_use == 0) 1009450397Sobrien { 1009552284Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); 1009650397Sobrien add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); 1009750397Sobrien } 1009850397Sobrien 1009952284Sobrien add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, 1010052284Sobrien debug_line_section_label); 1010150397Sobrien } 1010250397Sobrien 1010350397Sobrien /* Output the abbreviation table. */ 1010450397Sobrien fputc ('\n', asm_out_file); 1010550397Sobrien ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION); 1010650397Sobrien build_abbrev_table (comp_unit_die); 1010750397Sobrien output_abbrev_section (); 1010850397Sobrien 1010950397Sobrien /* Initialize the beginning DIE offset - and calculate sizes/offsets. */ 1011050397Sobrien next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE; 1011150397Sobrien calc_die_sizes (comp_unit_die); 1011250397Sobrien 1011350397Sobrien /* Output debugging information. */ 1011450397Sobrien fputc ('\n', asm_out_file); 1011550397Sobrien ASM_OUTPUT_SECTION (asm_out_file, DEBUG_INFO_SECTION); 1011650397Sobrien output_compilation_unit_header (); 1011750397Sobrien output_die (comp_unit_die); 1011850397Sobrien 1011950397Sobrien if (pubname_table_in_use) 1012050397Sobrien { 1012150397Sobrien /* Output public names table. */ 1012250397Sobrien fputc ('\n', asm_out_file); 1012350397Sobrien ASM_OUTPUT_SECTION (asm_out_file, PUBNAMES_SECTION); 1012450397Sobrien output_pubnames (); 1012550397Sobrien } 1012650397Sobrien 1012750397Sobrien if (fde_table_in_use) 1012850397Sobrien { 1012950397Sobrien /* Output the address range information. */ 1013050397Sobrien fputc ('\n', asm_out_file); 1013150397Sobrien ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION); 1013250397Sobrien output_aranges (); 1013350397Sobrien } 1013450397Sobrien} 1013550397Sobrien#endif /* DWARF2_DEBUGGING_INFO */ 10136