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